@mobileai/react-native 0.9.26 → 0.9.28

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 (67) hide show
  1. package/README.md +28 -15
  2. package/android/build.gradle +17 -0
  3. package/android/src/main/java/com/mobileai/overlay/FloatingOverlayDialogRootViewGroup.kt +243 -0
  4. package/android/src/main/java/com/mobileai/overlay/FloatingOverlayView.kt +281 -87
  5. package/android/src/newarch/com/mobileai/overlay/FloatingOverlayViewManager.kt +52 -17
  6. package/android/src/oldarch/com/mobileai/overlay/FloatingOverlayViewManager.kt +49 -2
  7. package/bin/generate-map.cjs +556 -126
  8. package/ios/Podfile +63 -0
  9. package/ios/Podfile.lock +2290 -0
  10. package/ios/Podfile.properties.json +4 -0
  11. package/ios/mobileaireactnative/AppDelegate.swift +69 -0
  12. package/ios/mobileaireactnative/Images.xcassets/AppIcon.appiconset/Contents.json +13 -0
  13. package/ios/mobileaireactnative/Images.xcassets/Contents.json +6 -0
  14. package/ios/mobileaireactnative/Images.xcassets/SplashScreenLegacy.imageset/Contents.json +21 -0
  15. package/ios/mobileaireactnative/Images.xcassets/SplashScreenLegacy.imageset/SplashScreenLegacy.png +0 -0
  16. package/ios/mobileaireactnative/Info.plist +55 -0
  17. package/ios/mobileaireactnative/PrivacyInfo.xcprivacy +48 -0
  18. package/ios/mobileaireactnative/SplashScreen.storyboard +47 -0
  19. package/ios/mobileaireactnative/Supporting/Expo.plist +6 -0
  20. package/ios/mobileaireactnative/mobileaireactnative-Bridging-Header.h +3 -0
  21. package/ios/mobileaireactnative.xcodeproj/project.pbxproj +547 -0
  22. package/ios/mobileaireactnative.xcodeproj/xcshareddata/xcschemes/mobileaireactnative.xcscheme +88 -0
  23. package/ios/mobileaireactnative.xcworkspace/contents.xcworkspacedata +10 -0
  24. package/lib/module/components/AIAgent.js +407 -148
  25. package/lib/module/components/AgentChatBar.js +253 -62
  26. package/lib/module/components/FloatingOverlayWrapper.js +68 -32
  27. package/lib/module/config/endpoints.js +22 -1
  28. package/lib/module/core/AgentRuntime.js +192 -24
  29. package/lib/module/core/FiberTreeWalker.js +410 -34
  30. package/lib/module/core/OutcomeVerifier.js +149 -0
  31. package/lib/module/core/systemPrompt.js +126 -44
  32. package/lib/module/providers/GeminiProvider.js +9 -3
  33. package/lib/module/services/MobileAIKnowledgeRetriever.js +1 -1
  34. package/lib/module/services/telemetry/MobileAI.js +1 -1
  35. package/lib/module/services/telemetry/TelemetryService.js +21 -2
  36. package/lib/module/services/telemetry/TouchAutoCapture.js +45 -35
  37. package/lib/module/specs/FloatingOverlayNativeComponent.ts +7 -1
  38. package/lib/module/support/supportPrompt.js +22 -7
  39. package/lib/module/support/supportStyle.js +55 -0
  40. package/lib/module/support/types.js +2 -0
  41. package/lib/module/tools/tapTool.js +77 -6
  42. package/lib/module/tools/typeTool.js +20 -0
  43. package/lib/module/utils/humanizeScreenName.js +49 -0
  44. package/lib/typescript/src/components/AIAgent.d.ts +6 -2
  45. package/lib/typescript/src/components/AgentChatBar.d.ts +15 -1
  46. package/lib/typescript/src/components/FloatingOverlayWrapper.d.ts +22 -10
  47. package/lib/typescript/src/config/endpoints.d.ts +4 -0
  48. package/lib/typescript/src/core/AgentRuntime.d.ts +17 -1
  49. package/lib/typescript/src/core/FiberTreeWalker.d.ts +12 -1
  50. package/lib/typescript/src/core/OutcomeVerifier.d.ts +46 -0
  51. package/lib/typescript/src/core/systemPrompt.d.ts +3 -10
  52. package/lib/typescript/src/core/types.d.ts +37 -1
  53. package/lib/typescript/src/index.d.ts +1 -0
  54. package/lib/typescript/src/services/MobileAIKnowledgeRetriever.d.ts +1 -1
  55. package/lib/typescript/src/services/telemetry/TelemetryService.d.ts +7 -1
  56. package/lib/typescript/src/services/telemetry/types.d.ts +1 -1
  57. package/lib/typescript/src/specs/FloatingOverlayNativeComponent.d.ts +5 -0
  58. package/lib/typescript/src/support/index.d.ts +1 -0
  59. package/lib/typescript/src/support/supportStyle.d.ts +9 -0
  60. package/lib/typescript/src/support/types.d.ts +3 -0
  61. package/lib/typescript/src/tools/tapTool.d.ts +3 -2
  62. package/lib/typescript/src/utils/humanizeScreenName.d.ts +6 -0
  63. package/lib/typescript/test-tree.d.ts +2 -0
  64. package/package.json +5 -2
  65. package/src/specs/FloatingOverlayNativeComponent.ts +7 -1
  66. package/ios/MobileAIFloatingOverlayComponentView.mm +0 -73
  67. package/ios/MobileAIPilotIntents.swift +0 -51
