@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
@@ -0,0 +1,30 @@
1
+ // src/core/appVersion.ts
2
+ import { existsSync, readFileSync } from "fs";
3
+ import { dirname, join } from "path";
4
+ import { fileURLToPath } from "url";
5
+ function findPackageVersion() {
6
+ const moduleDir = dirname(fileURLToPath(import.meta.url));
7
+ const searchRoots = [
8
+ moduleDir,
9
+ dirname(moduleDir),
10
+ dirname(dirname(moduleDir)),
11
+ dirname(dirname(dirname(moduleDir)))
12
+ ];
13
+ for (const root of searchRoots) {
14
+ const packageJsonPath = join(root, "package.json");
15
+ if (!existsSync(packageJsonPath)) continue;
16
+ try {
17
+ const pkg = JSON.parse(readFileSync(packageJsonPath, "utf8"));
18
+ if (typeof pkg.version === "string" && pkg.version.trim()) {
19
+ return pkg.version.trim();
20
+ }
21
+ } catch {
22
+ }
23
+ }
24
+ return "0.0.0";
25
+ }
26
+ var APP_VERSION = findPackageVersion();
27
+
28
+ export {
29
+ APP_VERSION
30
+ };
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-SLNJEF32.js";
4
4
  import {
5
5
  PROJECTS_DIR
6
- } from "./chunk-VY3BLXBW.js";
6
+ } from "./chunk-VVIOB362.js";
7
7
 
8
8
  // src/core/testing/playwright.ts
9
9
  import { exec, spawn } from "child_process";
@@ -234,7 +234,8 @@ async function runPlaywrightTest(options) {
234
234
  project,
235
235
  workers = 1,
236
236
  retries = 0,
237
- reporter = "json"
237
+ reporter = "json",
238
+ env = {}
238
239
  } = options;
239
240
  await fs.promises.mkdir(outputDir, { recursive: true });
240
241
  const startTime = Date.now();
