@veolab/discoverylab 1.4.4 → 1.6.5

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 (33) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/README.md +70 -211
  4. package/assets/applab-bundle-icon.png +0 -0
  5. package/assets/icons/icons8-claude-150.png +0 -0
  6. package/assets/icons/icons8-claude-500.png +0 -0
  7. package/dist/{chunk-CUBQRT5L.js → chunk-JAA53ES7.js} +111 -2
  8. package/dist/{chunk-HB3YPWF3.js → chunk-Q7Q3A2ZI.js} +301 -10
  9. package/dist/{chunk-XKX6NBHF.js → chunk-TWRWARU4.js} +52 -2
  10. package/dist/{chunk-2UUMLAVR.js → chunk-V6RREMYD.js} +332 -38
  11. package/dist/cli.js +164 -28
  12. package/dist/export/infographic-template.html +254 -0
  13. package/dist/import-W2JEW254.js +180 -0
  14. package/dist/index.d.ts +30 -6
  15. package/dist/index.html +473 -11
  16. package/dist/index.js +5 -5
  17. package/dist/infographic-GQAHEOAA.js +183 -0
  18. package/dist/mcpb/node_modules/@anthropic-ai/sdk/src/lib/.keep +4 -0
  19. package/dist/mcpb/node_modules/better-sqlite3/build/Release/.deps/Release/better_sqlite3.node.d +1 -0
  20. package/dist/mcpb/node_modules/better-sqlite3/build/Release/.deps/Release/obj.target/better_sqlite3/src/better_sqlite3.o.d +133 -0
  21. package/dist/mcpb/node_modules/better-sqlite3/build/Release/.deps/Release/obj.target/deps/locate_sqlite3.stamp.d +1 -0
  22. package/dist/mcpb/node_modules/better-sqlite3/build/Release/.deps/Release/obj.target/sqlite3/gen/sqlite3/sqlite3.o.d +4 -0
  23. package/dist/mcpb/node_modules/better-sqlite3/build/Release/.deps/Release/obj.target/test_extension/deps/test_extension.o.d +7 -0
  24. package/dist/mcpb/node_modules/better-sqlite3/build/Release/.deps/Release/sqlite3.a.d +1 -0
  25. package/dist/mcpb/node_modules/better-sqlite3/build/Release/.deps/Release/test_extension.node.d +1 -0
  26. package/dist/mcpb/node_modules/better-sqlite3/build/Release/.deps/ba23eeee118cd63e16015df367567cb043fed872.intermediate.d +1 -0
  27. package/dist/{server-QFNKZCOJ.js → server-C2NZM2RV.js} +1 -1
  28. package/dist/{server-OVOACIOJ.js → server-WN6DCCUA.js} +1 -1
  29. package/dist/{setup-6JJYKKBS.js → setup-SMN7FJNZ.js} +5 -2
  30. package/dist/{tools-Q7OZO732.js → tools-VXU3JEQP.js} +6 -4
  31. package/doc/esvp-protocol.md +116 -0
  32. package/package.json +9 -3
  33. package/skills/knowledge-brain/SKILL.md +44 -43
@@ -12,7 +12,7 @@
12
12
  "name": "discoverylab",
13
13
  "source": ".",
14
14
  "description": "AI-powered app testing & marketing asset generator. Record mobile/web apps, run automated tests with Maestro & Playwright, and generate professional screenshots, GIFs, and test reports.",