@@ -6,7 +6,7 @@
6
6
  * interactive elements by their type and props (onPress, onChangeText, etc.).
7
7
  *
8
8
  */
9
- import type { InteractiveElement } from './types';
9
+ import type { InteractiveElement, WireframeSnapshot } from './types';
10
10
  export interface WalkConfig {
11
11
  /** React refs of elements to exclude */
12
12
  interactiveBlacklist?: React.RefObject<any>[];
@@ -64,4 +64,15 @@ export interface ScrollableContainer {
64
64
  * For ScrollView: the stateNode IS the native scroll view directly.
65
65
  */
66
66
  export declare function findScrollableContainers(rootRef: any, screenName?: string): ScrollableContainer[];
67
+ /**
68
+ * Capture a privacy-safe wireframe of the current screen.
69
+ *
70
+ * Performance guarantees:
71
+ * - Capped at WIREFRAME_MAX_ELEMENTS (50) — enough for wireframe context
72
+ * - Measures in batches of WIREFRAME_BATCH_SIZE (10), yielding a frame
73
+ * between batches so the bridge stays free for user interactions
74
+ * - The caller (AIAgent) defers this via InteractionManager so it
75
+ * never competes with screen transitions or gestures
76
+ */
77
+ export declare function captureWireframe(rootRef: React.RefObject<any>, config?: WalkConfig): Promise<WireframeSnapshot | null>;
67
78
  //# sourceMappingURL=FiberTreeWalker.d.ts.map
@@ -0,0 +1,46 @@
1
+ import type { AIProvider, AgentConfig, InteractiveElement } from './types';
2
+ export type VerificationStatus = 'success' | 'error' | 'uncertain';
3
+ export type VerificationFailureKind = 'controllable' | 'uncontrollable';
4
+ export interface VerificationSnapshot {
5
+ screenName: string;
6
+ screenContent: string;
7
+ elements: InteractiveElement[];
8
+ screenshot?: string;
9
+ }
10
+ export interface VerificationAction {
11
+ toolName: string;
12
+ args: Record<string, any>;
13
+ label: string;
14
+ targetElement?: InteractiveElement;
15
+ }
16
+ export interface VerificationContext {
17
+ goal: string;
18
+ action: VerificationAction;
19
+ preAction: VerificationSnapshot;
20
+ postAction: VerificationSnapshot;
21
+ }
22
+ export interface VerificationResult {
23
+ status: VerificationStatus;
24
+ failureKind: VerificationFailureKind;
25
+ evidence: string;
26
+ source: 'deterministic' | 'llm';
27
+ }
28
+ export interface PendingVerification {
29
+ goal: string;
30
+ action: VerificationAction;
31
+ preAction: VerificationSnapshot;
32
+ followupSteps: number;
33
+ }
34
+ export declare function createVerificationSnapshot(screenName: string, screenContent: string, elements: InteractiveElement[], screenshot?: string): VerificationSnapshot;
35
+ export declare function buildVerificationAction(toolName: string, args: Record<string, any>, elements: InteractiveElement[], fallbackLabel: string): VerificationAction;
36
+ export declare function isCriticalVerificationAction(action: VerificationAction): boolean;
37
+ export declare class OutcomeVerifier {
38
+ private readonly provider;
39
+ private readonly config;
40
+ constructor(provider: AIProvider, config: AgentConfig);
41
+ isEnabled(): boolean;
42
+ getMaxFollowupSteps(): number;
43
+ isCriticalAction(action: VerificationAction): boolean;
44
+ verify(context: VerificationContext): Promise<VerificationResult>;
45
+ }
46
+ //# sourceMappingURL=OutcomeVerifier.d.ts.map
@@ -1,13 +1,6 @@
1
- /**
2
- * System prompt for the AI agent.
3
- *
4
- * Shared fragments are extracted as constants at the top so that all
5
- * three prompt builders (text agent, voice agent, knowledge-only) stay
6
- * in sync — one change propagates everywhere. The prompt uses XML-style
7
- * tags to give the LLM clear, structured instructions.
8
- */
9
- export declare function buildSystemPrompt(language: string, hasKnowledge?: boolean, isCopilot?: boolean): string;
10
- export declare function buildVoiceSystemPrompt(language: string, userInstructions?: string, hasKnowledge?: boolean): string;
1
+ import type { SupportStyle } from './types';
2
+ export declare function buildSystemPrompt(language: string, hasKnowledge?: boolean, isCopilot?: boolean, supportStyle?: SupportStyle): string;
3
+ export declare function buildVoiceSystemPrompt(language: string, userInstructions?: string, hasKnowledge?: boolean, supportStyle?: SupportStyle): string;
11
4
  /**
12
5
  * Build a knowledge-only system prompt (no UI control tools).
13
6
  *
@@ -11,7 +11,17 @@ export type AgentMode = 'text' | 'voice' | 'human';
11
11
  */
12
12
  export type InteractionMode = 'copilot' | 'autopilot';
13
13
  export type AIProviderName = 'gemini' | 'openai';
14
- export type ElementType = 'pressable' | 'text-input' | 'switch' | 'scrollable' | 'slider' | 'picker' | 'date-picker';
14
+ export type SupportStyle = 'warm-concise' | 'wow-service' | 'neutral-professional';
15
+ export interface VerifierConfig {
16
+ enabled?: boolean;
17
+ mode?: 'critical-actions';
18
+ provider?: AIProviderName;
19
+ model?: string;
20
+ proxyUrl?: string;
21
+ proxyHeaders?: Record<string, string>;
22
+ maxFollowupSteps?: number;
23
+ }
24
+ export type ElementType = 'pressable' | 'text-input' | 'switch' | 'radio' | 'scrollable' | 'slider' | 'picker' | 'date-picker';
15
25
  export interface InteractiveElement {
16
26
  /** Unique index assigned during tree walk */
17
27
  index: number;
@@ -33,6 +43,7 @@ export interface InteractiveElement {
33
43
  * - Picker: onValueChange, items, selectedValue
34
44
  * - DatePicker: onChange, onDateChange, mode
35
45
  * - Switch: onValueChange, value
46
+ * - Radio: onPress, onValueChange/onChange, value, checked
36
47
  */
37
48
  props: Record<string, any>;
38
49
  /**
@@ -50,6 +61,21 @@ export interface InteractiveElement {
50
61
  alertButtonIndex: number;
51
62
  };
52
63
  }
64
+ export interface WireframeComponent {
65
+ type: ElementType;
66
+ label: string;
67
+ x: number;
68
+ y: number;
69
+ width: number;
70
+ height: number;
71
+ }
72
+ export interface WireframeSnapshot {
73
+ screen: string;
74
+ components: WireframeComponent[];
75
+ deviceWidth: number;
76
+ deviceHeight: number;
77
+ capturedAt: string;
78
+ }
53
79
  export interface DehydratedScreen {
54
80
  /** Current screen name (from navigation state) */
55
81
  screenName: string;
@@ -122,6 +148,16 @@ export interface AgentConfig {
122
148
  */
123
149
  voiceProxyHeaders?: Record<string, string>;
124
150
  model?: string;
151
+ /**
152
+ * Support personality preset used when the agent is handling support-style requests.
153
+ * Default: 'warm-concise'
154
+ */
155
+ supportStyle?: SupportStyle;
156
+ /**
157
+ * Optional outcome verifier settings for critical app-changing actions.
158
+ * Defaults to enabled critical-action verification using the main provider.
159
+ */
160
+ verifier?: VerifierConfig;
125
161
  /** Maximum steps per task */
126
162
  maxSteps?: number;
127
163
  /**
@@ -28,4 +28,5 @@ export type { TelemetryConfig, TelemetryEvent } from './services/telemetry';
28
28
  export { SupportGreeting, CSATSurvey, buildSupportPrompt, createEscalateTool, EscalationSocket, } from './support';
29
29
  export { createReportIssueTool } from './support';
30
30
  export type { SupportModeConfig, QuickReply, EscalationConfig, EscalationContext, CSATConfig, CSATRating, BusinessHoursConfig, SupportTicket, ReportedIssue, ReportedIssueCustomerStatus, ReportedIssueStatusUpdate, } from './support';
31
+ export type { SupportStyle } from './support';
31
32
  //# sourceMappingURL=index.d.ts.map
@@ -1,6 +1,6 @@
1
1
  import type { KnowledgeRetriever } from '../core/types';
2
2
  export interface MobileAIKnowledgeRetrieverOptions {
3
- publishableKey: string;
3
+ analyticsKey: string;
4
4
  baseUrl?: string;
5
5
  headers?: Record<string, string>;
6
6
  limit?: number;
@@ -18,6 +18,7 @@ export declare class TelemetryService {
18
18
  private flushTimer;
19
19
  private isFlushing;
20
20
  private appStateSubscription;
21
+ private wireframesSent;
21
22
  get screen(): string;
22
23
  getScreenFlow(): string[];
23
24
  /**
@@ -37,7 +38,12 @@ export declare class TelemetryService {
37
38
  /** Track an event (auto or custom) */
38
39
  track(type: string, data?: Record<string, unknown>): void;
39
40
  /** Update current screen (called by AIAgent on navigation) */
40
- setScreen(screenName: string): void;
41
+ setScreen(rawScreenName: string): void;
42
+ /**
43
+ * Track a wireframe snapshot.
44
+ * Deduped per session (only one wireframe per screen over a session).
45
+ */
46
+ trackWireframe(snapshot: import('../../core/types').WireframeSnapshot): void;
41
47
  /** Send queued events to the cloud API */
42
48
  flush(): Promise<void>;
43
49
  /** Save queued events to AsyncStorage for crash/restart recovery */
@@ -6,7 +6,7 @@
6
6
  * 2. Consumer-tracked: via MobileAI.track() API
7
7
  */
8
8
  /** Auto-captured event types */
9
- export type AutoEventType = 'screen_view' | 'user_action' | 'scroll_depth' | 'idle_detected' | 'session_start' | 'session_end' | 'agent_request' | 'agent_step' | 'agent_trace' | 'agent_complete' | 'escalation' | 'knowledge_query' | 'knowledge_miss' | 'csat_response' | 'ces_response' | 'agent_first_response' | 'human_first_response' | 'fcr_achieved' | 'engagement_signal' | 'health_signal' | 'onboarding_step';
9
+ export type AutoEventType = 'screen_view' | 'user_action' | 'user_interaction' | 'scroll_depth' | 'idle_detected' | 'session_start' | 'session_end' | 'agent_request' | 'agent_step' | 'agent_trace' | 'agent_complete' | 'escalation' | 'knowledge_query' | 'knowledge_miss' | 'csat_response' | 'ces_response' | 'agent_first_response' | 'human_first_response' | 'fcr_achieved' | 'engagement_signal' | 'health_signal' | 'onboarding_step' | 'business_escalation' | 'dead_click' | 'dead_click_detected' | 'rage_click' | 'rage_click_detected' | 'error_screen' | 'repeated_navigation' | 'checkout_started' | 'purchase_complete' | 'purchase_completed' | 'wireframe_snapshot';
10
10
  /** All event types (auto + custom) */
11
11
  export type EventType = AutoEventType | string;
12
12
  export interface TelemetryEvent {
@@ -10,7 +10,12 @@
10
10
  * Naming convention: file must end in NativeComponent.ts (Codegen convention).
11
11
  */
12
12
  import type { ViewProps } from 'react-native';
13
+ import type { Int32 } from 'react-native/Libraries/Types/CodegenTypes';
13
14
  export interface NativeProps extends ViewProps {
15
+ windowX?: Int32;
16
+ windowY?: Int32;
17
+ windowWidth?: Int32;
18
+ windowHeight?: Int32;
14
19
  }
15
20
  declare const _default: import("react-native/Libraries/Utilities/codegenNativeComponent").NativeComponentType<NativeProps>;
16
21
  export default _default;
@@ -2,6 +2,7 @@
2
2
  * Support Mode — barrel export.
3
3
  */
4
4
  export type { SupportModeConfig, QuickReply, EscalationConfig, EscalationContext, CSATConfig, CSATRating, BusinessHoursConfig, SupportTicket, ReportedIssue, ReportedIssueCustomerStatus, ReportedIssueStatusUpdate, } from './types';
5
+ export type { SupportStyle } from './supportStyle';
5
6
  export { buildSupportPrompt } from './supportPrompt';
6
7
  export { createEscalateTool } from './escalateTool';
7
8
  export { createReportIssueTool } from './reportIssueTool';
@@ -0,0 +1,9 @@
1
+ export type SupportStyle = 'warm-concise' | 'wow-service' | 'neutral-professional';
2
+ interface SupportStylePreset {
3
+ tone: string;
4
+ prompt: string;
5
+ }
6
+ export declare function resolveSupportStyle(style?: SupportStyle): SupportStylePreset;
7
+ export declare function buildSupportStylePrompt(style?: SupportStyle): string;
8
+ export {};
9
+ //# sourceMappingURL=supportStyle.d.ts.map
@@ -7,6 +7,7 @@
7
7
  * - Human escalation capability
8
8
  * - CSAT (Customer Satisfaction) collection after conversation
9
9
  */
10
+ import type { SupportStyle } from './supportStyle';
10
11
  export interface SupportModeConfig {
11
12
  /** Enable support mode. Default: false */
12
13
  enabled: boolean;
@@ -42,6 +43,8 @@ export interface SupportModeConfig {
42
43
  * Options for the AI's persona and tone.
43
44
  */
44
45
  persona?: {
46
+ /** Preset support personality. Default: 'warm-concise'. */
47
+ preset?: SupportStyle;
45
48
  /** The agent's name to use in conversation. */
46
49
  agentName?: string;
47
50
  /** The tone of the AI (e.g., 'professional', 'casual', 'empathetic'). Default: 'empathetic' */
@@ -3,8 +3,9 @@
3
3
  *
4
4
  * Strategies (in priority order):
5
5
  * 1. Switch → onValueChange (toggle)
6
- * 2. Direct onPress on element
7
- * 3. Bubble up fiber tree to find parent onPress (max 5 levels)
6
+ * 2. Radio onPress / onValueChange / parent radio-group handler
7
+ * 3. Direct onPress on element
8
+ * 4. Bubble up fiber tree to find parent onPress (max 5 levels)
8
9
  *
9
10
  * Includes Maestro-style tap verification:
10
11
  * - Captures element count + screen name before tap
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Transforms raw navigation route names into human-readable labels.
3
+ * Designed to handle both Expo Router (file-based) and React Navigation conventions.
4
+ */
5
+ export declare function humanizeScreenName(route: string | null | undefined): string;
6
+ //# sourceMappingURL=humanizeScreenName.d.ts.map
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=test-tree.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mobileai/react-native",
3
- "version": "0.9.26",
3
+ "version": "0.9.28",
4
4
  "description": "Build autonomous AI agents for React Native and Expo apps. Provides AI-native UI traversal, tool calling, and structured reasoning.",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",
@@ -96,7 +96,10 @@
96
96
  "dependencies": {
97
97
  "@babel/parser": "^7.29.2",
98
98
  "@babel/traverse": "^7.29.0",
99
- "@babel/types": "^7.29.0"
99
+ "@babel/types": "^7.29.0",
100
+ "expo": "~55.0.8",
101
+ "react": "19.2.0",
102
+ "react-native": "0.83.2"
100
103
  },
101
104
  "devDependencies": {
102
105
  "@eslint/compat": "^1.3.2",
@@ -11,9 +11,15 @@
11
11
  */
12
12
 
13
13
  import type { ViewProps } from 'react-native';
14
+ import type { Int32 } from 'react-native/Libraries/Types/CodegenTypes';
14
15
  import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent';
15
16
 
16
- export interface NativeProps extends ViewProps {}
17
+ export interface NativeProps extends ViewProps {
18
+ windowX?: Int32;
19
+ windowY?: Int32;
20
+ windowWidth?: Int32;
21
+ windowHeight?: Int32;
22
+ }
17
23
 
18
24
  // Codegen reads this export to generate the native component interfaces.
19
25
  export default codegenNativeComponent<NativeProps>('MobileAIFloatingOverlay');
@@ -1,73 +0,0 @@
1
- #import <React/RCTViewComponentView.h>
2
- #import <UIKit/UIKit.h>
3
-
4
- #import <react/renderer/components/RNMobileAIOverlaySpec/ComponentDescriptors.h>
5
- #import <react/renderer/components/RNMobileAIOverlaySpec/EventEmitters.h>
6
- #import <react/renderer/components/RNMobileAIOverlaySpec/Props.h>
7
- #import <react/renderer/components/RNMobileAIOverlaySpec/RCTComponentViewHelpers.h>
8
-
9
- #import "RCTFabricComponentsPlugins.h"
10
-
11
- NS_ASSUME_NONNULL_BEGIN
12
- @interface MobileAIFloatingOverlayComponentView : RCTViewComponentView
13
- @end
14
- NS_ASSUME_NONNULL_END
15
-
16
- using namespace facebook::react;
17
-
18
- @interface MobileAIFloatingOverlayComponentView () <RCTMobileAIFloatingOverlayViewProtocol>
19
- @end
20
-
21
- @implementation MobileAIFloatingOverlayComponentView {
22
- UIView * _view;
23
- }
24
-
25
- + (ComponentDescriptorProvider)componentDescriptorProvider
26
- {
27
- return concreteComponentDescriptorProvider<MobileAIFloatingOverlayComponentDescriptor>();
28
- }
29
-
30
- - (instancetype)initWithFrame:(CGRect)frame
31
- {
32
- if (self = [super initWithFrame:frame]) {
33
- static const auto defaultProps = std::make_shared<const MobileAIFloatingOverlayProps>();
34
- _props = defaultProps;
35
-
36
- _view = [[UIView alloc] init];
37
-
38
- self.contentView = _view;
39
- }
40
-
41
- return self;
42
- }
43
-
44
- - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps
45
- {
46
- const auto &oldViewProps = *std::static_pointer_cast<MobileAIFloatingOverlayProps const>(_props);
47
- const auto &newViewProps = *std::static_pointer_cast<MobileAIFloatingOverlayProps const>(props);
48
-
49
- [super updateProps:props oldProps:oldProps];
50
- }
51
-
52
- @end
53
-
54
- Class<RCTComponentViewProtocol> MobileAIFloatingOverlayCls(void)
55
- {
56
- return MobileAIFloatingOverlayComponentView.class;
57
- }
58
-
59
- // ─── Linker Fix: Force inclusion of the library ────────────────
60
-
61
- #import <React/RCTViewManager.h>
62
-
63
- @interface MobileAIFloatingOverlayManager : RCTViewManager
64
- @end
65
-
66
- @implementation MobileAIFloatingOverlayManager
67
- RCT_EXPORT_MODULE(MobileAIFloatingOverlay)
68
-
69
- - (UIView *)view
70
- {
71
- return [[UIView alloc] init];
72
- }
73
- @end
@@ -1,51 +0,0 @@
1
- import AppIntents
2
- import UIKit
3
-
4
- // Auto-generated by react-native-ai-agent
5
- // Do not edit manually.
6
-
7
- @available(iOS 16.0, *)
8
- struct CheckoutCartIntent: AppIntent {
9
- static var title: LocalizedStringResource = "checkout_cart"
10
- static var description = IntentDescription("Process checkout")
11
- static var openAppWhenRun: Bool = true
12
-
13
- @Parameter(title: "Total amount")
14
- var amount: Double?
15
-
16
- @Parameter(title: "Currency code")
17
- var currency: String?
18
-
19
- @Parameter(title: "Express checkout")
20
- var isExpress: Bool?
21
-
22
- @MainActor
23
- func perform() async throws -> some IntentResult {
24
- var components = URLComponents()
25
- components.scheme = "feedyum"
26
- components.host = "ai-action"
27
- components.path = "/checkout_cart"
28
- var queryItems: [URLQueryItem] = []
29
- if let val = amount {
30
- queryItems.append(URLQueryItem(name: "amount", value: String(describing: val)))
31
- }
32
- if let val = currency {
33
- queryItems.append(URLQueryItem(name: "currency", value: String(describing: val)))
34
- }
35
- if let val = isExpress {
36
- queryItems.append(URLQueryItem(name: "isExpress", value: String(describing: val)))
37
- }
38
- components.queryItems = queryItems
39
- if let url = components.url {
40
- await UIApplication.shared.open(url)
41
- }
42
- return .result()
43
- }
44
- }
45
-
46
- @available(iOS 16.0, *)
47
- struct MobileAIAppShortcuts: AppShortcutsProvider {
48
- static var appShortcuts: [AppShortcut] {
49
- AppShortcut(intent: CheckoutCartIntent(), phrases: ["\\(.applicationName) checkout cart"])
50
- }
51
- }