@@ -263,7 +264,8 @@ async function runPlaywrightTest(options) {
263
264
  try {
264
265
  const { stdout, stderr } = await execAsync(`npx ${args.join(" ")}`, {
265
266
  timeout: config.timeout || 3e5,
266
- cwd: process.cwd()
267
+ cwd: process.cwd(),
268
+ env: { ...process.env, ...env }
267
269
  });
268
270
  const duration = Date.now() - startTime;
269
271
  let passed = 0;
@@ -1,11 +1,11 @@
1
- import {
2
- DATA_DIR,
3
- DB_PATH
4
- } from "./chunk-TJ3H23LL.js";
5
1
  import {
6
2
  createJsonResult,
7
3
  createTextResult
8
- } from "./chunk-QJXXHOV7.js";
4
+ } from "./chunk-XKX6NBHF.js";
5
+ import {
6
+ DATA_DIR,
7
+ DB_PATH
8
+ } from "./chunk-VVIOB362.js";
9
9
 
10
10
  // src/mcp/tools/setup.ts
11
11
  import { z } from "zod";
@@ -224,7 +224,7 @@ var setupInitTool = {
224
224
  inputSchema: z.object({}),
225
225
  handler: async () => {
226
226
  try {
227
- const { getDatabase, DATA_DIR: DATA_DIR2, PROJECTS_DIR, EXPORTS_DIR, FRAMES_DIR } = await import("./db-ADBEBNH6.js");
227
+ const { getDatabase, DATA_DIR: DATA_DIR2, PROJECTS_DIR, EXPORTS_DIR, FRAMES_DIR } = await import("./db-6WLEVKUV.js");
228
228
  getDatabase();
229
229
  return createJsonResult({
230
230
  message: "DiscoveryLab initialized successfully",
@@ -0,0 +1,481 @@
1
+ import {
2
+ DATA_DIR
3
+ } from "./chunk-VVIOB362.js";
4
+
5
+ // src/core/integrations/esvp-local.ts
6
+ import { existsSync } from "fs";
7
+ import { dirname, join, resolve } from "path";
8
+ import { fileURLToPath, pathToFileURL } from "url";
9
+ var localServerPromise = null;
10
+ var cleanupRegistered = false;
11
+ var activeLocalServer = null;
12
+ async function resolveESVPConnection(serverUrl) {
13
+ const explicit = typeof serverUrl === "string" && serverUrl.trim() ? normalizeBaseUrl(serverUrl) : null;
14
+ if (explicit) {
15
+ return {
16
+ mode: "remote",
17
+ serverUrl: explicit
18
+ };
19
+ }
20
+ const envUrl = typeof process.env.ESVP_BASE_URL === "string" && process.env.ESVP_BASE_URL.trim() ? normalizeBaseUrl(process.env.ESVP_BASE_URL) : null;
21
+ if (envUrl) {
22
+ return {
23
+ mode: "remote",
24
+ serverUrl: envUrl
25
+ };
26
+ }
27
+ if (!localServerPromise) {
28
+ localServerPromise = startEmbeddedLocalServer().catch((error) => {
29
+ localServerPromise = null;
30
+ throw error;
31
+ });
32
+ }
33
+ return localServerPromise;
34
+ }
35
+ function normalizeBaseUrl(value) {
36
+ return value.trim().replace(/\/+$/, "");
37
+ }
38
+ async function startEmbeddedLocalServer() {
39
+ const runtime = await loadLocalRuntimeModule();
40
+ const rootDir = join(DATA_DIR, "esvp-local");
41
+ const started = await runtime.startServer({
42
+ host: "127.0.0.1",
43
+ port: 0,
44
+ rootDir
45
+ });
46
+ activeLocalServer = {
47
+ startResult: started,
48
+ runtime
49
+ };
50
+ if (!cleanupRegistered) {
51
+ cleanupRegistered = true;
52
+ const cleanup = async () => {
53
+ try {
54
+ await stopEmbeddedESVPServer();
55
+ } catch {
56
+ }
57
+ };
58
+ process.once("beforeExit", () => {
59
+ void cleanup();
60
+ });
61
+ process.once("SIGINT", () => {
62
+ void cleanup().finally(() => process.exit(0));
63
+ });
64
+ process.once("SIGTERM", () => {
65
+ void cleanup().finally(() => process.exit(0));
66
+ });
67
+ process.once("uncaughtException", (error) => {
68
+ void cleanup().finally(() => {
69
+ console.error("[esvp-local] uncaught exception after proxy cleanup:", error);
70
+ process.exit(1);
71
+ });
72
+ });
73
+ process.once("unhandledRejection", (reason) => {
74
+ void cleanup().finally(() => {
75
+ console.error("[esvp-local] unhandled rejection after proxy cleanup:", reason);
76
+ process.exit(1);
77
+ });
78
+ });
79
+ }
80
+ return {
81
+ mode: "local",
82
+ serverUrl: normalizeBaseUrl(started.url)
83
+ };
84
+ }
85
+ async function stopEmbeddedESVPServer() {
86
+ const current = activeLocalServer;
87
+ activeLocalServer = null;
88
+ localServerPromise = null;
89
+ if (!current) return;
90
+ const manager = current.startResult.manager;
91
+ if (manager && typeof manager.cleanupIosSimProxies === "function") {
92
+ try {
93
+ await manager.cleanupIosSimProxies();
94
+ } catch {
95
+ }
96
+ }
97
+ if (current.runtime.stopServer) {
98
+ await current.runtime.stopServer(current.startResult);
99
+ return;
100
+ }
101
+ await new Promise((resolveClose, rejectClose) => {
102
+ current.startResult.server.close((error) => {
103
+ if (error) {
104
+ rejectClose(error);
105
+ return;
106
+ }
107
+ resolveClose();
108
+ });
109
+ });
110
+ }
111
+ async function loadLocalRuntimeModule() {
112
+ const explicitModulePath = process.env.DISCOVERYLAB_ESVP_LOCAL_MODULE?.trim();
113
+ const candidates = explicitModulePath ? [explicitModulePath] : ["@entropylab/esvp-local", ...discoverWorkspaceRuntimeCandidates()];
114
+ let lastError = null;
115
+ for (const candidate of candidates) {
116
+ try {
117
+ const module = await dynamicImport(resolveModuleSpecifier(candidate));
118
+ if (typeof module.startServer === "function") {
119
+ return module;
120
+ }
121
+ throw new Error(`M\xF3dulo ${candidate} n\xE3o exporta startServer()`);
122
+ } catch (error) {
123
+ lastError = error;
124
+ }
125
+ }
126
+ throw new Error(
127
+ [
128
+ "ESVP local n\xE3o dispon\xEDvel.",
129
+ "Instale o pacote p\xFAblico @entropylab/esvp-local, mantenha o entropy-poc acess\xEDvel no workspace, ou defina DISCOVERYLAB_ESVP_LOCAL_MODULE com o caminho do server.js do runtime local.",
130
+ lastError instanceof Error ? `Detalhe: ${lastError.message}` : null
131
+ ].filter(Boolean).join(" ")
132
+ );
133
+ }
134
+ function discoverWorkspaceRuntimeCandidates() {
135
+ const seen = /* @__PURE__ */ new Set();
136
+ const roots = [process.cwd(), dirname(fileURLToPath(import.meta.url))];
137
+ const suffixes = [
138
+ ["esvp-server-reference", "server.js"],
139
+ ["entropy-poc", "esvp-server-reference", "server.js"],
140
+ ["entropy", "entropy-poc", "esvp-server-reference", "server.js"]
141
+ ];
142
+ const candidates = [];
143
+ for (const root of roots) {
144
+ let current = resolve(root);
145
+ for (let depth = 0; depth < 6; depth += 1) {
146
+ for (const suffix of suffixes) {
147
+ const candidate = join(current, ...suffix);
148
+ if (existsSync(candidate) && !seen.has(candidate)) {
149
+ seen.add(candidate);
150
+ candidates.push(candidate);
151
+ }
152
+ }
153
+ const parent = dirname(current);
154
+ if (parent === current) break;
155
+ current = parent;
156
+ }
157
+ }
158
+ return candidates;
159
+ }
160
+ function resolveModuleSpecifier(value) {
161
+ if (value.startsWith(".") || value.startsWith("/") || value.startsWith("file://")) {
162
+ return value.startsWith("file://") ? value : pathToFileURL(resolve(process.cwd(), value)).href;
163
+ }
164
+ return value;
165
+ }
166
+ async function dynamicImport(specifier) {
167
+ return Function("specifier", "return import(specifier)")(specifier);
168
+ }
169
+
170
+ // src/core/integrations/esvp.ts
171
+ var DEFAULT_ESVP_BASE_URL = "http://127.0.0.1:8787";
172
+ var DEFAULT_ESVP_REQUEST_TIMEOUT_MS = 2e4;
173
+ var LONG_RUNNING_ESVP_REQUEST_TIMEOUT_MS = 12e4;
174
+ function normalizeBaseUrl2(serverUrl) {
175
+ const raw = (serverUrl || process.env.ESVP_BASE_URL || DEFAULT_ESVP_BASE_URL).trim();
176
+ return raw.replace(/\/+$/, "");
177
+ }
178
+ async function resolveBaseUrl(serverUrl) {
179
+ return resolveESVPConnection(serverUrl);
180
+ }
181
+ async function readJsonSafe(response) {
182
+ const text = await response.text();
183
+ if (!text.trim()) return null;
184
+ try {
185
+ return JSON.parse(text);
186
+ } catch {
187
+ return { raw: text };
188
+ }
189
+ }
190
+ async function readResponseContent(response) {
191
+ const contentType = (response.headers.get("content-type") || "").toLowerCase();
192
+ const text = await response.text();
193
+ if (!text.trim()) return null;
194
+ if (contentType.includes("json")) {
195
+ try {
196
+ return JSON.parse(text);
197
+ } catch {
198
+ return text;
199
+ }
200
+ }
201
+ try {
202
+ return JSON.parse(text);
203
+ } catch {
204
+ return text;
205
+ }
206
+ }
207
+ async function esvpRequest(path, init = {}, serverUrl, timeoutMs = DEFAULT_ESVP_REQUEST_TIMEOUT_MS) {
208
+ const controller = new AbortController();
209
+ const timeout = setTimeout(() => controller.abort(), timeoutMs);
210
+ try {
211
+ const connection = await resolveBaseUrl(serverUrl);
212
+ const response = await fetch(`${connection.serverUrl}${path}`, {
213
+ ...init,
214
+ headers: {
215
+ "content-type": "application/json",
216
+ ...init.headers || {}
217
+ },
218
+ signal: controller.signal
219
+ });
220
+ const payload = await readJsonSafe(response);
221
+ if (!response.ok) {
222
+ const message = payload?.error || payload?.message || `ESVP request failed (${response.status} ${response.statusText})`;
223
+ throw new Error(message);
224
+ }
225
+ return payload;
226
+ } catch (error) {
227
+ if (error instanceof DOMException && error.name === "AbortError") {
228
+ throw new Error(`ESVP request timed out after ${timeoutMs}ms: ${path}`);
229
+ }
230
+ if (error instanceof TypeError) {
231
+ throw new Error(`ESVP connection failed: ${error.message}`);
232
+ }
233
+ throw error;
234
+ } finally {
235
+ clearTimeout(timeout);
236
+ }
237
+ }
238
+ function getESVPBaseUrl(serverUrl) {
239
+ return normalizeBaseUrl2(serverUrl);
240
+ }
241
+ async function resolveESVPBaseUrl(serverUrl) {
242
+ const connection = await resolveBaseUrl(serverUrl);
243
+ return connection.serverUrl;
244
+ }
245
+ async function getESVPConnection(serverUrl) {
246
+ return resolveBaseUrl(serverUrl);
247
+ }
248
+ async function getESVPHealth(serverUrl) {
249
+ return esvpRequest("/health", { method: "GET" }, serverUrl);
250
+ }
251
+ async function listESVPSessions(serverUrl) {
252
+ return esvpRequest("/sessions", { method: "GET" }, serverUrl);
253
+ }
254
+ async function createESVPSession(input, serverUrl) {
255
+ return esvpRequest(
256
+ "/sessions",
257
+ {
258
+ method: "POST",
259
+ body: JSON.stringify(input)
260
+ },
261
+ serverUrl
262
+ );
263
+ }
264
+ async function getESVPSession(sessionId, serverUrl) {
265
+ return esvpRequest(`/sessions/${encodeURIComponent(sessionId)}`, { method: "GET" }, serverUrl);
266
+ }
267
+ async function getESVPTranscript(sessionId, serverUrl) {
268
+ return esvpRequest(
269
+ `/sessions/${encodeURIComponent(sessionId)}/transcript`,
270
+ { method: "GET" },
271
+ serverUrl
272
+ );
273
+ }
274
+ async function listESVPArtifacts(sessionId, serverUrl) {
275
+ return esvpRequest(
276
+ `/sessions/${encodeURIComponent(sessionId)}/artifacts`,
277
+ { method: "GET" },
278
+ serverUrl
279
+ );
280
+ }
281
+ async function runESVPActions(sessionId, input, serverUrl) {
282
+ return esvpRequest(
283
+ `/sessions/${encodeURIComponent(sessionId)}/actions`,
284
+ {
285
+ method: "POST",
286
+ body: JSON.stringify(input)
287
+ },
288
+ serverUrl,
289
+ LONG_RUNNING_ESVP_REQUEST_TIMEOUT_MS
290
+ );
291
+ }
292
+ async function finishESVPSession(sessionId, input = {}, serverUrl) {
293
+ return esvpRequest(
294
+ `/sessions/${encodeURIComponent(sessionId)}/finish`,
295
+ {
296
+ method: "POST",
297
+ body: JSON.stringify(input)
298
+ },
299
+ serverUrl
300
+ );
301
+ }
302
+ async function runESVPPreflight(sessionId, config, serverUrl) {
303
+ return esvpRequest(
304
+ `/sessions/${encodeURIComponent(sessionId)}/preflight`,
305
+ { method: "POST", body: JSON.stringify(config) },
306
+ serverUrl,
307
+ LONG_RUNNING_ESVP_REQUEST_TIMEOUT_MS
308
+ );
309
+ }
310
+ async function inspectESVPSession(sessionId, input = {}, serverUrl) {
311
+ const [session, transcript, artifacts] = await Promise.all([
312
+ getESVPSession(sessionId, serverUrl),
313
+ input.includeTranscript === true ? esvpRequest(
314
+ `/sessions/${encodeURIComponent(sessionId)}/transcript`,
315
+ { method: "GET" },
316
+ serverUrl
317
+ ) : Promise.resolve(null),
318
+ input.includeArtifacts === true ? esvpRequest(
319
+ `/sessions/${encodeURIComponent(sessionId)}/artifacts`,
320
+ { method: "GET" },
321
+ serverUrl
322
+ ) : Promise.resolve(null)
323
+ ]);
324
+ return {
325
+ session: session?.session || session,
326
+ transcript: transcript?.events || null,
327
+ artifacts: artifacts?.artifacts || null
328
+ };
329
+ }
330
+ async function getESVPArtifactContent(sessionId, artifactPath, serverUrl) {
331
+ const controller = new AbortController();
332
+ const timeout = setTimeout(() => controller.abort(), 2e4);
333
+ try {
334
+ const connection = await resolveBaseUrl(serverUrl);
335
+ const response = await fetch(
336
+ `${connection.serverUrl}/sessions/${encodeURIComponent(sessionId)}/artifacts/${artifactPath.split("/").map((part) => encodeURIComponent(part)).join("/")}`,
337
+ {
338
+ method: "GET",
339
+ signal: controller.signal
340
+ }
341
+ );
342
+ const payload = await readResponseContent(response);
343
+ if (!response.ok) {
344
+ const message = (payload && typeof payload === "object" ? payload.error || payload.message : null) || `ESVP artifact request failed (${response.status} ${response.statusText})`;
345
+ throw new Error(String(message));
346
+ }
347
+ return payload;
348
+ } finally {
349
+ clearTimeout(timeout);
350
+ }
351
+ }
352
+ async function getESVPSessionNetwork(sessionId, serverUrl) {
353
+ return esvpRequest(`/sessions/${encodeURIComponent(sessionId)}/network`, { method: "GET" }, serverUrl);
354
+ }
355
+ async function replayESVPSession(sessionId, input = {}, serverUrl) {
356
+ return esvpRequest(
357
+ `/sessions/${encodeURIComponent(sessionId)}/replay-run`,
358
+ {
359
+ method: "POST",
360
+ body: JSON.stringify(input)
361
+ },
362
+ serverUrl,
363
+ LONG_RUNNING_ESVP_REQUEST_TIMEOUT_MS
364
+ );
365
+ }
366
+ async function getESVPReplayConsistency(sessionId, serverUrl) {
367
+ return esvpRequest(`/sessions/${encodeURIComponent(sessionId)}/replay-consistency`, { method: "GET" }, serverUrl);
368
+ }
369
+ async function validateESVPReplay(sessionId, serverUrl) {
370
+ const controller = new AbortController();
371
+ const timeout = setTimeout(() => controller.abort(), LONG_RUNNING_ESVP_REQUEST_TIMEOUT_MS);
372
+ try {
373
+ const connection = await resolveBaseUrl(serverUrl);
374
+ const response = await fetch(`${connection.serverUrl}/sessions/${encodeURIComponent(sessionId)}/replay-validate`, {
375
+ method: "POST",
376
+ headers: {
377
+ "content-type": "application/json"
378
+ },
379
+ body: JSON.stringify({}),
380
+ signal: controller.signal
381
+ });
382
+ const payload = await readJsonSafe(response);
383
+ if (!response.ok && ![409, 422].includes(response.status)) {
384
+ const message = payload?.error || payload?.message || `ESVP replay validation failed (${response.status} ${response.statusText})`;
385
+ throw new Error(message);
386
+ }
387
+ return {
388
+ http_status: response.status,
389
+ ...payload && typeof payload === "object" ? payload : { payload }
390
+ };
391
+ } finally {
392
+ clearTimeout(timeout);
393
+ }
394
+ }
395
+ async function captureESVPCheckpoint(sessionId, input = {}, serverUrl) {
396
+ return esvpRequest(
397
+ `/sessions/${encodeURIComponent(sessionId)}/checkpoint`,
398
+ {
399
+ method: "POST",
400
+ body: JSON.stringify(input)
401
+ },
402
+ serverUrl
403
+ );
404
+ }
405
+ async function configureESVPNetwork(sessionId, input, serverUrl) {
406
+ return esvpRequest(
407
+ `/sessions/${encodeURIComponent(sessionId)}/network/profile`,
408
+ {
409
+ method: "POST",
410
+ body: JSON.stringify(input)
411
+ },
412
+ serverUrl
413
+ );
414
+ }
415
+ async function clearESVPNetwork(sessionId, serverUrl) {
416
+ return esvpRequest(
417
+ `/sessions/${encodeURIComponent(sessionId)}/network/clear`,
418
+ {
419
+ method: "POST",
420
+ body: JSON.stringify({})
421
+ },
422
+ serverUrl
423
+ );
424
+ }
425
+ async function attachESVPNetworkTrace(sessionId, input, serverUrl) {
426
+ return esvpRequest(
427
+ `/sessions/${encodeURIComponent(sessionId)}/network/trace`,
428
+ {
429
+ method: "POST",
430
+ body: JSON.stringify(input)
431
+ },
432
+ serverUrl
433
+ );
434
+ }
435
+ async function listESVPDevices(platform = "all", serverUrl) {
436
+ if (platform === "adb") {
437
+ return esvpRequest("/devices/adb", { method: "GET" }, serverUrl);
438
+ }
439
+ if (platform === "ios-sim") {
440
+ return esvpRequest("/devices/ios-sim", { method: "GET" }, serverUrl);
441
+ }
442
+ if (platform === "maestro-ios") {
443
+ return esvpRequest("/devices/maestro-ios", { method: "GET" }, serverUrl);
444
+ }
445
+ const [adb, iosSim, maestroIos] = await Promise.all([
446
+ esvpRequest("/devices/adb", { method: "GET" }, serverUrl).catch((error) => ({ error: error instanceof Error ? error.message : String(error), devices: [] })),
447
+ esvpRequest("/devices/ios-sim", { method: "GET" }, serverUrl).catch((error) => ({ error: error instanceof Error ? error.message : String(error), devices: [] })),
448
+ esvpRequest("/devices/maestro-ios", { method: "GET" }, serverUrl).catch((error) => ({ error: error instanceof Error ? error.message : String(error), devices: [] }))
449
+ ]);
450
+ return {
451
+ adb,
452
+ iosSim,
453
+ maestroIos
454
+ };
455
+ }
456
+
457
+ export {
458
+ getESVPBaseUrl,
459
+ resolveESVPBaseUrl,
460
+ getESVPConnection,
461
+ getESVPHealth,
462
+ listESVPSessions,
463
+ createESVPSession,
464
+ getESVPSession,
465
+ getESVPTranscript,
466
+ listESVPArtifacts,
467
+ runESVPActions,
468
+ finishESVPSession,
469
+ runESVPPreflight,
470
+ inspectESVPSession,
471
+ getESVPArtifactContent,
472
+ getESVPSessionNetwork,
473
+ replayESVPSession,
474
+ getESVPReplayConsistency,
475
+ validateESVPReplay,
476
+ captureESVPCheckpoint,
477
+ configureESVPNetwork,
478
+ clearESVPNetwork,
479
+ attachESVPNetworkTrace,
480
+ listESVPDevices
481
+ };
@@ -0,0 +1,109 @@
1
+ // src/core/integrations/esvp-network-profile.ts
2
+ function isObject(value) {
3
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
4
+ }
5
+ function normalizeOptionalString(value) {
6
+ if (typeof value !== "string") return null;
7
+ const normalized = value.trim();
8
+ return normalized ? normalized : null;
9
+ }
10
+ function normalizeOptionalPort(value) {
11
+ const port = Number(value);
12
+ if (!Number.isFinite(port) || port <= 0) return null;
13
+ return Math.round(port);
14
+ }
15
+ function normalizeOptionalBypass(value) {
16
+ if (!Array.isArray(value)) return null;
17
+ const normalized = value.map((entry) => normalizeOptionalString(entry)).filter((entry) => Boolean(entry));
18
+ return normalized.length > 0 ? normalized : null;
19
+ }
20
+ function readExternalProxyPortFromEnv() {
21
+ return normalizeOptionalPort(process.env.DISCOVERYLAB_NETWORK_PROXY_PORT);
22
+ }
23
+ function readExternalProxyHostFromEnv() {
24
+ return normalizeOptionalString(process.env.DISCOVERYLAB_NETWORK_PROXY_HOST);
25
+ }
26
+ function readExternalProxyProtocolFromEnv() {
27
+ return normalizeOptionalString(process.env.DISCOVERYLAB_NETWORK_PROXY_PROTOCOL);
28
+ }
29
+ function readExternalProxyBypassFromEnv() {
30
+ const raw = normalizeOptionalString(process.env.DISCOVERYLAB_NETWORK_PROXY_BYPASS);
31
+ if (!raw) return null;
32
+ const normalized = raw.split(",").map((entry) => entry.trim()).filter(Boolean);
33
+ return normalized.length > 0 ? normalized : null;
34
+ }
35
+ function normalizeAppLabNetworkMode(mode) {
36
+ const normalized = String(mode || "").trim().toLowerCase();
37
+ if (normalized === "managed-proxy") return "managed-proxy";
38
+ if (normalized === "external-mitm") return "external-mitm";
39
+ if (normalized === "app-http-trace") return "app-http-trace";
40
+ return "external-proxy";
41
+ }
42
+ function inferAppLabExternalProxyHost(input) {
43
+ const explicitHost = normalizeOptionalString(input.explicitHost);
44
+ if (explicitHost) return explicitHost;
45
+ const envHost = readExternalProxyHostFromEnv();
46
+ if (envHost) return envHost;
47
+ const platform = String(input.platform || "").trim().toLowerCase();
48
+ if (platform === "ios") return "127.0.0.1";
49
+ if (platform === "android") {
50
+ const deviceId = String(input.deviceId || "").trim();
51
+ if (deviceId.startsWith("emulator-")) return "10.0.2.2";
52
+ }
53
+ return null;
54
+ }
55
+ function resolveAppLabExternalProxy(input) {
56
+ const explicitProxy = isObject(input.proxy) ? input.proxy : null;
57
+ const host = inferAppLabExternalProxyHost({
58
+ platform: input.platform,
59
+ deviceId: input.deviceId,
60
+ explicitHost: explicitProxy?.host
61
+ });
62
+ const port = normalizeOptionalPort(explicitProxy?.port) || readExternalProxyPortFromEnv();
63
+ if (!host || !port) return null;
64
+ const proxy = {
65
+ host,
66
+ port,
67
+ protocol: normalizeOptionalString(explicitProxy?.protocol) || readExternalProxyProtocolFromEnv() || "http"
68
+ };
69
+ const bypass = normalizeOptionalBypass(explicitProxy?.bypass) || readExternalProxyBypassFromEnv();
70
+ if (bypass) proxy.bypass = bypass;
71
+ return proxy;
72
+ }
73
+ function buildAppLabNetworkProfile(input, context) {
74
+ if (!input || input.enabled === false) return null;
75
+ const mode = normalizeAppLabNetworkMode(input.mode);
76
+ const capture = {
77
+ ...isObject(input.capture) ? input.capture : {},
78
+ enabled: true,
79
+ mode: mode === "managed-proxy" ? "esvp-managed-proxy" : mode === "app-http-trace" ? "app-http-trace" : "external-proxy",
80
+ ...mode === "external-mitm" ? { applabMode: "external-mitm" } : {}
81
+ };
82
+ const profile = {
83
+ ...input.profile ? { profile: input.profile } : {},
84
+ ...input.label ? { label: input.label } : {},
85
+ ...input.connectivity ? { connectivity: input.connectivity } : {},
86
+ ...isObject(input.faults) ? { faults: input.faults } : {},
87
+ capture
88
+ };
89
+ if (mode === "managed-proxy" || mode === "app-http-trace") {
90
+ if (isObject(input.proxy)) {
91
+ profile.proxy = input.proxy;
92
+ }
93
+ return profile;
94
+ }
95
+ const resolvedProxy = resolveAppLabExternalProxy({
96
+ platform: context?.platform,
97
+ deviceId: context?.deviceId,
98
+ proxy: isObject(input.proxy) ? input.proxy : null
99
+ });
100
+ if (resolvedProxy) {
101
+ profile.proxy = resolvedProxy;
102
+ }
103
+ return profile;
104
+ }
105
+
106
+ export {
107
+ inferAppLabExternalProxyHost,
108
+ buildAppLabNetworkProfile
109
+ };