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 +26 -0
- package/README.md +164 -0
- package/cordis.patch.yml +10 -0
- package/lib/client.js +828 -0
- package/lib/device-build.js +964 -0
- package/lib/device-preview.js +870 -0
- package/lib/index.js +976 -0
- package/lib/setup.js +243 -0
- package/package.json +68 -0
- package/scripts/ocr.py +111 -0
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.
|
package/cordis.patch.yml
ADDED
|
@@ -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'
|