capacitor-mobile-claw 1.6.3 → 1.6.4

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 (2) hide show
  1. package/README.md +153 -39
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  **On-device AI agent engine for mobile apps** — run Claude directly on your phone with file tools, code execution, git, and extensible MCP tool support.
8
8
 
9
- Mobile Claw is a [Capacitor](https://capacitorjs.com/) plugin that embeds a full AI agent runtime on Android and iOS via an embedded Node.js worker. No cloud relay, no proxy the agent runs locally on the device and talks directly to the Anthropic API.
9
+ Mobile Claw is a [Capacitor](https://capacitorjs.com/) plugin that embeds a full AI agent runtime on Android and iOS. Two execution modes: a **WebView agent** for instant cold start (agent loop runs in-process) or a **Node.js worker** for full sandboxed tooling. Both talk directly to the Anthropic API — no cloud relay, no proxy. Includes native Kotlin + Swift plugins for streaming HTTP (CORS bypass), background heartbeat scheduling, cron jobs, and on-device vector memory.
10
10
 
11
11
  > Built on [OpenClaw](https://github.com/openclaw/openclaw) and the [Pi framework](https://www.npmjs.com/package/@mariozechner/pi-ai) by [Mario Zechner](https://github.com/badlogic). Pi's philosophy of *"what you leave out matters more than what you put in"* — just 4 core tools and a system prompt under 1,000 tokens — is what makes running a capable AI agent on a phone possible at all.
12
12
 
@@ -79,13 +79,16 @@ npx cap open ios
79
79
  ### Running Tests
80
80
 
81
81
  ```bash
82
- # Android E2E (100 tests, requires ADB device)
82
+ # Unit tests (64 tests)
83
+ npm test
84
+
85
+ # Android E2E (111 tests, requires ADB device)
83
86
  npm run test:android
84
87
 
85
- # iOS E2E (104 tests, requires booted Simulator)
88
+ # iOS E2E (111 tests, requires booted Simulator)
86
89
  npm run test:ios
87
90
 
88
- # Full suite: node + Android + iOS (skips unavailable platforms)
91
+ # Full suite: unit + Android + iOS (skips unavailable platforms)
89
92
  npm run test:full
90
93
  ```
91
94
 
@@ -93,29 +96,54 @@ Once the app launches, enter your Anthropic API key in settings and start chatti
93
96
 
94
97
  ## How It Works
95
98
 
99
+ Mobile Claw supports two agent execution modes:
100
+
101
+ ### WebView Agent (recommended)
102
+
103
+ The agent loop runs directly in the WebView for instant cold start. LLM API calls go through a native HTTP plugin (OkHttp on Android, URLSession on iOS) that bypasses WebView CORS restrictions and provides true streaming via `ReadableStream`. Worker tools are transparently proxied via the bridge.
104
+
105
+ ```
106
+ ┌──────────────────────────────────────────────────────────┐
107
+ │ Your App (Vue, React, Svelte, vanilla JS) │
108
+ │ ┌────────────────────────────────────────────────────┐ │
109
+ │ │ MobileClawEngine (useWebViewAgent: true) │ │
110
+ │ │ ┌──────────────┐ ┌───────────────────────────┐ │ │
111
+ │ │ │ Pi Agent │ │ HttpStreamPlugin (native) │ │ │
112
+ │ │ │ (in WebView) │ │ - OkHttp (Android) │ │ │
113
+ │ │ │ │──│ - URLSession (iOS) │ │ │
114
+ │ │ │ │ │ - CORS bypass │ │ │
115
+ │ │ │ │ │ - ReadableStream assembly │ │ │
116
+ │ │ └──────┬───────┘ └───────────────────────────┘ │ │
117
+ │ │ │ ToolProxy (bridge IPC) │ │
118
+ │ │ ┌──────▼───────────────────────────────────────┐ │ │
119
+ │ │ │ Node.js Worker (file tools, git, code exec) │ │ │
120
+ │ │ └──────────────────────────────────────────────┘ │ │
121
+ │ └────────────────────────────────────────────────────┘ │
122
+ └──────────────────────────────────────────────────────────┘
123
+ ```
124
+
125
+ ### Worker Agent (legacy)
126
+
127
+ The full agent loop runs inside the embedded Node.js worker. Higher cold start latency but full isolation.
128
+
96
129
  ```
97
- ┌─────────────────────────────────────────────────────┐
98
- │ Your App (Vue, React, Svelte, vanilla JS)
99
- ┌───────────────────────────────────────────────┐
100
- │ │ MobileClawEngine (framework-agnostic) │ │
101
- - sendMessage() / stopTurn() / steerAgent()
102
- - readFile() / writeFile()
103
- - listSessions() / resumeSession()
104
- │ │ - invokeTool() │ │
105
- └──────────────────┬────────────────────────────┘
106
- Bridge Protocol (IPC)
107
- ┌──────────────────▼────────────────────────────┐
108
- │ │ Embedded Node.js Worker (Capacitor-NodeJS) │ │
109
- │ │ ┌──────────────┐ ┌──────────────────────┐ │ │
110
- │ │ │ Pi Agent │ MCP Server │ │
111
- │ │ (@mariozechner│ │ - Bridge transport
112
- /pi-ai) │ │ - STOMP transport │ │ │
113
- │ │ │ │ │ - Custom tools (BYO) │ │ │
114
- │ │ └──────┬───────┘ └──────────────────────┘ │ │
115
- │ │ │ │ │
116
- │ │ ▼ Anthropic Messages API │ │
117
- │ └────────────────────────────────────────────────┘ │
118
- └─────────────────────────────────────────────────────┘
130
+ ┌──────────────────────────────────────────────────────────┐
131
+ │ Your App
132
+ ┌────────────────────────────────────────────────────┐
133
+ │ │ MobileClawEngine │ │
134
+ └──────────────────┬─────────────────────────────────┘
135
+ Bridge Protocol (IPC)
136
+ ┌──────────────────▼─────────────────────────────────┐
137
+ │ │ Node.js Worker (Capacitor-NodeJS) │ │
138
+ ┌──────────────┐ ┌──────────────────────┐
139
+ Pi Agent │ │ MCP Server │ │
140
+ (pi-ai) │ │ - Bridge transport │ │ │
141
+ │ │ │ │ │ - STOMP transport
142
+ │ │ │ │ - Custom tools (BYO) │ │
143
+ │ │ └──────┬───────┘ └──────────────────────┘ │ │
144
+ │ │ Anthropic Messages API │ │
145
+ └─────────────────────────────────────────────────────┘
146
+ └──────────────────────────────────────────────────────────┘
119
147
  ```
120
148
 
121
149
  ## Install in Your Own App
@@ -124,6 +152,16 @@ Once the app launches, enter your Anthropic API key in settings and start chatti
124
152
  npm install capacitor-mobile-claw @capacitor/core @capacitor/device @choreruiz/capacitor-node-js @capacitor-community/sqlite
125
153
  ```
126
154
 
155
+ If using Vite, add the bundler plugin to `vite.config.js` (stubs Node.js-only transitive deps):
156
+
157
+ ```javascript
158
+ import { mobileClawVitePlugin } from 'capacitor-mobile-claw/vite-plugin'
159
+
160
+ export default defineConfig({
161
+ plugins: [mobileClawVitePlugin(), vue()],
162
+ })
163
+ ```
164
+
127
165
  Then add these scripts to your `package.json`:
128
166
 
129
167
  ```json
@@ -156,13 +194,13 @@ import { MobileClawEngine } from 'capacitor-mobile-claw'
156
194
 
157
195
  const engine = new MobileClawEngine()
158
196
 
159
- // Initialize the embedded Node.js worker
160
- await engine.init()
197
+ // WebView agent instant cold start, streaming via native HTTP
198
+ await engine.init({ useWebViewAgent: true })
161
199
 
162
200
  // Listen for streaming text
163
201
  engine.addListener('agentEvent', (event) => {
164
202
  if (event.eventType === 'text_delta') {
165
- process.stdout.write(event.data.text)
203
+ console.log(event.data.text)
166
204
  }
167
205
  })
168
206
 
@@ -189,12 +227,55 @@ const engine = new MobileClawEngine()
189
227
 
190
228
  await engine.init({
191
229
  tools: myTools,
192
- enableBridge: true,
230
+ useWebViewAgent: true,
231
+ })
232
+ ```
233
+
234
+ ### With Heartbeat Scheduling
235
+
236
+ ```typescript
237
+ const engine = new MobileClawEngine()
238
+ await engine.init({ useWebViewAgent: true, mobileCron: MobileCron })
239
+
240
+ // Enable scheduler + heartbeat (runs every 30 minutes)
241
+ await engine.setSchedulerConfig({ enabled: true, schedulingMode: 'balanced' })
242
+ await engine.setHeartbeat({ enabled: true, everyMs: 1800000 })
243
+
244
+ // Listen for heartbeat results
245
+ engine.addListener('heartbeatCompleted', (event) => {
246
+ console.log(`Heartbeat: ${event.status} (${event.durationMs}ms)`)
247
+ })
248
+
249
+ // Manual trigger
250
+ await engine.triggerHeartbeatWake('manual')
251
+ ```
252
+
253
+ ### With Cron Jobs
254
+
255
+ ```typescript
256
+ // Create a skill (reusable prompt + tool constraints)
257
+ const skill = await engine.addSkill({
258
+ name: 'daily-summary',
259
+ maxTurns: 3,
260
+ timeoutMs: 60000,
261
+ })
262
+
263
+ // Schedule a cron job
264
+ await engine.addCronJob({
265
+ name: 'morning-briefing',
266
+ enabled: true,
267
+ sessionTarget: 'isolated',
268
+ schedule: { kind: 'every', everyMs: 86400000 }, // 24h
269
+ skillId: skill.id,
270
+ prompt: 'Summarize my workspace changes since yesterday',
271
+ deliveryMode: 'notification',
193
272
  })
194
273
  ```
195
274
 
196
275
  ## Features
197
276
 
277
+ - **Two agent modes** — WebView (instant cold start) or Node.js worker (full isolation)
278
+ - **Native streaming HTTP** — OkHttp (Android) + URLSession (iOS) bypass CORS, stream SSE chunks as `ReadableStream`
198
279
  - **Real-time streaming** — text deltas, tool use, and thinking events
199
280
  - **Multi-turn conversations** — session persistence via native SQLite
200
281
  - **OAuth PKCE + API key** — sign in with Claude Max or use a direct API key
@@ -202,8 +283,12 @@ await engine.init({
202
283
  - **Code execution** — JavaScript (sandbox) + Python (Pyodide/WebAssembly)
203
284
  - **Git** — clone, commit, push, diff via isomorphic-git
204
285
  - **MCP device tools** — extensible via Model Context Protocol
205
- - **Tool approval gate** — approve/deny tool executions before they run
286
+ - **Tool approval gate** — approve/deny tool executions before they run (120s TTL)
206
287
  - **Agent steering** — inject follow-up instructions into a running turn
288
+ - **Background heartbeat** — scheduled agent check-ins via MobileCron + WorkManager
289
+ - **Cron jobs** — recurring agent tasks with skills, schedules, and delivery modes
290
+ - **On-device vector memory** — store/recall/search via LanceDB (capacitor-lancedb)
291
+ - **Vite plugin** — stubs Node.js-only transitive deps for browser bundling
207
292
 
208
293
  ## API Reference
209
294
 
@@ -211,18 +296,38 @@ await engine.init({
211
296
 
212
297
  | Method | Description |
213
298
  |--------|-------------|
214
- | `init(options?)` | Start the Node.js worker and MCP bridge |
299
+ | `init(options?)` | Start engine. Options: `useWebViewAgent`, `tools`, `mobileCron`, `enableBridge`, `enableStomp` |
215
300
  | `sendMessage(prompt, agentId?)` | Send a prompt to the agent |
216
301
  | `stopTurn()` | Cancel the running agent turn |
217
- | `approveTool(toolCallId, approved)` | Approve/deny a tool execution |
302
+ | `respondToPreExecute(toolCallId, args, deny?)` | Approve/deny a tool execution |
218
303
  | `steerAgent(text)` | Inject a follow-up instruction |
219
- | `updateConfig(config)` | Update worker config (auth, model, etc.) |
220
- | `getAuthStatus()` | Get current auth profile status |
221
- | `getModels()` | List available models |
304
+ | `updateConfig(config)` | Update config (auth, model, provider) |
305
+ | `exchangeOAuthCode(tokenUrl, body)` | OAuth token exchange via native HTTP |
306
+ | `getAuthStatus(provider?)` | Get current auth profile status |
307
+ | `getModels(provider?)` | List available models |
222
308
  | `readFile(path)` / `writeFile(path, content)` | Workspace file operations |
223
309
  | `listSessions()` / `resumeSession(key)` | Session management |
224
310
  | `invokeTool(toolName, args?)` | Call a tool directly |
225
- | `addListener(eventName, handler)` | Subscribe to agent events |
311
+ | `addListener(eventName, handler)` | Subscribe to events |
312
+
313
+ #### Scheduler & Heartbeat
314
+
315
+ | Method | Description |
316
+ |--------|-------------|
317
+ | `setSchedulerConfig(config)` | Set scheduler state (enabled, mode, runOnCharging, activeHours) |
318
+ | `getSchedulerConfig()` | Read scheduler + heartbeat config |
319
+ | `setHeartbeat(config)` | Configure heartbeat (enabled, interval, skillId, prompt) |
320
+ | `triggerHeartbeatWake(source?)` | Trigger immediate heartbeat (`manual` bypasses scheduler gate) |
321
+
322
+ #### Cron Jobs & Skills
323
+
324
+ | Method | Description |
325
+ |--------|-------------|
326
+ | `addCronJob(job)` / `updateCronJob(id, patch)` / `removeCronJob(id)` | CRUD for cron jobs |
327
+ | `listCronJobs()` / `runCronJob(id)` | List or manually trigger a job |
328
+ | `getCronRunHistory(jobId?, limit?)` | Get historical run records |
329
+ | `addSkill(skill)` / `updateSkill(id, patch)` / `removeSkill(id)` | CRUD for skills |
330
+ | `listSkills()` | List all defined skills |
226
331
 
227
332
  ### Events
228
333
 
@@ -231,8 +336,11 @@ await engine.init({
231
336
  | `agentEvent` | Text delta, tool use, tool result, or thinking update |
232
337
  | `agentCompleted` | Agent turn finished (includes token usage) |
233
338
  | `agentError` | Agent execution failed |
234
- | `toolApprovalRequest` | Agent wants to run a tool (approval gate) |
339
+ | `toolPreExecute` | Agent wants to run a tool (approval gate) |
235
340
  | `workerReady` | Node.js worker initialized |
341
+ | `heartbeatStarted` / `heartbeatCompleted` / `heartbeatSkipped` | Heartbeat lifecycle |
342
+ | `cronJobStarted` / `cronJobCompleted` / `cronJobError` | Cron job lifecycle |
343
+ | `schedulerStatus` | Scheduler state changed (next run times) |
236
344
 
237
345
  ## Documentation
238
346
 
@@ -243,6 +351,8 @@ await engine.init({
243
351
  ## Related Packages
244
352
 
245
353
  - [capacitor-mobile-claw-device-tools](https://www.npmjs.com/package/capacitor-mobile-claw-device-tools) — 64+ pre-built device tools (camera, clipboard, sensors, SSH, etc.)
354
+ - [capacitor-lancedb](https://www.npmjs.com/package/capacitor-lancedb) — on-device vector database for agent memory
355
+ - [capacitor-mobilecron](https://www.npmjs.com/package/capacitor-mobilecron) — native background scheduling (WorkManager / BGTaskScheduler)
246
356
 
247
357
  ## Contributing
248
358
 
@@ -255,13 +365,17 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup, workflow, and guid
255
365
  | Mobile framework | [Capacitor 8](https://capacitorjs.com/) |
256
366
  | Agent core | [Pi](https://www.npmjs.com/package/@mariozechner/pi-ai) by Mario Zechner |
257
367
  | Embedded runtime | [@choreruiz/capacitor-node-js](https://github.com/rogelioRuiz/capacitor-node-js) |
368
+ | Native HTTP | OkHttp (Android) + URLSession (iOS) — streaming, CORS bypass |
258
369
  | Tool protocol | [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) |
259
370
  | LLM provider | [Anthropic Claude](https://anthropic.com/) |
371
+ | Vector memory | [LanceDB](https://lancedb.com/) via [capacitor-lancedb](https://www.npmjs.com/package/capacitor-lancedb) |
372
+ | Background scheduling | [capacitor-mobilecron](https://www.npmjs.com/package/capacitor-mobilecron) (WorkManager / BGTaskScheduler) |
260
373
  | Git | [isomorphic-git](https://isomorphic-git.org/) |
261
374
  | Database | [@capacitor-community/sqlite](https://github.com/nicepkg/capacitor-community-sqlite) (native SQLite via JSON-RPC bridge) |
262
375
  | Python | [Pyodide](https://pyodide.org/) (CPython via WebAssembly) |
263
376
  | Type system | TypeScript (strict mode) |
264
- | Tests | [Vitest](https://vitest.dev/) |
377
+ | Lint | [Biome](https://biomejs.dev/) |
378
+ | Tests | [Vitest](https://vitest.dev/) (64 unit) + Sentinel E2E (111 on-device) |
265
379
 
266
380
  ## Acknowledgments
267
381
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "capacitor-mobile-claw",
3
- "version": "1.6.3",
3
+ "version": "1.6.4",
4
4
  "description": "On-device AI agent engine for Capacitor apps — embedded Node.js worker with LLM, file tools, code execution, git, and extensible MCP server",
5
5
  "main": "dist/esm/index.js",
6
6
  "types": "dist/esm/index.d.ts",