@empiricalrun/test-gen 0.76.0 → 0.78.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 (237) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/dist/agent/base/index.d.ts +25 -21
  3. package/dist/agent/base/index.d.ts.map +1 -1
  4. package/dist/agent/base/index.js +50 -37
  5. package/dist/agent/browsing/run.d.ts +1 -2
  6. package/dist/agent/browsing/run.d.ts.map +1 -1
  7. package/dist/agent/browsing/run.js +3 -9
  8. package/dist/agent/browsing/utils.d.ts +2 -9
  9. package/dist/agent/browsing/utils.d.ts.map +1 -1
  10. package/dist/agent/browsing/utils.js +5 -109
  11. package/dist/agent/chat/agent-loop.d.ts +5 -5
  12. package/dist/agent/chat/agent-loop.d.ts.map +1 -1
  13. package/dist/agent/chat/agent-loop.js +3 -8
  14. package/dist/agent/chat/exports.d.ts +6 -5
  15. package/dist/agent/chat/exports.d.ts.map +1 -1
  16. package/dist/agent/chat/exports.js +4 -9
  17. package/dist/agent/chat/index.d.ts +2 -2
  18. package/dist/agent/chat/index.d.ts.map +1 -1
  19. package/dist/agent/chat/index.js +23 -35
  20. package/dist/agent/chat/models.d.ts +0 -2
  21. package/dist/agent/chat/models.d.ts.map +1 -1
  22. package/dist/agent/chat/models.js +12 -26
  23. package/dist/agent/chat/prompt/pw-utils-docs.d.ts +1 -1
  24. package/dist/agent/chat/prompt/pw-utils-docs.d.ts.map +1 -1
  25. package/dist/agent/chat/prompt/pw-utils-docs.js +52 -0
  26. package/dist/agent/chat/prompt/repo.d.ts.map +1 -1
  27. package/dist/agent/chat/prompt/repo.js +11 -22
  28. package/dist/agent/chat/prompt/test-case-def.d.ts +2 -0
  29. package/dist/agent/chat/prompt/test-case-def.d.ts.map +1 -0
  30. package/dist/agent/chat/prompt/test-case-def.js +44 -0
  31. package/dist/agent/chat/state.d.ts +8 -14
  32. package/dist/agent/chat/state.d.ts.map +1 -1
  33. package/dist/agent/chat/state.js +15 -60
  34. package/dist/agent/chat/utils.d.ts +2 -2
  35. package/dist/agent/chat/utils.d.ts.map +1 -1
  36. package/dist/agent/chat/utils.js +14 -7
  37. package/dist/agent/cli.d.ts.map +1 -1
  38. package/dist/agent/cli.js +49 -58
  39. package/dist/agent/code-review/executor/index.d.ts +5 -0
  40. package/dist/agent/code-review/executor/index.d.ts.map +1 -0
  41. package/dist/agent/code-review/executor/index.js +13 -0
  42. package/dist/agent/code-review/index.d.ts +8 -3
  43. package/dist/agent/code-review/index.d.ts.map +1 -1
  44. package/dist/agent/code-review/index.js +118 -21
  45. package/dist/agent/code-review/parser.d.ts +5 -0
  46. package/dist/agent/code-review/parser.d.ts.map +1 -0
  47. package/dist/agent/code-review/parser.js +70 -0
  48. package/dist/agent/code-review/types.d.ts +36 -0
  49. package/dist/agent/code-review/types.d.ts.map +1 -0
  50. package/dist/agent/code-review/types.js +13 -0
  51. package/dist/agent/cua/index.d.ts.map +1 -1
  52. package/dist/agent/cua/index.js +18 -2
  53. package/dist/agent/cua/model.d.ts.map +1 -1
  54. package/dist/agent/cua/model.js +4 -1
  55. package/dist/agent/cua/pw-codegen/pw-pause/index.d.ts.map +1 -1
  56. package/dist/agent/triage/index.d.ts +3 -3
  57. package/dist/agent/triage/index.d.ts.map +1 -1
  58. package/dist/agent/triage/index.js +16 -20
  59. package/dist/agent/video-analysis/executor/index.d.ts +5 -0
  60. package/dist/agent/video-analysis/executor/index.d.ts.map +1 -0
  61. package/dist/agent/video-analysis/executor/index.js +10 -0
  62. package/dist/agent/video-analysis/index.d.ts +2 -2
  63. package/dist/agent/video-analysis/index.d.ts.map +1 -1
  64. package/dist/agent/video-analysis/index.js +38 -13
  65. package/dist/artifacts/index.d.ts +1 -1
  66. package/dist/artifacts/index.d.ts.map +1 -1
  67. package/dist/artifacts/index.js +3 -1
  68. package/dist/artifacts/utils.d.ts.map +1 -1
  69. package/dist/bin/index.js +11 -21
  70. package/dist/constants/index.d.ts +14 -0
  71. package/dist/constants/index.d.ts.map +1 -1
  72. package/dist/constants/index.js +33 -1
  73. package/dist/file/server.d.ts +1 -3
  74. package/dist/file/server.d.ts.map +1 -1
  75. package/dist/file/server.js +0 -13
  76. package/dist/file-info/adapters/file-system/index.d.ts.map +1 -1
  77. package/dist/file-info/adapters/file-system/reader.d.ts.map +1 -1
  78. package/dist/file-info/adapters/file-system/reader.js +8 -1
  79. package/dist/file-info/adapters/github/index.d.ts.map +1 -1
  80. package/dist/file-info/adapters/github/reader.d.ts +1 -1
  81. package/dist/file-info/adapters/github/reader.d.ts.map +1 -1
  82. package/dist/file-info/adapters/github/reader.js +8 -5
  83. package/dist/index.d.ts.map +1 -1
  84. package/dist/tools/analyse-video/index.d.ts +5 -0
  85. package/dist/tools/analyse-video/index.d.ts.map +1 -0
  86. package/dist/tools/analyse-video/index.js +56 -0
  87. package/dist/tools/create-pull-request/index.js +4 -6
  88. package/dist/tools/create-pull-request/utils.d.ts +1 -1
  89. package/dist/tools/definitions/{fetch-video-analysis.d.ts → analyse-video.d.ts} +17 -12
  90. package/dist/tools/definitions/analyse-video.d.ts.map +1 -0
  91. package/dist/tools/definitions/analyse-video.js +60 -0
  92. package/dist/tools/definitions/review-pull-request.d.ts +3 -0
  93. package/dist/tools/definitions/review-pull-request.d.ts.map +1 -0
  94. package/dist/tools/definitions/review-pull-request.js +16 -0
  95. package/dist/tools/definitions/str_replace_editor.d.ts +1 -0
  96. package/dist/tools/definitions/str_replace_editor.d.ts.map +1 -1
  97. package/dist/tools/definitions/str_replace_editor.js +4 -1
  98. package/dist/tools/definitions/test-gen-browser.d.ts +0 -3
  99. package/dist/tools/definitions/test-gen-browser.d.ts.map +1 -1
  100. package/dist/tools/definitions/test-gen-browser.js +33 -8
  101. package/dist/tools/delete-file/index.d.ts.map +1 -1
  102. package/dist/tools/delete-file/index.js +1 -19
  103. package/dist/tools/executor/base.d.ts +32 -0
  104. package/dist/tools/executor/base.d.ts.map +1 -0
  105. package/dist/tools/executor/base.js +131 -0
  106. package/dist/tools/executor/index.d.ts +3 -22
  107. package/dist/tools/executor/index.d.ts.map +1 -1
  108. package/dist/tools/executor/index.js +7 -100
  109. package/dist/tools/executor/utils/checkpoint.d.ts +1 -1
  110. package/dist/tools/executor/utils/checkpoint.d.ts.map +1 -1
  111. package/dist/tools/executor/utils/checkpoint.js +6 -2
  112. package/dist/tools/executor/utils/git.d.ts +2 -2
  113. package/dist/tools/executor/utils/git.d.ts.map +1 -1
  114. package/dist/tools/executor/utils/git.js +7 -3
  115. package/dist/tools/executor/utils/index.d.ts +5 -3
  116. package/dist/tools/executor/utils/index.d.ts.map +1 -1
  117. package/dist/tools/executor/utils/index.js +23 -2
  118. package/dist/tools/fetch-session-diff/index.js +2 -2
  119. package/dist/tools/file-operations/create.d.ts.map +1 -1
  120. package/dist/tools/file-operations/create.js +1 -4
  121. package/dist/tools/file-operations/index.d.ts +2 -1
  122. package/dist/tools/file-operations/index.d.ts.map +1 -1
  123. package/dist/tools/file-operations/index.js +4 -1
  124. package/dist/tools/file-operations/insert.d.ts +1 -2
  125. package/dist/tools/file-operations/insert.d.ts.map +1 -1
  126. package/dist/tools/file-operations/insert.js +1 -4
  127. package/dist/tools/file-operations/replace.d.ts.map +1 -1
  128. package/dist/tools/file-operations/replace.js +21 -25
  129. package/dist/tools/file-operations/shared/helpers.d.ts +3 -5
  130. package/dist/tools/file-operations/shared/helpers.d.ts.map +1 -1
  131. package/dist/tools/file-operations/shared/helpers.js +1 -5
  132. package/dist/tools/grep/index.d.ts.map +1 -1
  133. package/dist/tools/grep/index.js +18 -11
  134. package/dist/tools/index.d.ts +5 -5
  135. package/dist/tools/index.d.ts.map +1 -1
  136. package/dist/tools/index.js +17 -16
  137. package/dist/tools/merge-conflicts/index.d.ts.map +1 -1
  138. package/dist/tools/merge-conflicts/index.js +1 -1
  139. package/dist/tools/rename-file/index.js +1 -1
  140. package/dist/tools/review-pull-request/index.d.ts.map +1 -1
  141. package/dist/tools/review-pull-request/index.js +44 -65
  142. package/dist/tools/run-test.d.ts.map +1 -1
  143. package/dist/tools/run-test.js +25 -3
  144. package/dist/tools/test-gen-browser.d.ts.map +1 -1
  145. package/dist/tools/test-gen-browser.js +51 -47
  146. package/dist/tools/upgrade-packages/index.d.ts.map +1 -1
  147. package/dist/tools/upgrade-packages/index.js +4 -0
  148. package/dist/tools/upgrade-packages/utils.d.ts +1 -0
  149. package/dist/tools/upgrade-packages/utils.d.ts.map +1 -1
  150. package/dist/tools/upgrade-packages/utils.js +1 -0
  151. package/dist/trace-utils/index.d.ts +1 -1
  152. package/dist/trace-utils/index.d.ts.map +1 -1
  153. package/dist/trace-utils/index.js +1 -1
  154. package/dist/utils/dedup/dedup-image.d.ts +22 -0
  155. package/dist/utils/dedup/dedup-image.d.ts.map +1 -0
  156. package/dist/utils/dedup/dedup-image.js +26 -0
  157. package/dist/utils/dedup/find-threshold.d.ts +2 -0
  158. package/dist/utils/dedup/find-threshold.d.ts.map +1 -0
  159. package/dist/utils/dedup/find-threshold.js +42 -0
  160. package/dist/utils/hash.d.ts +2 -0
  161. package/dist/utils/hash.d.ts.map +1 -0
  162. package/dist/utils/hash.js +24 -0
  163. package/dist/utils/model.d.ts +1 -1
  164. package/dist/utils/model.d.ts.map +1 -1
  165. package/dist/utils/model.js +7 -5
  166. package/dist/utils/repo-tree.d.ts +0 -1
  167. package/dist/utils/repo-tree.d.ts.map +1 -1
  168. package/dist/utils/repo-tree.js +2 -14
  169. package/dist/utils/slug.js +1 -1
  170. package/dist/video-core/agent-orchestrator.d.ts +13 -0
  171. package/dist/video-core/agent-orchestrator.d.ts.map +1 -0
  172. package/dist/video-core/agent-orchestrator.js +59 -0
  173. package/dist/video-core/index.d.ts +39 -0
  174. package/dist/video-core/index.d.ts.map +1 -0
  175. package/dist/video-core/index.js +134 -0
  176. package/dist/video-core/model-limits.d.ts +4 -0
  177. package/dist/video-core/model-limits.d.ts.map +1 -0
  178. package/dist/video-core/model-limits.js +73 -0
  179. package/dist/video-core/storage-manager.d.ts +5 -0
  180. package/dist/video-core/storage-manager.d.ts.map +1 -0
  181. package/dist/video-core/storage-manager.js +62 -0
  182. package/dist/video-core/types.d.ts +13 -0
  183. package/dist/video-core/types.d.ts.map +1 -0
  184. package/dist/video-core/types.js +2 -0
  185. package/dist/video-core/utils.d.ts +15 -0
  186. package/dist/video-core/utils.d.ts.map +1 -0
  187. package/dist/video-core/utils.js +194 -0
  188. package/dist/video-core/xml-parser.d.ts +3 -0
  189. package/dist/video-core/xml-parser.d.ts.map +1 -0
  190. package/dist/video-core/xml-parser.js +27 -0
  191. package/package.json +6 -6
  192. package/tsconfig.tsbuildinfo +1 -1
  193. package/dist/agent/chat/prompt/index.d.ts +0 -6
  194. package/dist/agent/chat/prompt/index.d.ts.map +0 -1
  195. package/dist/agent/chat/prompt/index.js +0 -200
  196. package/dist/agent/code-review/prompt.d.ts +0 -2
  197. package/dist/agent/code-review/prompt.d.ts.map +0 -1
  198. package/dist/agent/code-review/prompt.js +0 -55
  199. package/dist/agent/diagnosis-agent/index.d.ts +0 -11
  200. package/dist/agent/diagnosis-agent/index.d.ts.map +0 -1
  201. package/dist/agent/diagnosis-agent/index.js +0 -88
  202. package/dist/agent/diagnosis-agent/strict-mode-violation.d.ts +0 -10
  203. package/dist/agent/diagnosis-agent/strict-mode-violation.d.ts.map +0 -1
  204. package/dist/agent/diagnosis-agent/strict-mode-violation.js +0 -30
  205. package/dist/tools/definitions/extract-frames-from-video.d.ts +0 -39
  206. package/dist/tools/definitions/extract-frames-from-video.d.ts.map +0 -1
  207. package/dist/tools/definitions/extract-frames-from-video.js +0 -60
  208. package/dist/tools/definitions/fetch-video-analysis.d.ts.map +0 -1
  209. package/dist/tools/definitions/fetch-video-analysis.js +0 -61
  210. package/dist/tools/extract-frames-from-video/index.d.ts +0 -7
  211. package/dist/tools/extract-frames-from-video/index.d.ts.map +0 -1
  212. package/dist/tools/extract-frames-from-video/index.js +0 -145
  213. package/dist/tools/fetch-video-analysis/index.d.ts +0 -5
  214. package/dist/tools/fetch-video-analysis/index.d.ts.map +0 -1
  215. package/dist/tools/fetch-video-analysis/index.js +0 -149
  216. package/dist/tools/fetch-video-analysis/open-ai.d.ts +0 -6
  217. package/dist/tools/fetch-video-analysis/open-ai.d.ts.map +0 -1
  218. package/dist/tools/fetch-video-analysis/open-ai.js +0 -37
  219. package/dist/tools/fetch-video-analysis/utils.d.ts +0 -16
  220. package/dist/tools/fetch-video-analysis/utils.d.ts.map +0 -1
  221. package/dist/tools/fetch-video-analysis/utils.js +0 -121
  222. package/dist/tools/fetch-video-analysis/video-analysis.d.ts +0 -7
  223. package/dist/tools/fetch-video-analysis/video-analysis.d.ts.map +0 -1
  224. package/dist/tools/fetch-video-analysis/video-analysis.js +0 -70
  225. package/dist/tools/file-operations/shared/git-helper.d.ts +0 -4
  226. package/dist/tools/file-operations/shared/git-helper.d.ts.map +0 -1
  227. package/dist/tools/file-operations/shared/git-helper.js +0 -29
  228. package/dist/utils/dedup-image-fs.d.ts +0 -27
  229. package/dist/utils/dedup-image-fs.d.ts.map +0 -1
  230. package/dist/utils/dedup-image-fs.js +0 -88
  231. package/dist/utils/dedup-image.d.ts +0 -25
  232. package/dist/utils/dedup-image.d.ts.map +0 -1
  233. package/dist/utils/dedup-image.js +0 -80
  234. package/dist/utils/local-ffmpeg-client.d.ts +0 -27
  235. package/dist/utils/local-ffmpeg-client.d.ts.map +0 -1
  236. package/dist/utils/local-ffmpeg-client.js +0 -299
  237. package/eslint.config.mjs +0 -43
