@ansight/react-native 1.4.0 → 1.5.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
@@ -1,6 +1,14 @@
1
1
  # @ansight/react-native
2
2
 
3
- React Native bridge for the Ansight mobile SDK.
3
+ Ansight gives coding agents the runtime evidence to verify their own work in
4
+ React Native and Expo development builds. The SDK captures screenshots, visual trees, touches, logs,
5
+ crashes and unhandled errors, HTTP requests, screen views and navigation, lifecycle events, app events, custom metrics, and sampled memory,
6
+ FPS, frame timing, and battery while the app runs, and exposes app state,
7
+ preferences, secure storage, files, SQLite, artifacts, and your own custom
8
+ tools through guarded remote tools on request. Your agent reads all of it
9
+ through the `ansight` CLI. Nothing leaves your machine unless you export or
10
+ share it. See https://www.ansight.ai and the
11
+ [getting started guide](https://www.ansight.ai/docs/getting-started).
4
12
 
5
13
  The package is intentionally thin: pairing, transport, telemetry, screen
6
14
  capture, touch capture, native tool discovery, and native tool execution are
@@ -80,8 +88,8 @@ bundle; its API requires the native Ansight module.
80
88
 
81
89
  This package version expects matching native SDK packages:
82
90
 
83
- - CocoaPods: `Ansight`, `AnsightObjC` version `1.4.0`
84
- - Maven: `ai.ansight:ansight-android:1.4.0`
91
+ - CocoaPods: `Ansight`, `AnsightObjC` version `1.5.0`
92
+ - Maven: `ai.ansight:ansight-android:1.5.0`
85
93
 
86
94
  ## Quickstart
87
95
 
@@ -672,3 +680,7 @@ It is pinned to Expo SDK 57 and React Native 0.86 with the New Architecture and
672
680
  Hermes enabled. It validates Expo CNG/autolinking, the bundled config plugin,
673
681
  Android and iOS native builds, and the same live host feature surface as the
674
682
  baseline harness.
683
+
684
+ ## Purchase diagnostics
685
+
686
+ See [purchase observations, adapters, and remote validation](../../docs/purchases.md) for the base SDK purchase suite.
@@ -67,6 +67,6 @@ repositories {
67
67
  dependencies {
68
68
  implementation("com.facebook.react:react-android")
69
69
  def ansightAndroidVersion =
70
- findProperty("ansightAndroidVersion") ?: "1.4.0"
71
- implementation("ai.ansight:ansight-android:1.4.0")
70
+ findProperty("ansightAndroidVersion") ?: "1.5.0"
71
+ implementation("ai.ansight:ansight-android:1.5.0")
72
72
  }
@@ -48,6 +48,8 @@ import ai.ansight.tools.filesystem.AndroidFileSystemRoot
48
48
  import ai.ansight.tools.filesystem.AndroidFileSystemToolsOptions
49
49
  import ai.ansight.tools.filesystem.withFileSystemTools
50
50
  import ai.ansight.tools.preferences.AndroidPreferencesToolsOptions
51
+ import ai.ansight.tools.clipboard.ClipboardToolIds
52
+ import ai.ansight.tools.clipboard.withClipboardTools
51
53
  import ai.ansight.tools.preferences.withPreferencesTools
52
54
  import ai.ansight.tools.reflection.AndroidReflectionToolsOptions
53
55
  import ai.ansight.tools.reflection.withReflectionTools
@@ -135,6 +137,13 @@ class AnsightReactNativeModule(
135
137
 
136
138
  override fun onHostDestroy() = Unit
137
139
 
140
+ @ReactMethod
141
+ fun purchaseCommand(json: String, promise: Promise) {
142
+ try { promise.resolve(ai.ansight.runtime.purchases.PurchaseDiagnostics.shared.command(json)) }
143
+ catch (error: ai.ansight.runtime.purchases.PurchaseEnvironmentException) { promise.reject(ai.ansight.runtime.purchases.PurchaseEnvironmentException.ERROR_CODE, error.message, error) }
144
+ catch (error: Exception) { promise.reject("purchases_command_failed", "Purchase command failed.", error) }
145
+ }
146
+
138
147
  @ReactMethod
139
148
  fun addListener(eventName: String) {
140
149
  listenerCount.incrementAndGet()
@@ -962,6 +971,11 @@ class AnsightReactNativeModule(
962
971
  ): AnsightOptions {
963
972
  val remoteTools = map.getMapOrNull("remoteTools")
964
973
  val builder = AnsightOptions.createBuilder(this)
974
+ val clipboardIds = setOf(ClipboardToolIds.GetText, ClipboardToolIds.HasText, ClipboardToolIds.SetText, ClipboardToolIds.Clear)
975
+ builder.withTools(initialTools.filterNot { it.definition.id in clipboardIds })
976
+ if (remoteTools.booleanValue("clipboard", true)) {
977
+ builder.withClipboardTools()
978
+ }
965
979
  if (remoteTools.toolSuiteEnabled("visualTree", enableVisualTreeToolsByDefault)) {
966
980
  builder.withVisualTreeTools()
967
981
  }
package/index.d.ts CHANGED
@@ -1,3 +1,6 @@
1
+ import type { PurchaseDiagnostics } from "./purchases";
2
+ export * from "./purchases";
3
+ export const purchases: PurchaseDiagnostics;
1
4
  export type AnsightLifecycleState = "unknown" | "foreground" | "background";
2
5
  export type AnsightToolPolicy = "read" | "write" | "critical";
3
6
 
@@ -144,6 +147,8 @@ export interface AnsightVisualTreeToolsOptions {
144
147
  }
145
148
 
146
149
  export interface AnsightRemoteToolsOptions {
150
+ /** Include native clipboard tools; defaults to true. */
151
+ clipboard?: boolean;
147
152
  visualTree?: boolean | AnsightVisualTreeToolsOptions;
148
153
  fileSystem?: AnsightFileSystemToolsOptions;
149
154
  database?: AnsightDatabaseToolsOptions;
@@ -392,6 +397,7 @@ export class AnsightOptionsBuilder {
392
397
  withoutVisualTreeTools(): this;
393
398
  withFileSystemTools(options?: AnsightFileSystemToolsOptions): this;
394
399
  withDatabaseTools(options?: AnsightDatabaseToolsOptions): this;
400
+ withClipboardTools(enabled?: boolean): this;
395
401
  withPreferencesTools(options?: AnsightPreferencesToolsOptions): this;
396
402
  withReflectionTools(options?: AnsightReflectionToolsOptions): this;
397
403
  build(): AnsightOptions;
@@ -676,6 +682,7 @@ export function installErrorHandlers(options?: { chain?: boolean }): () => void;
676
682
  export function createReactNavigationTracker(navigationRef: unknown, options?: { recordInitial?: boolean }): ReactNavigationTracker;
677
683
 
678
684
  declare const Ansight: {
685
+ purchases: PurchaseDiagnostics;
679
686
  initialize: typeof initialize;
680
687
  initializeAndActivate: typeof initializeAndActivate;
681
688
  activate: typeof activate;
package/index.js CHANGED
@@ -608,6 +608,11 @@ class AnsightOptionsBuilder {
608
608
  return this;
609
609
  }
610
610
 
611
+ withClipboardTools(enabled = true) {
612
+ this._options.remoteTools = { ...this._options.remoteTools, clipboard: enabled };
613
+ return this;
614
+ }
615
+
611
616
  withPreferencesTools(options = {}) {
612
617
  this._options.remoteTools = {
613
618
  ...(this._options.remoteTools || {}),
@@ -2669,3 +2674,6 @@ module.exports.recordNetworkRequest = recordNetworkRequest;
2669
2674
  module.exports.installNetworkCapture = installNetworkCapture;
2670
2675
  module.exports.uninstallNetworkCapture = uninstallNetworkCapture;
2671
2676
  module.exports.sanitizeNetworkRequest = sanitizeNetworkRequest;
2677
+
2678
+ module.exports.purchases = require("./purchases").createPurchaseDiagnostics((json) => nativeModule.purchaseCommand(json));
2679
+ module.exports.createPurchaseDiagnostics = require("./purchases").createPurchaseDiagnostics;
@@ -4,6 +4,15 @@ import React
4
4
 
5
5
  @objc(AnsightReactNative)
6
6
  final class AnsightReactNative: RCTEventEmitter {
7
+ @objc(purchaseCommand:resolver:rejecter:)
8
+ func purchaseCommand(_ json: String, resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
9
+ Task {
10
+ do { resolve(try await PurchaseDiagnostics.shared.commandAsync(json)) }
11
+ catch PurchaseDiagnosticsError.environmentNotAllowed { reject(PurchaseDiagnosticsError.environmentErrorCode, "Purchase interop is restricted to simulators and emulators.", PurchaseDiagnosticsError.environmentNotAllowed) }
12
+ catch { reject("purchases_command_failed", "Purchase command failed.", error) }
13
+ }
14
+ }
15
+
7
16
  private final class PendingToolCall {
8
17
  let semaphore = DispatchSemaphore(value: 0)
9
18
  var result: AnsightToolExecutionResult?
@@ -1153,6 +1162,7 @@ final class AnsightReactNative: RCTEventEmitter {
1153
1162
  remoteTools?["visualTree"],
1154
1163
  defaultValue: useNativeAllInOneDefaults
1155
1164
  ),
1165
+ clipboard: boolValue(remoteTools, "clipboard", defaultValue: true),
1156
1166
  database: databaseToolsOptions(remoteTools?["database"] as? NSDictionary),
1157
1167
  fileSystem: fileSystemToolsOptions(remoteTools?["fileSystem"] as? NSDictionary),
1158
1168
  preferences: preferencesToolsOptions(remoteTools?["preferences"] as? NSDictionary),
@@ -3,6 +3,10 @@
3
3
 
4
4
  @interface RCT_EXTERN_MODULE(AnsightReactNative, RCTEventEmitter)
5
5
 
6
+ RCT_EXTERN_METHOD(purchaseCommand:(NSString *)json
7
+ resolver:(RCTPromiseResolveBlock)resolve
8
+ rejecter:(RCTPromiseRejectBlock)reject)
9
+
6
10
  RCT_EXTERN_METHOD(initialize:(NSDictionary *)options
7
11
  resolver:(RCTPromiseResolveBlock)resolve
8
12
  rejecter:(RCTPromiseRejectBlock)reject)
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ansight/react-native",
3
- "version": "1.4.0",
4
- "description": "React Native bridge for the Ansight mobile SDK.",
3
+ "version": "1.5.0",
4
+ "description": "React Native bridge for Ansight: runtime evidence from your app for coding agents. Screenshots, UI trees, logs, network, telemetry, and app state.",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
7
7
  "license": "SEE LICENSE IN LICENSE",
@@ -34,7 +34,9 @@
34
34
  "expo-plugin.js",
35
35
  "tsconfig.json",
36
36
  "AnsightReactNative.podspec",
37
- "react-native.config.js"
37
+ "react-native.config.js",
38
+ "purchases.js",
39
+ "purchases.d.ts"
38
40
  ],
39
41
  "keywords": [
40
42
  "ansight",
package/purchases.d.ts ADDED
@@ -0,0 +1,61 @@
1
+ export interface PurchaseObservation {
2
+ productId: string;
3
+ source: "store" | "app" | "backend";
4
+ transactionRef?: string | null;
5
+ observedAt?: number;
6
+ state?: "unknown" | "pending" | "purchased" | "cancelled" | "expired" | "revoked" | "failed" | "gracePeriod" | "billingRetry";
7
+ verification?: "unknown" | "verified" | "unverified";
8
+ entitled?: boolean | null;
9
+ deliveryCount?: number | null;
10
+ finished?: boolean | null;
11
+ acknowledged?: boolean | null;
12
+ consumed?: boolean | null;
13
+ expiresAt?: number | null;
14
+ gracePeriodExpiresAt?: number | null;
15
+ environment?: "unknown" | "xcode" | "sandbox" | "production";
16
+ productType?: "unknown" | "consumable" | "nonConsumable" | "subscription" | "nonRenewingSubscription";
17
+ }
18
+ export interface PurchaseProduct {
19
+ productId: string;
20
+ available: boolean;
21
+ observedAt?: number;
22
+ displayPrice?: string | null;
23
+ price?: string | null;
24
+ currencyCode?: string | null;
25
+ productType?: PurchaseObservation["productType"];
26
+ }
27
+ export interface PurchaseExpectations {
28
+ transactionRef?: string;
29
+ productId: string;
30
+ expectedEntitled: boolean;
31
+ requireVerified?: boolean;
32
+ requireBackendVerification?: boolean;
33
+ expectedDeliveryCount?: number;
34
+ maxAgeMilliseconds?: number;
35
+ }
36
+ export interface PurchaseSnapshot {
37
+ schema: "ansight.purchases.v1";
38
+ capturedAt: number;
39
+ droppedEvents: number;
40
+ coverage: "observedOnly";
41
+ observations: PurchaseObservation[];
42
+ products: PurchaseProduct[];
43
+ }
44
+ export interface PurchaseValidationReport extends PurchaseSnapshot {
45
+ status: "pass" | "fail" | "inconclusive";
46
+ checks: { source: string; status: "pass" | "fail" | "inconclusive"; reason: string }[];
47
+ }
48
+ export interface PurchaseDiagnostics {
49
+ createTransactionReference(identifier: string): Promise<{ transactionRef: string }>;
50
+ /** Register read-only remote tools after SDK initialization. */
51
+ register(): Promise<{ success: boolean }>;
52
+ record(observation: PurchaseObservation): Promise<{ success: boolean }>;
53
+ recordProduct(product: PurchaseProduct): Promise<{ success: boolean }>;
54
+ /** Clear evidence on account switch. Does not clear store transactions. */
55
+ clear(): Promise<{ success: boolean }>;
56
+ snapshot(productId?: string): Promise<PurchaseSnapshot>;
57
+ validate(expectations: PurchaseExpectations): Promise<PurchaseValidationReport>;
58
+ /** Apple only. Reads StoreKit 2 using known product IDs. */
59
+ refreshStoreKit(productIds: string[]): Promise<PurchaseSnapshot>;
60
+ }
61
+ export function createPurchaseDiagnostics(send: (json: string) => Promise<string>): PurchaseDiagnostics;
package/purchases.js ADDED
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+
3
+ // All observation retention, validation and tools live in the native base SDK.
4
+ function createPurchaseDiagnostics(send) {
5
+ const command = async (action, fields = {}) => JSON.parse(await send(JSON.stringify({ action, ...fields })));
6
+ return {
7
+ createTransactionReference: (identifier) => command("reference", { identifier }),
8
+ register: () => command("register"),
9
+ record: (observation) => command("record", { observation: { observedAt: Date.now(), ...observation } }),
10
+ recordProduct: (product) => command("recordProduct", { product: { observedAt: Date.now(), productType: "unknown", ...product } }),
11
+ clear: () => command("clear"),
12
+ snapshot: (productId) => command("purchases.get_state", { arguments: productId === undefined ? {} : { productId } }),
13
+ validate: (expectations) => command("purchases.validate", { arguments: expectations }),
14
+ refreshStoreKit: (productIds) => command("refreshStoreKit", { productIds }),
15
+ };
16
+ }
17
+ module.exports = { createPurchaseDiagnostics };