@e2edev/e2e 0.11.0 → 0.13.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 (344) hide show
  1. package/README.md +7 -7
  2. package/dist/agent/act.d.ts +43 -9
  3. package/dist/agent/act.d.ts.map +1 -1
  4. package/dist/agent/act.js +126 -734
  5. package/dist/agent/act.js.map +1 -1
  6. package/dist/agent/action-dispatcher.d.ts +98 -0
  7. package/dist/agent/action-dispatcher.d.ts.map +1 -0
  8. package/dist/agent/action-dispatcher.js +319 -0
  9. package/dist/agent/action-dispatcher.js.map +1 -0
  10. package/dist/agent/actions.d.ts +16 -1
  11. package/dist/agent/actions.d.ts.map +1 -1
  12. package/dist/agent/actions.js +5 -1
  13. package/dist/agent/actions.js.map +1 -1
  14. package/dist/agent/default-agent.d.ts +17 -8
  15. package/dist/agent/default-agent.d.ts.map +1 -1
  16. package/dist/agent/default-agent.js +65 -43
  17. package/dist/agent/default-agent.js.map +1 -1
  18. package/dist/agent/executor.d.ts +30 -2
  19. package/dist/agent/executor.d.ts.map +1 -1
  20. package/dist/agent/executor.js.map +1 -1
  21. package/dist/agent/index.js +1 -1
  22. package/dist/agent/index.js.map +1 -1
  23. package/dist/agent/interactive-step.d.ts +38 -0
  24. package/dist/agent/interactive-step.d.ts.map +1 -0
  25. package/dist/agent/interactive-step.js +131 -0
  26. package/dist/agent/interactive-step.js.map +1 -0
  27. package/dist/agent/invocation.d.ts +4 -9
  28. package/dist/agent/invocation.d.ts.map +1 -1
  29. package/dist/agent/invocation.js +1 -6
  30. package/dist/agent/invocation.js.map +1 -1
  31. package/dist/agent/model/sdk.d.ts +1 -1
  32. package/dist/agent/model/sdk.js +1 -1
  33. package/dist/agent/model/tool-choice.d.ts +21 -0
  34. package/dist/agent/model/tool-choice.d.ts.map +1 -0
  35. package/dist/agent/model/tool-choice.js +49 -0
  36. package/dist/agent/model/tool-choice.js.map +1 -0
  37. package/dist/agent/observation-feed.d.ts +123 -0
  38. package/dist/agent/observation-feed.d.ts.map +1 -0
  39. package/dist/agent/observation-feed.js +281 -0
  40. package/dist/agent/observation-feed.js.map +1 -0
  41. package/dist/agent/observation.d.ts +14 -1
  42. package/dist/agent/observation.d.ts.map +1 -1
  43. package/dist/agent/observation.js +58 -2
  44. package/dist/agent/observation.js.map +1 -1
  45. package/dist/agent/operation-queue.d.ts +21 -0
  46. package/dist/agent/operation-queue.d.ts.map +1 -0
  47. package/dist/agent/operation-queue.js +27 -0
  48. package/dist/agent/operation-queue.js.map +1 -0
  49. package/dist/agent/pixels.d.ts +21 -0
  50. package/dist/agent/pixels.d.ts.map +1 -0
  51. package/dist/agent/pixels.js +85 -0
  52. package/dist/agent/pixels.js.map +1 -0
  53. package/dist/agent/point-tap.d.ts +52 -0
  54. package/dist/agent/point-tap.d.ts.map +1 -0
  55. package/dist/agent/point-tap.js +88 -0
  56. package/dist/agent/point-tap.js.map +1 -0
  57. package/dist/agent/primitives.d.ts +7 -1
  58. package/dist/agent/primitives.d.ts.map +1 -1
  59. package/dist/agent/primitives.js +96 -25
  60. package/dist/agent/primitives.js.map +1 -1
  61. package/dist/agent/replay.d.ts +8 -3
  62. package/dist/agent/replay.d.ts.map +1 -1
  63. package/dist/agent/replay.js +44 -15
  64. package/dist/agent/replay.js.map +1 -1
  65. package/dist/agent/screen-update.d.ts +50 -18
  66. package/dist/agent/screen-update.d.ts.map +1 -1
  67. package/dist/agent/screen-update.js +76 -94
  68. package/dist/agent/screen-update.js.map +1 -1
  69. package/dist/agent/step-accounting.d.ts +95 -0
  70. package/dist/agent/step-accounting.d.ts.map +1 -0
  71. package/dist/agent/step-accounting.js +201 -0
  72. package/dist/agent/step-accounting.js.map +1 -0
  73. package/dist/agent/step-cache.d.ts.map +1 -1
  74. package/dist/agent/step-cache.js +2 -2
  75. package/dist/agent/step-cache.js.map +1 -1
  76. package/dist/agent/tool-loop.d.ts +4 -4
  77. package/dist/agent/tool-loop.d.ts.map +1 -1
  78. package/dist/agent/tool-loop.js +109 -25
  79. package/dist/agent/tool-loop.js.map +1 -1
  80. package/dist/agent/transcript-compaction.d.ts +38 -0
  81. package/dist/agent/transcript-compaction.d.ts.map +1 -0
  82. package/dist/agent/transcript-compaction.js +165 -0
  83. package/dist/agent/transcript-compaction.js.map +1 -0
  84. package/dist/cache/recorder.d.ts.map +1 -1
  85. package/dist/cache/recorder.js +20 -0
  86. package/dist/cache/recorder.js.map +1 -1
  87. package/dist/cache/trace.d.ts +28 -1
  88. package/dist/cache/trace.d.ts.map +1 -1
  89. package/dist/cache/trace.js +44 -0
  90. package/dist/cache/trace.js.map +1 -1
  91. package/dist/cli/docs-url.d.ts +1 -1
  92. package/dist/cli/docs-url.d.ts.map +1 -1
  93. package/dist/cli/docs-url.js +1 -1
  94. package/dist/cli/docs-url.js.map +1 -1
  95. package/dist/cli/index.d.ts.map +1 -1
  96. package/dist/cli/index.js +71 -26
  97. package/dist/cli/index.js.map +1 -1
  98. package/dist/cli/init/engine-versions.json +1 -1
  99. package/dist/cli/init/engines.d.ts +26 -16
  100. package/dist/cli/init/engines.d.ts.map +1 -1
  101. package/dist/cli/init/engines.js +33 -24
  102. package/dist/cli/init/engines.js.map +1 -1
  103. package/dist/cli/init/gateways.js +3 -3
  104. package/dist/cli/init/mcp-config.d.ts +31 -0
  105. package/dist/cli/init/mcp-config.d.ts.map +1 -0
  106. package/dist/cli/init/mcp-config.js +72 -0
  107. package/dist/cli/init/mcp-config.js.map +1 -0
  108. package/dist/cli/init/scaffold.d.ts +1 -1
  109. package/dist/cli/init/scaffold.js +2 -2
  110. package/dist/cli/init/scaffold.js.map +1 -1
  111. package/dist/cli/init.d.ts.map +1 -1
  112. package/dist/cli/init.js +65 -29
  113. package/dist/cli/init.js.map +1 -1
  114. package/dist/cli/mcp.d.ts +15 -0
  115. package/dist/cli/mcp.d.ts.map +1 -0
  116. package/dist/cli/mcp.js +63 -0
  117. package/dist/cli/mcp.js.map +1 -0
  118. package/dist/collect/collect.d.ts +8 -3
  119. package/dist/collect/collect.d.ts.map +1 -1
  120. package/dist/collect/collect.js +29 -5
  121. package/dist/collect/collect.js.map +1 -1
  122. package/dist/collect/registry.d.ts +20 -5
  123. package/dist/collect/registry.d.ts.map +1 -1
  124. package/dist/collect/registry.js +162 -56
  125. package/dist/collect/registry.js.map +1 -1
  126. package/dist/collect/select.d.ts +9 -2
  127. package/dist/collect/select.d.ts.map +1 -1
  128. package/dist/collect/select.js +60 -12
  129. package/dist/collect/select.js.map +1 -1
  130. package/dist/config/agent.d.ts +1 -7
  131. package/dist/config/agent.d.ts.map +1 -1
  132. package/dist/config/agent.js +5 -8
  133. package/dist/config/agent.js.map +1 -1
  134. package/dist/config/app.d.ts +24 -2
  135. package/dist/config/app.d.ts.map +1 -1
  136. package/dist/config/app.js +82 -15
  137. package/dist/config/app.js.map +1 -1
  138. package/dist/config/resolve.d.ts +23 -6
  139. package/dist/config/resolve.d.ts.map +1 -1
  140. package/dist/config/resolve.js +34 -14
  141. package/dist/config/resolve.js.map +1 -1
  142. package/dist/credentials.d.ts +6 -0
  143. package/dist/credentials.d.ts.map +1 -1
  144. package/dist/credentials.js +9 -0
  145. package/dist/credentials.js.map +1 -1
  146. package/dist/engine/contract.d.ts +9 -2
  147. package/dist/engine/contract.d.ts.map +1 -1
  148. package/dist/engine/contract.js.map +1 -1
  149. package/dist/engine/index.d.ts +18 -4
  150. package/dist/engine/index.d.ts.map +1 -1
  151. package/dist/engine/index.js +8 -0
  152. package/dist/engine/index.js.map +1 -1
  153. package/dist/engine/session.d.ts.map +1 -1
  154. package/dist/engine/session.js +3 -0
  155. package/dist/engine/session.js.map +1 -1
  156. package/dist/engine/surface.d.ts +6 -2
  157. package/dist/engine/surface.d.ts.map +1 -1
  158. package/dist/engine/surface.js.map +1 -1
  159. package/dist/expect/attempt.d.ts +15 -0
  160. package/dist/expect/attempt.d.ts.map +1 -0
  161. package/dist/expect/attempt.js +33 -0
  162. package/dist/expect/attempt.js.map +1 -0
  163. package/dist/expect/index.d.ts +7 -5
  164. package/dist/expect/index.d.ts.map +1 -1
  165. package/dist/expect/index.js +8 -1
  166. package/dist/expect/index.js.map +1 -1
  167. package/dist/expect/poll.d.ts +5 -0
  168. package/dist/expect/poll.d.ts.map +1 -0
  169. package/dist/expect/poll.js +118 -0
  170. package/dist/expect/poll.js.map +1 -0
  171. package/dist/expect/values.d.ts.map +1 -1
  172. package/dist/expect/values.js +6 -1
  173. package/dist/expect/values.js.map +1 -1
  174. package/dist/explore/body.d.ts.map +1 -1
  175. package/dist/explore/body.js +2 -0
  176. package/dist/explore/body.js.map +1 -1
  177. package/dist/explore/executor.js +16 -11
  178. package/dist/explore/executor.js.map +1 -1
  179. package/dist/explore/index.d.ts +3 -2
  180. package/dist/explore/index.d.ts.map +1 -1
  181. package/dist/explore/index.js +11 -9
  182. package/dist/explore/index.js.map +1 -1
  183. package/dist/explore/plan.d.ts.map +1 -1
  184. package/dist/explore/plan.js +16 -5
  185. package/dist/explore/plan.js.map +1 -1
  186. package/dist/explore/progress.d.ts +43 -0
  187. package/dist/explore/progress.d.ts.map +1 -0
  188. package/dist/explore/progress.js +9 -0
  189. package/dist/explore/progress.js.map +1 -0
  190. package/dist/explore/state.d.ts +13 -12
  191. package/dist/explore/state.d.ts.map +1 -1
  192. package/dist/explore/state.js +28 -11
  193. package/dist/explore/state.js.map +1 -1
  194. package/dist/internal/ai-trace.d.ts +2 -0
  195. package/dist/internal/ai-trace.d.ts.map +1 -1
  196. package/dist/internal/ai-trace.js +3 -0
  197. package/dist/internal/ai-trace.js.map +1 -1
  198. package/dist/internal/brands.d.ts +2 -0
  199. package/dist/internal/brands.d.ts.map +1 -1
  200. package/dist/internal/brands.js +2 -0
  201. package/dist/internal/brands.js.map +1 -1
  202. package/dist/internal/geometry.d.ts +13 -0
  203. package/dist/internal/geometry.d.ts.map +1 -0
  204. package/dist/internal/geometry.js +16 -0
  205. package/dist/internal/geometry.js.map +1 -0
  206. package/dist/internal/ids.d.ts +2 -2
  207. package/dist/internal/ids.d.ts.map +1 -1
  208. package/dist/internal/ids.js +3 -3
  209. package/dist/internal/ids.js.map +1 -1
  210. package/dist/internal/package-manager.d.ts +4 -0
  211. package/dist/internal/package-manager.d.ts.map +1 -1
  212. package/dist/internal/package-manager.js +26 -0
  213. package/dist/internal/package-manager.js.map +1 -1
  214. package/dist/internal/urls.d.ts +6 -0
  215. package/dist/internal/urls.d.ts.map +1 -1
  216. package/dist/internal/urls.js +28 -0
  217. package/dist/internal/urls.js.map +1 -1
  218. package/dist/mcp/catalog.d.ts +51 -0
  219. package/dist/mcp/catalog.d.ts.map +1 -0
  220. package/dist/mcp/catalog.js +141 -0
  221. package/dist/mcp/catalog.js.map +1 -0
  222. package/dist/mcp/config.d.ts +11 -0
  223. package/dist/mcp/config.d.ts.map +1 -0
  224. package/dist/mcp/config.js +16 -0
  225. package/dist/mcp/config.js.map +1 -0
  226. package/dist/mcp/server.d.ts +29 -0
  227. package/dist/mcp/server.d.ts.map +1 -0
  228. package/dist/mcp/server.js +86 -0
  229. package/dist/mcp/server.js.map +1 -0
  230. package/dist/mcp/session.d.ts +68 -0
  231. package/dist/mcp/session.d.ts.map +1 -0
  232. package/dist/mcp/session.js +319 -0
  233. package/dist/mcp/session.js.map +1 -0
  234. package/dist/mcp/tools.d.ts +77 -0
  235. package/dist/mcp/tools.d.ts.map +1 -0
  236. package/dist/mcp/tools.js +179 -0
  237. package/dist/mcp/tools.js.map +1 -0
  238. package/dist/report/build.d.ts +8 -0
  239. package/dist/report/build.d.ts.map +1 -1
  240. package/dist/report/build.js +3 -1
  241. package/dist/report/build.js.map +1 -1
  242. package/dist/report/format.d.ts +19 -0
  243. package/dist/report/format.d.ts.map +1 -1
  244. package/dist/report/format.js +42 -0
  245. package/dist/report/format.js.map +1 -1
  246. package/dist/report/junit.d.ts.map +1 -1
  247. package/dist/report/junit.js +4 -1
  248. package/dist/report/junit.js.map +1 -1
  249. package/dist/report/list-explore.d.ts +109 -0
  250. package/dist/report/list-explore.d.ts.map +1 -0
  251. package/dist/report/list-explore.js +388 -0
  252. package/dist/report/list-explore.js.map +1 -0
  253. package/dist/report/list.d.ts +31 -1
  254. package/dist/report/list.d.ts.map +1 -1
  255. package/dist/report/list.js +114 -16
  256. package/dist/report/list.js.map +1 -1
  257. package/dist/report/running-tree.d.ts +7 -7
  258. package/dist/report/running-tree.d.ts.map +1 -1
  259. package/dist/report/running-tree.js +12 -13
  260. package/dist/report/running-tree.js.map +1 -1
  261. package/dist/run/app-ports.d.ts +17 -0
  262. package/dist/run/app-ports.d.ts.map +1 -0
  263. package/dist/run/app-ports.js +74 -0
  264. package/dist/run/app-ports.js.map +1 -0
  265. package/dist/run/events.d.ts +21 -7
  266. package/dist/run/events.d.ts.map +1 -1
  267. package/dist/run/events.js.map +1 -1
  268. package/dist/run/execute.d.ts +2 -2
  269. package/dist/run/execute.d.ts.map +1 -1
  270. package/dist/run/execute.js +42 -20
  271. package/dist/run/execute.js.map +1 -1
  272. package/dist/run/extended-fixtures.d.ts +33 -0
  273. package/dist/run/extended-fixtures.d.ts.map +1 -0
  274. package/dist/run/extended-fixtures.js +91 -0
  275. package/dist/run/extended-fixtures.js.map +1 -0
  276. package/dist/run/fixtures.d.ts +10 -4
  277. package/dist/run/fixtures.d.ts.map +1 -1
  278. package/dist/run/fixtures.js +40 -27
  279. package/dist/run/fixtures.js.map +1 -1
  280. package/dist/run/in-process.d.ts.map +1 -1
  281. package/dist/run/in-process.js +4 -3
  282. package/dist/run/in-process.js.map +1 -1
  283. package/dist/run/managed-process.d.ts +18 -0
  284. package/dist/run/managed-process.d.ts.map +1 -1
  285. package/dist/run/managed-process.js +101 -6
  286. package/dist/run/managed-process.js.map +1 -1
  287. package/dist/run/provision.d.ts +51 -0
  288. package/dist/run/provision.d.ts.map +1 -0
  289. package/dist/run/provision.js +94 -0
  290. package/dist/run/provision.js.map +1 -0
  291. package/dist/run/realm.d.ts +5 -4
  292. package/dist/run/realm.d.ts.map +1 -1
  293. package/dist/run/realm.js +8 -7
  294. package/dist/run/realm.js.map +1 -1
  295. package/dist/run/records.d.ts +4 -0
  296. package/dist/run/records.d.ts.map +1 -1
  297. package/dist/run/runner.d.ts +14 -5
  298. package/dist/run/runner.d.ts.map +1 -1
  299. package/dist/run/runner.js +28 -71
  300. package/dist/run/runner.js.map +1 -1
  301. package/dist/run/scheduler.d.ts +5 -2
  302. package/dist/run/scheduler.d.ts.map +1 -1
  303. package/dist/run/scheduler.js +13 -10
  304. package/dist/run/scheduler.js.map +1 -1
  305. package/dist/run/serial.d.ts +1 -1
  306. package/dist/run/serial.d.ts.map +1 -1
  307. package/dist/run/serial.js +7 -2
  308. package/dist/run/serial.js.map +1 -1
  309. package/dist/run/standalone.d.ts +63 -0
  310. package/dist/run/standalone.d.ts.map +1 -0
  311. package/dist/run/standalone.js +152 -0
  312. package/dist/run/standalone.js.map +1 -0
  313. package/dist/run/units.d.ts +6 -3
  314. package/dist/run/units.d.ts.map +1 -1
  315. package/dist/run/units.js +0 -0
  316. package/dist/run/units.js.map +1 -1
  317. package/dist/run/worker/entry.js +4 -3
  318. package/dist/run/worker/entry.js.map +1 -1
  319. package/dist/run/worker/protocol.d.ts +12 -1
  320. package/dist/run/worker/protocol.d.ts.map +1 -1
  321. package/dist/run/worker/protocol.js.map +1 -1
  322. package/dist/run/worker/session.d.ts +3 -4
  323. package/dist/run/worker/session.d.ts.map +1 -1
  324. package/dist/run/worker/session.js +5 -4
  325. package/dist/run/worker/session.js.map +1 -1
  326. package/dist/types.d.ts +77 -17
  327. package/dist/types.d.ts.map +1 -1
  328. package/package.json +11 -7
  329. package/skills/e2e/SKILL.md +9 -7
  330. package/skills/e2e/references/agent.md +27 -12
  331. package/skills/e2e/references/debugging.md +5 -5
  332. package/skills/e2e/references/explore.md +15 -9
  333. package/skills/e2e/references/mcp.md +88 -0
  334. package/skills/e2e/references/running.md +23 -18
  335. package/skills/e2e/references/setup.md +32 -18
  336. package/skills/e2e/references/writing-tests.md +12 -5
  337. package/dist/agent/model/router.d.ts +0 -36
  338. package/dist/agent/model/router.d.ts.map +0 -1
  339. package/dist/agent/model/router.js +0 -45
  340. package/dist/agent/model/router.js.map +0 -1
  341. package/dist/explore/reporter.d.ts +0 -11
  342. package/dist/explore/reporter.d.ts.map +0 -1
  343. package/dist/explore/reporter.js +0 -54
  344. package/dist/explore/reporter.js.map +0 -1
