capacitor-native-agent 0.7.4 → 0.9.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/README.md CHANGED
@@ -20,6 +20,16 @@ npm install capacitor-native-agent
20
20
  npx cap sync
21
21
  ```
22
22
 
23
+ ## Cloning this repository
24
+
25
+ The Rust FFI crate lives in a separate GitLab repository and is pulled in as a git submodule. After cloning:
26
+
27
+ ```bash
28
+ git submodule update --init --recursive
29
+ ```
30
+
31
+ Upstream URL: https://gitlab.k8s.t6x.io/rruiz/native-agent-ffi
32
+
23
33
  ## Android Setup
24
34
 
25
35
  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:
@@ -27,10 +37,11 @@ The npm package includes the Kotlin plugin source and UniFFI bindings, but **not
27
37
  ### 1. Build the Rust .so
28
38
 
29
39
  ```bash
30
- cd rust/native-agent-ffi
31
- cargo ndk -t arm64-v8a build --release
40
+ scripts/build-android.sh
32
41
  ```
33
42
 
43
+ This runs `cargo ndk -t arm64-v8a build --release` on the submodule and copies the result into `android/src/main/jniLibs/arm64-v8a/`.
44
+
34
45
  ### 2. Place the .so in your app
35
46
 
36
47
  Copy the built library to your Android app's jniLibs:
@@ -154,13 +165,40 @@ Events are emitted via `addListener('nativeAgentEvent', handler)`:
154
165
  - `heartbeat.*` — Heartbeat lifecycle
155
166
  - `scheduler.status` — Scheduler state updates
156
167
 
168
+ ## Supported LLM providers
169
+
170
+ The `provider` argument is a free string. The Rust agent loop currently accepts:
171
+
172
+ | Provider string | Default model | Endpoint |
173
+ |---|---|---|
174
+ | `anthropic` | `claude-sonnet-4-20250514` | Anthropic Messages API |
175
+ | `openai` | `gpt-4o` | OpenAI Chat Completions |
176
+ | `openrouter` | `anthropic/claude-sonnet-4.5` | OpenRouter |
177
+ | `kimi` (aliases `kimi-coding`, `kimi-code`) | `kimi-for-coding` | Kimi Coding (Anthropic-messages-compatible, https://api.kimi.com/coding) |
178
+
179
+ > **Note (0.9.0 — iOS):** Kimi is fully wired in the Android `.so` shipped with this version. The iOS `xcframework` in this release is the pre-existing `0.8.x` build and has **not** been rebuilt against `native-agent-ffi 9946e0f`. iOS callers using `provider: 'kimi'` will receive `Unsupported provider`. Track [#TODO-ios-0.9.1](#known-limitations) for the 0.9.1 iOS rebuild.
180
+
157
181
  ## Platform Support
158
182
 
159
- | Platform | Status |
160
- |----------|--------|
161
- | Android | Supported |
162
- | iOS | Not yet implemented |
163
- | Web | N/A (throws unavailable error) |
183
+ | Platform | Status (this release: **0.9.0**) |
184
+ |----------|-----------------------------------|
185
+ | Android | Supported. Rust pinned to `native-agent-ffi@9946e0f` (Kimi, SSE no-space fix, session-context fix, AgentStore refactor, runtime-drop fix). |
186
+ | iOS | Stale binary `xcframework` is pre-`0.9.0` and will be refreshed in `0.9.1`. See *Known limitations* below. |
187
+ | Web | N/A (throws unavailable error). |
188
+
189
+ ## Known limitations
190
+
191
+ ### 0.9.0 — iOS xcframework not rebuilt
192
+
193
+ The Mac build host was unreachable when `0.9.0` was cut, so `ios/Frameworks/NativeAgentFFI.xcframework/` was **not** rebuilt against `native-agent-ffi@9946e0f`. iOS users on `0.9.0` are missing the following upstream changes (Android users have them):
194
+
195
+ - `ba8c97e` `feat(llm): add kimi (Kimi Code) provider` — `provider: 'kimi'` will fail on iOS until `0.9.1`.
196
+ - `2cb34be` `fix(llm): tolerate "data:" SSE without space` — Anthropic-compatible streaming endpoints that omit the space after `data:` will return empty messages on iOS.
197
+ - `9735f4d` `ffi: keep session context across send_message` — after a cold-boot resume, the next `sendMessage` may start without prior history on iOS.
198
+ - `02b1955` `feat(store): extract AgentStore trait` — internal refactor only; mobile `SqliteStore` default behavior unchanged, so no user-visible iOS impact.
199
+ - `9946e0f` `ffi: detach inner runtime on drop` — server-side concern only (handle dropped from inside another tokio runtime); does not affect Capacitor.
200
+
201
+ Action plan: rebuild `xcframework` on the Mac under `~/choreruiz/` via `scripts/build-ios.sh`, rsync `ios/Frameworks/` and `ios/Sources/NativeAgentPlugin/Generated/` back, bump to `0.9.1`, republish.
164
202
 
165
203
  ## License
166
204
 
@@ -113,6 +113,16 @@ class NativeAgentPlugin : Plugin() {
113
113
  }
114
114
  }
115
115
 
116
+ // ── Governance (native-to-native, not a @PluginMethod) ──────────
117
+
118
+ /**
119
+ * Register an optional governance provider for taint, audit, loop-guard, and cost tracking.
120
+ * Called by capacitor-agent-os at init time — not exposed to JavaScript.
121
+ */
122
+ fun registerGovernance(provider: uniffi.native_agent_ffi.GovernanceProvider) {
123
+ handle?.setGovernanceProvider(provider)
124
+ }
125
+
116
126
  // ── Agent ──────────────────────────────────────────────────────────
117
127
 
118
128
  @PluginMethod
@@ -654,6 +654,24 @@ internal open class UniffiForeignFutureStructVoid(
654
654
  internal interface UniffiForeignFutureCompleteVoid : com.sun.jna.Callback {
655
655
  fun callback(`callbackData`: Long,`result`: UniffiForeignFutureStructVoid.UniffiByValue,)
656
656
  }
657
+ internal interface UniffiCallbackInterfaceGovernanceProviderMethod0 : com.sun.jna.Callback {
658
+ fun callback(`uniffiHandle`: Long,`toolName`: RustBuffer.ByValue,`paramsJson`: RustBuffer.ByValue,`uniffiOutReturn`: RustBuffer,uniffiCallStatus: UniffiRustCallStatus,)
659
+ }
660
+ internal interface UniffiCallbackInterfaceGovernanceProviderMethod1 : com.sun.jna.Callback {
661
+ fun callback(`uniffiHandle`: Long,`toolName`: RustBuffer.ByValue,`paramsJson`: RustBuffer.ByValue,`result`: RustBuffer.ByValue,`uniffiOutReturn`: RustBuffer,uniffiCallStatus: UniffiRustCallStatus,)
662
+ }
663
+ internal interface UniffiCallbackInterfaceGovernanceProviderMethod2 : com.sun.jna.Callback {
664
+ fun callback(`uniffiHandle`: Long,`agentId`: RustBuffer.ByValue,`action`: RustBuffer.ByValue,`detail`: RustBuffer.ByValue,`outcome`: RustBuffer.ByValue,`uniffiOutReturn`: Pointer,uniffiCallStatus: UniffiRustCallStatus,)
665
+ }
666
+ internal interface UniffiCallbackInterfaceGovernanceProviderMethod3 : com.sun.jna.Callback {
667
+ fun callback(`uniffiHandle`: Long,`sinkType`: RustBuffer.ByValue,`content`: RustBuffer.ByValue,`uniffiOutReturn`: RustBuffer,uniffiCallStatus: UniffiRustCallStatus,)
668
+ }
669
+ internal interface UniffiCallbackInterfaceGovernanceProviderMethod4 : com.sun.jna.Callback {
670
+ fun callback(`uniffiHandle`: Long,`uniffiOutReturn`: Pointer,uniffiCallStatus: UniffiRustCallStatus,)
671
+ }
672
+ internal interface UniffiCallbackInterfaceGovernanceProviderMethod5 : com.sun.jna.Callback {
673
+ fun callback(`uniffiHandle`: Long,`modelId`: RustBuffer.ByValue,`inputTokens`: Int,`outputTokens`: Int,`uniffiOutReturn`: Pointer,uniffiCallStatus: UniffiRustCallStatus,)
674
+ }
657
675
  internal interface UniffiCallbackInterfaceMemoryProviderMethod0 : com.sun.jna.Callback {
658
676
  fun callback(`uniffiHandle`: Long,`key`: RustBuffer.ByValue,`text`: RustBuffer.ByValue,`metadataJson`: RustBuffer.ByValue,`uniffiOutReturn`: RustBuffer,uniffiCallStatus: UniffiRustCallStatus,)
659
677
  }
@@ -675,6 +693,37 @@ internal interface UniffiCallbackInterfaceNativeEventCallbackMethod0 : com.sun.j
675
693
  internal interface UniffiCallbackInterfaceNativeNotifierMethod0 : com.sun.jna.Callback {
676
694
  fun callback(`uniffiHandle`: Long,`title`: RustBuffer.ByValue,`body`: RustBuffer.ByValue,`dataJson`: RustBuffer.ByValue,`uniffiOutReturn`: RustBuffer,uniffiCallStatus: UniffiRustCallStatus,)
677
695
  }
696
+ @Structure.FieldOrder("checkLoop", "recordOutcome", "recordAudit", "checkSink", "reset", "recordUsage", "uniffiFree")
697
+ internal open class UniffiVTableCallbackInterfaceGovernanceProvider(
698
+ @JvmField internal var `checkLoop`: UniffiCallbackInterfaceGovernanceProviderMethod0? = null,
699
+ @JvmField internal var `recordOutcome`: UniffiCallbackInterfaceGovernanceProviderMethod1? = null,
700
+ @JvmField internal var `recordAudit`: UniffiCallbackInterfaceGovernanceProviderMethod2? = null,
701
+ @JvmField internal var `checkSink`: UniffiCallbackInterfaceGovernanceProviderMethod3? = null,
702
+ @JvmField internal var `reset`: UniffiCallbackInterfaceGovernanceProviderMethod4? = null,
703
+ @JvmField internal var `recordUsage`: UniffiCallbackInterfaceGovernanceProviderMethod5? = null,
704
+ @JvmField internal var `uniffiFree`: UniffiCallbackInterfaceFree? = null,
705
+ ) : Structure() {
706
+ class UniffiByValue(
707
+ `checkLoop`: UniffiCallbackInterfaceGovernanceProviderMethod0? = null,
708
+ `recordOutcome`: UniffiCallbackInterfaceGovernanceProviderMethod1? = null,
709
+ `recordAudit`: UniffiCallbackInterfaceGovernanceProviderMethod2? = null,
710
+ `checkSink`: UniffiCallbackInterfaceGovernanceProviderMethod3? = null,
711
+ `reset`: UniffiCallbackInterfaceGovernanceProviderMethod4? = null,
712
+ `recordUsage`: UniffiCallbackInterfaceGovernanceProviderMethod5? = null,
713
+ `uniffiFree`: UniffiCallbackInterfaceFree? = null,
714
+ ): UniffiVTableCallbackInterfaceGovernanceProvider(`checkLoop`,`recordOutcome`,`recordAudit`,`checkSink`,`reset`,`recordUsage`,`uniffiFree`,), Structure.ByValue
715
+
716
+ internal fun uniffiSetValue(other: UniffiVTableCallbackInterfaceGovernanceProvider) {
717
+ `checkLoop` = other.`checkLoop`
718
+ `recordOutcome` = other.`recordOutcome`
719
+ `recordAudit` = other.`recordAudit`
720
+ `checkSink` = other.`checkSink`
721
+ `reset` = other.`reset`
722
+ `recordUsage` = other.`recordUsage`
723
+ `uniffiFree` = other.`uniffiFree`
724
+ }
725
+
726
+ }
678
727
  @Structure.FieldOrder("store", "recall", "forget", "search", "list", "uniffiFree")
679
728
  internal open class UniffiVTableCallbackInterfaceMemoryProvider(
680
729
  @JvmField internal var `store`: UniffiCallbackInterfaceMemoryProviderMethod0? = null,
@@ -895,6 +944,15 @@ internal open class UniffiVTableCallbackInterfaceNativeNotifier(
895
944
 
896
945
 
897
946
 
947
+
948
+
949
+
950
+
951
+
952
+
953
+
954
+
955
+
898
956
 
899
957
 
900
958
 
@@ -915,6 +973,7 @@ internal interface UniffiLib : Library {
915
973
  .also { lib: UniffiLib ->
916
974
  uniffiCheckContractApiVersion(lib)
917
975
  uniffiCheckApiChecksums(lib)
976
+ uniffiCallbackInterfaceGovernanceProvider.register(lib)
918
977
  uniffiCallbackInterfaceMemoryProvider.register(lib)
919
978
  uniffiCallbackInterfaceNativeEventCallback.register(lib)
920
979
  uniffiCallbackInterfaceNativeNotifier.register(lib)
@@ -1007,6 +1066,8 @@ internal interface UniffiLib : Library {
1007
1066
  ): Unit
1008
1067
  fun uniffi_native_agent_ffi_fn_method_nativeagenthandle_set_event_callback(`ptr`: Pointer,`callback`: Long,uniffi_out_err: UniffiRustCallStatus,
1009
1068
  ): Unit
1069
+ fun uniffi_native_agent_ffi_fn_method_nativeagenthandle_set_governance_provider(`ptr`: Pointer,`provider`: Long,uniffi_out_err: UniffiRustCallStatus,
1070
+ ): Unit
1010
1071
  fun uniffi_native_agent_ffi_fn_method_nativeagenthandle_set_heartbeat_config(`ptr`: Pointer,`configJson`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus,
1011
1072
  ): Unit
1012
1073
  fun uniffi_native_agent_ffi_fn_method_nativeagenthandle_set_memory_provider(`ptr`: Pointer,`provider`: Long,uniffi_out_err: UniffiRustCallStatus,
@@ -1027,6 +1088,8 @@ internal interface UniffiLib : Library {
1027
1088
  ): Unit
1028
1089
  fun uniffi_native_agent_ffi_fn_method_nativeagenthandle_update_skill(`ptr`: Pointer,`id`: RustBuffer.ByValue,`patchJson`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus,
1029
1090
  ): Unit
1091
+ fun uniffi_native_agent_ffi_fn_init_callback_vtable_governanceprovider(`vtable`: UniffiVTableCallbackInterfaceGovernanceProvider,
1092
+ ): Unit
1030
1093
  fun uniffi_native_agent_ffi_fn_init_callback_vtable_memoryprovider(`vtable`: UniffiVTableCallbackInterfaceMemoryProvider,
1031
1094
  ): Unit
1032
1095
  fun uniffi_native_agent_ffi_fn_init_callback_vtable_nativeeventcallback(`vtable`: UniffiVTableCallbackInterfaceNativeEventCallback,
@@ -1227,6 +1290,8 @@ internal interface UniffiLib : Library {
1227
1290
  ): Short
1228
1291
  fun uniffi_native_agent_ffi_checksum_method_nativeagenthandle_set_event_callback(
1229
1292
  ): Short
1293
+ fun uniffi_native_agent_ffi_checksum_method_nativeagenthandle_set_governance_provider(
1294
+ ): Short
1230
1295
  fun uniffi_native_agent_ffi_checksum_method_nativeagenthandle_set_heartbeat_config(
1231
1296
  ): Short
1232
1297
  fun uniffi_native_agent_ffi_checksum_method_nativeagenthandle_set_memory_provider(
@@ -1249,6 +1314,18 @@ internal interface UniffiLib : Library {
1249
1314
  ): Short
1250
1315
  fun uniffi_native_agent_ffi_checksum_constructor_nativeagenthandle_new(
1251
1316
  ): Short
1317
+ fun uniffi_native_agent_ffi_checksum_method_governanceprovider_check_loop(
1318
+ ): Short
1319
+ fun uniffi_native_agent_ffi_checksum_method_governanceprovider_record_outcome(
1320
+ ): Short
1321
+ fun uniffi_native_agent_ffi_checksum_method_governanceprovider_record_audit(
1322
+ ): Short
1323
+ fun uniffi_native_agent_ffi_checksum_method_governanceprovider_check_sink(
1324
+ ): Short
1325
+ fun uniffi_native_agent_ffi_checksum_method_governanceprovider_reset(
1326
+ ): Short
1327
+ fun uniffi_native_agent_ffi_checksum_method_governanceprovider_record_usage(
1328
+ ): Short
1252
1329
  fun uniffi_native_agent_ffi_checksum_method_memoryprovider_store(
1253
1330
  ): Short
1254
1331
  fun uniffi_native_agent_ffi_checksum_method_memoryprovider_recall(
@@ -1397,6 +1474,9 @@ private fun uniffiCheckApiChecksums(lib: UniffiLib) {
1397
1474
  if (lib.uniffi_native_agent_ffi_checksum_method_nativeagenthandle_set_event_callback() != 56165.toShort()) {
1398
1475
  throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
1399
1476
  }
1477
+ if (lib.uniffi_native_agent_ffi_checksum_method_nativeagenthandle_set_governance_provider() != 45093.toShort()) {
1478
+ throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
1479
+ }
1400
1480
  if (lib.uniffi_native_agent_ffi_checksum_method_nativeagenthandle_set_heartbeat_config() != 33968.toShort()) {
1401
1481
  throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
1402
1482
  }
@@ -1430,6 +1510,24 @@ private fun uniffiCheckApiChecksums(lib: UniffiLib) {
1430
1510
  if (lib.uniffi_native_agent_ffi_checksum_constructor_nativeagenthandle_new() != 18383.toShort()) {
1431
1511
  throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
1432
1512
  }
1513
+ if (lib.uniffi_native_agent_ffi_checksum_method_governanceprovider_check_loop() != 64194.toShort()) {
1514
+ throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
1515
+ }
1516
+ if (lib.uniffi_native_agent_ffi_checksum_method_governanceprovider_record_outcome() != 15801.toShort()) {
1517
+ throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
1518
+ }
1519
+ if (lib.uniffi_native_agent_ffi_checksum_method_governanceprovider_record_audit() != 34049.toShort()) {
1520
+ throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
1521
+ }
1522
+ if (lib.uniffi_native_agent_ffi_checksum_method_governanceprovider_check_sink() != 37338.toShort()) {
1523
+ throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
1524
+ }
1525
+ if (lib.uniffi_native_agent_ffi_checksum_method_governanceprovider_reset() != 57214.toShort()) {
1526
+ throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
1527
+ }
1528
+ if (lib.uniffi_native_agent_ffi_checksum_method_governanceprovider_record_usage() != 907.toShort()) {
1529
+ throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
1530
+ }
1433
1531
  if (lib.uniffi_native_agent_ffi_checksum_method_memoryprovider_store() != 49136.toShort()) {
1434
1532
  throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
1435
1533
  }
@@ -1977,6 +2075,12 @@ public interface NativeAgentHandleInterface {
1977
2075
  */
1978
2076
  fun `setEventCallback`(`callback`: NativeEventCallback)
1979
2077
 
2078
+ /**
2079
+ * Set the optional governance provider (taint, audit, loop-guard, cost tracking).
2080
+ * Typically called by capacitor-agent-os when it auto-registers at init time.
2081
+ */
2082
+ fun `setGovernanceProvider`(`provider`: GovernanceProvider)
2083
+
1980
2084
  /**
1981
2085
  * Set heartbeat config.
1982
2086
  */
@@ -2696,6 +2800,22 @@ open class NativeAgentHandle: Disposable, AutoCloseable, NativeAgentHandleInterf
2696
2800
 
2697
2801
 
2698
2802
 
2803
+ /**
2804
+ * Set the optional governance provider (taint, audit, loop-guard, cost tracking).
2805
+ * Typically called by capacitor-agent-os when it auto-registers at init time.
2806
+ */
2807
+ @Throws(NativeAgentException::class)override fun `setGovernanceProvider`(`provider`: GovernanceProvider)
2808
+ =
2809
+ callWithPointer {
2810
+ uniffiRustCallWithError(NativeAgentException) { _status ->
2811
+ UniffiLib.INSTANCE.uniffi_native_agent_ffi_fn_method_nativeagenthandle_set_governance_provider(
2812
+ it, FfiConverterTypeGovernanceProvider.lower(`provider`),_status)
2813
+ }
2814
+ }
2815
+
2816
+
2817
+
2818
+
2699
2819
  /**
2700
2820
  * Set heartbeat config.
2701
2821
  */
@@ -3333,20 +3453,45 @@ public object FfiConverterTypeNativeAgentError : FfiConverterRustBuffer<NativeAg
3333
3453
 
3334
3454
 
3335
3455
  /**
3336
- * Callback interface for memory operations (LanceDB or any vector store).
3337
- * Implemented by Kotlin/Swift, which bridges to the actual memory backend.
3456
+ * Optional governance provider for security, audit, and loop-guard checks.
3457
+ * Implemented by Kotlin/Swift typically backed by capacitor-agent-os when
3458
+ * that plugin is installed. When absent, the agent loop runs without
3459
+ * governance checks.
3338
3460
  */
3339
- public interface MemoryProvider {
3461
+ public interface GovernanceProvider {
3340
3462
 
3341
- fun `store`(`key`: kotlin.String, `text`: kotlin.String, `metadataJson`: kotlin.String?): kotlin.String
3463
+ /**
3464
+ * Check if a tool call should proceed. Returns JSON verdict:
3465
+ * `{"type":"Allow"}` | `{"type":"Warn","reason":"..."}` |
3466
+ * `{"type":"Block","reason":"..."}` | `{"type":"CircuitBreak","reason":"..."}`
3467
+ */
3468
+ fun `checkLoop`(`toolName`: kotlin.String, `paramsJson`: kotlin.String): kotlin.String
3342
3469
 
3343
- fun `recall`(`query`: kotlin.String, `limit`: kotlin.UInt): kotlin.String
3470
+ /**
3471
+ * Record tool outcome for loop detection. Returns optional warning string.
3472
+ */
3473
+ fun `recordOutcome`(`toolName`: kotlin.String, `paramsJson`: kotlin.String, `result`: kotlin.String): kotlin.String?
3344
3474
 
3345
- fun `forget`(`key`: kotlin.String): kotlin.String
3475
+ /**
3476
+ * Record an audit trail entry.
3477
+ */
3478
+ fun `recordAudit`(`agentId`: kotlin.String, `action`: kotlin.String, `detail`: kotlin.String, `outcome`: kotlin.String)
3346
3479
 
3347
- fun `search`(`query`: kotlin.String, `maxResults`: kotlin.UInt): kotlin.String
3480
+ /**
3481
+ * Check if content is tainted before passing to LLM. Returns JSON:
3482
+ * `{"blocked":true/false,"reason":"...","matchedLabels":[...]}`
3483
+ */
3484
+ fun `checkSink`(`sinkType`: kotlin.String, `content`: kotlin.String): kotlin.String
3348
3485
 
3349
- fun `list`(`prefix`: kotlin.String?, `limit`: kotlin.UInt?): kotlin.String
3486
+ /**
3487
+ * Reset loop guard state (e.g. on new session).
3488
+ */
3489
+ fun `reset`()
3490
+
3491
+ /**
3492
+ * Record token usage for cost tracking.
3493
+ */
3494
+ fun `recordUsage`(`modelId`: kotlin.String, `inputTokens`: kotlin.UInt, `outputTokens`: kotlin.UInt)
3350
3495
 
3351
3496
  companion object
3352
3497
  }
@@ -3384,6 +3529,144 @@ public abstract class FfiConverterCallbackInterface<CallbackInterface: Any>: Ffi
3384
3529
  }
3385
3530
  }
3386
3531
 
3532
+ // Put the implementation in an object so we don't pollute the top-level namespace
3533
+ internal object uniffiCallbackInterfaceGovernanceProvider {
3534
+ internal object `checkLoop`: UniffiCallbackInterfaceGovernanceProviderMethod0 {
3535
+ override fun callback(`uniffiHandle`: Long,`toolName`: RustBuffer.ByValue,`paramsJson`: RustBuffer.ByValue,`uniffiOutReturn`: RustBuffer,uniffiCallStatus: UniffiRustCallStatus,) {
3536
+ val uniffiObj = FfiConverterTypeGovernanceProvider.handleMap.get(uniffiHandle)
3537
+ val makeCall = { ->
3538
+ uniffiObj.`checkLoop`(
3539
+ FfiConverterString.lift(`toolName`),
3540
+ FfiConverterString.lift(`paramsJson`),
3541
+ )
3542
+ }
3543
+ val writeReturn = { value: kotlin.String -> uniffiOutReturn.setValue(FfiConverterString.lower(value)) }
3544
+ uniffiTraitInterfaceCall(uniffiCallStatus, makeCall, writeReturn)
3545
+ }
3546
+ }
3547
+ internal object `recordOutcome`: UniffiCallbackInterfaceGovernanceProviderMethod1 {
3548
+ override fun callback(`uniffiHandle`: Long,`toolName`: RustBuffer.ByValue,`paramsJson`: RustBuffer.ByValue,`result`: RustBuffer.ByValue,`uniffiOutReturn`: RustBuffer,uniffiCallStatus: UniffiRustCallStatus,) {
3549
+ val uniffiObj = FfiConverterTypeGovernanceProvider.handleMap.get(uniffiHandle)
3550
+ val makeCall = { ->
3551
+ uniffiObj.`recordOutcome`(
3552
+ FfiConverterString.lift(`toolName`),
3553
+ FfiConverterString.lift(`paramsJson`),
3554
+ FfiConverterString.lift(`result`),
3555
+ )
3556
+ }
3557
+ val writeReturn = { value: kotlin.String? -> uniffiOutReturn.setValue(FfiConverterOptionalString.lower(value)) }
3558
+ uniffiTraitInterfaceCall(uniffiCallStatus, makeCall, writeReturn)
3559
+ }
3560
+ }
3561
+ internal object `recordAudit`: UniffiCallbackInterfaceGovernanceProviderMethod2 {
3562
+ override fun callback(`uniffiHandle`: Long,`agentId`: RustBuffer.ByValue,`action`: RustBuffer.ByValue,`detail`: RustBuffer.ByValue,`outcome`: RustBuffer.ByValue,`uniffiOutReturn`: Pointer,uniffiCallStatus: UniffiRustCallStatus,) {
3563
+ val uniffiObj = FfiConverterTypeGovernanceProvider.handleMap.get(uniffiHandle)
3564
+ val makeCall = { ->
3565
+ uniffiObj.`recordAudit`(
3566
+ FfiConverterString.lift(`agentId`),
3567
+ FfiConverterString.lift(`action`),
3568
+ FfiConverterString.lift(`detail`),
3569
+ FfiConverterString.lift(`outcome`),
3570
+ )
3571
+ }
3572
+ val writeReturn = { _: Unit -> Unit }
3573
+ uniffiTraitInterfaceCall(uniffiCallStatus, makeCall, writeReturn)
3574
+ }
3575
+ }
3576
+ internal object `checkSink`: UniffiCallbackInterfaceGovernanceProviderMethod3 {
3577
+ override fun callback(`uniffiHandle`: Long,`sinkType`: RustBuffer.ByValue,`content`: RustBuffer.ByValue,`uniffiOutReturn`: RustBuffer,uniffiCallStatus: UniffiRustCallStatus,) {
3578
+ val uniffiObj = FfiConverterTypeGovernanceProvider.handleMap.get(uniffiHandle)
3579
+ val makeCall = { ->
3580
+ uniffiObj.`checkSink`(
3581
+ FfiConverterString.lift(`sinkType`),
3582
+ FfiConverterString.lift(`content`),
3583
+ )
3584
+ }
3585
+ val writeReturn = { value: kotlin.String -> uniffiOutReturn.setValue(FfiConverterString.lower(value)) }
3586
+ uniffiTraitInterfaceCall(uniffiCallStatus, makeCall, writeReturn)
3587
+ }
3588
+ }
3589
+ internal object `reset`: UniffiCallbackInterfaceGovernanceProviderMethod4 {
3590
+ override fun callback(`uniffiHandle`: Long,`uniffiOutReturn`: Pointer,uniffiCallStatus: UniffiRustCallStatus,) {
3591
+ val uniffiObj = FfiConverterTypeGovernanceProvider.handleMap.get(uniffiHandle)
3592
+ val makeCall = { ->
3593
+ uniffiObj.`reset`(
3594
+ )
3595
+ }
3596
+ val writeReturn = { _: Unit -> Unit }
3597
+ uniffiTraitInterfaceCall(uniffiCallStatus, makeCall, writeReturn)
3598
+ }
3599
+ }
3600
+ internal object `recordUsage`: UniffiCallbackInterfaceGovernanceProviderMethod5 {
3601
+ override fun callback(`uniffiHandle`: Long,`modelId`: RustBuffer.ByValue,`inputTokens`: Int,`outputTokens`: Int,`uniffiOutReturn`: Pointer,uniffiCallStatus: UniffiRustCallStatus,) {
3602
+ val uniffiObj = FfiConverterTypeGovernanceProvider.handleMap.get(uniffiHandle)
3603
+ val makeCall = { ->
3604
+ uniffiObj.`recordUsage`(
3605
+ FfiConverterString.lift(`modelId`),
3606
+ FfiConverterUInt.lift(`inputTokens`),
3607
+ FfiConverterUInt.lift(`outputTokens`),
3608
+ )
3609
+ }
3610
+ val writeReturn = { _: Unit -> Unit }
3611
+ uniffiTraitInterfaceCall(uniffiCallStatus, makeCall, writeReturn)
3612
+ }
3613
+ }
3614
+
3615
+ internal object uniffiFree: UniffiCallbackInterfaceFree {
3616
+ override fun callback(handle: Long) {
3617
+ FfiConverterTypeGovernanceProvider.handleMap.remove(handle)
3618
+ }
3619
+ }
3620
+
3621
+ internal var vtable = UniffiVTableCallbackInterfaceGovernanceProvider.UniffiByValue(
3622
+ `checkLoop`,
3623
+ `recordOutcome`,
3624
+ `recordAudit`,
3625
+ `checkSink`,
3626
+ `reset`,
3627
+ `recordUsage`,
3628
+ uniffiFree,
3629
+ )
3630
+
3631
+ // Registers the foreign callback with the Rust side.
3632
+ // This method is generated for each callback interface.
3633
+ internal fun register(lib: UniffiLib) {
3634
+ lib.uniffi_native_agent_ffi_fn_init_callback_vtable_governanceprovider(vtable)
3635
+ }
3636
+ }
3637
+
3638
+ /**
3639
+ * The ffiConverter which transforms the Callbacks in to handles to pass to Rust.
3640
+ *
3641
+ * @suppress
3642
+ */
3643
+ public object FfiConverterTypeGovernanceProvider: FfiConverterCallbackInterface<GovernanceProvider>()
3644
+
3645
+
3646
+
3647
+
3648
+
3649
+ /**
3650
+ * Callback interface for memory operations (LanceDB or any vector store).
3651
+ * Implemented by Kotlin/Swift, which bridges to the actual memory backend.
3652
+ */
3653
+ public interface MemoryProvider {
3654
+
3655
+ fun `store`(`key`: kotlin.String, `text`: kotlin.String, `metadataJson`: kotlin.String?): kotlin.String
3656
+
3657
+ fun `recall`(`query`: kotlin.String, `limit`: kotlin.UInt): kotlin.String
3658
+
3659
+ fun `forget`(`key`: kotlin.String): kotlin.String
3660
+
3661
+ fun `search`(`query`: kotlin.String, `maxResults`: kotlin.UInt): kotlin.String
3662
+
3663
+ fun `list`(`prefix`: kotlin.String?, `limit`: kotlin.UInt?): kotlin.String
3664
+
3665
+ companion object
3666
+ }
3667
+
3668
+
3669
+
3387
3670
  // Put the implementation in an object so we don't pollute the top-level namespace
3388
3671
  internal object uniffiCallbackInterfaceMemoryProvider {
3389
3672
  internal object `store`: UniffiCallbackInterfaceMemoryProviderMethod0 {
@@ -176,6 +176,14 @@ public class NativeAgentPlugin: CAPPlugin, CAPBridgedPlugin {
176
176
  }
177
177
  }
178
178
 
179
+ // ── Governance (native-to-native, not a plugin method) ─────────────────
180
+
181
+ /// Register an optional governance provider for taint, audit, loop-guard, and cost tracking.
182
+ /// Called by capacitor-agent-os at init time — not exposed to JavaScript.
183
+ public func registerGovernance(_ provider: GovernanceProvider) {
184
+ try? handle?.setGovernanceProvider(provider: provider)
185
+ }
186
+
179
187
  // ── Agent ────────────────────────────────────────────────────────────────
180
188
 
181
189
  @objc func sendMessage(_ call: CAPPluginCall) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "capacitor-native-agent",
3
- "version": "0.7.4",
3
+ "version": "0.9.0",
4
4
  "description": "Native AI agent loop for Capacitor — runs LLM completions, tool execution, and cron jobs in native Rust, enabling background execution.",
5
5
  "main": "dist/esm/index.js",
6
6
  "types": "dist/esm/index.d.ts",