@veolab/discoverylab 1.2.1 → 1.3.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 (160) hide show
  1. package/.mcp.json +2 -2
  2. package/README.md +182 -0
  3. package/dist/{chunk-TAODYZ52.js → chunk-3QRQEDWR.js} +510 -213
  4. package/dist/{chunk-L4SA5F5W.js → chunk-4L76GPRC.js} +1162 -58
  5. package/dist/chunk-6EGBXRDK.js +30 -0
  6. package/dist/{chunk-I6YD3QFM.js → chunk-FIL7IWEL.js} +5 -3
  7. package/dist/{chunk-4KLG6DDE.js → chunk-FNUN7EPB.js} +6 -6
  8. package/dist/chunk-GAKEFJ5T.js +481 -0
  9. package/dist/chunk-LB3RNE3O.js +109 -0
  10. package/dist/chunk-N6JJ2RGV.js +2680 -0
  11. package/dist/{chunk-XUKWS2CE.js → chunk-VRM42PML.js} +3546 -926
  12. package/dist/{chunk-TJ3H23LL.js → chunk-VVIOB362.js} +3 -1
  13. package/dist/{chunk-W3WJGYR6.js → chunk-XFVDP332.js} +8 -2
  14. package/dist/{chunk-QJXXHOV7.js → chunk-XKX6NBHF.js} +5 -1
  15. package/dist/cli.js +405 -11
  16. package/dist/{db-ADBEBNH6.js → db-6WLEVKUV.js} +3 -1
  17. package/dist/esvp-GSISVXLC.js +52 -0
  18. package/dist/esvp-mobile-GC7MAGMI.js +20 -0
  19. package/dist/index.d.ts +123 -1
  20. package/dist/index.html +11689 -8690
  21. package/dist/index.js +67 -11
  22. package/dist/{ocr-UTWC7537.js → ocr-QDYNCSPE.js} +1 -1
  23. package/dist/{playwright-R7Y5HREH.js → playwright-VZ7PXDC5.js} +2 -2
  24. package/dist/runtime/esvp-host-runtime/darwin-arm64/esvp-host-runtime +0 -0
  25. package/dist/runtime/esvp-host-runtime/manifest.json +10 -0
  26. package/dist/{server-3FBHBA7L.js → server-6N3KIEGP.js} +2 -1
  27. package/dist/server-FO3UVUZU.js +22 -0
  28. package/dist/{setup-27CQAX6K.js → setup-2SQC5UHJ.js} +4 -3
  29. package/dist/{tools-L6PKKQPY.js → tools-OCRMOQ4U.js} +63 -8
  30. package/package.json +36 -5
  31. package/dist/chunk-22OCFYHG.js +0 -6283
  32. package/dist/chunk-24VARQVO.js +0 -7818
  33. package/dist/chunk-2OGZX6C4.js +0 -588
  34. package/dist/chunk-2WCNIFRO.js +0 -6191
  35. package/dist/chunk-43U6UYV7.js +0 -590
  36. package/dist/chunk-4H2E3K2G.js +0 -7638
  37. package/dist/chunk-4MS6YW2B.js +0 -6490
  38. package/dist/chunk-4NNTRJOI.js +0 -7791
  39. package/dist/chunk-5F76VWME.js +0 -6397
  40. package/dist/chunk-5NEFN42O.js +0 -7791
  41. package/dist/chunk-63MEQ6UH.js +0 -7673
  42. package/dist/chunk-6H3NXFX3.js +0 -6861
  43. package/dist/chunk-7IDQLLBW.js +0 -311
  44. package/dist/chunk-7NP64TGJ.js +0 -6822
  45. package/dist/chunk-AATLY4KT.js +0 -6505
  46. package/dist/chunk-C7QUR7XX.js +0 -6397
  47. package/dist/chunk-CGKCE6MC.js +0 -6279
  48. package/dist/chunk-D25V6IWE.js +0 -6487
  49. package/dist/chunk-EQOZSXAT.js +0 -6822
  50. package/dist/chunk-FPHD7HSQ.js +0 -6812
  51. package/dist/chunk-GGJJUCFK.js +0 -7160
  52. package/dist/chunk-GLHOY3NN.js +0 -7805
  53. package/dist/chunk-GML5MKQA.js +0 -6398
  54. package/dist/chunk-GOL6FUJL.js +0 -6045
  55. package/dist/chunk-GSWHWEYC.js +0 -1346
  56. package/dist/chunk-HDKEQOF5.js +0 -7788
  57. package/dist/chunk-HZGSWVVS.js +0 -7111
  58. package/dist/chunk-IGZ5TICZ.js +0 -334
  59. package/dist/chunk-IRKQG33A.js +0 -7054
  60. package/dist/chunk-JFTBF4JR.js +0 -6040
  61. package/dist/chunk-JVLVBPUJ.js +0 -6180
  62. package/dist/chunk-JY3KC67R.js +0 -6504
  63. package/dist/chunk-KUFBCBNJ.js +0 -6815
  64. package/dist/chunk-KV7KDJ43.js +0 -7639
  65. package/dist/chunk-L5IJZV5F.js +0 -6822
  66. package/dist/chunk-MFFPQLU4.js +0 -7102
  67. package/dist/chunk-MJS2YKNR.js +0 -6397
  68. package/dist/chunk-MN6LCZHZ.js +0 -1320
  69. package/dist/chunk-NBAUZ7X2.js +0 -1336
  70. package/dist/chunk-NDBW6ELQ.js +0 -7638
  71. package/dist/chunk-O2HBSDI2.js +0 -6175
  72. package/dist/chunk-OFFIUYMG.js +0 -6341
  73. package/dist/chunk-OVCQGF2J.js +0 -1321
  74. package/dist/chunk-P4S7ZY6G.js +0 -7638
  75. package/dist/chunk-PBHUHSC3.js +0 -6002
  76. package/dist/chunk-PC4LR4ZI.js +0 -6359
  77. package/dist/chunk-PMTGGZ7R.js +0 -6397
  78. package/dist/chunk-PTXSB3UV.js +0 -497
  79. package/dist/chunk-PYUCY3U6.js +0 -1340
  80. package/dist/chunk-RDZDSOAL.js +0 -7750
  81. package/dist/chunk-RLW2OI2L.js +0 -6383
  82. package/dist/chunk-RUGHHO4K.js +0 -6395
  83. package/dist/chunk-SIOQVM2E.js +0 -6819
  84. package/dist/chunk-SR67SRIT.js +0 -1336
  85. package/dist/chunk-SSRXIO2V.js +0 -6822
  86. package/dist/chunk-SWSEKFON.js +0 -6487
  87. package/dist/chunk-TBG76CYG.js +0 -6395
  88. package/dist/chunk-V3CBINLD.js +0 -6812
  89. package/dist/chunk-VPYSLEGM.js +0 -6710
  90. package/dist/chunk-VY3BLXBW.js +0 -329
  91. package/dist/chunk-WTFOGVJQ.js +0 -6365
  92. package/dist/chunk-X64SFUT5.js +0 -6099
  93. package/dist/chunk-XIBF5LBD.js +0 -6395
  94. package/dist/chunk-Y5VDMSYC.js +0 -6701
  95. package/dist/chunk-YUBL36H4.js +0 -6605
  96. package/dist/chunk-YWVXFVSW.js +0 -6456
  97. package/dist/chunk-ZXZACOLD.js +0 -6822
  98. package/dist/db-IWIL65EX.js +0 -33
  99. package/dist/gridCompositor-ENKLFPWR.js +0 -409
  100. package/dist/playwright-A3OGSDRG.js +0 -38
  101. package/dist/playwright-ATDC4NYW.js +0 -38
  102. package/dist/playwright-E6EUFIJG.js +0 -38
  103. package/dist/server-2DXLKLFM.js +0 -13
  104. package/dist/server-2ICEWJVK.js +0 -13
  105. package/dist/server-2MQV3FNY.js +0 -13
  106. package/dist/server-2NGD7GE3.js +0 -13
  107. package/dist/server-2VKO76UK.js +0 -14
  108. package/dist/server-3BK2VFU7.js +0 -13
  109. package/dist/server-4LDOB3NX.js +0 -13
  110. package/dist/server-4YI44KDR.js +0 -13
  111. package/dist/server-64XMXA5P.js +0 -13
  112. package/dist/server-6IPHVUYT.js +0 -14
  113. package/dist/server-73ORHMJN.js +0 -13
  114. package/dist/server-73P7M3QB.js +0 -14
  115. package/dist/server-BPVRW5LJ.js +0 -14
  116. package/dist/server-BW4RKZIX.js +0 -13
  117. package/dist/server-CFS5SM5K.js +0 -13
  118. package/dist/server-DX7VYHHM.js +0 -13
  119. package/dist/server-F3YPX6ET.js +0 -13
  120. package/dist/server-FUXTR33I.js +0 -13
  121. package/dist/server-G2SY3DOS.js +0 -13
  122. package/dist/server-G32U7VOQ.js +0 -13
  123. package/dist/server-IOOZK4NP.js +0 -14
  124. package/dist/server-J52LMTBT.js +0 -13
  125. package/dist/server-JG7UKFGK.js +0 -14
  126. package/dist/server-JSCHEBOD.js +0 -13
  127. package/dist/server-K6KC4ZOM.js +0 -13
  128. package/dist/server-KJVRGWFE.js +0 -13
  129. package/dist/server-LCPB2L4U.js +0 -13
  130. package/dist/server-M7LDYKAJ.js +0 -13
  131. package/dist/server-MKVK6ZQQ.js +0 -13
  132. package/dist/server-MU52LCXT.js +0 -13
  133. package/dist/server-NM5CKDUU.js +0 -13
  134. package/dist/server-NPZN3FWO.js +0 -14
  135. package/dist/server-O5FIAHSY.js +0 -14
  136. package/dist/server-OESJUEYC.js +0 -13
  137. package/dist/server-ONSKQO4W.js +0 -13
  138. package/dist/server-P27BZXBL.js +0 -14
  139. package/dist/server-Q4FBWQUA.js +0 -13
  140. package/dist/server-RNQ7VUAL.js +0 -13
  141. package/dist/server-S6B5WUBT.js +0 -14
  142. package/dist/server-SRYNSGSP.js +0 -14
  143. package/dist/server-SUN3W2YK.js +0 -13
  144. package/dist/server-UA62LHZB.js +0 -13
  145. package/dist/server-UJB44EW5.js +0 -13
  146. package/dist/server-X3TLP6DX.js +0 -14
  147. package/dist/server-YT2UGEZK.js +0 -13
  148. package/dist/server-ZBPQ33V6.js +0 -14
  149. package/dist/setup-AQX4JQVR.js +0 -17
  150. package/dist/setup-EQTU7FI6.js +0 -17
  151. package/dist/tools-2KPB37GK.js +0 -178
  152. package/dist/tools-3H6IOWXV.js +0 -178
  153. package/dist/tools-3KYHPDCJ.js +0 -178
  154. package/dist/tools-75BAPCUM.js +0 -177
  155. package/dist/tools-BUVCUCRL.js +0 -178
  156. package/dist/tools-HDNODRS6.js +0 -178
  157. package/dist/tools-HP5MNY3D.js +0 -177
  158. package/dist/tools-N5N2IO7V.js +0 -178
  159. package/dist/tools-NFJEZ2FF.js +0 -177
  160. package/dist/tools-TLCKABUW.js +0 -178
