@veolab/discoverylab 1.3.2 → 1.3.3
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.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/dist/chunk-7EDIUVIO.js +4304 -0
- package/dist/{chunk-H4FYBUX6.js → chunk-AHVBE25Y.js} +23 -17
- package/dist/chunk-HGWEHWKJ.js +94 -0
- package/dist/{chunk-2RQ7BDPA.js → chunk-LXSWDEXV.js} +276 -56
- package/dist/{chunk-N6JJ2RGV.js → chunk-ZLHIHMSL.js} +1 -1
- package/dist/cli.js +26 -26
- package/dist/{esvp-GSISVXLC.js → esvp-KVOWYW6G.js} +2 -1
- package/dist/{esvp-mobile-GC7MAGMI.js → esvp-mobile-GZ5EMYPG.js} +3 -2
- package/dist/index.d.ts +13 -17
- package/dist/index.html +149 -29
- package/dist/index.js +6 -6
- package/dist/{server-RBJ2VROA.js → server-T5X6GGOO.js} +5 -5
- package/dist/templates/bundle/bundle.js +8 -4
- package/dist/templates/bundle/public/mockup-android-galaxy.png +0 -0
- package/dist/{tools-EYWRLTRB.js → tools-YGM5HRIB.js} +4 -4
- package/package.json +2 -2
- package/dist/chunk-GAKEFJ5T.js +0 -481
- package/dist/chunk-VEIZLLCI.js +0 -1696
|
@@ -3,13 +3,13 @@ import {
|
|
|
3
3
|
getServerPort,
|
|
4
4
|
startServer,
|
|
5
5
|
stopServer
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-6EGBXRDK.js";
|
|
6
|
+
} from "./chunk-LXSWDEXV.js";
|
|
7
|
+
import "./chunk-HGWEHWKJ.js";
|
|
9
8
|
import "./chunk-FIL7IWEL.js";
|
|
10
|
-
import "./chunk-
|
|
9
|
+
import "./chunk-ZLHIHMSL.js";
|
|
11
10
|
import "./chunk-LB3RNE3O.js";
|
|
12
|
-
import "./chunk-
|
|
11
|
+
import "./chunk-7EDIUVIO.js";
|
|
12
|
+
import "./chunk-6EGBXRDK.js";
|
|
13
13
|
import "./chunk-SLNJEF32.js";
|
|
14
14
|
import "./chunk-VVIOB362.js";
|
|
15
15
|
import "./chunk-XFVDP332.js";
|
|
@@ -6271,7 +6271,8 @@ const IosFrame = ({
|
|
|
6271
6271
|
const AndroidFrame = ({
|
|
6272
6272
|
children,
|
|
6273
6273
|
width,
|
|
6274
|
-
height
|
|
6274
|
+
height,
|
|
6275
|
+
deviceMockup
|
|
6275
6276
|
}) => {
|
|
6276
6277
|
const screenInsetX = width * 0.03;
|
|
6277
6278
|
const screenInsetY = height * 0.016;
|
|
@@ -6298,7 +6299,7 @@ const AndroidFrame = ({
|
|
|
6298
6299
|
/* @__PURE__ */ (0,jsx_runtime.jsx)(
|
|
6299
6300
|
esm.Img,
|
|
6300
6301
|
{
|
|
6301
|
-
src: (0,esm.staticFile)("mockup-android.png"),
|
|
6302
|
+
src: (0,esm.staticFile)(deviceMockup || "mockup-android-galaxy.png"),
|
|
6302
6303
|
style: {
|
|
6303
6304
|
position: "absolute",
|
|
6304
6305
|
top: 0,
|
|
@@ -6383,7 +6384,8 @@ const DeviceFrame = ({
|
|
|
6383
6384
|
platform,
|
|
6384
6385
|
children,
|
|
6385
6386
|
width,
|
|
6386
|
-
height
|
|
6387
|
+
height,
|
|
6388
|
+
deviceMockup
|
|
6387
6389
|
}) => {
|
|
6388
6390
|
if (platform === "ios") {
|
|
6389
6391
|
const h2 = height || 820;
|
|
@@ -6391,9 +6393,11 @@ const DeviceFrame = ({
|
|
|
6391
6393
|
return /* @__PURE__ */ (0,jsx_runtime.jsx)(IosFrame, { width: w2, height: h2, children });
|
|
6392
6394
|
}
|
|
6393
6395
|
if (platform === "android") {
|
|
6396
|
+
const inputProps = typeof window === "undefined" || (0,esm.getRemotionEnvironment)().isPlayer ? {} : (0,esm.getInputProps)() ?? {};
|
|
6397
|
+
const resolvedDeviceMockup = deviceMockup || inputProps.deviceMockup || "mockup-android-galaxy.png";
|
|
6394
6398
|
const h2 = height || 820;
|
|
6395
6399
|
const w2 = width || h2 * ANDROID_ASPECT;
|
|
6396
|
-
return /* @__PURE__ */ (0,jsx_runtime.jsx)(AndroidFrame, { width: w2, height: h2, children });
|
|
6400
|
+
return /* @__PURE__ */ (0,jsx_runtime.jsx)(AndroidFrame, { deviceMockup: resolvedDeviceMockup, width: w2, height: h2, children });
|
|
6397
6401
|
}
|
|
6398
6402
|
const w = width || 900;
|
|
6399
6403
|
const h = height || 580;
|
|
Binary file
|
|
@@ -104,7 +104,7 @@ import {
|
|
|
104
104
|
uiStatusTool,
|
|
105
105
|
uiTools,
|
|
106
106
|
videoInfoTool
|
|
107
|
-
} from "./chunk-
|
|
107
|
+
} from "./chunk-AHVBE25Y.js";
|
|
108
108
|
import {
|
|
109
109
|
setupCheckTool,
|
|
110
110
|
setupInitTool,
|
|
@@ -112,11 +112,11 @@ import {
|
|
|
112
112
|
setupTools
|
|
113
113
|
} from "./chunk-FNUN7EPB.js";
|
|
114
114
|
import "./chunk-XKX6NBHF.js";
|
|
115
|
-
import "./chunk-
|
|
116
|
-
import "./chunk-6EGBXRDK.js";
|
|
115
|
+
import "./chunk-HGWEHWKJ.js";
|
|
117
116
|
import "./chunk-FIL7IWEL.js";
|
|
118
117
|
import "./chunk-LB3RNE3O.js";
|
|
119
|
-
import "./chunk-
|
|
118
|
+
import "./chunk-7EDIUVIO.js";
|
|
119
|
+
import "./chunk-6EGBXRDK.js";
|
|
120
120
|
import "./chunk-SLNJEF32.js";
|
|
121
121
|
import "./chunk-VVIOB362.js";
|
|
122
122
|
import "./chunk-XFVDP332.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@veolab/discoverylab",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.3",
|
|
4
4
|
"description": "AI-powered app testing & evidence generator - Claude Code Plugin",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
"claude-plugin": {
|
|
69
69
|
"name": "DiscoveryLab",
|
|
70
70
|
"description": "AI-powered app testing & evidence generator",
|
|
71
|
-
"version": "1.3.
|
|
71
|
+
"version": "1.3.3",
|
|
72
72
|
"tools": [
|
|
73
73
|
"dlab.capture.screen",
|
|
74
74
|
"dlab.capture.emulator",
|
package/dist/chunk-GAKEFJ5T.js
DELETED
|
@@ -1,481 +0,0 @@
|
|
|
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
|
-
};
|