@@ -0,0 +1,319 @@
1
+ /**
2
+ * The live session behind `e2e mcp`: one standalone attempt on one target
3
+ * with one interactive agent step open on it, driven by a coding agent
4
+ * through a fixed, four-tool surface. `open_session` loads the project's
5
+ * config and opens the attempt and the step; `tools` renders the session's
6
+ * catalog; `call` runs one catalog tool by name inside the step;
7
+ * `close_session` ends the step and tears the attempt down. The catalog is
8
+ * data, not registrations, so it follows the config and the target without a
9
+ * restart and the client's tool list never changes.
10
+ */
11
+ import path from 'node:path';
12
+ import { z } from 'zod';
13
+ import { openInteractiveStep } from '../agent/interactive-step.js';
14
+ import { ScreenPresenter } from '../agent/screen-update.js';
15
+ import { credentials } from '../credentials.js';
16
+ import { ConfigurationError, errorMessage } from '../internal/errors.js';
17
+ import { uuidv7 } from '../internal/ids.js';
18
+ import { LocatorEngine } from '../locator/engine.js';
19
+ import { allocateAppPorts } from '../run/app-ports.js';
20
+ import { openStandaloneAttempt } from '../run/standalone.js';
21
+ import { createSessionCatalog, isGrammarVerb } from './catalog.js';
22
+ import { catalogLine, defineMcpTool, describeToolDetail, invokeTool, textResult } from './tools.js';
23
+ /** How long one session may live, whatever happens. */
24
+ const SESSION_TTL_MS = 4 * 60 * 60 * 1000;
25
+ /** A session nobody has touched for this long is closed, so no browser is left behind. */
26
+ const SESSION_IDLE_MS = 30 * 60 * 1000;
27
+ /** How long the attempt outlives its step, so a step that hit the TTL is still closed in order. */
28
+ const CLOSE_GRACE_MS = 60 * 1000;
29
+ const SESSION_INSTRUCTION = 'Interactive session: a coding agent drives the app over MCP.';
30
+ /** Owns at most one live session and the fixed MCP tools that drive it. */
31
+ export class SessionHost {
32
+ options;
33
+ live;
34
+ opening;
35
+ /** Why the previous session ended, for the error a call on a closed session gets. */
36
+ lastEnd;
37
+ constructor(options) {
38
+ this.options = options;
39
+ }
40
+ get isOpen() {
41
+ return this.live !== undefined;
42
+ }
43
+ /** The server's tools: the same four whatever the project, the config, or the target. */
44
+ toolSpecs() {
45
+ return [this.openSpec(), this.catalogSpec(), this.callSpec(), this.closeSpec()];
46
+ }
47
+ /** Opens a session and returns its opening text: the summary, the catalog, and the first screen. */
48
+ open(options) {
49
+ if (this.live !== undefined) {
50
+ return Promise.reject(new ConfigurationError('SESSION_OPEN', `session ${this.live.id} is already open on target "${this.live.target.name}"; use it, or close_session first`));
51
+ }
52
+ this.opening ??= this.openSession(options).finally(() => {
53
+ this.opening = undefined;
54
+ });
55
+ return this.opening;
56
+ }
57
+ /** Closes the live session, if any, and returns what happened. */
58
+ async close(reason, session) {
59
+ const live = this.live;
60
+ if (live === undefined)
61
+ return 'No session is open.';
62
+ if (session !== undefined && session !== live.id)
63
+ throw this.wrongSession(live, session);
64
+ this.live = undefined;
65
+ this.lastEnd = reason;
66
+ if (live.idleTimer !== undefined)
67
+ clearTimeout(live.idleTimer);
68
+ await live.step.end({ status: 'passed', summary: `session closed: ${reason}` });
69
+ const outcome = await live.step.done;
70
+ const cleanupErrors = await live.attempt.close();
71
+ live.abort.abort();
72
+ const lines = [`Session ${live.id} closed (${reason}); ${live.actions} tool calls ran.`];
73
+ if (outcome.error !== undefined)
74
+ lines.push(`The session step ended with: ${errorMessage(outcome.error)}`);
75
+ for (const error of cleanupErrors)
76
+ lines.push(`Cleanup: ${error.code}: ${error.message}`);
77
+ return lines.join('\n');
78
+ }
79
+ /** The session's catalog, or one tool's full contract. */
80
+ catalog(session, tool) {
81
+ const live = this.requireLive(session);
82
+ if (tool === undefined) {
83
+ return [`Session ${live.id} on target "${live.target.name}": ${Object.keys(live.catalog.tools).length} tools. Run one with call {tool, args}; tools {tool} shows a tool's arguments.`, ...this.catalogLines(live)].join('\n');
84
+ }
85
+ const found = live.catalog.tools[tool];
86
+ if (found === undefined)
87
+ throw this.unknownTool(live, tool);
88
+ return describeToolDetail(tool, found, live.catalog.readOnly.has(tool));
89
+ }
90
+ /** Runs one catalog tool inside the live session's step. */
91
+ call(session, name, args, extra) {
92
+ const live = this.requireLive(session);
93
+ const tool = live.catalog.tools[name];
94
+ if (tool === undefined)
95
+ throw this.unknownTool(live, name);
96
+ return this.run(live, () => invokeTool(name, tool, args, extra));
97
+ }
98
+ async openSession(options) {
99
+ // A session is its own run: a URL declared with port 0 gets a port here.
100
+ const config = await allocateAppPorts(await this.options.loadConfig(options.config));
101
+ const target = this.resolveTarget(config, options.target);
102
+ const ttlMs = this.options.ttlMs ?? SESSION_TTL_MS;
103
+ const abort = new AbortController();
104
+ const id = uuidv7();
105
+ let attempt;
106
+ let step;
107
+ try {
108
+ attempt = await openStandaloneAttempt({
109
+ config,
110
+ target,
111
+ headed: this.options.headed,
112
+ env: this.options.env,
113
+ signal: abort.signal,
114
+ timeoutMs: ttlMs + CLOSE_GRACE_MS,
115
+ artifactsRoot: path.join(config.projectRoot, '.e2e', 'artifacts'),
116
+ notice: (scope, message) => this.options.log('info', `${scope}: ${message}`),
117
+ });
118
+ // The coding agent is the brain: the step is driven from here, and the
119
+ // configured model stays out of the way.
120
+ const params = this.secretParams(config);
121
+ step = await openInteractiveStep(attempt.agentRuntime, {
122
+ instruction: SESSION_INSTRUCTION,
123
+ ...(params === undefined ? {} : { params }),
124
+ timeout: ttlMs,
125
+ });
126
+ const screen = new ScreenPresenter();
127
+ const catalog = createSessionCatalog({
128
+ context: step.context,
129
+ screen,
130
+ session: attempt.session,
131
+ executor: config.agent.executor,
132
+ locator: new LocatorEngine({
133
+ session: attempt.session,
134
+ budget: attempt.budget,
135
+ runId: attempt.runId,
136
+ attemptId: attempt.attemptId,
137
+ actionTimeout: config.actionTimeout,
138
+ assertionTimeout: config.assertionTimeout,
139
+ }),
140
+ warn: (message) => this.options.log('warning', message),
141
+ });
142
+ const live = {
143
+ id,
144
+ target,
145
+ configPath: config.configPath ?? options.config ?? 'e2e.config.ts',
146
+ attempt,
147
+ step,
148
+ screen,
149
+ catalog,
150
+ abort,
151
+ idleTimer: undefined,
152
+ actions: 0,
153
+ };
154
+ this.live = live;
155
+ this.lastEnd = undefined;
156
+ // A step that ends on its own (the TTL, a hard stop) ends the session.
157
+ void step.done.then(async (outcome) => {
158
+ if (this.live !== live)
159
+ return;
160
+ const why = outcome.error === undefined ? 'the session step concluded' : errorMessage(outcome.error);
161
+ this.options.log('warning', `session ${id} ended: ${why}`);
162
+ await this.close(why);
163
+ });
164
+ this.touch(live);
165
+ return this.openingText(live, config, await this.firstScreen(live));
166
+ }
167
+ catch (cause) {
168
+ // Whatever failed after the attempt opened, the attempt is torn down:
169
+ // an engine or app process left behind would block the next session.
170
+ this.live = undefined;
171
+ await step?.end({ status: 'failed', summary: 'opening the session failed' }).catch(() => undefined);
172
+ await attempt?.close().catch(() => undefined);
173
+ abort.abort();
174
+ throw cause;
175
+ }
176
+ }
177
+ /** Opens the app when the engine can navigate, then observes. */
178
+ async firstScreen(live) {
179
+ const base = live.target.app.base?.href;
180
+ if (base !== undefined && live.step.context.target.verbs.has('navigate')) {
181
+ try {
182
+ await live.step.run((context) => context.actions.navigate(base));
183
+ }
184
+ catch (cause) {
185
+ return `Opening ${base} failed: ${errorMessage(cause)}\nUse navigate once the app is reachable.`;
186
+ }
187
+ }
188
+ const observation = await live.step.run((context) => context.observe());
189
+ return live.screen.initial(observation);
190
+ }
191
+ openingText(live, config, screen) {
192
+ const engine = live.target.engine;
193
+ const lines = [
194
+ `Session ${live.id} open on target "${live.target.name}" (platform ${live.target.platform}, engine ${engine === undefined ? 'none' : `${engine.name} ${engine.version}`}), ${this.options.headed ? 'headed' : 'headless'}; config ${live.configPath}.`,
195
+ ];
196
+ if (live.target.app.base !== undefined) {
197
+ lines.push(`App: ${live.target.app.base.href}; allowed origins: ${live.target.app.allowedOrigins.join(', ')}.`);
198
+ }
199
+ if (config.credentials.size > 0) {
200
+ const described = [...config.credentials.values()].map((credential) => `"${credential.name}" (username ${JSON.stringify(credential.username)})`);
201
+ lines.push(`Credentials: ${described.join(', ')}. Type the username with type; fill the password with type_secret and the credential name.`);
202
+ }
203
+ lines.push(`Tools (run one with call {tool, args}; tools {tool} shows a tool's arguments):`, ...this.catalogLines(live));
204
+ lines.push('Node ids ("n42") are valid only for the newest observation; every action reports what changed on screen, and observe shows the whole screen. Call close_session when you are done.');
205
+ return `${lines.join('\n')}\n\n${screen}`;
206
+ }
207
+ catalogLines(live) {
208
+ return Object.entries(live.catalog.tools).map(([name, tool]) => catalogLine(name, tool, live.catalog.readOnly.has(name)));
209
+ }
210
+ resolveTarget(config, requested) {
211
+ const name = requested ?? this.options.defaultTarget;
212
+ const names = config.targets.map((target) => target.name);
213
+ if (name !== undefined) {
214
+ const target = config.targets.find((candidate) => candidate.name === name);
215
+ if (target === undefined) {
216
+ throw new ConfigurationError('UNKNOWN_TARGET', `unknown target "${name}"; the config declares ${names.map((n) => `"${n}"`).join(', ')}`);
217
+ }
218
+ return target;
219
+ }
220
+ const [only] = config.targets;
221
+ if (only !== undefined && config.targets.length === 1)
222
+ return only;
223
+ if (only === undefined)
224
+ throw new ConfigurationError('INVALID_CONFIG', 'the config declares no targets');
225
+ throw new ConfigurationError('TARGET_REQUIRED', `the config declares several targets (${names.join(', ')}); pass target to open_session, or start e2e mcp --target <name>`);
226
+ }
227
+ /** Every configured credential's password as a step secret, so `type_secret` can fill it. */
228
+ secretParams(config) {
229
+ if (config.credentials.size === 0)
230
+ return undefined;
231
+ return Object.fromEntries([...config.credentials.keys()].map((name) => [name, credentials.user(name).password]));
232
+ }
233
+ requireLive(session) {
234
+ if (this.live === undefined) {
235
+ const previous = this.lastEnd === undefined ? '' : ` (the previous session ended: ${this.lastEnd})`;
236
+ throw new ConfigurationError('NO_SESSION', `no session is open; call open_session first${previous}`);
237
+ }
238
+ if (session !== undefined && session !== this.live.id)
239
+ throw this.wrongSession(this.live, session);
240
+ return this.live;
241
+ }
242
+ wrongSession(live, session) {
243
+ return new ConfigurationError('NO_SESSION', `session "${session}" is not open; the open session is ${live.id}`);
244
+ }
245
+ unknownTool(live, name) {
246
+ if (isGrammarVerb(name)) {
247
+ return new ConfigurationError('UNSUPPORTED_CAPABILITY', `tool "${name}" is not available in this session: the engine of target "${live.target.name}" declares no such action; tools lists what it can do`);
248
+ }
249
+ return new ConfigurationError('UNKNOWN_TOOL', `tool "${name}" is not available in this session; tools: ${Object.keys(live.catalog.tools).join(', ')}`);
250
+ }
251
+ touch(live) {
252
+ if (live.idleTimer !== undefined)
253
+ clearTimeout(live.idleTimer);
254
+ const idleMs = this.options.idleMs ?? SESSION_IDLE_MS;
255
+ live.idleTimer = setTimeout(() => {
256
+ if (this.live !== live)
257
+ return;
258
+ this.options.log('warning', `session ${live.id} idle for ${Math.round(idleMs / 60_000)} minutes; closing it`);
259
+ void this.close('idle timeout');
260
+ }, idleMs);
261
+ live.idleTimer.unref();
262
+ }
263
+ /** Runs one tool body inside the live session's step. */
264
+ run(live, body) {
265
+ this.touch(live);
266
+ live.actions += 1;
267
+ return live.step.run(body);
268
+ }
269
+ // --- the fixed tools ---
270
+ openSpec() {
271
+ return defineMcpTool({
272
+ name: 'open_session',
273
+ description: 'Open a live session on one target of an e2e project: loads the config, starts the app command the engine declares (if any), boots the engine (a browser, a simulator), opens the app URL, and returns the session id, the catalog of tools it can run, and the first observation. One session at a time. Then act with call and look with call {tool: "observe"}.',
274
+ inputSchema: z.object({
275
+ target: z.string().min(1).optional().describe('Target name from the config; required when the config declares several'),
276
+ config: z.string().min(1).optional().describe("Path to an e2e config file, relative to the server's directory; default: the nearest e2e.config.ts"),
277
+ }),
278
+ readOnly: false,
279
+ call: async (args) => textResult(await this.open(args)),
280
+ });
281
+ }
282
+ catalogSpec() {
283
+ return defineMcpTool({
284
+ name: 'tools',
285
+ description: "List the tools the open session can run through call: observe, the grammar its engine honors (tap, type, press, select, scroll, navigate, type_secret, and screenshot and tap_at while no secret has been filled), locate, and the project's own tools. With tool, shows that tool's full description and the JSON Schema of its arguments.",
286
+ inputSchema: z.object({
287
+ tool: z.string().min(1).optional().describe('A catalog tool name, for its full contract'),
288
+ session: z.string().min(1).optional().describe('Session id; defaults to the open session'),
289
+ }),
290
+ readOnly: true,
291
+ call: async (args) => textResult(this.catalog(args.session, args.tool)),
292
+ });
293
+ }
294
+ callSpec() {
295
+ return defineMcpTool({
296
+ name: 'call',
297
+ description: "Run one tool of the open session by name, with its arguments as an object: call {tool: \"tap\", args: {target: \"n42\"}}. The session's catalog (from open_session or tools) names the tools and their arguments. Actions report what changed on screen; node ids are valid only for the newest observation.",
298
+ inputSchema: z.object({
299
+ tool: z.string().min(1).describe('A catalog tool name, e.g. "observe", "tap", "locate", "screenshot"'),
300
+ args: z.record(z.string(), z.unknown()).optional().describe("The tool's arguments; omit for a tool without any"),
301
+ session: z.string().min(1).optional().describe('Session id; defaults to the open session'),
302
+ }),
303
+ readOnly: false,
304
+ call: (args, extra) => this.call(args.session, args.tool, args.args ?? {}, extra),
305
+ });
306
+ }
307
+ closeSpec() {
308
+ return defineMcpTool({
309
+ name: 'close_session',
310
+ description: 'Close the live session: end the attempt, dispose the engine, and stop the app processes the session started.',
311
+ inputSchema: z.object({
312
+ session: z.string().min(1).optional().describe('Session id; defaults to the open session'),
313
+ }),
314
+ readOnly: false,
315
+ call: async (args) => textResult(await this.close('closed by the agent', args.session)),
316
+ });
317
+ }
318
+ }
319
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/mcp/session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,77 @@
1
+ /**
2
+ * The bridge from the agent's AI SDK tools to the MCP `call` tool. The
3
+ * testing agent's vocabulary (the grammar, the engine packs, the project's
4
+ * `defineTool` values) is a set of AI SDK tools: a description, a zod input
5
+ * schema, and an execute function. The server keeps its own tool list fixed
6
+ * and small, and serves that vocabulary as a catalog: `tools` renders it from
7
+ * the same descriptions and schemas the testing agent reads, and `call`
8
+ * validates the arguments against the schema, runs the tool, and renders its
9
+ * output in the MCP result envelope.
10
+ */
11
+ import { type JSONSchema7, type ToolSet } from 'ai';
12
+ import type { z } from 'zod';
13
+ /** One MCP content part this server emits. */
14
+ export type McpContent = {
15
+ readonly type: 'text';
16
+ readonly text: string;
17
+ } | {
18
+ readonly type: 'image';
19
+ readonly data: string;
20
+ readonly mimeType: string;
21
+ };
22
+ /** The MCP tool result envelope, as the SDK's `CallToolResult` spells it. */
23
+ export interface McpToolResult {
24
+ readonly content: McpContent[];
25
+ readonly isError?: boolean;
26
+ [key: string]: unknown;
27
+ }
28
+ /** What a tool body gets from the request. */
29
+ export interface McpToolCallExtra {
30
+ readonly signal: AbortSignal;
31
+ }
32
+ /** What the server registers: the contract and the body of one of its fixed tools. */
33
+ export interface McpToolSpec<Shape extends z.ZodRawShape = z.ZodRawShape> {
34
+ readonly name: string;
35
+ readonly description: string;
36
+ readonly inputSchema: z.ZodObject<Shape>;
37
+ /** Hint for clients: a tool that changes nothing on the app or disk. */
38
+ readonly readOnly: boolean;
39
+ /** Runs the tool on validated arguments; a thrown error becomes an error result. */
40
+ call(args: z.infer<z.ZodObject<Shape>>, extra: McpToolCallExtra): Promise<McpToolResult>;
41
+ }
42
+ /** Declares one fixed tool with `call` typed from its `inputSchema`. */
43
+ export declare function defineMcpTool<Shape extends z.ZodRawShape>(spec: McpToolSpec<Shape>): McpToolSpec<Shape>;
44
+ export declare function textResult(text: string): McpToolResult;
45
+ /**
46
+ * A failure as a tool result the agent can react to, never a protocol error:
47
+ * the code and message are what a test would have reported.
48
+ */
49
+ export declare function errorResult(cause: unknown): McpToolResult;
50
+ /**
51
+ * The JSON Schema of a tool's arguments, without the draft marker clients
52
+ * never need. A zod schema converts synchronously; a schema that only
53
+ * resolves lazily is shown as an open object rather than awaited, since the
54
+ * catalog is rendered inline.
55
+ */
56
+ export declare function toolJsonSchema(tool: ToolSet[string]): JSONSchema7;
57
+ /**
58
+ * One catalog line: the name, the argument names (`?` marks an optional
59
+ * one), the first sentence of the description, and the read-only mark.
60
+ * `- tap {target}: Tap or click one node.`
61
+ */
62
+ export declare function catalogLine(name: string, tool: ToolSet[string], readOnly: boolean): string;
63
+ /** The full contract of one tool: its description and the JSON Schema of its arguments. */
64
+ export declare function describeToolDetail(name: string, tool: ToolSet[string], readOnly: boolean): string;
65
+ /**
66
+ * Validates the arguments against the tool's own schema and runs it. The
67
+ * server's `call` tool takes any object, so this is where a wrong argument is
68
+ * caught, with the same message a model would get, before the tool runs.
69
+ */
70
+ export declare function invokeTool(name: string, tool: ToolSet[string], args: Record<string, unknown>, extra: McpToolCallExtra): Promise<McpToolResult>;
71
+ /**
72
+ * Renders a tool's output the way the tool renders it for a model: text as
73
+ * text, and a `toModelOutput` that yields file parts as images. Anything
74
+ * else is JSON, so a structured output is never lost.
75
+ */
76
+ export declare function resultFromOutput(tool: ToolSet[string], output: unknown, input?: unknown): Promise<McpToolResult>;
77
+ //# sourceMappingURL=tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../src/mcp/tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAY,KAAK,WAAW,EAAwC,KAAK,OAAO,EAAE,MAAM,IAAI,CAAC;AACpG,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAG7B,8CAA8C;AAC9C,MAAM,MAAM,UAAU,GAClB;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAChD;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjF,6EAA6E;AAC7E,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,OAAO,EAAE,UAAU,EAAE,CAAC;IAC/B,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,8CAA8C;AAC9C,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;CAC9B;AAED,sFAAsF;AACtF,MAAM,WAAW,WAAW,CAAC,KAAK,SAAS,CAAC,CAAC,WAAW,GAAG,CAAC,CAAC,WAAW;IACtE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IACzC,wEAAwE;IACxE,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,oFAAoF;IACpF,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;CAC1F;AAED,wEAAwE;AACxE,wBAAgB,aAAa,CAAC,KAAK,SAAS,CAAC,CAAC,WAAW,EAAE,IAAI,EAAE,WAAW,CAAC,KAAK,CAAC,GAAG,WAAW,CAAC,KAAK,CAAC,CAEvG;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,CAEtD;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,aAAa,CAGzD;AAKD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,GAAG,WAAW,CAKjE;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,OAAO,GAAG,MAAM,CAM1F;AAED,2FAA2F;AAC3F,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,OAAO,GAAG,MAAM,CAQjG;AAmBD;;;;GAIG;AACH,wBAAsB,UAAU,CAC9B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,EACrB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,KAAK,EAAE,gBAAgB,GACtB,OAAO,CAAC,aAAa,CAAC,CAYxB;AAgDD;;;;GAIG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,GAAE,OAAmB,GAAG,OAAO,CAAC,aAAa,CAAC,CAOjI"}
@@ -0,0 +1,179 @@
1
+ /**
2
+ * The bridge from the agent's AI SDK tools to the MCP `call` tool. The
3
+ * testing agent's vocabulary (the grammar, the engine packs, the project's
4
+ * `defineTool` values) is a set of AI SDK tools: a description, a zod input
5
+ * schema, and an execute function. The server keeps its own tool list fixed
6
+ * and small, and serves that vocabulary as a catalog: `tools` renders it from
7
+ * the same descriptions and schemas the testing agent reads, and `call`
8
+ * validates the arguments against the schema, runs the tool, and renders its
9
+ * output in the MCP result envelope.
10
+ */
11
+ import { asSchema } from 'ai';
12
+ import { ConfigurationError, errorMessage, E2EError, isForeignE2EError } from '../internal/errors.js';
13
+ /** Declares one fixed tool with `call` typed from its `inputSchema`. */
14
+ export function defineMcpTool(spec) {
15
+ return spec;
16
+ }
17
+ export function textResult(text) {
18
+ return { content: [{ type: 'text', text }] };
19
+ }
20
+ /**
21
+ * A failure as a tool result the agent can react to, never a protocol error:
22
+ * the code and message are what a test would have reported.
23
+ */
24
+ export function errorResult(cause) {
25
+ const code = cause instanceof E2EError || isForeignE2EError(cause) ? `${cause.code}: ` : '';
26
+ return { content: [{ type: 'text', text: `${code}${errorMessage(cause)}` }], isError: true };
27
+ }
28
+ /** How much of a description the catalog shows per tool: its first sentence, bounded. */
29
+ const CATALOG_SENTENCE_MAX = 160;
30
+ /**
31
+ * The JSON Schema of a tool's arguments, without the draft marker clients
32
+ * never need. A zod schema converts synchronously; a schema that only
33
+ * resolves lazily is shown as an open object rather than awaited, since the
34
+ * catalog is rendered inline.
35
+ */
36
+ export function toolJsonSchema(tool) {
37
+ const raw = asSchema(tool.inputSchema).jsonSchema;
38
+ if (typeof raw.then === 'function')
39
+ return { type: 'object' };
40
+ const { $schema: _draft, ...schema } = raw;
41
+ return schema;
42
+ }
43
+ /**
44
+ * One catalog line: the name, the argument names (`?` marks an optional
45
+ * one), the first sentence of the description, and the read-only mark.
46
+ * `- tap {target}: Tap or click one node.`
47
+ */
48
+ export function catalogLine(name, tool, readOnly) {
49
+ const schema = toolJsonSchema(tool);
50
+ const required = new Set(schema.required ?? []);
51
+ const args = Object.keys(schema.properties ?? {}).map((key) => (required.has(key) ? key : `${key}?`));
52
+ const signature = args.length === 0 ? name : `${name} {${args.join(', ')}}`;
53
+ return `- ${signature}: ${firstSentence(toolDescription(name, tool))}${readOnly ? ' [read-only]' : ''}`;
54
+ }
55
+ /** The full contract of one tool: its description and the JSON Schema of its arguments. */
56
+ export function describeToolDetail(name, tool, readOnly) {
57
+ return [
58
+ `${name}${readOnly ? ' [read-only]' : ''}`,
59
+ toolDescription(name, tool),
60
+ '',
61
+ 'Arguments (JSON Schema):',
62
+ JSON.stringify(toolJsonSchema(tool), null, 2),
63
+ ].join('\n');
64
+ }
65
+ function toolDescription(name, tool) {
66
+ return typeof tool.description === 'string' && tool.description !== '' ? tool.description : name;
67
+ }
68
+ /** Abbreviations whose period does not end a sentence. */
69
+ const ABBREVIATIONS = /\b(?:e\.g|i\.e|etc|vs)\./gi;
70
+ function firstSentence(text) {
71
+ const flat = text.replaceAll(/\s+/g, ' ').trim();
72
+ const guarded = flat.replaceAll(ABBREVIATIONS, (match) => match.replaceAll('.', '\u0000'));
73
+ const end = guarded.search(/[.!?](?:\s|$)/);
74
+ const sentence = (end === -1 ? guarded : guarded.slice(0, end + 1)).replaceAll('\u0000', '.');
75
+ if (sentence.length <= CATALOG_SENTENCE_MAX)
76
+ return sentence;
77
+ const cut = sentence.lastIndexOf(' ', CATALOG_SENTENCE_MAX - 1);
78
+ return `${sentence.slice(0, cut > 0 ? cut : CATALOG_SENTENCE_MAX - 1).replace(/[,;:]$/, '')}…`;
79
+ }
80
+ /**
81
+ * Validates the arguments against the tool's own schema and runs it. The
82
+ * server's `call` tool takes any object, so this is where a wrong argument is
83
+ * caught, with the same message a model would get, before the tool runs.
84
+ */
85
+ export async function invokeTool(name, tool, args, extra) {
86
+ if (tool.execute === undefined) {
87
+ throw new ConfigurationError('UNSUPPORTED_CAPABILITY', `tool "${name}" has no execute function`);
88
+ }
89
+ const input = await validateArgs(name, tool, args);
90
+ const options = {
91
+ toolCallId: `mcp-${Date.now().toString(36)}`,
92
+ messages: [],
93
+ abortSignal: extra.signal,
94
+ context: undefined,
95
+ };
96
+ return resultFromOutput(tool, await resolveOutput(await tool.execute(input, options)), input);
97
+ }
98
+ async function validateArgs(name, tool, args) {
99
+ const schema = asSchema(tool.inputSchema);
100
+ if (schema.validate === undefined)
101
+ return args;
102
+ const result = await schema.validate(args);
103
+ if (result.success)
104
+ return result.value;
105
+ throw new ConfigurationError('INVALID_ARGUMENT', `call ${name}: ${describeValidationError(result.error)}; tools {tool: ${JSON.stringify(name)}} shows its arguments`);
106
+ }
107
+ /**
108
+ * The issues a zod (or any standard schema) failure carries, one per line;
109
+ * else the message. The SDK types the failure as a plain `Error`, so the
110
+ * issues are probed on it and on its cause.
111
+ */
112
+ function describeValidationError(error) {
113
+ const issues = issuesOf(error) ?? issuesOf(error.cause);
114
+ if (issues === undefined || issues.length === 0)
115
+ return errorMessage(error);
116
+ return issues
117
+ .map((issue) => {
118
+ const path = Array.isArray(issue.path) && issue.path.length > 0 ? `${issue.path.map(String).join('.')}: ` : '';
119
+ return `${path}${typeof issue.message === 'string' ? issue.message : 'invalid'}`;
120
+ })
121
+ .join('; ');
122
+ }
123
+ function issuesOf(value) {
124
+ if (typeof value !== 'object' || value === null)
125
+ return undefined;
126
+ const issues = value.issues;
127
+ return Array.isArray(issues) ? issues : undefined;
128
+ }
129
+ /** An execute function may stream; the last value is the tool's output. */
130
+ async function resolveOutput(value) {
131
+ if (value !== null && typeof value === 'object' && Symbol.asyncIterator in value) {
132
+ let last;
133
+ for await (const part of value)
134
+ last = part;
135
+ return last;
136
+ }
137
+ return value;
138
+ }
139
+ /**
140
+ * Renders a tool's output the way the tool renders it for a model: text as
141
+ * text, and a `toModelOutput` that yields file parts as images. Anything
142
+ * else is JSON, so a structured output is never lost.
143
+ */
144
+ export async function resultFromOutput(tool, output, input = undefined) {
145
+ if (typeof output === 'string')
146
+ return textResult(output);
147
+ if (tool.toModelOutput !== undefined) {
148
+ const content = contentFromModelOutput(await tool.toModelOutput({ toolCallId: 'mcp', input, output }));
149
+ if (content !== undefined)
150
+ return { content };
151
+ }
152
+ return textResult(output === undefined ? 'Done.' : JSON.stringify(output, null, 2));
153
+ }
154
+ function contentFromModelOutput(output) {
155
+ switch (output.type) {
156
+ case 'text':
157
+ case 'error-text':
158
+ return [{ type: 'text', text: output.value }];
159
+ case 'json':
160
+ case 'error-json':
161
+ return [{ type: 'text', text: JSON.stringify(output.value, null, 2) }];
162
+ case 'content': {
163
+ const parts = [];
164
+ for (const part of output.value) {
165
+ if (part.type === 'text') {
166
+ parts.push({ type: 'text', text: part.text });
167
+ }
168
+ else if (part.type === 'file' && part.data.type === 'data') {
169
+ const data = typeof part.data.data === 'string' ? part.data.data : Buffer.from(new Uint8Array(part.data.data)).toString('base64');
170
+ parts.push({ type: 'image', data, mimeType: part.mediaType });
171
+ }
172
+ }
173
+ return parts.length === 0 ? undefined : parts;
174
+ }
175
+ default:
176
+ return undefined;
177
+ }
178
+ }
179
+ //# sourceMappingURL=tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.js","sourceRoot":"","sources":["../../src/mcp/tools.ts"],"names":[],"mappings":"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"}
@@ -163,6 +163,8 @@ export interface ReportSerialGroup {
163
163
  titlePath: readonly string[];
164
164
  targetId: string;
165
165
  platform: string;
166
+ /** The configured agent this variant of the group ran as. */
167
+ agent: string;
166
168
  memberTestIds: readonly string[];
167
169
  status: SerialGroupRecord['status'];
168
170
  skip?: SkipInfo | undefined;
@@ -178,6 +180,12 @@ export interface ReportResult {
178
180
  source: ReportSource;
179
181
  targetId: string;
180
182
  platform: string;
183
+ /**
184
+ * The configured agent the test ran as. A test pinned to several agents,
185
+ * or a run with several `--agent` names, yields one result per agent, each
186
+ * with its own `id`.
187
+ */
188
+ agent: string;
181
189
  serialGroupId?: string | undefined;
182
190
  status: ResultRecord['status'];
183
191
  skip?: SkipInfo | undefined;