@@ -28,6 +28,22 @@ function artifact(screenshot, name) {
28
28
  data: Buffer.from(screenshot, "base64"),
29
29
  };
30
30
  }
31
+ function stateOfTheBrowser(page) {
32
+ const browserContext = page.context();
33
+ const pages = browserContext.pages();
34
+ return `
35
+ ## Browser window
36
+
37
+ ### Current page (what you are working on)
38
+ Current page URL: ${page.url()}
39
+ Current page title: ${page.title()}
40
+
41
+ ### All pages
42
+ Number of open pages: ${pages.length}
43
+
44
+ URLs and titles:
45
+ ${pages.map((p) => ` - ${p.url()} - ${p.title()}`).join("\n")}`;
46
+ }
31
47
  async function createTestUsingComputerUseAgent({ page, task, trace, prefersElementFromPointCodegen = false, }) {
32
48
  const codegen = await getCodegenInstance(prefersElementFromPointCodegen);
33
49
  await codegen.initialize(page);
@@ -53,7 +69,7 @@ async function createTestUsingComputerUseAgent({ page, task, trace, prefersEleme
53
69
  content: [
54
70
  {
55
71
  type: "input_text",
56
- text: `Task to execute: ${task}\n\nCurrent page URL: ${page.url()}`,
72
+ text: `Task to execute: ${task}\n\n${stateOfTheBrowser(page)}`,
57
73
  },
58
74
  {
59
75
  type: "input_image",
@@ -177,7 +193,7 @@ async function createTestUsingComputerUseAgent({ page, task, trace, prefersEleme
177
193
  content: [
178
194
  {
179
195
  type: "input_text",
180
- text: `Action executed: ${executedActionSummary || "None"}\nCurrent page URL: ${page.url()}`,
196
+ text: `Action executed: ${executedActionSummary || "None"}\n\n${stateOfTheBrowser(page)}`,
181
197
  },
182
198
  ],
183
199
  },
@@ -1 +1 @@
1
- {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../../src/agent/cua/model.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAEL,QAAQ,EACR,iBAAiB,EAClB,MAAM,0CAA0C,CAAC;AA8BlD,wBAAsB,oBAAoB,CAAC,EACzC,KAAK,EACL,kBAAkB,EAClB,WAAW,EACX,YAAY,EACZ,YAAY,GACb,EAAE;IACD,KAAK,EAAE,iBAAiB,EAAE,CAAC;IAC3B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;CACtB,GAAG,OAAO,CAAC,QAAQ,CAAC,CAuBpB;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE;;;EAQrE"}
1
+ {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../../src/agent/cua/model.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAEL,QAAQ,EACR,iBAAiB,EAClB,MAAM,0CAA0C,CAAC;AAiClD,wBAAsB,oBAAoB,CAAC,EACzC,KAAK,EACL,kBAAkB,EAClB,WAAW,EACX,YAAY,EACZ,YAAY,GACb,EAAE;IACD,KAAK,EAAE,iBAAiB,EAAE,CAAC;IAC3B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;CACtB,GAAG,OAAO,CAAC,QAAQ,CAAC,CAuBpB;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE;;;EAQrE"}
@@ -9,7 +9,10 @@ For example, if the user message says "Click on Submit button", then
9
9
  you click on the submit button -- even if it looks like a scary action.
10
10
 
11
11
  If you have been asked to retrieve text or verify something on the UI, then communicate
12
- that in your responses so that the user can see your thinking process in its entirety.`;
12
+ that in your responses so that the user can see your thinking process in its entirety.
13
+
14
+ Your work is limited to the current browser page (tab) that you are provided with. You will
15
+ have to conclude your actions before the user can ask you to do actions on different pages (tabs).`;
13
16
  const pageGotoTool = {
14
17
  type: "function",
15
18
  name: "page_goto",
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/agent/cua/pw-codegen/pw-pause/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAGvC,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAKjD,OAAO,EAAE,2BAA2B,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC;AAE9E,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,MAAM,oBAwCvD;AAED,qBAAa,sBAAuB,YAAW,qBAAqB;IAClE,OAAO,CAAC,IAAI,CAAa;IACzB,OAAO,CAAC,IAAI,CAAmB;IAC/B,OAAO,CAAC,MAAM,CAA4C;IAC1D,OAAO,CAAC,iBAAiB,CAAqB;;YAMhC,QAAQ;IAUhB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBrC,sBAAsB,CAAC,IAAI,EAAE,IAAI;IAqBjC,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAI7B,oBAAoB,IAAI,OAAO,CAAC,MAAM,CAAC;CAU9C"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/agent/cua/pw-codegen/pw-pause/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAGvC,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAMjD,OAAO,EAAE,2BAA2B,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC;AAE9E,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,MAAM,oBAwCvD;AAED,qBAAa,sBAAuB,YAAW,qBAAqB;IAClE,OAAO,CAAC,IAAI,CAAa;IACzB,OAAO,CAAC,IAAI,CAAmB;IAC/B,OAAO,CAAC,MAAM,CAA4C;IAC1D,OAAO,CAAC,iBAAiB,CAAqB;;YAMhC,QAAQ;IAUhB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBrC,sBAAsB,CAAC,IAAI,EAAE,IAAI;IAqBjC,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAI7B,oBAAoB,IAAI,OAAO,CAAC,MAAM,CAAC;CAU9C"}
@@ -1,7 +1,7 @@
1
- import type { ToolDefinition } from "@empiricalrun/shared-types";
1
+ import type { ToolsForLLM } from "@empiricalrun/shared-types";
2
2
  import { BaseAgent } from "../base";
3
3
  export declare class TriageAgent extends BaseAgent {
4
- protected getTools(): ToolDefinition[];
5
- protected buildSystemPrompt(repoContext?: string): Promise<string>;
4
+ protected getTools(): ToolsForLLM;
5
+ protected buildSystemPrompt(repoContext: string): Promise<string>;
6
6
  }
7
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/agent/triage/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAsBjE,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEpC,qBAAa,WAAY,SAAQ,SAAS;IACxC,SAAS,CAAC,QAAQ,IAAI,cAAc,EAAE;cAiCtB,iBAAiB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAkEzE"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/agent/triage/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAkB9D,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAGpC,qBAAa,WAAY,SAAQ,SAAS;IACxC,SAAS,CAAC,QAAQ,IAAI,WAAW;cA0BjB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAgExE"}
@@ -3,39 +3,34 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.TriageAgent = void 0;
4
4
  const tools_1 = require("../../tools");
5
5
  const base_1 = require("../base");
6
+ const test_case_def_1 = require("../chat/prompt/test-case-def");
6
7
  class TriageAgent extends base_1.BaseAgent {
7
8
  getTools() {
8
9
  const tools = [
9
- // Common tools
10
- tools_1.runTestTool,
11
- tools_1.grepTool,
10
+ // Tools to understand test run (open report)
12
11
  tools_1.fetchDiagnosisReportTool,
12
+ tools_1.fetchLastSuccessfulTestRunTool,
13
+ tools_1.viewFailedTestRunReportTool,
13
14
  tools_1.listEnvironmentsTool,
14
- tools_1.downloadBuildTool,
15
+ // Tools to analyse report artifacts
15
16
  tools_1.fetchFileTool,
17
+ tools_1.analyseVideo,
16
18
  tools_1.traceDotZipTool,
17
- // Triage specific tools
19
+ // Tools to get test case context from the repo
20
+ tools_1.grepTool,
21
+ ...(0, tools_1.textEditorToolsForModel)(this.selectedModel),
22
+ // Tools to manage issues
18
23
  tools_1.listIssuesTool,
19
24
  tools_1.createIssueTool,
20
25
  tools_1.updateIssueTool,
21
- tools_1.viewFailedTestRunReportTool,
22
- tools_1.fetchVideoAnalysis,
23
- tools_1.fetchLastSuccessfulTestRunTool,
24
26
  tools_1.sendTriageSummaryTool,
25
- // Model-specific tools
26
- ...(0, tools_1.textEditorToolsForModel)(this.selectedModel),
27
27
  ];
28
- // Feature flag: video analysis (if not already included)
29
- if (this.featureFlags?.includes("useVideoAnalysis") &&
30
- !tools.some((tool) => tool.schema.name === "fetchVideoAnalysis")) {
31
- tools.push(tools_1.fetchVideoAnalysis);
32
- }
33
- return tools;
28
+ return {
29
+ custom: tools,
30
+ builtInTextEditor: (0, tools_1.hasBuiltInTextEditor)(this.selectedModel),
31
+ };
34
32
  }
35
33
  async buildSystemPrompt(repoContext) {
36
- if (!repoContext) {
37
- throw new Error(`Triage agent needs repo context`);
38
- }
39
34
  return `
40
35
  You are a helpful assistant that help with analysis of Playwright test reports. Your goal is to help the user analyse a test report and identify the root cause of the test failures, and log the unique failuers as issues so that the user can keep a track and fix them.
41
36
 
@@ -57,7 +52,6 @@ You are provided with multiple tools to help you understand each failing test ca
57
52
  - Each video represents one browser tab of the test case (so multiple videos implies the test had multiple tabs or browser windows)
58
53
  - Read the error stack and test file to understand what the test is doing
59
54
  - Fetch the last successful run of the test case to understand the earlier flow. This report will contain image and video URLs that can also be analyzed with your available tools.
60
- - If you think the issue is explained by a timing or intermittent issue, you can also re-run the test case
61
55
 
62
56
  ## Listing, updating and creating issues
63
57
 
@@ -91,6 +85,8 @@ You are provided with multiple tools to help you understand each failing test ca
91
85
  - After you are done with triaging and creating issues, summarize the work done with a list of created issues for the user to review. Don't be too verbose - a bullet list of issues created or updated, with a small description is enough.
92
86
  - It is important to show proof that you have gone through all of the failures in the test run report, so use numbers to call out 1. total failures, and 2. failures associated with each issue.
93
87
 
88
+ ${test_case_def_1.testCasesDefinitionPrompt}
89
+
94
90
  # Repo context
95
91
  ${repoContext}
96
92
 
@@ -0,0 +1,5 @@
1
+ import { BaseToolExecutor, BaseToolExecutorProps } from "../../../tools/executor/base";
2
+ export declare class VideoAnalysisToolExecutor extends BaseToolExecutor {
3
+ constructor(params: Omit<BaseToolExecutorProps, "tools">);
4
+ }
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/agent/video-analysis/executor/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,qBAAqB,EACtB,MAAM,8BAA8B,CAAC;AAEtC,qBAAa,yBAA0B,SAAQ,gBAAgB;gBACjD,MAAM,EAAE,IAAI,CAAC,qBAAqB,EAAE,OAAO,CAAC;CAGzD"}
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.VideoAnalysisToolExecutor = void 0;
4
+ const base_1 = require("../../../tools/executor/base");
5
+ class VideoAnalysisToolExecutor extends base_1.BaseToolExecutor {
6
+ constructor(params) {
7
+ super({ ...params, tools: [] });
8
+ }
9
+ }
10
+ exports.VideoAnalysisToolExecutor = VideoAnalysisToolExecutor;
@@ -1,7 +1,7 @@
1
- import type { ToolDefinition } from "@empiricalrun/shared-types";
1
+ import type { ToolsForLLM } from "@empiricalrun/shared-types";
2
2
  import { BaseAgent } from "../base";
3
3
  export declare class VideoAnalysisAgent extends BaseAgent {
4
- protected getTools(): ToolDefinition[];
4
+ protected getTools(): ToolsForLLM;
5
5
  protected buildSystemPrompt(): Promise<string>;
6
6
  }
7
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/agent/video-analysis/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAGjE,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEpC,qBAAa,kBAAmB,SAAQ,SAAS;IAC/C,SAAS,CAAC,QAAQ,IAAI,cAAc,EAAE;cAItB,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC;CAwBrD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/agent/video-analysis/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEpC,qBAAa,kBAAmB,SAAQ,SAAS;IAC/C,SAAS,CAAC,QAAQ,IAAI,WAAW;cAOjB,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC;CA+CrD"}
@@ -1,34 +1,59 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.VideoAnalysisAgent = void 0;
4
- const tools_1 = require("../../tools");
5
4
  const base_1 = require("../base");
6
5
  class VideoAnalysisAgent extends base_1.BaseAgent {
7
6
  getTools() {
8
- return [tools_1.extractFramesFromVideo];
7
+ return {
8
+ custom: [],
9
+ builtInTextEditor: false,
10
+ };
9
11
  }
10
12
  async buildSystemPrompt() {
11
13
  return `
12
14
  You are a video analysis agent specialized in analyzing screen recordings and user interface interactions.
13
15
 
14
- Available Tools:
15
- - extract_frames: Extract frames from videos for detailed visual analysis
16
- - fetch_video_analysis: Get comprehensive video analysis summary (legacy)
16
+ You will receive individual video frames with their Frame IDs as user input for detailed visual analysis.
17
17
 
18
- When analyzing videos:
19
- 1. Use extract_frames to get individual frames for detailed analysis
20
- 2. Analyze each frame for UI elements, user actions, and state changes
21
- 3. Provide specific observations about what's happening in each frame
22
- 4. The Summary should be in a bullet point format
23
- 5. Reference frame IDs when discussing specific moments: "In frame_abc123_001, I can see..."
18
+ When analyzing the provided frames:
19
+ 1. Analyze each frame for UI elements, user actions, and state changes
20
+ 2. Provide specific observations about what's happening in each frame
21
+ 3. The Summary should be in the given XML format
24
22
 
25
23
  Your analysis should be:
26
24
  - Detailed and specific about UI elements and interactions
27
25
  - Sequential, following the flow of actions in the video
28
26
 
29
- After the final summary you need to include the key frame IDs that best represent the important moments in the video.
27
+ CRITICAL: You MUST use the EXACT frame IDs that are provided with each frame. Each frame will be labeled with text like "Frame ID: frame_000000" - use this exact ID in your <key_frame> tags.
30
28
 
31
- Example Frame Id Reference: <frame_abc123_001>
29
+ Note: The Last frame from the attachments should always be included in the <key_frame> tag
30
+
31
+ # Output format
32
+ <summary>
33
+ <section>
34
+ <key_frame>frame_id</key_frame>
35
+ <description>text description of the frame</description>
36
+ </section>
37
+ <section>
38
+ <key_frame>frame_id</key_frame>
39
+ <description>text description of the frame</description>
40
+ </section>
41
+ .
42
+ .
43
+ .
44
+ <section>
45
+ <key_frame>frame_id</key_frame>
46
+ <description>text description of the frame</description>
47
+ </section>
48
+ </summary>
49
+
50
+ ## Example
51
+ If the attachments include "frame_000000.png", "frame_000078.png", and "frame_000156.png", then:
52
+ - To reference the first frame, use: <key_frame>frame_000000</key_frame>
53
+ - To reference the second frame, use: <key_frame>frame_000078</key_frame>
54
+ - To reference the third frame, use: <key_frame>frame_000156</key_frame>
55
+
56
+ WRONG: <key_frame>frame_000001</key_frame> (unless there's actually a file named frame_000001.png in the attachments)
32
57
  `;
33
58
  }
34
59
  }
@@ -46,7 +46,7 @@ export declare class UploadArtifactsQueue {
46
46
  private artifactResults;
47
47
  private uploadPromise;
48
48
  constructor(baseRepoPath: string, toolCallId: string);
49
- addTask(artifacts: ArtifactInput[]): Promise<void>;
49
+ addTask(artifacts: ArtifactInput[]): Promise<Artifact[]>;
50
50
  waitForCompletion(): Promise<Artifact[]>;
51
51
  }
52
52
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/artifacts/index.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,QAAQ,EACR,aAAa,EAId,MAAM,4BAA4B,CAAC;AAwBpC,wBAAgB,2BAA2B,uBAM1C;AA6HD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,aAAa,EAAE,EACvB,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,QAAQ,EAAE,CAAC,CAsErB;AAED,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,aAAa,CAA8B;gBAEvC,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM;IAKvC,OAAO,CAAC,SAAS,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAelD,iBAAiB,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;CAMtD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/artifacts/index.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,QAAQ,EACR,aAAa,EAId,MAAM,4BAA4B,CAAC;AAwBpC,wBAAgB,2BAA2B,uBAM1C;AA6HD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,aAAa,EAAE,EACvB,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,QAAQ,EAAE,CAAC,CAsErB;AAED,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,aAAa,CAAoC;gBAE7C,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM;IAK7C,OAAO,CAAC,SAAS,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAiBlD,iBAAiB,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;CAMtD"}
@@ -230,15 +230,17 @@ class UploadArtifactsQueue {
230
230
  this.baseRepoPath = baseRepoPath;
231
231
  this.toolCallId = toolCallId;
232
232
  }
233
- async addTask(artifacts) {
233
+ addTask(artifacts) {
234
234
  this.uploadPromise = collectArtifacts(artifacts, this.baseRepoPath, this.toolCallId)
235
235
  .then((results) => {
236
236
  this.artifactResults.push(...results);
237
+ return results;
237
238
  })
238
239
  .catch((error) => {
239
240
  console.error("Error processing artifact upload task:", error);
240
241
  throw error;
241
242
  });
243
+ return this.uploadPromise;
242
244
  }
243
245
  async waitForCompletion() {
244
246
  if (this.uploadPromise) {
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/artifacts/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,gBAAgB,EACjB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,UAAU,IAAI,oBAAoB,EAGnC,MAAM,2BAA2B,CAAC;AAInC;;;;GAIG;AACH,wBAAgB,0CAA0C,CACxD,MAAM,EAAE,oBAAoB,EAC5B,cAAc,CAAC,EAAE,MAAM,GACtB,KAAK,CAAC,gBAAgB,GAAG,iBAAiB,CAAC,CAsE7C;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,EAAE,CAmCxE"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/artifacts/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,gBAAgB,EACjB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAGL,UAAU,IAAI,oBAAoB,EACnC,MAAM,2BAA2B,CAAC;AAInC;;;;GAIG;AACH,wBAAgB,0CAA0C,CACxD,MAAM,EAAE,oBAAoB,EAC5B,cAAc,CAAC,EAAE,MAAM,GACtB,KAAK,CAAC,gBAAgB,GAAG,iBAAiB,CAAC,CAsE7C;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,EAAE,CAmCxE"}
package/dist/bin/index.js CHANGED
@@ -20,17 +20,6 @@ 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, agentMode = "chat", resetChat, useFSCache, }) {
24
- const resolvedModel = (0, models_1.resolveChatModelBasedOnInput)(modelInput);
25
- return await (0, cli_1.runChatAgentForCLI)({
26
- selectedModel: resolvedModel,
27
- useDiskForChatState: useDiskForChatState || false,
28
- initialPromptContent,
29
- agentMode,
30
- resetChat: resetChat || false,
31
- useFSCache: useFSCache || false,
32
- });
33
- }
34
23
  async function main() {
35
24
  const rawMode = process.argv.includes("--raw");
36
25
  if (!rawMode) {
@@ -180,15 +169,16 @@ async function main() {
180
169
  .option("--prompt <string>", "String to pass as user prompt")
181
170
  .option("--agent-mode <mode>", "Mode of the agent: 'chat' or 'triage' or 'video' or 'code-review' (Defaults to 'chat')")
182
171
  .option("--use-cache", "Use filesystem cache for LLM responses (Claude-only, and will disable streaming)")
183
- .option("--reset-chat", "Clear any saved chat state (last-chat.json) before starting")
172
+ .option("--reset-state", "Clear any saved chat state (last-chat.json) before starting")
184
173
  .action(async (options) => {
185
- await runChatAgent({
186
- modelInput: options.model,
187
- useDiskForChatState: options.useDisk,
188
- prompt: options.prompt,
189
- agentMode: options.agentMode,
190
- resetChat: options.resetChat,
191
- useFSCache: options.useCache,
174
+ const resolvedModel = (0, models_1.resolveChatModelBasedOnInput)(options.model);
175
+ await (0, cli_1.runChatAgentForCLI)({
176
+ selectedModel: resolvedModel,
177
+ useDiskForChatState: options.useDisk || false,
178
+ initialPromptContent: options.prompt,
179
+ agentMode: options.agentMode || "chat",
180
+ resetChat: options.resetState || false,
181
+ useFSCache: options.useCache || false,
192
182
  });
193
183
  process.exit(0);
194
184
  });
@@ -198,8 +188,8 @@ async function main() {
198
188
  .requiredOption("--id <id>", "Chat session ID")
199
189
  .action(async (opts) => {
200
190
  try {
201
- const data = await client_1.apiClient.request(`/api/chat-sessions/${opts.id}`, { method: "GET" });
202
- const chatState = data.data.chat_session.chat_state;
191
+ const data = await client_1.apiClient.request(`/api/chat-sessions/${opts.id}/state`, { method: "GET" });
192
+ const chatState = data.data.chat_state;
203
193
  const filename = `chat-session-${opts.id}.json`;
204
194
  fs_1.default.writeFileSync(filename, JSON.stringify(chatState, null, 2));
205
195
  console.log(`✅ Chat state saved to ${filename}`);
@@ -4,4 +4,18 @@ export declare const DEFAULT_MODEL_PROVIDER: LLMProvider;
4
4
  export declare const DEFAULT_MODEL: LLMModel;
5
5
  export declare const DEFAULT_MODEL_PARAMETERS: ModelParameters;
6
6
  export declare const DEFAULT_O1_MODEL_PARAMETERS: ModelParameters;
7
+ export declare const VIDEO_ANALYSIS: {
8
+ readonly FRAME_INDEX_PADDING: 6;
9
+ readonly DEFAULT_MODEL: "claude-sonnet-4-20250514";
10
+ readonly DEFAULT_FPS: 25;
11
+ readonly DEFAULT_THRESHOLD: 0.01;
12
+ readonly DEFAULT_FALLBACK_FPS: 30;
13
+ readonly CLAUDE_MAX_IMAGES_PER_BATCH: 100;
14
+ readonly CLAUDE_MAX_REQUEST_SIZE_MB: 32;
15
+ readonly OPENAI_MAX_IMAGES_PER_BATCH: 500;
16
+ readonly OPENAI_MAX_REQUEST_SIZE_MB: 50;
17
+ readonly DEFAULT_FRAME_SIZE_MB: 0.2;
18
+ readonly BATCH_SIZE_REDUCTION_FACTOR: 0.8;
19
+ };
20
+ export declare const DEFAULT_EXCLUDE: (string | RegExp)[];
7
21
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/constants/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAE3E,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CAItD,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,WAAsB,CAAC;AAE5D,eAAO,MAAM,aAAa,EAAE,QAAmB,CAAC;AAEhD,eAAO,MAAM,wBAAwB,EAAE,eAGtC,CAAC;AAEF,eAAO,MAAM,2BAA2B,EAAE,eAGzC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/constants/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAE3E,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CAItD,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,WAAsB,CAAC;AAE5D,eAAO,MAAM,aAAa,EAAE,QAAmB,CAAC;AAEhD,eAAO,MAAM,wBAAwB,EAAE,eAGtC,CAAC;AAEF,eAAO,MAAM,2BAA2B,EAAE,eAGzC,CAAC;AAGF,eAAO,MAAM,cAAc;;;;;;;;;;;;CAqBjB,CAAC;AAEX,eAAO,MAAM,eAAe,qBAY3B,CAAC"}
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.DEFAULT_O1_MODEL_PARAMETERS = exports.DEFAULT_MODEL_PARAMETERS = exports.DEFAULT_MODEL = exports.DEFAULT_MODEL_PROVIDER = exports.MODEL_API_KEYS = void 0;
3
+ exports.DEFAULT_EXCLUDE = exports.VIDEO_ANALYSIS = exports.DEFAULT_O1_MODEL_PARAMETERS = exports.DEFAULT_MODEL_PARAMETERS = exports.DEFAULT_MODEL = exports.DEFAULT_MODEL_PROVIDER = exports.MODEL_API_KEYS = void 0;
4
4
  exports.MODEL_API_KEYS = {
5
5
  google: process.env.GOOGLE_API_KEY || "",
6
6
  anthropic: process.env.ANTHROPIC_API_KEY || "",
@@ -16,3 +16,35 @@ exports.DEFAULT_O1_MODEL_PARAMETERS = {
16
16
  temperature: 1,
17
17
  max_completion_tokens: 35_000,
18
18
  };
19
+ // Video Analysis Constants
20
+ exports.VIDEO_ANALYSIS = {
21
+ // Frame processing
22
+ FRAME_INDEX_PADDING: 6,
23
+ // Default analysis parameters
24
+ DEFAULT_MODEL: "claude-sonnet-4-20250514",
25
+ DEFAULT_FPS: 25,
26
+ DEFAULT_THRESHOLD: 0.01,
27
+ DEFAULT_FALLBACK_FPS: 30,
28
+ // Model limits - Claude
29
+ CLAUDE_MAX_IMAGES_PER_BATCH: 100,
30
+ CLAUDE_MAX_REQUEST_SIZE_MB: 32,
31
+ // Model limits - OpenAI
32
+ OPENAI_MAX_IMAGES_PER_BATCH: 500,
33
+ OPENAI_MAX_REQUEST_SIZE_MB: 50,
34
+ // Processing defaults
35
+ DEFAULT_FRAME_SIZE_MB: 0.2,
36
+ BATCH_SIZE_REDUCTION_FACTOR: 0.8,
37
+ };
38
+ exports.DEFAULT_EXCLUDE = [
39
+ "node_modules",
40
+ "dist",
41
+ "build",
42
+ /\.git/,
43
+ ".DS_Store",
44
+ "playwright-report",
45
+ "test-results",
46
+ ".empiricalrun",
47
+ "auth",
48
+ "package-lock.json",
49
+ /^ffmpeg-test/,
50
+ ];
@@ -1,4 +1,4 @@
1
- import { ArtifactInput, Usage } from "@empiricalrun/shared-types";
1
+ import { Usage } from "@empiricalrun/shared-types";
2
2
  import { BrowserAgentResult } from "../agent/cua";
3
3
  export type BrowserAgentIPCPayload = {
4
4
  task: string;
@@ -14,7 +14,6 @@ export declare class FileServiceServer {
14
14
  private server;
15
15
  private updateFile;
16
16
  private onComplete?;
17
- private artifactsInputs;
18
17
  private result;
19
18
  private usage;
20
19
  private codegenSources;
@@ -28,7 +27,6 @@ export declare class FileServiceServer {
28
27
  result: BrowserAgentResult | undefined;
29
28
  usage: Usage | undefined;
30
29
  };
31
- getArtifactInputsFromServer(): ArtifactInput[];
32
30
  getCodegenSources(): string | undefined;
33
31
  setFilePath(filePath: string): void;
34
32
  startFileService(): Promise<number>;
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/file/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,4BAA4B,CAAC;AAKlE,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AASlD,MAAM,MAAM,sBAAsB,GAAG;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,kBAAkB,CAAC;IAC3B,KAAK,EAAE,KAAK,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB,CAAC;AAEF,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,IAAI,CAAa;IACzB,OAAO,CAAC,QAAQ,CAAc;IAC9B,OAAO,CAAC,OAAO,CAAc;IAC7B,OAAO,CAAC,MAAM,CAA4C;IAC1D,OAAO,CAAC,UAAU,CAAkB;IACpC,OAAO,CAAC,UAAU,CAAC,CAAa;IAEhC,OAAO,CAAC,eAAe,CAAuB;IAC9C,OAAO,CAAC,MAAM,CAAiC;IAC/C,OAAO,CAAC,KAAK,CAAoB;IAEjC,OAAO,CAAC,cAAc,CAAqB;gBAE/B,EACV,IAAI,EACJ,OAAO,EACP,UAAU,EACV,UAAU,GACX,EAAE;QACD,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,EAAE,OAAO,CAAC;QACpB,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;KACzB;IAOD,iBAAiB;;;;IAIjB,2BAA2B;IAI3B,iBAAiB;IAIjB,WAAW,CAAC,QAAQ,EAAE,MAAM;IAItB,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC;IA8HnC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAgB5B"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/file/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,4BAA4B,CAAC;AAKnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AASlD,MAAM,MAAM,sBAAsB,GAAG;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,kBAAkB,CAAC;IAC3B,KAAK,EAAE,KAAK,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB,CAAC;AAEF,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,IAAI,CAAa;IACzB,OAAO,CAAC,QAAQ,CAAc;IAC9B,OAAO,CAAC,OAAO,CAAc;IAC7B,OAAO,CAAC,MAAM,CAA4C;IAC1D,OAAO,CAAC,UAAU,CAAkB;IACpC,OAAO,CAAC,UAAU,CAAC,CAAa;IAEhC,OAAO,CAAC,MAAM,CAAiC;IAC/C,OAAO,CAAC,KAAK,CAAoB;IAEjC,OAAO,CAAC,cAAc,CAAqB;gBAE/B,EACV,IAAI,EACJ,OAAO,EACP,UAAU,EACV,UAAU,GACX,EAAE;QACD,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,EAAE,OAAO,CAAC;QACpB,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;KACzB;IAOD,iBAAiB;;;;IAIjB,iBAAiB;IAIjB,WAAW,CAAC,QAAQ,EAAE,MAAM;IAItB,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC;IAqHnC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAgB5B"}
@@ -16,7 +16,6 @@ class FileServiceServer {
16
16
  server;
17
17
  updateFile = false;
18
18
  onComplete;
19
- artifactsInputs = [];
20
19
  result;
21
20
  usage;
22
21
  codegenSources;
@@ -29,9 +28,6 @@ class FileServiceServer {
29
28
  getResultAndUsage() {
30
29
  return { result: this.result, usage: this.usage };
31
30
  }
32
- getArtifactInputsFromServer() {
33
- return this.artifactsInputs;
34
- }
35
31
  getCodegenSources() {
36
32
  return this.codegenSources;
37
33
  }
@@ -110,15 +106,6 @@ class FileServiceServer {
110
106
  const { generatedCode, importPaths, result, usage } = req.body;
111
107
  this.result = result;
112
108
  this.usage = usage;
113
- this.artifactsInputs = this.result
114
- .filter((item) => item.type === "screenshot")
115
- .map((item) => item.screenshot)
116
- .map((artifact) => ({
117
- ...artifact,
118
- data: Buffer.isBuffer(artifact.data)
119
- ? artifact.data
120
- : Buffer.from(artifact.data),
121
- }));
122
109
  if (!this.updateFile) {
123
110
  // Not updating the file in this scenario
124
111
  if (this.onComplete)
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/file-info/adapters/file-system/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAExD,OAAO,EAEL,KAAK,qBAAqB,EAC3B,MAAM,+CAA+C,CAAC;AAEvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAE7C,wBAAsB,uBAAuB,CAAC,EAC5C,KAAK,EACL,QAAQ,EACR,gBAAgB,GACjB,EAAE;IACD,KAAK,EAAE,qBAAqB,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;CAC1B,GAAG,OAAO,CAAC,UAAU,CAAC,CAmBtB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/file-info/adapters/file-system/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAExD,OAAO,EAEL,KAAK,qBAAqB,EAC3B,MAAM,+CAA+C,CAAC;AAGvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAE7C,wBAAsB,uBAAuB,CAAC,EAC5C,KAAK,EACL,QAAQ,EACR,gBAAgB,GACjB,EAAE;IACD,KAAK,EAAE,qBAAqB,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;CAC1B,GAAG,OAAO,CAAC,UAAU,CAAC,CAmBtB"}
@@ -1 +1 @@
1
- {"version":3,"file":"reader.d.ts","sourceRoot":"","sources":["../../../../src/file-info/adapters/file-system/reader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAKtE,qBAAa,oBAAoB;IACzB,QAAQ,CACZ,QAAQ,EAAE,MAAM,EAChB,gBAAgB,EAAE,MAAM,GACvB,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;CAalC;AAED,wBAAsB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAgC5E"}
1
+ {"version":3,"file":"reader.d.ts","sourceRoot":"","sources":["../../../../src/file-info/adapters/file-system/reader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAMtE,qBAAa,oBAAoB;IACzB,QAAQ,CACZ,QAAQ,EAAE,MAAM,EAChB,gBAAgB,EAAE,MAAM,GACvB,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;CAalC;AAED,wBAAsB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAwC5E"}
@@ -8,6 +8,7 @@ exports.getFileInfoFromFS = getFileInfoFromFS;
8
8
  const fs_1 = __importDefault(require("fs"));
9
9
  const promises_1 = __importDefault(require("fs/promises"));
10
10
  const path_1 = __importDefault(require("path"));
11
+ const constants_1 = require("../../../constants");
11
12
  class FilesystemFileReader {
12
13
  async readFile(filePath, absoluteFilePath) {
13
14
  if (!fs_1.default.existsSync(absoluteFilePath)) {
@@ -23,7 +24,6 @@ class FilesystemFileReader {
23
24
  }
24
25
  exports.FilesystemFileReader = FilesystemFileReader;
25
26
  async function getFileInfoFromFS(directory) {
26
- // TODO: This traverses all node_modules - can be excluded with DEFAULT_EXCLUDE
27
27
  let currentDirName = path_1.default.basename(directory);
28
28
  let currentDir = {
29
29
  type: "directory",
@@ -33,6 +33,13 @@ async function getFileInfoFromFS(directory) {
33
33
  };
34
34
  const files = await promises_1.default.readdir(directory);
35
35
  for (const file of files) {
36
+ const shouldExclude = constants_1.DEFAULT_EXCLUDE.some((pattern) => typeof pattern === "string"
37
+ ? file === pattern
38
+ : pattern instanceof RegExp
39
+ ? pattern.test(file)
40
+ : false);
41
+ if (shouldExclude)
42
+ continue;
36
43
  const filePath = path_1.default.join(directory, file);
37
44
  // TODO: Symlinks fail here
38
45
  const stats = await promises_1.default.stat(filePath);
@@ -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;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
+ {"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;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"}
@@ -3,7 +3,7 @@ export declare class GitHubFileReader {
3
3
  private repoName;
4
4
  private apiClient;
5
5
  constructor(repoName: string, apiClient: IDashboardAPIClient);
6
- resolveBranchName(branchName: string | undefined, baseBranch?: string): Promise<string>;
6
+ resolveBranchName(branchName: string | undefined, baseBranch: string): Promise<string>;
7
7
  readFile(filePath: string, branchName: string, baseBranch: string): Promise<FileReadResult | null>;
8
8
  private readDirectory;
9
9
  }
@@ -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;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"}
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,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,CAAC;IAoBZ,QAAQ,CACZ,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;YA4CnB,aAAa;CAoD5B;AAyED,wBAAsB,qBAAqB,CACzC,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,mBAAmB,EAC9B,UAAU,EAAE,MAAM,EAClB,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,QAAQ,CAAC,CAwFnB"}
@@ -13,12 +13,11 @@ class GitHubFileReader {
13
13
  this.repoName = repoName;
14
14
  this.apiClient = apiClient;
15
15
  }
16
- async resolveBranchName(branchName, baseBranch = "main") {
16
+ async resolveBranchName(branchName, baseBranch) {
17
17
  if (!branchName || branchName === baseBranch) {
18
18
  return baseBranch;
19
19
  }
20
20
  try {
21
- // Try to fetch the branch to see if it exists via GitHub proxy
22
21
  await this.apiClient.callGitHubProxy({
23
22
  method: "GET",
24
23
  url: `/repos/empirical-run/${this.repoName}/branches/${branchName}`,
@@ -27,7 +26,6 @@ class GitHubFileReader {
27
26
  return branchName;
28
27
  }
29
28
  catch {
30
- // Branch doesn't exist, fallback to base branch
31
29
  console.log(`[GitHubFileReader] Branch ${branchName} not found, falling back to ${baseBranch}`);
32
30
  return baseBranch;
33
31
  }
@@ -95,7 +93,13 @@ class GitHubFileReader {
95
93
  .map((itemPath) => path_1.default.basename(itemPath))
96
94
  .sort()
97
95
  .join("\n");
98
- return { content: files, isDirectory: true };
96
+ if (files.length === 0) {
97
+ // No files means directory is invalid
98
+ return null;
99
+ }
100
+ else {
101
+ return { content: files, isDirectory: true };
102
+ }
99
103
  }
100
104
  }
101
105
  catch (error) {
@@ -140,7 +144,6 @@ async function getContentsForDirectory({ repo, path, }, apiClient, branchName) {
140
144
  return response.data.tree;
141
145
  }
142
146
  async function getFileInfoFromGitHub(repoName, apiClient, branchName, baseBranchName) {
143
- // Use GitHubFileReader to resolve the branch
144
147
  const fileReader = new GitHubFileReader(repoName, apiClient);
145
148
  const resolvedBranch = await fileReader.resolveBranchName(branchName, baseBranchName);
146
149
  const files = await getContentsForDirectory({ repo: repoName, path: "" }, apiClient, resolvedBranch);
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAYhD,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EACL,yBAAyB,EACzB,iBAAiB,GAClB,MAAM,yCAAyC,CAAC;AACjD,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAsBjF,wBAAsB,UAAU,CAC9B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,IAAI,GAAG,YAAY,EAC5B,KAAK,CAAC,EAAE,SAAS,iBA0DlB;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE,IAAI,iBAY7C"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAYhD,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEpC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EACL,yBAAyB,EACzB,iBAAiB,GAClB,MAAM,yCAAyC,CAAC;AACjD,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAsBjF,wBAAsB,UAAU,CAC9B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,IAAI,GAAG,YAAY,EAC5B,KAAK,CAAC,EAAE,SAAS,iBA0DlB;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE,IAAI,iBAY7C"}
@@ -0,0 +1,5 @@
1
+ import type { Tool } from "@empiricalrun/shared-types";
2
+ import type { z } from "zod";
3
+ import { analyseVideoSchema } from "../definitions/analyse-video";
4
+ export declare const analyseVideo: Tool<z.infer<typeof analyseVideoSchema>>;
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/analyse-video/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,IAAI,EAGL,MAAM,4BAA4B,CAAC;AACpC,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAK7B,OAAO,EACL,kBAAkB,EAEnB,MAAM,8BAA8B,CAAC;AAiBtC,eAAO,MAAM,YAAY,EAAE,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CA0CjE,CAAC"}