@@ -159,8 +159,9 @@ var DB_PATH = join(DATA_DIR, "data.db");
159
159
  var PROJECTS_DIR = join(DATA_DIR, "projects");
160
160
  var EXPORTS_DIR = join(DATA_DIR, "exports");
161
161
  var FRAMES_DIR = join(DATA_DIR, "frames");
162
+ var TEMPLATES_DIR = join(DATA_DIR, "templates");
162
163
  function ensureDirectories() {
163
- const dirs = [DATA_DIR, PROJECTS_DIR, EXPORTS_DIR, FRAMES_DIR];
164
+ const dirs = [DATA_DIR, PROJECTS_DIR, EXPORTS_DIR, FRAMES_DIR, TEMPLATES_DIR];
164
165
  for (const dir of dirs) {
165
166
  if (!existsSync(dir)) {
166
167
  mkdirSync(dir, { recursive: true });
@@ -356,6 +357,7 @@ export {
356
357
  PROJECTS_DIR,
357
358
  EXPORTS_DIR,
358
359
  FRAMES_DIR,
360
+ TEMPLATES_DIR,
359
361
  getDatabase,
360
362
  getSqlite,
361
363
  closeDatabase
@@ -181,12 +181,18 @@ async function recognizeText(imagePath, options = {}) {
181
181
  }
182
182
  return recognizeTextWithTesseract(imagePath, options);
183
183
  }
184
- async function recognizeTextBatch(imagePaths, options = {}) {
184
+ async function recognizeTextBatch(imagePaths, options = {}, onProgress) {
185
185
  const results = [];
186
186
  const textParts = [];
187
- for (const imagePath of imagePaths) {
187
+ for (const [index, imagePath] of imagePaths.entries()) {
188
188
  const ocr = await recognizeText(imagePath, options);
189
189
  results.push({ imagePath, ocr });
190
+ onProgress?.({
191
+ current: index + 1,
192
+ total: imagePaths.length,
193
+ imagePath,
194
+ ocr
195
+ });
190
196
  if (ocr.success && ocr.text) {
191
197
  textParts.push(ocr.text);
192
198
  }
@@ -1,10 +1,14 @@
1
+ import {
2
+ APP_VERSION
3
+ } from "./chunk-6EGBXRDK.js";
4
+
1
5
  // src/mcp/server.ts
2
6
  import { z } from "zod";
3
7
  var MCPServer = class {
4
8
  tools = /* @__PURE__ */ new Map();
5
9
  serverInfo = {
6
10
  name: "discoverylab",
7
- version: "0.1.0"
11
+ version: APP_VERSION
8
12
  };
9
13
  registerTool(tool) {
10
14
  this.tools.set(tool.name, tool);
package/dist/cli.js CHANGED
@@ -1,17 +1,395 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ APP_VERSION
4
+ } from "./chunk-6EGBXRDK.js";
5
+ import {
6
+ buildAppLabNetworkProfile
7
+ } from "./chunk-LB3RNE3O.js";
8
+ import "./chunk-MLKGABMK.js";
2
9
 
3
10
  // src/cli.ts
4
11
  import { Command } from "commander";
5
12
  import chalk from "chalk";
6
13
  import open from "open";
7
14
  var program = new Command();
8
- program.name("discoverylab").description("AI-powered app testing & evidence generator - Claude Code Plugin").version("0.1.0");
9
- program.command("serve").description("Start the DiscoveryLab web UI server").option("-p, --port <number>", "Port to listen on", "3847").option("-o, --open", "Open browser automatically", false).action(async (options) => {
15
+ var binName = process.argv[1]?.replace(/.*[\\/]/, "").replace(/\.[^.]+$/, "") === "applab" ? "applab" : "discoverylab";
16
+ program.name(binName).description("AI-powered app testing & evidence generator - Claude Code Plugin").version(APP_VERSION);
17
+ function printCliOutput(value) {
18
+ if (typeof value === "string") {
19
+ console.log(value);
20
+ return;
21
+ }
22
+ console.log(JSON.stringify(value, null, 2));
23
+ }
24
+ function failCli(message) {
25
+ throw new Error(message);
26
+ }
27
+ async function readJsonSource(json, filePath, label = "payload") {
28
+ if (json && filePath) {
29
+ failCli(`Use either --json or --file for ${label}, not both.`);
30
+ }
31
+ if (json) {
32
+ try {
33
+ return JSON.parse(json);
34
+ } catch (error) {
35
+ failCli(`Invalid ${label} JSON: ${error instanceof Error ? error.message : String(error)}`);
36
+ }
37
+ }
38
+ if (filePath) {
39
+ const { readFile } = await import("fs/promises");
40
+ const { resolve } = await import("path");
41
+ const raw = await readFile(resolve(process.cwd(), filePath), "utf8");
42
+ try {
43
+ return JSON.parse(raw);
44
+ } catch {
45
+ return raw;
46
+ }
47
+ }
48
+ return null;
49
+ }
50
+ async function withESVPCli(action) {
51
+ try {
52
+ const result = await action();
53
+ printCliOutput(result);
54
+ } catch (error) {
55
+ console.error(chalk.red(` ESVP command failed: ${error instanceof Error ? error.message : String(error)}`));
56
+ process.exit(1);
57
+ }
58
+ }
59
+ async function getESVPBaseResult(serverUrl) {
60
+ const { getESVPConnection } = await import("./esvp-GSISVXLC.js");
61
+ const connection = await getESVPConnection(serverUrl);
62
+ return {
63
+ serverUrl: connection.serverUrl,
64
+ connectionMode: connection.mode
65
+ };
66
+ }
67
+ function executorToPlatform(executor) {
68
+ if (executor === "ios-sim" || executor === "maestro-ios") return "ios";
69
+ if (executor === "adb") return "android";
70
+ return void 0;
71
+ }
72
+ var esvp = program.command("esvp").description("Access the public ESVP protocol and runtime from the CLI");
73
+ esvp.command("status").description("Check the configured ESVP server health").option("-s, --server <url>", "ESVP base URL").action(async (options) => {
74
+ await withESVPCli(async () => {
75
+ const { getESVPHealth } = await import("./esvp-GSISVXLC.js");
76
+ return {
77
+ ...await getESVPBaseResult(options.server),
78
+ health: await getESVPHealth(options.server)
79
+ };
80
+ });
81
+ });
82
+ esvp.command("devices").description("List ESVP-visible devices").option("-s, --server <url>", "ESVP base URL").option("-p, --platform <platform>", "adb | ios-sim | maestro-ios | all", "all").action(async (options) => {
83
+ await withESVPCli(async () => {
84
+ const { listESVPDevices } = await import("./esvp-GSISVXLC.js");
85
+ return {
86
+ ...await getESVPBaseResult(options.server),
87
+ devices: await listESVPDevices(options.platform, options.server)
88
+ };
89
+ });
90
+ });
91
+ esvp.command("sessions").description("List public ESVP sessions").option("-s, --server <url>", "ESVP base URL").action(async (options) => {
92
+ await withESVPCli(async () => {
93
+ const { listESVPSessions } = await import("./esvp-GSISVXLC.js");
94
+ return {
95
+ ...await getESVPBaseResult(options.server),
96
+ ...await listESVPSessions(options.server)
97
+ };
98
+ });
99
+ });
100
+ esvp.command("create").description("Create a new ESVP session").requiredOption("-e, --executor <executor>", "fake | adb | ios-sim | maestro-ios").option("-s, --server <url>", "ESVP base URL").option("-d, --device-id <id>", "Device or simulator ID").option("--meta-json <json>", "Session metadata as JSON").option("--meta-file <path>", "Path to session metadata JSON").option("--crash-clip-json <json>", "Crash clip config as JSON").option("--crash-clip-file <path>", "Path to crash clip config JSON").option("--with-network", "Auto-configure the default App Lab external-proxy profile after creating the session").action(async (options) => {
101
+ await withESVPCli(async () => {
102
+ const { createESVPSession, configureESVPNetwork } = await import("./esvp-GSISVXLC.js");
103
+ const meta = await readJsonSource(options.metaJson, options.metaFile, "meta");
104
+ const crashClip = await readJsonSource(options.crashClipJson, options.crashClipFile, "crash clip");
105
+ const createResult = await createESVPSession(
106
+ {
107
+ executor: options.executor,
108
+ ...options.deviceId ? { deviceId: options.deviceId } : {},
109
+ ...meta ? { meta } : {},
110
+ ...crashClip ? { crash_clip: crashClip } : {}
111
+ },
112
+ options.server
113
+ );
114
+ let networkConfigured = null;
115
+ if (options.withNetwork) {
116
+ const sessionId = String(createResult?.session?.id || createResult?.id || "");
117
+ if (sessionId) {
118
+ networkConfigured = await configureESVPNetwork(
119
+ sessionId,
120
+ buildAppLabNetworkProfile(
121
+ {
122
+ enabled: true,
123
+ mode: "external-proxy",
124
+ profile: "applab-standard-capture",
125
+ label: "App Lab Standard Capture"
126
+ },
127
+ {
128
+ platform: executorToPlatform(options.executor),
129
+ deviceId: options.deviceId
130
+ }
131
+ ) || {},
132
+ options.server
133
+ ).catch((err) => ({ error: err.message }));
134
+ }
135
+ }
136
+ return {
137
+ ...await getESVPBaseResult(options.server),
138
+ ...createResult,
139
+ ...networkConfigured ? { networkConfigured } : {}
140
+ };
141
+ });
142
+ });
143
+ esvp.command("get <sessionId>").description("Get a public ESVP session summary").option("-s, --server <url>", "ESVP base URL").action(async (sessionId, options) => {
144
+ await withESVPCli(async () => {
145
+ const { getESVPSession } = await import("./esvp-GSISVXLC.js");
146
+ return {
147
+ ...await getESVPBaseResult(options.server),
148
+ ...await getESVPSession(sessionId, options.server)
149
+ };
150
+ });
151
+ });
152
+ esvp.command("inspect <sessionId>").description("Inspect a session and optionally load transcript and artifacts").option("-s, --server <url>", "ESVP base URL").option("--transcript", "Include transcript").option("--artifacts", "Include artifacts").action(async (sessionId, options) => {
153
+ await withESVPCli(async () => {
154
+ const { inspectESVPSession } = await import("./esvp-GSISVXLC.js");
155
+ return {
156
+ ...await getESVPBaseResult(options.server),
157
+ ...await inspectESVPSession(
158
+ sessionId,
159
+ {
160
+ includeTranscript: options.transcript === true,
161
+ includeArtifacts: options.artifacts === true
162
+ },
163
+ options.server
164
+ )
165
+ };
166
+ });
167
+ });
168
+ esvp.command("transcript <sessionId>").description("Fetch the canonical session transcript").option("-s, --server <url>", "ESVP base URL").action(async (sessionId, options) => {
169
+ await withESVPCli(async () => {
170
+ const { getESVPTranscript } = await import("./esvp-GSISVXLC.js");
171
+ return {
172
+ ...await getESVPBaseResult(options.server),
173
+ sessionId,
174
+ transcript: (await getESVPTranscript(sessionId, options.server))?.events || []
175
+ };
176
+ });
177
+ });
178
+ esvp.command("artifacts <sessionId>").description("List session artifacts").option("-s, --server <url>", "ESVP base URL").action(async (sessionId, options) => {
179
+ await withESVPCli(async () => {
180
+ const { listESVPArtifacts } = await import("./esvp-GSISVXLC.js");
181
+ return {
182
+ ...await getESVPBaseResult(options.server),
183
+ sessionId,
184
+ artifacts: (await listESVPArtifacts(sessionId, options.server))?.artifacts || []
185
+ };
186
+ });
187
+ });
188
+ esvp.command("artifact <sessionId> <artifactPath>").description("Read a public artifact payload").option("-s, --server <url>", "ESVP base URL").action(async (sessionId, artifactPath, options) => {
189
+ await withESVPCli(async () => {
190
+ const { getESVPArtifactContent } = await import("./esvp-GSISVXLC.js");
191
+ return await getESVPArtifactContent(sessionId, artifactPath, options.server);
192
+ });
193
+ });
194
+ esvp.command("actions <sessionId>").description("Run public ESVP actions inside a session").option("-s, --server <url>", "ESVP base URL").option("--actions-json <json>", "JSON array of ESVP actions").option("--actions-file <path>", "Path to a JSON file with ESVP actions").option("--finish", "Finish the session after actions").option("--capture-logcat", "Capture logcat on finish when supported").option("--checkpoint-after-each", "Set checkpointAfter on every action").option("--with-network", "Auto-configure the default App Lab external-proxy profile before running actions if not already configured").action(async (sessionId, options) => {
195
+ await withESVPCli(async () => {
196
+ const { runESVPActions, getESVPSessionNetwork, configureESVPNetwork } = await import("./esvp-GSISVXLC.js");
197
+ const actions = await readJsonSource(options.actionsJson, options.actionsFile, "actions");
198
+ if (!Array.isArray(actions) || actions.length === 0) {
199
+ failCli("Provide --actions-json or --actions-file with a non-empty array of ESVP actions.");
200
+ }
201
+ let networkConfigured = null;
202
+ if (options.withNetwork) {
203
+ const networkState = await getESVPSessionNetwork(sessionId, options.server).catch(() => null);
204
+ const hasActiveProfile = networkState?.network?.active_profile || networkState?.network?.effective_profile;
205
+ if (!hasActiveProfile) {
206
+ networkConfigured = await configureESVPNetwork(
207
+ sessionId,
208
+ buildAppLabNetworkProfile(
209
+ {
210
+ enabled: true,
211
+ mode: "external-proxy",
212
+ profile: "applab-standard-capture",
213
+ label: "App Lab Standard Capture"
214
+ },
215
+ {
216
+ platform: executorToPlatform(typeof networkState?.session?.executor === "string" ? networkState.session.executor : void 0),
217
+ deviceId: typeof networkState?.session?.device_id === "string" ? networkState.session.device_id : void 0
218
+ }
219
+ ) || {},
220
+ options.server
221
+ ).catch((err) => ({ error: err.message }));
222
+ }
223
+ }
224
+ return {
225
+ ...await getESVPBaseResult(options.server),
226
+ ...networkConfigured ? { networkConfigured } : {},
227
+ ...await runESVPActions(
228
+ sessionId,
229
+ {
230
+ actions,
231
+ finish: options.finish === true,
232
+ captureLogcat: options.captureLogcat === true,
233
+ checkpointAfterEach: options.checkpointAfterEach === true
234
+ },
235
+ options.server
236
+ )
237
+ };
238
+ });
239
+ });
240
+ esvp.command("checkpoint <sessionId>").description("Capture an ESVP checkpoint").option("-s, --server <url>", "ESVP base URL").option("-l, --label <label>", "Checkpoint label").action(async (sessionId, options) => {
241
+ await withESVPCli(async () => {
242
+ const { captureESVPCheckpoint } = await import("./esvp-GSISVXLC.js");
243
+ return {
244
+ ...await getESVPBaseResult(options.server),
245
+ ...await captureESVPCheckpoint(
246
+ sessionId,
247
+ {
248
+ ...options.label ? { label: options.label } : {}
249
+ },
250
+ options.server
251
+ )
252
+ };
253
+ });
254
+ });
255
+ esvp.command("finish <sessionId>").description("Finish an ESVP session").option("-s, --server <url>", "ESVP base URL").option("--capture-logcat", "Capture logcat on finish when supported").action(async (sessionId, options) => {
256
+ await withESVPCli(async () => {
257
+ const { finishESVPSession } = await import("./esvp-GSISVXLC.js");
258
+ return {
259
+ ...await getESVPBaseResult(options.server),
260
+ ...await finishESVPSession(
261
+ sessionId,
262
+ {
263
+ captureLogcat: options.captureLogcat === true
264
+ },
265
+ options.server
266
+ )
267
+ };
268
+ });
269
+ });
270
+ esvp.command("preflight <sessionId>").description("Run preflight/bootstrap rules on an ESVP session").option("-s, --server <url>", "ESVP base URL").option("--policy <policy>", "Preflight policy name (e.g. fresh_install)").option("--app-id <appId>", "Target app ID").option("--json <json>", "Preflight config as JSON string").option("--file <path>", "Path to preflight config JSON file").action(async (sessionId, options) => {
271
+ await withESVPCli(async () => {
272
+ const { runESVPPreflight } = await import("./esvp-GSISVXLC.js");
273
+ const fromSource = await readJsonSource(options.json, options.file, "preflight config");
274
+ const config = {
275
+ ...typeof fromSource === "object" && fromSource ? fromSource : {},
276
+ ...options.policy ? { policy: options.policy } : {},
277
+ ...options.appId ? { appId: options.appId } : {}
278
+ };
279
+ return {
280
+ ...await getESVPBaseResult(options.server),
281
+ ...await runESVPPreflight(sessionId, config, options.server)
282
+ };
283
+ });
284
+ });
285
+ esvp.command("replay-run <sessionId>").description("Replay a session to a new ESVP session").option("-s, --server <url>", "ESVP base URL").option("-e, --executor <executor>", "fake | adb | ios-sim | maestro-ios").option("-d, --device-id <id>", "Replay target device ID").option("--capture-logcat", "Capture logcat on finish when supported").option("--meta-json <json>", "Replay metadata as JSON").option("--meta-file <path>", "Path to replay metadata JSON").action(async (sessionId, options) => {
286
+ await withESVPCli(async () => {
287
+ const { replayESVPSession, getESVPReplayConsistency } = await import("./esvp-GSISVXLC.js");
288
+ const meta = await readJsonSource(options.metaJson, options.metaFile, "replay meta");
289
+ const replay = await replayESVPSession(
290
+ sessionId,
291
+ {
292
+ ...options.executor ? { executor: options.executor } : {},
293
+ ...options.deviceId ? { deviceId: options.deviceId } : {},
294
+ ...options.captureLogcat === true ? { captureLogcat: true } : {},
295
+ ...meta ? { meta } : {}
296
+ },
297
+ options.server
298
+ );
299
+ const replaySessionId = replay?.replay_session?.id;
300
+ const replayConsistency = replaySessionId ? (await getESVPReplayConsistency(replaySessionId, options.server)).replay_consistency : null;
301
+ return {
302
+ ...await getESVPBaseResult(options.server),
303
+ ...replay,
304
+ replayConsistency
305
+ };
306
+ });
307
+ });
308
+ esvp.command("replay-validate <sessionId>").description("Validate whether a session supports public replay").option("-s, --server <url>", "ESVP base URL").action(async (sessionId, options) => {
309
+ await withESVPCli(async () => {
310
+ const { validateESVPReplay } = await import("./esvp-GSISVXLC.js");
311
+ return {
312
+ ...await getESVPBaseResult(options.server),
313
+ ...await validateESVPReplay(sessionId, options.server)
314
+ };
315
+ });
316
+ });
317
+ esvp.command("replay-consistency <sessionId>").description("Inspect replay consistency for a replay session").option("-s, --server <url>", "ESVP base URL").action(async (sessionId, options) => {
318
+ await withESVPCli(async () => {
319
+ const { getESVPReplayConsistency } = await import("./esvp-GSISVXLC.js");
320
+ return {
321
+ ...await getESVPBaseResult(options.server),
322
+ ...await getESVPReplayConsistency(sessionId, options.server)
323
+ };
324
+ });
325
+ });
326
+ esvp.command("network <sessionId>").description("Read the public network state for a session").option("-s, --server <url>", "ESVP base URL").action(async (sessionId, options) => {
327
+ await withESVPCli(async () => {
328
+ const { getESVPSessionNetwork } = await import("./esvp-GSISVXLC.js");
329
+ return {
330
+ ...await getESVPBaseResult(options.server),
331
+ ...await getESVPSessionNetwork(sessionId, options.server)
332
+ };
333
+ });
334
+ });
335
+ esvp.command("network-configure <sessionId>").description("Apply a public ESVP network profile").option("-s, --server <url>", "ESVP base URL").option("--json <json>", "Raw network profile JSON").option("--file <path>", "Path to network profile JSON").option("--profile <name>", "Profile name").option("--label <label>", "Profile label").option("--connectivity <state>", "online | offline | reset").action(async (sessionId, options) => {
336
+ await withESVPCli(async () => {
337
+ const { configureESVPNetwork } = await import("./esvp-GSISVXLC.js");
338
+ const payload = await readJsonSource(options.json, options.file, "network profile") || {};
339
+ const merged = {
340
+ ...typeof payload === "object" && payload ? payload : {},
341
+ ...options.profile ? { profile: options.profile } : {},
342
+ ...options.label ? { label: options.label } : {},
343
+ ...options.connectivity ? { connectivity: options.connectivity } : {}
344
+ };
345
+ return {
346
+ ...await getESVPBaseResult(options.server),
347
+ ...await configureESVPNetwork(sessionId, merged, options.server)
348
+ };
349
+ });
350
+ });
351
+ esvp.command("network-clear <sessionId>").description("Clear the active ESVP network profile").option("-s, --server <url>", "ESVP base URL").action(async (sessionId, options) => {
352
+ await withESVPCli(async () => {
353
+ const { clearESVPNetwork } = await import("./esvp-GSISVXLC.js");
354
+ return {
355
+ ...await getESVPBaseResult(options.server),
356
+ ...await clearESVPNetwork(sessionId, options.server)
357
+ };
358
+ });
359
+ });
360
+ esvp.command("trace-attach <sessionId>").description("Attach a public network trace artifact to a session").requiredOption("--trace-kind <kind>", "Trace kind, e.g. http_trace or har").option("-s, --server <url>", "ESVP base URL").option("--json <json>", "Trace payload JSON").option("--file <path>", "Path to trace payload JSON/text").option("--label <label>", "Trace label").option("--source <source>", "Trace source").option("--request-id <id>", "Correlated request ID").option("--method <method>", "HTTP method").option("--url <url>", "Request URL").option("--status-code <code>", "HTTP status code").option("--format <format>", "Payload format label").action(async (sessionId, options) => {
361
+ await withESVPCli(async () => {
362
+ const { attachESVPNetworkTrace } = await import("./esvp-GSISVXLC.js");
363
+ const payload = await readJsonSource(options.json, options.file, "trace payload");
364
+ if (payload == null) {
365
+ failCli("Provide --json or --file with the trace payload to attach.");
366
+ }
367
+ return {
368
+ ...await getESVPBaseResult(options.server),
369
+ ...await attachESVPNetworkTrace(
370
+ sessionId,
371
+ {
372
+ trace_kind: options.traceKind,
373
+ ...options.label ? { label: options.label } : {},
374
+ ...options.source ? { source: options.source } : {},
375
+ ...options.requestId ? { request_id: options.requestId } : {},
376
+ ...options.method ? { method: options.method } : {},
377
+ ...options.url ? { url: options.url } : {},
378
+ ...options.statusCode ? { status_code: Number(options.statusCode) } : {},
379
+ ...options.format ? { format: options.format } : {},
380
+ payload
381
+ },
382
+ options.server
383
+ )
384
+ };
385
+ });
386
+ });
387
+ program.command("serve").alias("server").description("Start the DiscoveryLab web UI server").option("-p, --port <number>", "Port to listen on", "3847").option("-o, --open", "Open browser automatically", false).action(async (options) => {
10
388
  const port = parseInt(options.port, 10);
11
389
  console.log(chalk.cyan("\n DiscoveryLab"));
12
390
  console.log(chalk.gray(" AI-powered app testing & evidence generator\n"));
13
391
  try {
14
- const { startServer } = await import("./server-JG7UKFGK.js");
392
+ const { startServer } = await import("./server-FO3UVUZU.js");
15
393
  await startServer(port);
16
394
  console.log(chalk.green(` Server running at http://localhost:${port}`));
17
395
  console.log(chalk.gray(" Press Ctrl+C to stop\n"));
@@ -26,7 +404,7 @@ program.command("serve").description("Start the DiscoveryLab web UI server").opt
26
404
  program.command("setup").description("Check and configure DiscoveryLab dependencies").action(async () => {
27
405
  console.log(chalk.cyan("\n DiscoveryLab Setup\n"));
28
406
  try {
29
- const { setupStatusTool } = await import("./setup-AQX4JQVR.js");
407
+ const { setupStatusTool } = await import("./setup-2SQC5UHJ.js");
30
408
  const result = await setupStatusTool.handler({});
31
409
  if (result.isError) {
32
410
  console.error(chalk.red(" Setup check failed"));
@@ -62,7 +440,7 @@ program.command("setup").description("Check and configure DiscoveryLab dependenc
62
440
  program.command("init").description("Initialize DiscoveryLab data directories").action(async () => {
63
441
  console.log(chalk.cyan("\n Initializing DiscoveryLab...\n"));
64
442
  try {
65
- const { getDatabase, DATA_DIR, PROJECTS_DIR, EXPORTS_DIR } = await import("./db-ADBEBNH6.js");
443
+ const { getDatabase, DATA_DIR, PROJECTS_DIR, EXPORTS_DIR } = await import("./db-6WLEVKUV.js");
66
444
  getDatabase();
67
445
  console.log(chalk.green(" Created directories:"));
68
446
  console.log(chalk.gray(` ${DATA_DIR}`));
@@ -108,10 +486,22 @@ program.command("install").description("Install DiscoveryLab as Claude Code MCP
108
486
  });
109
487
  program.command("mcp").description("Run as MCP server (for Claude Code integration)").action(async () => {
110
488
  try {
111
- const { getDatabase } = await import("./db-ADBEBNH6.js");
489
+ const { getDatabase } = await import("./db-6WLEVKUV.js");
112
490
  getDatabase();
113
- const { mcpServer } = await import("./server-3FBHBA7L.js");
114
- const { uiTools, projectTools, setupTools, captureTools, analyzeTools, canvasTools, exportTools, testingTools, integrationTools } = await import("./tools-N5N2IO7V.js");
491
+ const { mcpServer } = await import("./server-6N3KIEGP.js");
492
+ const {
493
+ uiTools,
494
+ projectTools,
495
+ setupTools,
496
+ captureTools,
497
+ analyzeTools,
498
+ canvasTools,
499
+ exportTools,
500
+ testingTools,
501
+ integrationTools,
502
+ taskHubTools,
503
+ esvpTools
504
+ } = await import("./tools-OCRMOQ4U.js");
115
505
  mcpServer.registerTools([
116
506
  ...uiTools,
117
507
  ...projectTools,
@@ -121,7 +511,9 @@ program.command("mcp").description("Run as MCP server (for Claude Code integrati
121
511
  ...canvasTools,
122
512
  ...exportTools,
123
513
  ...testingTools,
124
- ...integrationTools
514
+ ...integrationTools,
515
+ ...taskHubTools,
516
+ ...esvpTools
125
517
  ]);
126
518
  await mcpServer.runStdio();
127
519
  } catch (error) {
@@ -130,11 +522,13 @@ program.command("mcp").description("Run as MCP server (for Claude Code integrati
130
522
  }
131
523
  });
132
524
  program.command("info").description("Show version and configuration info").action(async () => {
133
- console.log(chalk.cyan("\n DiscoveryLab v0.1.0\n"));
525
+ console.log(chalk.cyan(`
526
+ DiscoveryLab v${APP_VERSION}
527
+ `));
134
528
  console.log(chalk.gray(" AI-powered app testing & evidence generator"));
135
529
  console.log(chalk.gray(" Claude Code Plugin\n"));
136
530
  try {
137
- const { DATA_DIR, DB_PATH } = await import("./db-ADBEBNH6.js");
531
+ const { DATA_DIR, DB_PATH } = await import("./db-6WLEVKUV.js");
138
532
  console.log(chalk.white(" Paths:"));
139
533
  console.log(chalk.gray(` Data: ${DATA_DIR}`));
140
534
  console.log(chalk.gray(` Database: ${DB_PATH}`));
@@ -4,6 +4,7 @@ import {
4
4
  EXPORTS_DIR,
5
5
  FRAMES_DIR,
6
6
  PROJECTS_DIR,
7
+ TEMPLATES_DIR,
7
8
  closeDatabase,
8
9
  exportDestinations,
9
10
  exportRules,
@@ -14,7 +15,7 @@ import {
14
15
  projects,
15
16
  settings,
16
17
  testVariables
17
- } from "./chunk-TJ3H23LL.js";
18
+ } from "./chunk-VVIOB362.js";
18
19
  import "./chunk-MLKGABMK.js";
19
20
  export {
20
21
  DATA_DIR,
@@ -22,6 +23,7 @@ export {
22
23
  EXPORTS_DIR,
23
24
  FRAMES_DIR,
24
25
  PROJECTS_DIR,
26
+ TEMPLATES_DIR,
25
27
  closeDatabase,
26
28
  exportDestinations,
27
29
  exportRules,
@@ -0,0 +1,52 @@
1
+ import {
2
+ attachESVPNetworkTrace,
3
+ captureESVPCheckpoint,
4
+ clearESVPNetwork,
5
+ configureESVPNetwork,
6
+ createESVPSession,
7
+ finishESVPSession,
8
+ getESVPArtifactContent,
9
+ getESVPBaseUrl,
10
+ getESVPConnection,
11
+ getESVPHealth,
12
+ getESVPReplayConsistency,
13
+ getESVPSession,
14
+ getESVPSessionNetwork,
15
+ getESVPTranscript,
16
+ inspectESVPSession,
17
+ listESVPArtifacts,
18
+ listESVPDevices,
19
+ listESVPSessions,
20
+ replayESVPSession,
21
+ resolveESVPBaseUrl,
22
+ runESVPActions,
23
+ runESVPPreflight,
24
+ validateESVPReplay
25
+ } from "./chunk-GAKEFJ5T.js";
26
+ import "./chunk-VVIOB362.js";
27
+ import "./chunk-MLKGABMK.js";
28
+ export {
29
+ attachESVPNetworkTrace,
30
+ captureESVPCheckpoint,
31
+ clearESVPNetwork,
32
+ configureESVPNetwork,
33
+ createESVPSession,
34
+ finishESVPSession,
35
+ getESVPArtifactContent,
36
+ getESVPBaseUrl,
37
+ getESVPConnection,
38
+ getESVPHealth,
39
+ getESVPReplayConsistency,
40
+ getESVPSession,
41
+ getESVPSessionNetwork,
42
+ getESVPTranscript,
43
+ inspectESVPSession,
44
+ listESVPArtifacts,
45
+ listESVPDevices,
46
+ listESVPSessions,
47
+ replayESVPSession,
48
+ resolveESVPBaseUrl,
49
+ runESVPActions,
50
+ runESVPPreflight,
51
+ validateESVPReplay
52
+ };
@@ -0,0 +1,20 @@
1
+ import {
2
+ collectESVPSessionNetworkData,
3
+ createMobileNetworkCaptureMeta,
4
+ diagnoseESVPNetworkState,
5
+ translateMaestroActionsToESVP,
6
+ validateMaestroRecordingWithESVP
7
+ } from "./chunk-N6JJ2RGV.js";
8
+ import "./chunk-LB3RNE3O.js";
9
+ import "./chunk-GAKEFJ5T.js";
10
+ import "./chunk-SLNJEF32.js";
11
+ import "./chunk-VVIOB362.js";
12
+ import "./chunk-XFVDP332.js";
13
+ import "./chunk-MLKGABMK.js";
14
+ export {
15
+ collectESVPSessionNetworkData,
16
+ createMobileNetworkCaptureMeta,
17
+ diagnoseESVPNetworkState,
18
+ translateMaestroActionsToESVP,
19
+ validateMaestroRecordingWithESVP
20
+ };