capacitor-native-agent 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,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Techxagon
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,167 @@
1
+ # capacitor-native-agent
2
+
3
+ Native AI agent loop for Capacitor apps. Runs LLM completions, tool execution, cron jobs, and session persistence in native Rust via UniFFI, enabling true background execution on mobile.
4
+
5
+ ## Features
6
+
7
+ - **Native agent loop** — LLM streaming, multi-turn tool calling, abort/steer
8
+ - **Built-in tools** — File I/O, git (libgit2), grep, shell exec, fetch
9
+ - **SQLite persistence** — Sessions, cron jobs, skills, scheduler/heartbeat config
10
+ - **Background execution** — Runs outside the WebView lifecycle (WorkManager / BGProcessingTask)
11
+ - **Auth management** — API key and OAuth token storage with refresh
12
+ - **Cron & heartbeat** — Scheduled agent runs with wake evaluation
13
+ - **MCP support** — Model Context Protocol server integration
14
+ - **Event bridge** — Streams events (text_delta, tool_use, tool_result, etc.) to the WebView
15
+
16
+ ## Install
17
+
18
+ ```bash
19
+ npm install capacitor-native-agent
20
+ npx cap sync
21
+ ```
22
+
23
+ ## Android Setup
24
+
25
+ The npm package includes the Kotlin plugin source and UniFFI bindings, but **not** the compiled Rust shared library. You must build and place it yourself:
26
+
27
+ ### 1. Build the Rust .so
28
+
29
+ ```bash
30
+ cd rust/native-agent-ffi
31
+ cargo ndk -t arm64-v8a build --release
32
+ ```
33
+
34
+ ### 2. Place the .so in your app
35
+
36
+ Copy the built library to your Android app's jniLibs:
37
+
38
+ ```bash
39
+ cp target/aarch64-linux-android/release/libnative_agent_ffi.so \
40
+ <your-app>/android/app/src/main/jniLibs/arm64-v8a/
41
+ ```
42
+
43
+ ### 3. Sync and build
44
+
45
+ ```bash
46
+ npx cap sync android
47
+ cd android && ./gradlew assembleDebug
48
+ ```
49
+
50
+ ## Usage
51
+
52
+ ```typescript
53
+ import { NativeAgent } from 'capacitor-native-agent'
54
+
55
+ // Listen for agent events
56
+ NativeAgent.addListener('nativeAgentEvent', (event) => {
57
+ const { eventType, payloadJson } = event
58
+ const payload = JSON.parse(payloadJson)
59
+
60
+ if (eventType === 'text_delta') {
61
+ process.stdout.write(payload.text)
62
+ }
63
+ })
64
+
65
+ // Initialize
66
+ await NativeAgent.initialize({
67
+ dbPath: 'files://agent.db',
68
+ workspacePath: '/path/to/workspace',
69
+ authProfilesPath: '/path/to/auth-profiles.json',
70
+ })
71
+
72
+ // Set auth
73
+ await NativeAgent.setAuthKey({
74
+ key: 'sk-ant-...',
75
+ provider: 'anthropic',
76
+ authType: 'api_key',
77
+ })
78
+
79
+ // Send a message
80
+ const { runId } = await NativeAgent.sendMessage({
81
+ prompt: 'Hello!',
82
+ sessionKey: 'session-1',
83
+ systemPrompt: 'You are a helpful assistant.',
84
+ })
85
+ ```
86
+
87
+ ## API
88
+
89
+ See [definitions.ts](src/definitions.ts) for the full TypeScript interface.
90
+
91
+ ### Core Methods
92
+
93
+ | Method | Description |
94
+ |--------|-------------|
95
+ | `initialize()` | Create the native agent handle |
96
+ | `sendMessage()` | Start an agent turn |
97
+ | `followUp()` | Continue the conversation |
98
+ | `abort()` | Cancel the running turn |
99
+ | `steer()` | Inject guidance into a running turn |
100
+
101
+ ### Auth
102
+
103
+ | Method | Description |
104
+ |--------|-------------|
105
+ | `getAuthToken()` | Get stored auth token |
106
+ | `setAuthKey()` | Store API key or OAuth token |
107
+ | `deleteAuth()` | Remove auth for a provider |
108
+ | `refreshToken()` | Refresh an OAuth token |
109
+ | `getAuthStatus()` | Get masked key status |
110
+
111
+ ### Sessions
112
+
113
+ | Method | Description |
114
+ |--------|-------------|
115
+ | `listSessions()` | List all sessions |
116
+ | `loadSession()` | Load session message history |
117
+ | `resumeSession()` | Resume a previous session |
118
+ | `clearSession()` | Clear current session |
119
+
120
+ ### Cron & Scheduling
121
+
122
+ | Method | Description |
123
+ |--------|-------------|
124
+ | `addCronJob()` | Create a scheduled job |
125
+ | `updateCronJob()` | Update job config |
126
+ | `removeCronJob()` | Delete a job |
127
+ | `listCronJobs()` | List all jobs |
128
+ | `runCronJob()` | Force-trigger a job |
129
+ | `handleWake()` | Evaluate due jobs (called from WorkManager) |
130
+ | `getSchedulerConfig()` | Get scheduler + heartbeat config |
131
+ | `setSchedulerConfig()` | Update scheduler config |
132
+ | `setHeartbeatConfig()` | Update heartbeat config |
133
+
134
+ ### Tools
135
+
136
+ | Method | Description |
137
+ |--------|-------------|
138
+ | `invokeTool()` | Execute a tool directly |
139
+ | `startMcp()` | Start MCP server |
140
+ | `restartMcp()` | Restart MCP with new tools |
141
+
142
+ ## Event Types
143
+
144
+ Events are emitted via `addListener('nativeAgentEvent', handler)`:
145
+
146
+ - `text_delta` — Streaming text chunk
147
+ - `thinking` — Model thinking content
148
+ - `tool_use` — Tool invocation started
149
+ - `tool_result` — Tool completed
150
+ - `agent.completed` — Turn finished with usage stats
151
+ - `agent.error` — Error occurred
152
+ - `approval_request` — Tool needs user approval
153
+ - `cron.job.started` / `cron.job.completed` / `cron.job.error` — Cron lifecycle
154
+ - `heartbeat.*` — Heartbeat lifecycle
155
+ - `scheduler.status` — Scheduler state updates
156
+
157
+ ## Platform Support
158
+
159
+ | Platform | Status |
160
+ |----------|--------|
161
+ | Android | Supported |
162
+ | iOS | Not yet implemented |
163
+ | Web | N/A (throws unavailable error) |
164
+
165
+ ## License
166
+
167
+ MIT
@@ -0,0 +1,27 @@
1
+ apply plugin: 'com.android.library'
2
+ apply plugin: 'kotlin-android'
3
+
4
+ android {
5
+ namespace 'com.t6x.plugins.nativeagent'
6
+ compileSdk 36
7
+ defaultConfig {
8
+ minSdkVersion 23
9
+ targetSdkVersion 36
10
+ }
11
+ compileOptions {
12
+ sourceCompatibility JavaVersion.VERSION_17
13
+ targetCompatibility JavaVersion.VERSION_17
14
+ }
15
+ }
16
+
17
+ kotlin {
18
+ compilerOptions {
19
+ jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17
20
+ }
21
+ }
22
+
23
+ dependencies {
24
+ implementation project(':capacitor-android')
25
+ implementation 'net.java.dev.jna:jna:5.14.0@aar'
26
+ implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.1'
27
+ }
@@ -0,0 +1,397 @@
1
+ package com.t6x.plugins.nativeagent
2
+
3
+ import com.getcapacitor.JSObject
4
+ import com.getcapacitor.Plugin
5
+ import com.getcapacitor.PluginCall
6
+ import com.getcapacitor.PluginMethod
7
+ import com.getcapacitor.annotation.CapacitorPlugin
8
+ import kotlinx.coroutines.CoroutineScope
9
+ import kotlinx.coroutines.Dispatchers
10
+ import kotlinx.coroutines.SupervisorJob
11
+ import kotlinx.coroutines.cancel
12
+ import kotlinx.coroutines.launch
13
+ import uniffi.native_agent_ffi.InitConfig
14
+ import uniffi.native_agent_ffi.NativeAgentHandle
15
+ import uniffi.native_agent_ffi.NativeEventCallback
16
+ import uniffi.native_agent_ffi.SendMessageParams
17
+
18
+ @CapacitorPlugin(name = "NativeAgent")
19
+ class NativeAgentPlugin : Plugin() {
20
+
21
+ private var handle: NativeAgentHandle? = null
22
+ private val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())
23
+
24
+ // ── Helper: wrap common pattern ────────────────────────────────────
25
+
26
+ private inline fun withHandle(call: PluginCall, block: (NativeAgentHandle) -> Unit) {
27
+ val h = handle ?: return call.reject("NativeAgent not initialized — call initialize() first")
28
+ scope.launch {
29
+ try {
30
+ block(h)
31
+ } catch (e: Exception) {
32
+ call.reject("${call.methodName} failed: ${e.message}", e)
33
+ }
34
+ }
35
+ }
36
+
37
+ // ── Lifecycle ──────────────────────────────────────────────────────
38
+
39
+ @PluginMethod
40
+ fun initialize(call: PluginCall) {
41
+ val dbPath = call.getString("dbPath")
42
+ ?: return call.reject("dbPath is required")
43
+ val workspacePath = call.getString("workspacePath")
44
+ ?: return call.reject("workspacePath is required")
45
+ val authProfilesPath = call.getString("authProfilesPath")
46
+ ?: return call.reject("authProfilesPath is required")
47
+
48
+ scope.launch {
49
+ try {
50
+ val config = InitConfig(
51
+ dbPath = resolvePath(dbPath),
52
+ workspacePath = resolvePath(workspacePath),
53
+ authProfilesPath = resolvePath(authProfilesPath),
54
+ )
55
+ val h = NativeAgentHandle(config)
56
+ h.setEventCallback(object : NativeEventCallback {
57
+ override fun onEvent(eventType: String, payloadJson: String) {
58
+ val data = JSObject()
59
+ data.put("eventType", eventType)
60
+ data.put("payloadJson", payloadJson)
61
+ notifyListeners("nativeAgentEvent", data)
62
+ }
63
+ })
64
+ handle = h
65
+ call.resolve()
66
+ } catch (e: Exception) {
67
+ call.reject("Failed to initialize NativeAgent: ${e.message}", e)
68
+ }
69
+ }
70
+ }
71
+
72
+ // ── Agent ──────────────────────────────────────────────────────────
73
+
74
+ @PluginMethod
75
+ fun sendMessage(call: PluginCall) = withHandle(call) { h ->
76
+ val params = SendMessageParams(
77
+ prompt = call.getString("prompt") ?: return@withHandle call.reject("prompt is required"),
78
+ sessionKey = call.getString("sessionKey") ?: return@withHandle call.reject("sessionKey is required"),
79
+ model = call.getString("model"),
80
+ provider = call.getString("provider"),
81
+ systemPrompt = call.getString("systemPrompt") ?: return@withHandle call.reject("systemPrompt is required"),
82
+ maxTurns = call.getInt("maxTurns")?.toUInt(),
83
+ allowedToolsJson = call.getString("allowedToolsJson"),
84
+ )
85
+ val runId = h.sendMessage(params)
86
+ val ret = JSObject()
87
+ ret.put("runId", runId)
88
+ call.resolve(ret)
89
+ }
90
+
91
+ @PluginMethod
92
+ fun followUp(call: PluginCall) = withHandle(call) { h ->
93
+ h.followUp(call.getString("prompt") ?: "")
94
+ call.resolve()
95
+ }
96
+
97
+ @PluginMethod
98
+ fun abort(call: PluginCall) = withHandle(call) { h ->
99
+ h.abort()
100
+ call.resolve()
101
+ }
102
+
103
+ @PluginMethod
104
+ fun steer(call: PluginCall) = withHandle(call) { h ->
105
+ h.steer(call.getString("text") ?: "")
106
+ call.resolve()
107
+ }
108
+
109
+ // ── Approval gate ──────────────────────────────────────────────────
110
+
111
+ @PluginMethod
112
+ fun respondToApproval(call: PluginCall) = withHandle(call) { h ->
113
+ h.respondToApproval(
114
+ call.getString("toolCallId") ?: return@withHandle call.reject("toolCallId is required"),
115
+ call.getBoolean("approved") ?: true,
116
+ call.getString("reason"),
117
+ )
118
+ call.resolve()
119
+ }
120
+
121
+ @PluginMethod
122
+ fun respondToCronApproval(call: PluginCall) = withHandle(call) { h ->
123
+ h.respondToCronApproval(
124
+ call.getString("requestId") ?: return@withHandle call.reject("requestId is required"),
125
+ call.getBoolean("approved") ?: false,
126
+ )
127
+ call.resolve()
128
+ }
129
+
130
+ // ── Auth ──────────────────────────────────────────────────────────
131
+
132
+ @PluginMethod
133
+ fun getAuthToken(call: PluginCall) = withHandle(call) { h ->
134
+ val result = h.getAuthToken(call.getString("provider") ?: "anthropic")
135
+ val ret = JSObject()
136
+ ret.put("apiKey", result.apiKey)
137
+ ret.put("isOAuth", result.isOauth)
138
+ call.resolve(ret)
139
+ }
140
+
141
+ @PluginMethod
142
+ fun setAuthKey(call: PluginCall) = withHandle(call) { h ->
143
+ h.setAuthKey(
144
+ call.getString("key") ?: return@withHandle call.reject("key is required"),
145
+ call.getString("provider") ?: "anthropic",
146
+ call.getString("authType") ?: "api_key",
147
+ )
148
+ call.resolve()
149
+ }
150
+
151
+ @PluginMethod
152
+ fun deleteAuth(call: PluginCall) = withHandle(call) { h ->
153
+ h.deleteAuth(call.getString("provider") ?: "anthropic")
154
+ call.resolve()
155
+ }
156
+
157
+ @PluginMethod
158
+ fun refreshToken(call: PluginCall) = withHandle(call) { h ->
159
+ val result = h.refreshToken(call.getString("provider") ?: "anthropic")
160
+ val ret = JSObject()
161
+ ret.put("apiKey", result.apiKey)
162
+ ret.put("isOAuth", result.isOauth)
163
+ call.resolve(ret)
164
+ }
165
+
166
+ @PluginMethod
167
+ fun getAuthStatus(call: PluginCall) = withHandle(call) { h ->
168
+ val result = h.getAuthStatus(call.getString("provider") ?: "anthropic")
169
+ val ret = JSObject()
170
+ ret.put("hasKey", result.hasKey)
171
+ ret.put("masked", result.masked)
172
+ ret.put("provider", result.provider)
173
+ call.resolve(ret)
174
+ }
175
+
176
+ // ── Sessions ──────────────────────────────────────────────────────
177
+
178
+ @PluginMethod
179
+ fun listSessions(call: PluginCall) = withHandle(call) { h ->
180
+ val json = h.listSessions(call.getString("agentId") ?: "main")
181
+ val ret = JSObject()
182
+ ret.put("sessionsJson", json)
183
+ call.resolve(ret)
184
+ }
185
+
186
+ @PluginMethod
187
+ fun loadSession(call: PluginCall) = withHandle(call) { h ->
188
+ val sessKey = call.getString("sessionKey") ?: return@withHandle call.reject("sessionKey is required")
189
+ val json = h.loadSession(sessKey)
190
+ val ret = JSObject()
191
+ ret.put("sessionKey", sessKey)
192
+ ret.put("messagesJson", json)
193
+ call.resolve(ret)
194
+ }
195
+
196
+ @PluginMethod
197
+ fun resumeSession(call: PluginCall) = withHandle(call) { h ->
198
+ h.resumeSession(
199
+ call.getString("sessionKey") ?: return@withHandle call.reject("sessionKey is required"),
200
+ call.getString("agentId") ?: "main",
201
+ call.getString("messagesJson"),
202
+ call.getString("provider"),
203
+ call.getString("model"),
204
+ )
205
+ call.resolve()
206
+ }
207
+
208
+ @PluginMethod
209
+ fun clearSession(call: PluginCall) = withHandle(call) { h ->
210
+ h.clearSession()
211
+ call.resolve()
212
+ }
213
+
214
+ // ── Cron / heartbeat ──────────────────────────────────────────────
215
+
216
+ @PluginMethod
217
+ fun addCronJob(call: PluginCall) = withHandle(call) { h ->
218
+ val json = h.addCronJob(call.getString("inputJson") ?: return@withHandle call.reject("inputJson is required"))
219
+ val ret = JSObject()
220
+ ret.put("recordJson", json)
221
+ call.resolve(ret)
222
+ }
223
+
224
+ @PluginMethod
225
+ fun updateCronJob(call: PluginCall) = withHandle(call) { h ->
226
+ h.updateCronJob(
227
+ call.getString("id") ?: return@withHandle call.reject("id is required"),
228
+ call.getString("patchJson") ?: "{}",
229
+ )
230
+ call.resolve()
231
+ }
232
+
233
+ @PluginMethod
234
+ fun removeCronJob(call: PluginCall) = withHandle(call) { h ->
235
+ h.removeCronJob(call.getString("id") ?: return@withHandle call.reject("id is required"))
236
+ call.resolve()
237
+ }
238
+
239
+ @PluginMethod
240
+ fun listCronJobs(call: PluginCall) = withHandle(call) { h ->
241
+ val ret = JSObject()
242
+ ret.put("jobsJson", h.listCronJobs())
243
+ call.resolve(ret)
244
+ }
245
+
246
+ @PluginMethod
247
+ fun runCronJob(call: PluginCall) = withHandle(call) { h ->
248
+ h.runCronJob(call.getString("jobId") ?: return@withHandle call.reject("jobId is required"))
249
+ call.resolve()
250
+ }
251
+
252
+ @PluginMethod
253
+ fun listCronRuns(call: PluginCall) = withHandle(call) { h ->
254
+ val json = h.listCronRuns(
255
+ call.getString("jobId"),
256
+ (call.getInt("limit") ?: 100).toLong(),
257
+ )
258
+ val ret = JSObject()
259
+ ret.put("runsJson", json)
260
+ call.resolve(ret)
261
+ }
262
+
263
+ @PluginMethod
264
+ fun handleWake(call: PluginCall) = withHandle(call) { h ->
265
+ h.handleWake(call.getString("source") ?: "unknown")
266
+ call.resolve()
267
+ }
268
+
269
+ @PluginMethod
270
+ fun getSchedulerConfig(call: PluginCall) = withHandle(call) { h ->
271
+ val schedulerJson = h.getSchedulerConfig()
272
+ val heartbeatJson = h.getHeartbeatConfig()
273
+ val ret = JSObject()
274
+ ret.put("schedulerJson", schedulerJson)
275
+ ret.put("heartbeatJson", heartbeatJson)
276
+ call.resolve(ret)
277
+ }
278
+
279
+ @PluginMethod
280
+ fun setSchedulerConfig(call: PluginCall) = withHandle(call) { h ->
281
+ h.setSchedulerConfig(call.getString("configJson") ?: "{}")
282
+ call.resolve()
283
+ }
284
+
285
+ @PluginMethod
286
+ fun setHeartbeatConfig(call: PluginCall) = withHandle(call) { h ->
287
+ h.setHeartbeatConfig(call.getString("configJson") ?: "{}")
288
+ call.resolve()
289
+ }
290
+
291
+ // ── Skills ────────────────────────────────────────────────────────
292
+
293
+ @PluginMethod
294
+ fun addSkill(call: PluginCall) = withHandle(call) { h ->
295
+ val json = h.addSkill(call.getString("inputJson") ?: return@withHandle call.reject("inputJson is required"))
296
+ val ret = JSObject()
297
+ ret.put("recordJson", json)
298
+ call.resolve(ret)
299
+ }
300
+
301
+ @PluginMethod
302
+ fun updateSkill(call: PluginCall) = withHandle(call) { h ->
303
+ h.updateSkill(
304
+ call.getString("id") ?: return@withHandle call.reject("id is required"),
305
+ call.getString("patchJson") ?: "{}",
306
+ )
307
+ call.resolve()
308
+ }
309
+
310
+ @PluginMethod
311
+ fun removeSkill(call: PluginCall) = withHandle(call) { h ->
312
+ h.removeSkill(call.getString("id") ?: return@withHandle call.reject("id is required"))
313
+ call.resolve()
314
+ }
315
+
316
+ @PluginMethod
317
+ fun listSkills(call: PluginCall) = withHandle(call) { h ->
318
+ val ret = JSObject()
319
+ ret.put("skillsJson", h.listSkills())
320
+ call.resolve(ret)
321
+ }
322
+
323
+ @PluginMethod
324
+ fun startSkill(call: PluginCall) = withHandle(call) { h ->
325
+ val sessKey = h.startSkill(
326
+ call.getString("skillId") ?: return@withHandle call.reject("skillId is required"),
327
+ call.getString("configJson") ?: "{}",
328
+ call.getString("provider"),
329
+ )
330
+ val ret = JSObject()
331
+ ret.put("sessionKey", sessKey)
332
+ call.resolve(ret)
333
+ }
334
+
335
+ @PluginMethod
336
+ fun endSkill(call: PluginCall) = withHandle(call) { h ->
337
+ h.endSkill(call.getString("skillId") ?: return@withHandle call.reject("skillId is required"))
338
+ call.resolve()
339
+ }
340
+
341
+ // ── MCP ───────────────────────────────────────────────────────────
342
+
343
+ @PluginMethod
344
+ fun startMcp(call: PluginCall) = withHandle(call) { h ->
345
+ val count = h.startMcp(call.getString("toolsJson") ?: "[]")
346
+ val ret = JSObject()
347
+ ret.put("toolCount", count.toInt())
348
+ call.resolve(ret)
349
+ }
350
+
351
+ @PluginMethod
352
+ fun restartMcp(call: PluginCall) = withHandle(call) { h ->
353
+ val count = h.restartMcp(call.getString("toolsJson") ?: "[]")
354
+ val ret = JSObject()
355
+ ret.put("toolCount", count.toInt())
356
+ call.resolve(ret)
357
+ }
358
+
359
+ // ── Models ────────────────────────────────────────────────────────
360
+
361
+ @PluginMethod
362
+ fun getModels(call: PluginCall) = withHandle(call) { h ->
363
+ val json = h.getModels(call.getString("provider") ?: "anthropic")
364
+ val ret = JSObject()
365
+ ret.put("modelsJson", json)
366
+ call.resolve(ret)
367
+ }
368
+
369
+ // ── Tools ─────────────────────────────────────────────────────────
370
+
371
+ @PluginMethod
372
+ fun invokeTool(call: PluginCall) = withHandle(call) { h ->
373
+ val resultJson = h.invokeTool(
374
+ call.getString("toolName") ?: return@withHandle call.reject("toolName is required"),
375
+ call.getString("argsJson") ?: "{}",
376
+ )
377
+ val ret = JSObject()
378
+ ret.put("resultJson", resultJson)
379
+ call.resolve(ret)
380
+ }
381
+
382
+ // ── Cleanup ───────────────────────────────────────────────────────
383
+
384
+ override fun handleOnDestroy() {
385
+ scope.cancel()
386
+ handle = null
387
+ }
388
+
389
+ private fun resolvePath(path: String): String {
390
+ return if (path.startsWith("files://")) {
391
+ val rel = path.removePrefix("files://")
392
+ "${context.filesDir.absolutePath}/$rel"
393
+ } else {
394
+ path
395
+ }
396
+ }
397
+ }
@@ -0,0 +1,287 @@
1
+ /**
2
+ * Capacitor Native Agent — plugin definitions.
3
+ *
4
+ * Mirrors the UniFFI-exported API from Rust (NativeAgentHandle).
5
+ * The WebView engine.ts delegates ALL logic here — no agent logic in JS.
6
+ */
7
+ export interface InitConfig {
8
+ /** Path to the SQLite database */
9
+ dbPath: string;
10
+ /** Path to the workspace root */
11
+ workspacePath: string;
12
+ /** Path to auth-profiles.json */
13
+ authProfilesPath: string;
14
+ }
15
+ export interface SendMessageParams {
16
+ prompt: string;
17
+ sessionKey: string;
18
+ model?: string;
19
+ provider?: string;
20
+ systemPrompt: string;
21
+ maxTurns?: number;
22
+ /** JSON-encoded list of allowed tool names. Empty = all tools. */
23
+ allowedToolsJson?: string;
24
+ /** JSON-encoded extra tool definitions (account tools, MCP tools) */
25
+ extraToolsJson?: string;
26
+ }
27
+ export interface AuthTokenResult {
28
+ apiKey: string | null;
29
+ isOAuth: boolean;
30
+ }
31
+ export interface AuthStatusResult {
32
+ hasKey: boolean;
33
+ masked: string;
34
+ provider: string;
35
+ }
36
+ export interface SessionInfo {
37
+ sessionKey: string;
38
+ agentId: string;
39
+ updatedAt: number;
40
+ model?: string;
41
+ totalTokens?: number;
42
+ }
43
+ export interface SessionHistoryResult {
44
+ sessionKey: string;
45
+ /** JSON-encoded messages array */
46
+ messagesJson: string;
47
+ }
48
+ export interface SchedulerConfig {
49
+ enabled: boolean;
50
+ schedulingMode: string;
51
+ runOnCharging: boolean;
52
+ globalActiveHoursJson?: string;
53
+ }
54
+ export interface HeartbeatConfig {
55
+ enabled: boolean;
56
+ everyMs: number;
57
+ prompt?: string;
58
+ skillId?: string;
59
+ activeHoursJson?: string;
60
+ nextRunAt?: number;
61
+ lastHash?: string;
62
+ lastSentAt?: number;
63
+ }
64
+ export interface CronJobInput {
65
+ name: string;
66
+ enabled?: boolean;
67
+ sessionTarget?: string;
68
+ wakeMode?: string;
69
+ scheduleJson: string;
70
+ skillId: string;
71
+ prompt: string;
72
+ deliveryMode?: string;
73
+ deliveryWebhookUrl?: string;
74
+ deliveryNotificationTitle?: string;
75
+ activeHoursJson?: string;
76
+ }
77
+ export interface CronJobRecord {
78
+ id: string;
79
+ name: string;
80
+ enabled: boolean;
81
+ sessionTarget: string;
82
+ wakeMode: string;
83
+ scheduleJson: string;
84
+ skillId: string;
85
+ prompt: string;
86
+ deliveryMode: string;
87
+ deliveryWebhookUrl?: string;
88
+ deliveryNotificationTitle?: string;
89
+ activeHoursJson?: string;
90
+ lastRunAt?: number;
91
+ nextRunAt?: number;
92
+ lastRunStatus?: string;
93
+ lastError?: string;
94
+ lastDurationMs?: number;
95
+ consecutiveErrors: number;
96
+ createdAt: number;
97
+ updatedAt: number;
98
+ }
99
+ export interface CronRunRecord {
100
+ id: number;
101
+ jobId: string;
102
+ startedAt: number;
103
+ endedAt?: number;
104
+ status: string;
105
+ durationMs?: number;
106
+ error?: string;
107
+ responseText?: string;
108
+ wakeSource?: string;
109
+ }
110
+ export interface CronSkillInput {
111
+ name: string;
112
+ allowedToolsJson?: string;
113
+ systemPrompt?: string;
114
+ model?: string;
115
+ maxTurns?: number;
116
+ timeoutMs?: number;
117
+ }
118
+ export interface CronSkillRecord {
119
+ id: string;
120
+ name: string;
121
+ allowedToolsJson?: string;
122
+ systemPrompt?: string;
123
+ model?: string;
124
+ maxTurns?: number;
125
+ timeoutMs?: number;
126
+ createdAt: number;
127
+ updatedAt: number;
128
+ }
129
+ export interface ModelInfo {
130
+ id: string;
131
+ name: string;
132
+ description: string;
133
+ isDefault: boolean;
134
+ }
135
+ export interface TokenUsage {
136
+ inputTokens: number;
137
+ outputTokens: number;
138
+ totalTokens: number;
139
+ }
140
+ export type NativeAgentEventType = 'text_delta' | 'thinking' | 'tool_use' | 'tool_result' | 'user_message' | 'retry' | 'agent.completed' | 'agent.error' | 'approval_request' | 'wake.no_jobs' | 'wake.jobs_found' | 'max_turns_reached' | 'heartbeat.started' | 'heartbeat.completed' | 'heartbeat.skipped' | 'cron.job.started' | 'cron.job.completed' | 'cron.job.error' | 'cron.notification' | 'scheduler.status';
141
+ export interface NativeAgentEvent {
142
+ eventType: string;
143
+ payloadJson: string;
144
+ }
145
+ export interface NativeAgentPlugin {
146
+ initialize(config: InitConfig): Promise<void>;
147
+ sendMessage(params: SendMessageParams): Promise<{
148
+ runId: string;
149
+ }>;
150
+ followUp(options: {
151
+ prompt: string;
152
+ }): Promise<void>;
153
+ abort(): Promise<void>;
154
+ steer(options: {
155
+ text: string;
156
+ }): Promise<void>;
157
+ respondToApproval(options: {
158
+ toolCallId: string;
159
+ approved: boolean;
160
+ reason?: string;
161
+ }): Promise<void>;
162
+ getAuthToken(options: {
163
+ provider: string;
164
+ }): Promise<AuthTokenResult>;
165
+ setAuthKey(options: {
166
+ key: string;
167
+ provider: string;
168
+ authType: string;
169
+ }): Promise<void>;
170
+ deleteAuth(options: {
171
+ provider: string;
172
+ }): Promise<void>;
173
+ refreshToken(options: {
174
+ provider: string;
175
+ }): Promise<AuthTokenResult>;
176
+ getAuthStatus(options: {
177
+ provider: string;
178
+ }): Promise<AuthStatusResult>;
179
+ listSessions(options: {
180
+ agentId: string;
181
+ }): Promise<{
182
+ sessionsJson: string;
183
+ }>;
184
+ loadSession(options: {
185
+ sessionKey: string;
186
+ agentId: string;
187
+ }): Promise<SessionHistoryResult>;
188
+ resumeSession(options: {
189
+ sessionKey: string;
190
+ agentId: string;
191
+ messagesJson?: string;
192
+ provider?: string;
193
+ model?: string;
194
+ }): Promise<void>;
195
+ clearSession(): Promise<void>;
196
+ addCronJob(options: {
197
+ inputJson: string;
198
+ }): Promise<{
199
+ recordJson: string;
200
+ }>;
201
+ updateCronJob(options: {
202
+ id: string;
203
+ patchJson: string;
204
+ }): Promise<void>;
205
+ removeCronJob(options: {
206
+ id: string;
207
+ }): Promise<void>;
208
+ listCronJobs(): Promise<{
209
+ jobsJson: string;
210
+ }>;
211
+ runCronJob(options: {
212
+ jobId: string;
213
+ }): Promise<void>;
214
+ listCronRuns(options: {
215
+ jobId?: string;
216
+ limit?: number;
217
+ }): Promise<{
218
+ runsJson: string;
219
+ }>;
220
+ handleWake(options: {
221
+ source: string;
222
+ }): Promise<void>;
223
+ getSchedulerConfig(): Promise<{
224
+ schedulerJson: string;
225
+ heartbeatJson: string;
226
+ }>;
227
+ setSchedulerConfig(options: {
228
+ configJson: string;
229
+ }): Promise<void>;
230
+ setHeartbeatConfig(options: {
231
+ configJson: string;
232
+ }): Promise<void>;
233
+ respondToCronApproval(options: {
234
+ requestId: string;
235
+ approved: boolean;
236
+ }): Promise<void>;
237
+ addSkill(options: {
238
+ inputJson: string;
239
+ }): Promise<{
240
+ recordJson: string;
241
+ }>;
242
+ updateSkill(options: {
243
+ id: string;
244
+ patchJson: string;
245
+ }): Promise<void>;
246
+ removeSkill(options: {
247
+ id: string;
248
+ }): Promise<void>;
249
+ listSkills(): Promise<{
250
+ skillsJson: string;
251
+ }>;
252
+ startSkill(options: {
253
+ skillId: string;
254
+ configJson: string;
255
+ provider?: string;
256
+ }): Promise<{
257
+ sessionKey: string;
258
+ }>;
259
+ endSkill(options: {
260
+ skillId: string;
261
+ }): Promise<void>;
262
+ startMcp(options: {
263
+ toolsJson: string;
264
+ }): Promise<{
265
+ toolCount: number;
266
+ }>;
267
+ restartMcp(options: {
268
+ toolsJson: string;
269
+ }): Promise<{
270
+ toolCount: number;
271
+ }>;
272
+ getModels(options: {
273
+ provider: string;
274
+ }): Promise<{
275
+ modelsJson: string;
276
+ }>;
277
+ invokeTool(options: {
278
+ toolName: string;
279
+ argsJson: string;
280
+ }): Promise<{
281
+ resultJson: string;
282
+ }>;
283
+ addListener(eventName: 'nativeAgentEvent', handler: (event: NativeAgentEvent) => void): Promise<{
284
+ remove: () => Promise<void>;
285
+ }>;
286
+ }
287
+ //# sourceMappingURL=definitions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"definitions.d.ts","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Capacitor Native Agent — plugin definitions.
3
+ *
4
+ * Mirrors the UniFFI-exported API from Rust (NativeAgentHandle).
5
+ * The WebView engine.ts delegates ALL logic here — no agent logic in JS.
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=definitions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
@@ -0,0 +1,3 @@
1
+ export type { AuthStatusResult, AuthTokenResult, CronJobInput, CronJobRecord, CronRunRecord, CronSkillInput, CronSkillRecord, HeartbeatConfig, InitConfig, ModelInfo, NativeAgentEvent, NativeAgentEventType, NativeAgentPlugin, SchedulerConfig, SendMessageParams, SessionHistoryResult, SessionInfo, TokenUsage, } from './definitions';
2
+ export { NativeAgent } from './plugin';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,gBAAgB,EAChB,eAAe,EACf,YAAY,EACZ,aAAa,EACb,aAAa,EACb,cAAc,EACd,eAAe,EACf,eAAe,EACf,UAAU,EACV,SAAS,EACT,gBAAgB,EAChB,oBAAoB,EACpB,iBAAiB,EACjB,eAAe,EACf,iBAAiB,EACjB,oBAAoB,EACpB,WAAW,EACX,UAAU,GACX,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA"}
@@ -0,0 +1,2 @@
1
+ export { NativeAgent } from './plugin';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAoBA,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA"}
@@ -0,0 +1,3 @@
1
+ import type { NativeAgentPlugin } from './definitions';
2
+ export declare const NativeAgent: NativeAgentPlugin;
3
+ //# sourceMappingURL=plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/plugin.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AA2CtD,eAAO,MAAM,WAAW,mBAEtB,CAAA"}
@@ -0,0 +1,44 @@
1
+ import { registerPlugin, WebPlugin } from '@capacitor/core';
2
+ const ERR = 'NativeAgent is only available on native platforms.';
3
+ class NativeAgentWeb extends WebPlugin {
4
+ async initialize() { throw this.unavailable(ERR); }
5
+ async sendMessage() { throw this.unavailable(ERR); }
6
+ async followUp() { throw this.unavailable(ERR); }
7
+ async abort() { throw this.unavailable(ERR); }
8
+ async steer() { throw this.unavailable(ERR); }
9
+ async respondToApproval() { throw this.unavailable(ERR); }
10
+ async getAuthToken() { throw this.unavailable(ERR); }
11
+ async setAuthKey() { throw this.unavailable(ERR); }
12
+ async deleteAuth() { throw this.unavailable(ERR); }
13
+ async refreshToken() { throw this.unavailable(ERR); }
14
+ async getAuthStatus() { throw this.unavailable(ERR); }
15
+ async listSessions() { throw this.unavailable(ERR); }
16
+ async loadSession() { throw this.unavailable(ERR); }
17
+ async resumeSession() { throw this.unavailable(ERR); }
18
+ async clearSession() { throw this.unavailable(ERR); }
19
+ async addCronJob() { throw this.unavailable(ERR); }
20
+ async updateCronJob() { throw this.unavailable(ERR); }
21
+ async removeCronJob() { throw this.unavailable(ERR); }
22
+ async listCronJobs() { throw this.unavailable(ERR); }
23
+ async runCronJob() { throw this.unavailable(ERR); }
24
+ async listCronRuns() { throw this.unavailable(ERR); }
25
+ async handleWake() { throw this.unavailable(ERR); }
26
+ async getSchedulerConfig() { throw this.unavailable(ERR); }
27
+ async setSchedulerConfig() { throw this.unavailable(ERR); }
28
+ async setHeartbeatConfig() { throw this.unavailable(ERR); }
29
+ async respondToCronApproval() { throw this.unavailable(ERR); }
30
+ async addSkill() { throw this.unavailable(ERR); }
31
+ async updateSkill() { throw this.unavailable(ERR); }
32
+ async removeSkill() { throw this.unavailable(ERR); }
33
+ async listSkills() { throw this.unavailable(ERR); }
34
+ async startSkill() { throw this.unavailable(ERR); }
35
+ async endSkill() { throw this.unavailable(ERR); }
36
+ async startMcp() { throw this.unavailable(ERR); }
37
+ async restartMcp() { throw this.unavailable(ERR); }
38
+ async getModels() { throw this.unavailable(ERR); }
39
+ async invokeTool() { throw this.unavailable(ERR); }
40
+ }
41
+ export const NativeAgent = registerPlugin('NativeAgent', {
42
+ web: () => Promise.resolve(new NativeAgentWeb()),
43
+ });
44
+ //# sourceMappingURL=plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../../src/plugin.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,61 @@
1
+ {
2
+ "name": "capacitor-native-agent",
3
+ "version": "0.1.0",
4
+ "description": "Native AI agent loop for Capacitor — runs LLM completions, tool execution, and cron jobs in native Rust, enabling background execution.",
5
+ "main": "dist/esm/index.js",
6
+ "types": "dist/esm/index.d.ts",
7
+ "type": "module",
8
+ "license": "MIT",
9
+ "author": "Techxagon",
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "build:watch": "tsc --watch",
13
+ "clean": "rm -rf dist",
14
+ "typecheck": "tsc --noEmit",
15
+ "prepublishOnly": "npm run build"
16
+ },
17
+ "capacitor": {
18
+ "android": {
19
+ "src": "android"
20
+ }
21
+ },
22
+ "files": [
23
+ "dist/esm/",
24
+ "android/src/main/",
25
+ "android/build.gradle",
26
+ "README.md",
27
+ "LICENSE"
28
+ ],
29
+ "keywords": [
30
+ "capacitor",
31
+ "capacitor-plugin",
32
+ "agent",
33
+ "llm",
34
+ "native",
35
+ "rust",
36
+ "background",
37
+ "ai",
38
+ "anthropic",
39
+ "claude",
40
+ "cron",
41
+ "mcp"
42
+ ],
43
+ "repository": {
44
+ "type": "git",
45
+ "url": "https://github.com/ArcadeLabsInc/capacitor-native-agent.git"
46
+ },
47
+ "homepage": "https://github.com/ArcadeLabsInc/capacitor-native-agent#readme",
48
+ "bugs": {
49
+ "url": "https://github.com/ArcadeLabsInc/capacitor-native-agent/issues"
50
+ },
51
+ "peerDependencies": {
52
+ "@capacitor/core": "^6.0.0 || ^7.0.0 || ^8.0.0"
53
+ },
54
+ "devDependencies": {
55
+ "@capacitor/core": "^8.1.0",
56
+ "typescript": "~5.5.4"
57
+ },
58
+ "engines": {
59
+ "node": ">=20"
60
+ }
61
+ }