15
- "version": "1.4.4",
15
+ "version": "1.6.4",
16
16
  "author": {
17
17
  "name": "Anderson Melo"
18
18
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "discoverylab",
3
3
  "description": "AI-powered app testing & marketing asset generator. Record mobile/web apps, run automated tests with Maestro & Playwright, and generate professional screenshots, GIFs, and test reports.",
4
- "version": "1.4.4",
4
+ "version": "1.6.4",
5
5
  "author": {
6
6
  "name": "Anderson Melo",
7
7
  "email": "anderson.90@gmail.com"
package/README.md CHANGED
@@ -7,271 +7,130 @@
7
7
 
8
8
  ![Node.js](https://img.shields.io/badge/Node.js-20%2B-brightgreen?style=flat-square)
9
9
  [![npm](https://img.shields.io/npm/v/@veolab/discoverylab.svg?style=flat-square)](https://www.npmjs.com/package/@veolab/discoverylab)
10
+ [![npm downloads](https://img.shields.io/npm/dm/@veolab/discoverylab.svg?style=flat-square)](https://www.npmjs.com/package/@veolab/discoverylab)
11
+ [![GitHub stars](https://img.shields.io/github/stars/veolab/applab-discovery?style=flat-square)](https://github.com/veolab/applab-discovery/stargazers)
10
12
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue?style=flat-square)](https://opensource.org/licenses/MIT)
11
13
 
12
- > AI-powered app testing & marketing asset generator. A Claude Code plugin.
14
+ > AI-powered app testing, documentation & knowledge base. A plugin for Claude Code and Claude Desktop.
13
15
 
14
16
  ![DiscoveryLab](assets/applab-discovery.jpeg)
15
17
 
16
- ## How It Works
18
+ ## Quick Start
19
+
20
+ ```bash
21
+ npm install -g @veolab/discoverylab
22
+ discoverylab install # auto-detects Claude Code + Claude Desktop
23
+ discoverylab serve # opens web UI at localhost:3847
24
+ ```
25
+
26
+ `applab` works as an alias for `discoverylab`.
27
+
28
+ ## What It Does
29
+
30
+ Record app flows. AI analyzes every screen. Ask Claude about any flow in natural language.
17
31
 
18
32
  ```mermaid
19
33
  flowchart LR
20
- subgraph Input
34
+ subgraph Capture
21
35
  A[Mobile App] --> R[Record]
22
36
  B[Web App] --> R
23
37
  C[Video File] --> U[Upload]
24
38
  end
25
39
 
26
- subgraph DiscoveryLab
40
+ subgraph Analyze
27
41
  R --> P[Process]
28
42
  U --> P
29
43
  P --> AI[AI Analysis]
30
- AI --> O[OCR + Features]
44
+ AI --> K[Knowledge Base]
31
45
  end
32
46
 
33
- subgraph Output
34
- O --> E1[Screenshots]
35
- O --> E2[GIF / MP4]
36
- O --> E3[Test Reports]
47
+ subgraph Use
48
+ K --> Q[Ask Claude]
49
+ K --> E[Export Assets]
50
+ K --> S[Share .applab]
37
51
  end
38
52
  ```
39
53
 
40
- ## Quick Start
41
-
42
- ```bash
43
- npm install -g @veolab/discoverylab
44
- discoverylab install # configures Claude Code MCP
45
- discoverylab serve # opens web UI
46
- ```
47
-
48
- `applab serve` works as an alias — both `discoverylab` and `applab` are interchangeable.
49
- `serve` and `server` are also interchangeable.
50
-
51
54
  ## Features
52
55
 
53
56
  | Feature | Description |
54
57
  |---------|-------------|
55
58
  | **Screen Capture** | Record iOS/Android emulators or web apps |
59
+ | **AI Analysis** | OCR, feature detection, smart summaries (Anthropic, OpenAI, Ollama, Claude CLI) |
60
+ | **Knowledge Brain** | Ask Claude about any captured flow — visual answers with interactive infographics |
61
+ | **Interactive Visualizations** | Flow Diagram, Device Showcase, Metrics Dashboard, App Flow Map |
62
+ | **Grid Assets** | Infographic grids with AI annotations, step badges, flow arrows |
63
+ | **Export** | PNG, GIF, MP4, HTML infographic, .applab bundle |
64
+ | **Document Composer** | Build rich Notion pages with preview before export |
56
65
  | **Maestro Testing** | Automated mobile app testing with screenshots |
57
66
  | **Playwright Testing** | Web testing using your installed Chrome |
58
- | **AI Analysis** | OCR, feature detection, smart summaries |
59
- | **Export** | PNG, GIF, MP4 with professional quality |
60
67
  | **Task Hub** | Jira, Notion, Figma, GitHub integration |
61
- | **ESVP Client** | Connect to a shared ESVP control-plane for mobile sessions, replay, iOS Sim, and network traces |
68
+ | **ESVP Protocol** | Mobile sessions, replay, and network traces ([docs](doc/esvp-protocol.md)) |
69
+ | **Share** | Export .applab bundles → import on another machine with full context |
70
+
71
+ ## Claude Integration
62
72
 
63
- ## Skills
73
+ ### Claude Code (CLI)
64
74
 
65
- After installing, use these in Claude Code:
75
+ Skills available after install:
66
76
 
67
77
  ```
68
78
  /discoverylab:open-ui → Open web interface
69
79
  /discoverylab:quick-capture → Capture emulator screen
70
80
  /discoverylab:mobile-test → Mobile testing with Maestro
71
81
  /discoverylab:web-test → Web testing with Playwright
82
+ /discoverylab:generate-assets → Create marketing assets
72
83
  ```
73
84
 
74
- ## Requirements
85
+ ### Claude Desktop
75
86
 
76
- - Node.js 20+
77
- - FFmpeg (for video/GIF export)
78
- - Maestro CLI (optional)
79
- - Playwright (optional)
80
-
81
- ## Platform Support
87
+ Ask in natural language — Claude opens interactive visuals automatically:
82
88
 
83
- | | macOS | Windows | Linux |
84
- |---|:---:|:---:|:---:|
85
- | Web UI | ✓ | ✓ | ✓ |
86
- | iOS Capture | ✓ | — | — |
87
- | Android Capture | ✓ | ✓ | ✓ |
88
- | Web Recording | ✓ | ✓ | ✓ |
89
- | Apple Vision OCR | ✓ | — | — |
90
-
91
- ## ESVP Integration
92
-
93
- AppLab Discovery can act as an open-source client for a self-hosted ESVP control-plane. This integration is intentionally thin: it only calls the public HTTP contract and does not embed any private Entropy Lab runtime code.
94
-
95
- Default behavior:
96
-
97
- - if `ESVP_BASE_URL` is set, DiscoveryLab uses a remote/shared ESVP server
98
- - if `ESVP_BASE_URL` is not set, DiscoveryLab tries to boot an embedded local OSS runtime (`esvp-local`)
99
-
100
- For development, until `@entropylab/esvp-local` is published, point the local runtime module explicitly:
101
-
102
- ```bash
103
- export DISCOVERYLAB_ESVP_LOCAL_MODULE=/absolute/path/to/esvp-server-reference/server.js
104
89
  ```
105
-
106
- To force remote mode, set the control-plane URL:
107
-
108
- ```bash
109
- export ESVP_BASE_URL=http://your-esvp-host:8787
90
+ "how does the login flow work?" → opens infographic canvas
91
+ "what screens do we have captured?" lists all projects
92
+ "show me the onboarding" → visual flow map
110
93
  ```
111
94
 
112
- Local `external-proxy` capture is now backed by a bundled host runtime. To ship the binary inside `dist/runtime/esvp-host-runtime/`, run:
95
+ ### MCP Tools
113
96
 
114
- ```bash
115
- npm run build:host-runtime
116
97
  ```
117
-
118
- Regular `npm run build` attempts this step in best-effort mode so the JS build still succeeds on machines without Rust, but distributable builds that need local capture should include the runtime binary.
119
-
120
- Video templates are also staged automatically during `npm run build`. DiscoveryLab will copy templates from:
121
-
122
- - `DISCOVERYLAB_TEMPLATE_SOURCE_DIR` if set
123
- - otherwise `~/.discoverylab/templates`
124
-
125
- into `dist/templates`, so npm packages and fresh installs keep the template toggle icons and Remotion renders working without a second manual copy step.
126
-
127
- For a local distributable package that already contains the bundled runtime for the current host, run:
128
-
129
- ```bash
130
- npm run pack:local
98
+ dlab.knowledge.open → visual infographic of a flow (HTML canvas)
99
+ dlab.knowledge.search → text search across all projects
100
+ dlab.knowledge.summary → overview of all captured knowledge
101
+ dlab.export.infographic export self-contained HTML file
102
+ dlab.project.import → import shared .applab bundle
131
103
  ```
132
104
 
133
- That produces the npm tarball with `dist/runtime/esvp-host-runtime/...` embedded, so the installed end-user package only needs `discoverylab serve` or `discoverylab server`.
134
-
135
- Development vs packaged usage:
136
-
137
- - local development can use `bun run dev`; when a bundled runtime is not present, App Lab falls back to `cargo run` if Rust is installed
138
- - packaged/npm releases should be built with `npm run pack:local` or `npm publish`, which require the host runtime and embed it so end users only need `discoverylab serve` or `discoverylab server`
139
- - the bundled runtime is currently host-target specific, so cross-platform distribution still needs a build matrix that produces binaries for each target you want to ship
140
- - because App Lab is open source, the bundled runtime is intentionally limited to the local proxy/capture commodity path; it does not embed private Entropy Lab managed-proxy or protocol internals
141
-
142
- Available MCP tools:
143
-
144
- - `dlab.esvp.status`
145
- - `dlab.esvp.devices`
146
- - `dlab.esvp.sessions.list`
147
- - `dlab.esvp.session.create`
148
- - `dlab.esvp.session.get`
149
- - `dlab.esvp.session.inspect`
150
- - `dlab.esvp.session.transcript`
151
- - `dlab.esvp.session.artifacts.list`
152
- - `dlab.esvp.session.artifact.get`
153
- - `dlab.esvp.session.actions`
154
- - `dlab.esvp.session.checkpoint`
155
- - `dlab.esvp.session.finish`
156
- - `dlab.esvp.replay.run`
157
- - `dlab.esvp.replay.validate`
158
- - `dlab.esvp.session.network`
159
- - `dlab.esvp.network.configure`
160
- - `dlab.esvp.network.trace.attach`
161
- - `dlab.project.esvp.current`
162
- - `dlab.project.esvp.validate`
163
- - `dlab.project.esvp.replay`
164
- - `dlab.project.esvp.sync_network`
165
- - `dlab.project.esvp.app_trace_bootstrap`
166
-
167
- CLI surface:
168
-
169
- - `discoverylab esvp status`
170
- - `discoverylab esvp devices`
171
- - `discoverylab esvp sessions`
172
- - `discoverylab esvp create`
173
- - `discoverylab esvp get <sessionId>`
174
- - `discoverylab esvp inspect <sessionId>`
175
- - `discoverylab esvp transcript <sessionId>`
176
- - `discoverylab esvp artifacts <sessionId>`
177
- - `discoverylab esvp artifact <sessionId> <artifactPath>`
178
- - `discoverylab esvp actions <sessionId>`
179
- - `discoverylab esvp checkpoint <sessionId>`
180
- - `discoverylab esvp finish <sessionId>`
181
- - `discoverylab esvp replay-run <sessionId>`
182
- - `discoverylab esvp replay-validate <sessionId>`
183
- - `discoverylab esvp replay-consistency <sessionId>`
184
- - `discoverylab esvp network <sessionId>`
185
- - `discoverylab esvp network-configure <sessionId>`
186
- - `discoverylab esvp network-clear <sessionId>`
187
- - `discoverylab esvp trace-attach <sessionId>`
188
-
189
- Mobile recording bridge:
105
+ ## CLI Commands
190
106
 
191
- - App Lab mobile recordings can now sync `network_trace` artifacts from ESVP into the same `networkEntries` / segmented route tabs already used by web recordings.
192
- - When ESVP traces include headers and request/response previews, the Analysis view now exposes a request inspector with segmented tabs for `Overview`, `Request`, `Response`, and `Headers`.
193
- - Local MCP development can point `.mcp.json` at `node dist/index.js` so LLMs use the current branch build instead of `@latest`.
194
- - App Lab exposes server routes for this bridge:
195
- - `POST /api/testing/mobile/recordings/:id/esvp/validate`
196
- - `POST /api/testing/mobile/recordings/:id/esvp/sync-network`
197
- - Validation now uses the public executor that fits each platform:
198
- - Android recordings validate through `adb`
199
- - iOS recordings validate through `maestro-ios`
200
- - `POST /api/testing/mobile/recordings/:id/esvp/validate` also accepts an optional `network` payload. If present, App Lab asks ESVP to configure the session before replaying the flow.
201
- - App Lab local now prefers `network.mode=external-proxy`.
202
- - In `external-proxy` mode, the proxy belongs to the App Lab client and App Lab only uses ESVP to persist `network_profile` / `network_trace`.
203
- - If `network.mode` is omitted, App Lab defaults to `external-proxy`. `managed-proxy` remains available only when explicitly requested.
204
- - If `external-proxy` is selected without an explicit `proxy.host` / `proxy.port`, App Lab now auto-starts a local HTTP proxy for the ESVP session and attaches the resulting `network_trace` when the session stops.
205
- - Practical host rules for local proxying:
206
- - iOS Simulator can use `127.0.0.1` when the proxy runs on the same macOS host.
207
- - Android Emulator should use `10.0.2.2` to reach a proxy on the host.
208
- - Physical Android devices need a host/LAN IP, not `127.0.0.1`.
209
- - Optional env vars for the client-owned proxy:
210
- - `DISCOVERYLAB_NETWORK_PROXY_PORT`
211
- - `DISCOVERYLAB_NETWORK_PROXY_HOST`
212
- - `DISCOVERYLAB_NETWORK_PROXY_BIND_HOST`
213
- - `DISCOVERYLAB_NETWORK_PROXY_PROTOCOL`
214
- - `DISCOVERYLAB_NETWORK_PROXY_BYPASS`
215
- - `DISCOVERYLAB_NETWORK_PROXY_MAX_DURATION_MS`
216
- - Host compatibility for local proxying:
217
- - macOS host + iOS Simulator: supported. This is the only local iOS path, because Simulator / `maestro-ios` / `ios-sim` are macOS-only.
218
- - macOS host + Android Emulator / physical Android: supported, as long as `adb` is installed and the device is reachable.
219
- - Linux host + Android Emulator / physical Android: supported, as long as `adb` is installed and the device is reachable.
220
- - Android local proxying is not tied to macOS. The local proxy is a Node.js HTTP proxy and the ESVP `adb` executor applies the proxy through ADB.
221
- - Android prerequisites:
222
- - `adb` must be installed and available on `PATH` before starting App Lab / ESVP flows.
223
- - Android Emulator should use `10.0.2.2` to reach the host proxy.
224
- - Physical Android devices must use a host/LAN IP reachable from the device.
225
- - `DISCOVERYLAB_NETWORK_PROXY_BIND_HOST` can be used when the proxy must listen on a LAN-facing interface instead of loopback.
226
- - Safety defaults for the local proxy:
227
- - App Lab now auto-finalizes App-owned local proxies after `15m` by default to avoid leaving the host/device pointed at a stale proxy.
228
- - Auto-finalization clears ESVP network state, stops the local proxy, attaches the captured `network_trace`, and finishes the session.
229
- - App Lab Settings now expose an emergency lock for App-owned proxy autostart. Enabling it immediately finalizes active App-owned proxies and blocks new auto-started local proxies until you unlock it.
230
- - App Lab Settings also expose a `Disable Active Proxy Now` panic button that forces cleanup without changing the lock state.
231
- - Server shutdown always attempts the same cleanup path, so App-owned proxies are finalized automatically when the App Lab server exits normally.
232
- - Set `DISCOVERYLAB_NETWORK_PROXY_MAX_DURATION_MS=0` only if you explicitly want to disable this guardrail.
233
- - Current limitation:
234
- - Automatic local proxying covers HTTP proxy setup and trace attach only. Advanced fault injection still requires explicit `managed-proxy`.
235
- - `managed-proxy` is still useful for public-runtime validation and fault-injection experiments.
236
-
237
- Example request body for ESVP-backed validation with external proxy:
238
-
239
- ```json
240
- {
241
- "network": {
242
- "mode": "external-proxy",
243
- "profile": "applab-standard-capture",
244
- "proxy": {
245
- "host": "10.0.2.2",
246
- "port": 8080
247
- }
248
- }
249
- }
107
+ ```bash
108
+ discoverylab serve # start web UI
109
+ discoverylab install # auto-detect + configure MCP
110
+ discoverylab install --target desktop # Claude Desktop only
111
+ discoverylab export <project-id> --format infographic --open
112
+ discoverylab import <file.applab> # import shared project
113
+ discoverylab setup # check dependencies
114
+ discoverylab info # version info
250
115
  ```
251
116
 
252
- Example prompts for Claude Code or other MCP clients:
253
-
254
- - `Check my ESVP control-plane health`
255
- - `Create an ios-sim ESVP session and take a screenshot`
256
- - `Create a maestro-ios ESVP session and replay this iOS recording with an external proxy`
257
- - `Configure a proxy on this ESVP session and attach the HTTP trace from ./trace.json`
258
- - `Replay the failing Android session on the current emulator`
259
-
260
- Programmatic usage:
117
+ ## Requirements
261
118
 
262
- ```ts
263
- import { createESVPSession, runESVPActions } from '@veolab/discoverylab';
119
+ - Node.js 20+
120
+ - FFmpeg (for video/GIF export)
121
+ - Maestro CLI (optional, for mobile testing)
122
+ - Playwright (optional, for web testing)
264
123
 
265
- const created = await createESVPSession({
266
- executor: 'ios-sim',
267
- meta: { source: 'demo' },
268
- });
124
+ ## Platform Support
269
125
 
270
- await runESVPActions(created.session.id, {
271
- actions: [{ name: 'screenshot' }],
272
- finish: true,
273
- });
274
- ```
126
+ | | macOS | Windows | Linux |
127
+ |---|:---:|:---:|:---:|
128
+ | Web UI | ✓ | ✓ | ✓ |
129
+ | iOS Capture | ✓ | — | — |
130
+ | Android Capture | ✓ | ✓ | ✓ |
131
+ | Web Recording | ✓ | ✓ | ✓ |
132
+ | Apple Vision OCR | ✓ | — | — |
133
+ | Claude Desktop | ✓ | ✓ | — |
275
134
 
276
135
  ## License
277
136
 
Binary file
@@ -1,7 +1,12 @@
1
1
  import {
2
2
  createJsonResult,
3
3
  createTextResult
4
- } from "./chunk-XKX6NBHF.js";
4
+ } from "./chunk-TWRWARU4.js";
5
+ import {
6
+ LOCAL_ESVP_SERVER_URL,
7
+ getESVPHealth,
8
+ listESVPDevices
9
+ } from "./chunk-GRU332L4.js";
5
10
  import {
6
11
  DATA_DIR,
7
12
  DB_PATH
@@ -144,6 +149,24 @@ function checkMaestro(dep) {
144
149
  error: "Maestro not found in PATH or common installation directories"
145
150
  };
146
151
  }
152
+ function buildReplayExecutorStatus(input) {
153
+ return {
154
+ available: input.dependencyReady && input.devices.length > 0,
155
+ dependencyReady: input.dependencyReady,
156
+ deviceCount: input.devices.length,
157
+ devices: input.devices,
158
+ missing: input.missing
159
+ };
160
+ }
161
+ function createLocalReplayMessage(input) {
162
+ if (input.ready && input.recommendedExecutor) {
163
+ return `Local replay is ready. Recommended executor: ${input.recommendedExecutor}.`;
164
+ }
165
+ if (input.androidReady || input.iosReady) {
166
+ return "A mobile runtime is partially available, but the full local replay path still needs one or more dependencies.";
167
+ }
168
+ return "Local replay is not ready yet. Install the missing mobile dependencies and boot at least one iOS Simulator or Android device/emulator.";
169
+ }
147
170
  var setupStatusTool = {
148
171
  name: "dlab.setup.status",
149
172
  description: "Check the status of DiscoveryLab setup and all dependencies.",
@@ -218,6 +241,91 @@ Install with: ${dep.installHint}`);
218
241
  }
219
242
  }
220
243
  };
244
+ var setupReplayStatusTool = {
245
+ name: "dlab.setup.replay.status",
246
+ description: "Check whether this machine can run local ESVP replay for Claude Desktop using iOS Simulator or Android.",
247
+ inputSchema: z.object({}),
248
+ handler: async () => {
249
+ const adbStatus = checkDependency(dependencies[4]);
250
+ const xcodeStatus = platform() === "darwin" ? checkDependency(dependencies[3]) : { installed: false, version: null, error: "Xcode CLI Tools are only available on macOS" };
251
+ const maestroStatus = checkDependency(dependencies[1]);
252
+ const deviceEnvelope = await listESVPDevices("all").catch((error) => ({
253
+ adb: { devices: [], error: error instanceof Error ? error.message : String(error) },
254
+ iosSim: { devices: [], error: error instanceof Error ? error.message : String(error) },
255
+ maestroIos: { devices: [], error: error instanceof Error ? error.message : String(error) }
256
+ }));
257
+ const localEntropyHealth = await getESVPHealth(LOCAL_ESVP_SERVER_URL).catch((error) => ({
258
+ ok: false,
259
+ error: error instanceof Error ? error.message : String(error)
260
+ }));
261
+ const androidDevices = Array.isArray(deviceEnvelope?.adb?.devices) ? deviceEnvelope.adb.devices : [];
262
+ const iosSimDevices = Array.isArray(deviceEnvelope?.iosSim?.devices) ? deviceEnvelope.iosSim.devices : [];
263
+ const maestroIosDevices = Array.isArray(deviceEnvelope?.maestroIos?.devices) ? deviceEnvelope.maestroIos.devices : [];
264
+ const android = buildReplayExecutorStatus({
265
+ devices: androidDevices,
266
+ dependencyReady: adbStatus.installed,
267
+ missing: adbStatus.installed ? [] : ["adb"]
268
+ });
269
+ const iosSimulator = buildReplayExecutorStatus({
270
+ devices: iosSimDevices,
271
+ dependencyReady: xcodeStatus.installed,
272
+ missing: xcodeStatus.installed ? [] : ["xcode"]
273
+ });
274
+ const iosMaestro = buildReplayExecutorStatus({
275
+ devices: maestroIosDevices,
276
+ dependencyReady: maestroStatus.installed && xcodeStatus.installed,
277
+ missing: [
278
+ ...maestroStatus.installed ? [] : ["maestro"],
279
+ ...xcodeStatus.installed ? [] : ["xcode"]
280
+ ]
281
+ });
282
+ const recommendedExecutor = android.available ? "adb" : iosSimulator.available ? "ios-sim" : iosMaestro.available ? "maestro-ios" : null;
283
+ const ready = Boolean(localEntropyHealth?.ok) && Boolean(recommendedExecutor);
284
+ return createJsonResult({
285
+ ready,
286
+ minimumMobileReady: android.available || iosSimulator.available || iosMaestro.available,
287
+ recommendedExecutor,
288
+ message: createLocalReplayMessage({
289
+ ready,
290
+ recommendedExecutor,
291
+ androidReady: android.available,
292
+ iosReady: iosSimulator.available || iosMaestro.available
293
+ }),
294
+ entropyLocal: {
295
+ available: localEntropyHealth?.ok === true,
296
+ kind: "embedded-app-lab-runtime",
297
+ serverUrl: LOCAL_ESVP_SERVER_URL,
298
+ service: typeof localEntropyHealth?.service === "string" ? localEntropyHealth.service : "applab-esvp-local",
299
+ version: typeof localEntropyHealth?.version === "string" ? localEntropyHealth.version : null,
300
+ note: "Entropy local is the in-process AppLab ESVP runtime. It runs on this machine, stores runs under the local data directory, and uses local emulators/devices instead of a remote control-plane.",
301
+ error: localEntropyHealth?.ok === true ? null : typeof localEntropyHealth?.error === "string" ? localEntropyHealth.error : null
302
+ },
303
+ executors: {
304
+ android,
305
+ iosSimulator,
306
+ iosMaestro
307
+ },
308
+ dependencies: {
309
+ adb: {
310
+ installed: adbStatus.installed,
311
+ version: adbStatus.version,
312
+ installHint: adbStatus.installed ? null : dependencies[4].installHint
313
+ },
314
+ xcode: {
315
+ installed: xcodeStatus.installed,
316
+ version: xcodeStatus.version,
317
+ installHint: xcodeStatus.installed ? null : dependencies[3].installHint
318
+ },
319
+ maestro: {
320
+ installed: maestroStatus.installed,
321
+ version: maestroStatus.version,
322
+ installHint: maestroStatus.installed ? null : dependencies[1].installHint
323
+ }
324
+ },
325
+ dataDirectory: DATA_DIR
326
+ });
327
+ }
328
+ };
221
329
  var setupInitTool = {
222
330
  name: "dlab.setup.init",
223
331
  description: "Initialize DiscoveryLab data directories and database.",
@@ -323,11 +431,12 @@ Please run the following commands to install missing dependencies:
323
431
  );
324
432
  }
325
433
  };
326
- var setupTools = [setupStatusTool, setupCheckTool, setupInitTool, setupInstallTool];
434
+ var setupTools = [setupStatusTool, setupCheckTool, setupReplayStatusTool, setupInitTool, setupInstallTool];
327
435
 
328
436
  export {
329
437
  setupStatusTool,
330
438
  setupCheckTool,
439
+ setupReplayStatusTool,
331
440
  setupInitTool,
332
441
  setupInstallTool,
333
442
  setupTools