dsh-mobilecode 0.1.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.
package/LICENSE ADDED
@@ -0,0 +1,26 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 opencode (original mobilecode)
4
+ Copyright (c) 2026 spix18 (dsh-mobilecode port)
5
+
6
+ This project is a port of https://github.com/hsandhu/mobilecode (the opencode
7
+ fork with embedded iOS Simulator / Android Emulator support) into the
8
+ DeepSeek Harness (DSH) plugin architecture.
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,164 @@
1
+ # dsh-mobilecode
2
+
3
+ MobileCode for the dsh web GUI — a hot-pluggable DSH plugin porting
4
+ [hsandhu/mobilecode](https://github.com/hsandhu/mobilecode) (the opencode fork
5
+ with embedded iOS Simulator / Android Emulator support) into
6
+ [DeepSeek Harness](https://github.com/deepseek-ai/DeepSeek-Harness).
7
+
8
+ It detects the mobile project in a directory (iOS / Android, Expo / React
9
+ Native / native), starts the `serve-sim` / `serve-avd` preview servers, builds,
10
+ installs and launches the app on the booted simulator or emulator — and exposes
11
+ the same to the agent through tools.
12
+
13
+ ## What the plugin provides
14
+
15
+ **Device pane (web GUI)** — a sidebar entry ("Devices") opening a right-hand
16
+ drawer:
17
+
18
+ - project directory input (persisted in localStorage) + Detect
19
+ - platform pills (iOS / Android) with live server status
20
+ - per platform: **Start/Stop server**, **Run app / Stop app**, an embedded
21
+ iframe of the serve-sim / serve-avd stream, build status/step/error and an
22
+ expandable log tail
23
+ - a Metro (bundler) status card
24
+ - polls `GET /api/dsh-mobilecode` every 2 s while open
25
+
26
+ **Agent tools**
27
+
28
+ - `device_run` — action `run` (build+install+launch, then waits with a
29
+ configurable timeout), `stop` (cancel/terminate), or `status`. Platform
30
+ `ios` | `android` | `all`. Returns framework, platforms, per-platform build
31
+ summaries (status, step, target, appID, error, log tail — logs only when
32
+ failed or incomplete), the Metro state, and `complete`.
33
+ - `device_detect` — which platforms a directory supports, the framework, and
34
+ the first attached Android device.
35
+ - `device_screen` — see what is on an attached Android device: a PNG screenshot
36
+ plus the uiautomator UI hierarchy (text + pixel bounds) and **local PaddleOCR**
37
+ text recognition (text + confidence + box), so an agent can read the screen
38
+ and tap by coordinates. Also returns the foreground activity and screen size.
39
+ - `device_input` — act on the device: tap / swipe / type / press a key at
40
+ **absolute pixel coordinates** (the same space `device_screen` returns — take
41
+ the box center `x=(x1+x2)/2, y=(y1+y2)/2`). The deterministic control loop is
42
+ `device_screen → device_input → device_screen`.
43
+ - `device_log` — device logs: logcat `main`/`crash`/`events`/`kernel` buffers
44
+ (kernel = dmesg, needs adb root — works on emulators) with an optional
45
+ case-insensitive substring filter, capped line count.
46
+ - `device_status` — one normalized snapshot: attached devices, configured AVDs,
47
+ emulator binary, and what the plugin currently runs (preview servers, Metro,
48
+ builds per directory).
49
+
50
+ **First-run experience & settings**
51
+
52
+ - On first start after installation, a **welcome window** explains how to use the
53
+ plugin, shows a **copy-paste prompt for any AI model** (tells it about
54
+ `device_detect` / `device_run` / `device_screen` / `device_input` /
55
+ `device_log` / `device_status` and the recommended control loop), and offers a
56
+ **one-click PaddleOCR install** — `device_screen` reads on-screen text with
57
+ fully local OCR. The plugin works without it, just without OCR text.
58
+ - A **⚙ Settings** button in the Devices pane header opens the settings dialog
59
+ with three tabs:
60
+ - **Doctor** — runs every health check (node, Android SDK, emulator binary,
61
+ AVDs, attached device, PaddleOCR, OCR script) with ✓/✗ + details, and a
62
+ Fix button for auto-fixable checks (PaddleOCR install).
63
+ - **PaddleOCR** — install status, progress log, and the install button.
64
+ - **AI Prompt** — the copyable agent prompt.
65
+ - The same settings appear as a **`MobileCode` page in the DSH Settings**
66
+ (registered as a `settings.section` slot, like the other installed plugins),
67
+ so they are reachable from Settings even when the Devices pane is closed.
68
+ - State lives in `~/.dsh/mobilecode/` (settings.json, ocr-venv, install log,
69
+ OCR-INSTALL.md).
70
+
71
+ **HTTP API** (loopback-only, consumed by the pane) — `GET /api/dsh-mobilecode`
72
+ (info) and `POST /api/dsh-mobilecode/{start,stop,run,run/stop,focus}` with a
73
+ `directory` + `platform` body, mirroring mobilecode's `server.devicePreview`
74
+ group — plus setup endpoints: `GET /welcome`, `POST /welcome/dismiss`,
75
+ `GET /doctor`, `POST /doctor/fix {id}`, `GET /ocr`, `POST /ocr/install`,
76
+ `GET/POST /settings`.
77
+
78
+ ## How it works
79
+
80
+ - `lib/device-build.js` — port of `mobilecode/packages/core/src/device-build.ts`:
81
+ bounded project discovery (2-level walk, SKIP set), framework detection,
82
+ preflight (xcodebuild / pod / Android SDK / Java / gradle wrapper), Expo
83
+ `app.json` id injection and `prebuild`, Metro port/status helpers, iOS
84
+ target/build-arg resolution, Android SDK/adb/aapt2/gradle helpers.
85
+ - `lib/device-preview.js` — port of `mobilecode/packages/core/src/device-preview.ts`
86
+ with the **Effect runtime dropped**: a plain async `DevicePreviewEngine`
87
+ class holding the same `servers` / `builds` / `bundlers` maps and the same
88
+ lifecycle (park → halt → settle → execute; one project at a time; process
89
+ exit/signal hooks; win32 taskkill tree-kill).
90
+ - `lib/index.js` — host half: engine, `/api/dsh-mobilecode/*` routes (run
91
+ controls + welcome / doctor / ocr / settings), agent tools, system-prompt
92
+ guidance section, `ctx.provide('mobilecode', handle)`.
93
+ - `lib/setup.js` — settings store (~/.dsh/mobilecode/settings.json), the plugin
94
+ doctor (health checks + auto-fix), and the detached PaddleOCR installer
95
+ (writes an install script to disk and spawns it via cmd.exe, so the install
96
+ survives GUI restarts and its progress is pollable through `/ocr`).
97
+ - `lib/client.js` — browser half: `window.__ModuleLoader__.load({id, factory})`
98
+ bundle (the only client bundle format the web shell materializes) mounting
99
+ the sidebar entry, the drawer with DOM-level self-healing, the first-run
100
+ welcome modal, and the settings dialog (doctor / PaddleOCR / AI prompt), like
101
+ dsh-logcat.
102
+ - `cordis.patch.yml` + `package.json` (`dsh.bundle.patch`, `dsh.client.inject`)
103
+ make it a hot-pluggable profile bundle.
104
+
105
+ **No runtime dependencies** — the port replaces `cross-spawn` (not resolvable
106
+ from the profile node_modules tree) with a ~40-line `launch()` helper that does
107
+ PATHEXT lookup and spawns `.cmd`/`.bat` through `cmd.exe /d /s /c` with
108
+ double-wrapped quoting, and replaces the Effect/Schema types with plain JS.
109
+
110
+ ## Install / mount
111
+
112
+ The plugin mounts exactly like dsh-logcat — copy it into the web profile and
113
+ add it to the bundle list:
114
+
115
+ ```powershell
116
+ # from this repo
117
+ $profile = "$env:USERPROFILE\.dsh\profiles\web"
118
+ Copy-Item -Recurse lib, package.json, cordis.patch.yml "$profile\node_modules\dsh-mobilecode\"
119
+ ```
120
+
121
+ Then add `dsh-mobilecode` to the `dsh.profile.bundles` array in
122
+ `$profile\package.json` (the `cordis.patch.yml` insert row takes care of the
123
+ roster). Restart the GUI to load the host half; refresh the browser to load
124
+ the client bundle (`/plugins/dsh-mobilecode/client.js` — the URL id is the
125
+ package name, not the patch row id).
126
+
127
+ ## Verify
128
+
129
+ ```powershell
130
+ node test/smoke.mjs # engine unit smoke test (15 checks)
131
+ node test/e2e-android.mjs <dir> # full build+install+launch on a real device
132
+ ```
133
+
134
+ The e2e run performs a Gradle `assembleDebug`, reads the app id with aapt2,
135
+ `adb install -r -g`, and `am start` on the first attached device, then quits
136
+ the app.
137
+
138
+ ## Notes
139
+
140
+ - **PaddleOCR (optional, powers `device_screen`'s OCR)** — fully local, no
141
+ network at inference time. One-time install into the shared venv the plugin
142
+ looks for (`DSH_MOBILECODE_OCR_PY` env override wins, then
143
+ `~/.dsh/mobilecode/ocr-venv`):
144
+
145
+ ```powershell
146
+ py -3.12 -m venv $env:USERPROFILE\.dsh\mobilecode\ocr-venv
147
+ & $env:USERPROFILE\.dsh\mobilecode\ocr-venv\Scripts\python.exe -m pip install setuptools wheel "numpy<2" "paddleocr==3.7.0" "paddlepaddle==3.3.1"
148
+ ```
149
+
150
+ Paddle 3.x on Windows crashes in the oneDNN PIR executor, so `ocr.py` always
151
+ constructs PaddleOCR with `enable_mkldnn=False` — with that, 3.7.0 works and
152
+ its PP-OCRv6 models read text more accurately than the old 2.7.3 pin.
153
+ Without the venv, `device_screen` still returns the UI
154
+ hierarchy and screenshot; only OCR is skipped with a clear note.
155
+ - iOS support (xcodebuild / simctl / serve-sim) is darwin-gated exactly like
156
+ mobilecode: `findProjects` only walks for iOS on macOS, and the run pipeline
157
+ resolves Xcode targets on demand. On Windows the pane shows Android only.
158
+ - The engine keeps **one project at a time**: switching to another directory
159
+ parks the previous project's live apps (and its Metro), and switching back
160
+ revives them (`focus`).
161
+ - Agent tools take an explicit `directory` (default: plugin `defaultDirectory`
162
+ config or the host cwd) because DSH tools have no session-location concept.
163
+ - Preview URLs are embedded in an iframe; serve-* must not send an
164
+ `X-Frame-Options: DENY` header for the stream to render inside the pane.
@@ -0,0 +1,10 @@
1
+ # dsh-mobilecode bundle patch: inserts the mobilecode plugin row into the web
2
+ # profile roster. Applied as a profile bundle layer over dsh-base; the row is
3
+ # a bare plugin by package name — the node half (exports ".") runs in the
4
+ # host process (device-preview engine, /api/dsh-mobilecode routes, agent
5
+ # tools), and the `dsh.client` declaration in package.json makes the browser
6
+ # half (exports "./client", served at /plugins/mobilecode/client.js) load in
7
+ # the web GUI.
8
+ - insert:
9
+ - id: mobilecode
10
+ name: 'dsh-mobilecode'