@ateam-ai-mobile/expo 0.1.19 → 0.1.21
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/dist/aiLive/provider.d.mts +20 -0
- package/dist/aiLive/provider.d.ts +20 -0
- package/dist/aiLive/provider.js +400 -0
- package/dist/aiLive/provider.js.map +1 -0
- package/dist/aiLive/provider.mjs +15 -0
- package/dist/aiLive/provider.mjs.map +1 -0
- package/dist/bootstrap.js +350 -3
- package/dist/bootstrap.js.map +1 -1
- package/dist/bootstrap.mjs +17 -12
- package/dist/bootstrap.mjs.map +1 -1
- package/dist/capabilities/index.d.mts +40 -1
- package/dist/capabilities/index.d.ts +40 -1
- package/dist/capabilities/index.js +50 -14
- package/dist/capabilities/index.js.map +1 -1
- package/dist/capabilities/index.mjs +49 -32
- package/dist/capabilities/index.mjs.map +1 -1
- package/dist/{chunk-42FP5DTO.mjs → chunk-2ZQEQJQ6.mjs} +1 -1
- package/dist/chunk-2ZQEQJQ6.mjs.map +1 -0
- package/dist/chunk-AE55BKYV.mjs +24 -0
- package/dist/chunk-AE55BKYV.mjs.map +1 -0
- package/dist/chunk-BAZFMTCC.mjs +815 -0
- package/dist/chunk-BAZFMTCC.mjs.map +1 -0
- package/dist/{chunk-Z5AI2SXX.mjs → chunk-C62NQA4F.mjs} +203 -1004
- package/dist/chunk-C62NQA4F.mjs.map +1 -0
- package/dist/{chunk-DE6Y4VRI.mjs → chunk-GA7DS3PA.mjs} +1 -1
- package/dist/{chunk-DE6Y4VRI.mjs.map → chunk-GA7DS3PA.mjs.map} +1 -1
- package/dist/chunk-GW7YGXOW.mjs +47 -0
- package/dist/chunk-GW7YGXOW.mjs.map +1 -0
- package/dist/chunk-JUBLG3PN.mjs +351 -0
- package/dist/chunk-JUBLG3PN.mjs.map +1 -0
- package/dist/{chunk-Z3P7RUCC.mjs → chunk-OEX4OKYQ.mjs} +13 -13
- package/dist/{chunk-6JX222YX.mjs → chunk-WQK6PUBN.mjs} +9 -2
- package/dist/chunk-WQK6PUBN.mjs.map +1 -0
- package/dist/device/createDeviceProvider.js.map +1 -1
- package/dist/device/createDeviceProvider.mjs +7 -6
- package/dist/device-bridge/index.mjs +8 -6
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/push/index.d.mts +24 -0
- package/dist/push/index.d.ts +24 -0
- package/dist/push/index.js +224 -0
- package/dist/push/index.js.map +1 -0
- package/dist/push/index.mjs +174 -0
- package/dist/push/index.mjs.map +1 -0
- package/dist/push/silentSync.d.mts +8 -0
- package/dist/push/silentSync.d.ts +8 -0
- package/dist/push/silentSync.js +1075 -0
- package/dist/push/silentSync.js.map +1 -0
- package/dist/push/silentSync.mjs +67 -0
- package/dist/push/silentSync.mjs.map +1 -0
- package/dist/vision/index.d.mts +7 -1
- package/dist/vision/index.d.ts +7 -1
- package/dist/vision/index.js +8 -0
- package/dist/vision/index.js.map +1 -1
- package/dist/vision/index.mjs +3 -1
- package/ios/AdaVisionModule.swift +44 -1
- package/package.json +28 -6
- package/src/aiLive/provider.ts +242 -0
- package/src/aiLive/streamProtocol.ts +90 -0
- package/src/bootstrap.ts +7 -1
- package/src/capabilities/choices.ts +65 -0
- package/src/capabilities/config.ts +5 -4
- package/src/capabilities/index.ts +2 -0
- package/src/capabilities/picturesToAi.ts +40 -0
- package/src/capabilities/store.ts +38 -37
- package/src/index.ts +3 -0
- package/src/push/index.ts +18 -0
- package/src/push/messaging.ts +49 -0
- package/src/push/registration.ts +31 -0
- package/src/push/silentSync.ts +83 -0
- package/src/push/usePushNotifications.ts +224 -0
- package/src/vision/index.ts +14 -0
- package/dist/chunk-42FP5DTO.mjs.map +0 -1
- package/dist/chunk-6JX222YX.mjs.map +0 -1
- package/dist/chunk-Z5AI2SXX.mjs.map +0 -1
- /package/dist/{chunk-Z3P7RUCC.mjs.map → chunk-OEX4OKYQ.mjs.map} +0 -0
package/dist/bootstrap.mjs
CHANGED
|
@@ -1,33 +1,37 @@
|
|
|
1
|
-
import {
|
|
2
|
-
createDeviceProvider
|
|
3
|
-
} from "./chunk-Z3P7RUCC.mjs";
|
|
4
1
|
import {
|
|
5
2
|
createExpoOAuthProvider
|
|
6
3
|
} from "./chunk-L4V7OCJ3.mjs";
|
|
7
|
-
import "./chunk-6JX222YX.mjs";
|
|
8
4
|
import {
|
|
9
5
|
createDeviceState,
|
|
10
6
|
setupExpoProviders
|
|
11
|
-
} from "./chunk-
|
|
12
|
-
import
|
|
7
|
+
} from "./chunk-2ZQEQJQ6.mjs";
|
|
8
|
+
import {
|
|
9
|
+
createAiLiveProvider
|
|
10
|
+
} from "./chunk-JUBLG3PN.mjs";
|
|
13
11
|
import {
|
|
14
12
|
configureDeviceSync
|
|
15
|
-
} from "./chunk-
|
|
16
|
-
import
|
|
13
|
+
} from "./chunk-GA7DS3PA.mjs";
|
|
14
|
+
import {
|
|
15
|
+
createDeviceProvider
|
|
16
|
+
} from "./chunk-OEX4OKYQ.mjs";
|
|
17
|
+
import "./chunk-4BMWVN25.mjs";
|
|
18
|
+
import "./chunk-6LXF3JVX.mjs";
|
|
19
|
+
import "./chunk-WQK6PUBN.mjs";
|
|
20
|
+
import "./chunk-BAZFMTCC.mjs";
|
|
17
21
|
import {
|
|
18
22
|
connectivity_exports,
|
|
19
23
|
location_exports
|
|
20
|
-
} from "./chunk-
|
|
21
|
-
import "./chunk-KOXF2FZM.mjs";
|
|
24
|
+
} from "./chunk-C62NQA4F.mjs";
|
|
22
25
|
import "./chunk-XQSY6MHP.mjs";
|
|
26
|
+
import "./chunk-KOXF2FZM.mjs";
|
|
23
27
|
import "./chunk-7FWYEHN5.mjs";
|
|
24
28
|
import "./chunk-J6XRNX7P.mjs";
|
|
25
|
-
import "./chunk-
|
|
29
|
+
import "./chunk-FF6ZZZXH.mjs";
|
|
26
30
|
import "./chunk-WMJKH4XE.mjs";
|
|
27
31
|
|
|
28
32
|
// src/bootstrap.ts
|
|
29
33
|
import { initAdas, setAcsReachabilityReporter } from "@ateam-ai-mobile/core";
|
|
30
|
-
import { setDeviceStateProvider, registerNativePlugin, registerPlatformDeviceTools } from "@ateam-ai-mobile/plugin-runtime";
|
|
34
|
+
import { setDeviceStateProvider, registerNativePlugin, registerPlatformDeviceTools, setAiLiveProvider } from "@ateam-ai-mobile/plugin-runtime";
|
|
31
35
|
import { setOAuthProvider, setUIActionNavigator, setPluginWebViewExtraHosts, setCallAudioProvider } from "@ateam-ai-mobile/ui";
|
|
32
36
|
|
|
33
37
|
// src/audio/index.ts
|
|
@@ -71,6 +75,7 @@ function bootstrapExpoAdas(opts) {
|
|
|
71
75
|
setDeviceStateProvider(
|
|
72
76
|
createDeviceState({ connectivity: connectivity_exports, location: location_exports })
|
|
73
77
|
);
|
|
78
|
+
setAiLiveProvider(createAiLiveProvider());
|
|
74
79
|
registerPlatformDeviceTools();
|
|
75
80
|
setUIActionNavigator(opts.navigateToPlugin);
|
|
76
81
|
initAdas({
|
package/dist/bootstrap.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/bootstrap.ts","../src/audio/index.ts"],"sourcesContent":["/**\n * bootstrapExpoAdas — the single, self-contained SDK bootstrap (R10).\n *\n * The final high-level entry point of the \"fat SDK / thin shell\" arc: it folds\n * the ~15 hand-wired seams the host used to assemble in its own adas.ts into ONE\n * call, so the shell stops manually assembling platform providers/collectors/\n * plugins. Internally it initializes, in the order the migrated code established:\n * the Expo providers (haptics/bundle cache/clipboard/attachment cache + the\n * device-primitive provider), the host-bundled native plugins, the plugin-WebView\n * allow-list, native OAuth, the ACS reachability reporter, the L3 DeviceState\n * engine (with the SDK's OWN collectors — the shell injects none), the plugin/\n * UI-action navigator, and finally the core config+token bridge (initAdas).\n *\n * The API is DERIVED from the host's migrated adas.ts, not invented. Everything\n * the host still owns is passed in as a small values-and-getters bag: endpoint\n * getters (the host owns the dev/prod switch), the identity/token bridge, its\n * branded Google client id, its host-bundled plugin resolvers, the native\n * WebView module from its build, and its router callback.\n *\n * A SUBPATH (`@ateam-ai-mobile/expo/bootstrap`), like /device and /oauth: it\n * statically pulls the optional expo native modules (via createDeviceProvider /\n * the device-state collectors / the OAuth provider), so it must not sit on the\n * package's main entry, which a host without those modules still has to build.\n *\n * The two physical reasoning paths stay DISTINCT and are wired as SEPARATE\n * statements — never a merged bridge: LOCAL (the local tool registry + device\n * state the plugin/voice runtime reads) and SERVER (the relay allow-list here;\n * the DeviceBridge relay runtime itself is started by the host lifecycle, out of\n * this module-load bootstrap's scope).\n */\nimport { initAdas, setAcsReachabilityReporter, type TokenProvider, type AdasUser, type AdasSession } from '@ateam-ai-mobile/core';\nimport { setDeviceStateProvider, registerNativePlugin, registerPlatformDeviceTools, type RegisteredPlugin } from '@ateam-ai-mobile/plugin-runtime';\nimport { setOAuthProvider, setUIActionNavigator, setPluginWebViewExtraHosts, setCallAudioProvider, type UIActionRoute } from '@ateam-ai-mobile/ui';\nimport { createCallAudioProvider } from './audio';\n\nimport { setupExpoProviders, type ExpoAttachmentCache } from './index';\nimport { createDeviceProvider } from './device/createDeviceProvider';\nimport { createDeviceState } from './device-state';\nimport { createExpoOAuthProvider } from './oauth/expoOAuth';\nimport * as deviceConnectivity from './device-bridge/collectors/connectivity';\nimport * as deviceLocation from './device-bridge/collectors/location';\nimport { configureDeviceSync } from './capabilities/config';\nimport type { SecureKv } from './device-bridge/deviceId';\n\n/** A host-bundled native plugin: one lazy resolver registered under one or more ids. */\nexport interface NativePluginRegistration {\n resolver: () => Promise<RegisteredPlugin>;\n ids: string[];\n}\n\nexport interface BootstrapExpoAdasOptions {\n /**\n * Endpoint GETTERS — the host owns the dev/prod env switch, so these are read\n * live on every SDK request (never snapshotted). `core` is required; the rest\n * are optional (voice/consumer-auth features light up when present).\n */\n urls: {\n core: () => string;\n voice?: () => string;\n consumerAuth?: () => string;\n /** Trusted extra host for plugin WebViews (the relay device-bridge auth flows). */\n relay?: () => string;\n };\n /** The host's token bridge — outcome mapping (transient vs auth_failed) owned by the host. */\n tokenProvider: TokenProvider;\n /** Current user projection for chat routing (host reads its auth store). */\n getUser: () => AdasUser | null;\n /** Active tenant getter (signed-in tenant, falling back to the pre-auth pick). */\n tenant?: () => string;\n /** Adopt a freshly-minted session on tenant switch (host persists tenant-first, then logs in). */\n onSession?: (session: AdasSession) => void | Promise<void>;\n /** The host's bundled Google iOS client id, for the join/open-join OAuth path. */\n googleIosClientId?: string;\n /** Host-bundled native plugins (AuthWebView, ConnectionsPanel, …) — lazy resolvers. */\n nativePlugins?: NativePluginRegistration[];\n /** Native modules remote bundles may require() (e.g. react-native-webview) — from the host build. */\n bundleModules?: Record<string, unknown>;\n /** Pre-SDK AsyncStorage keys, so an existing install keeps its warm caches. */\n storageKeys?: { attachmentIndex?: string; bundleIndex?: string };\n /** Connectivity sink — the SDK reports fetch reachability up/down; the host feeds its banner. */\n onReachabilityChange?: (up: boolean) => void;\n /** Open the host's plugin screen for a UI-action chip (the host owns its router). */\n navigateToPlugin: (route: UIActionRoute) => void;\n /**\n * Reachability probe URL for the device-primitive connectivity API. The host\n * passes this EXPLICITLY (typically `${core}/health`) as a load-time snapshot —\n * deliberately NOT derived from `urls.core()`, so a dev/E2E core override does\n * not silently flow into the health probe (the asymmetry the host relied on).\n */\n reachabilityUrl?: string;\n /**\n * Device sync (the user's device permissions → the relay). Needs `urls.relay`.\n * Leave it out and the capabilities store refuses to start the bridge, by name.\n */\n deviceSync?: {\n /** The relay's shared key, sent as `Authorization: Bearer`. */\n relayKey: string;\n /** Secure storage for the install's device id (Keychain / Keystore). */\n secureStorage: SecureKv;\n };\n}\n\n/**\n * Wire the entire Expo-backed ADAS platform in one call. Run for its side effect\n * at module load, before the router mounts. Returns the attachment cache so the\n * host can hand it to anything that needs it (initAdas already received it).\n */\nexport function bootstrapExpoAdas(opts: BootstrapExpoAdasOptions): { attachmentCache: ExpoAttachmentCache } {\n // Expo providers + the device-primitive implementation (props.device). The SDK\n // owns createDeviceProvider; the shell injects only its reachability URL.\n const { attachmentCache } = setupExpoProviders({\n bundleModules: opts.bundleModules,\n attachmentIndexKey: opts.storageKeys?.attachmentIndex,\n bundleIndexKey: opts.storageKeys?.bundleIndex,\n deviceProvider: createDeviceProvider({ reachabilityUrl: opts.reachabilityUrl }),\n });\n\n // Host-bundled native plugins: register each lazy resolver under its id aliases.\n for (const plugin of opts.nativePlugins ?? []) {\n for (const id of plugin.ids) registerNativePlugin(id, plugin.resolver);\n }\n\n // Plugin WebViews may navigate to the relay (device-bridge auth flows) —\n // whitelist it alongside core/voice. Getter → live across env switches.\n const relay = opts.urls.relay;\n setPluginWebViewExtraHosts(() => (relay ? [relay()] : []));\n\n // Device sync settings for the capabilities store — values only; the bootstrap\n // loads no device-bridge code for this.\n if (opts.deviceSync) {\n if (!relay) throw new Error('bootstrapExpoAdas: deviceSync needs urls.relay');\n configureDeviceSync({ relayUrl: relay, ...opts.deviceSync });\n }\n\n // Native OAuth for the relocated auth screens (the ONLY native OAuth wiring).\n setOAuthProvider(createExpoOAuthProvider({ googleIosClientId: opts.googleIosClientId }));\n\n // The voice call's device audio mode (echo cancellation on the loudspeaker).\n setCallAudioProvider(createCallAudioProvider());\n\n // ACS fetch outcomes feed the host's connectivity banner (any response = up,\n // thrown fetch = down). The host's sink stays host-side (lazy, no load cycle).\n if (opts.onReachabilityChange) {\n const onReach = opts.onReachabilityChange;\n setAcsReachabilityReporter({ up: () => onReach(true), down: () => onReach(false) });\n }\n\n // L3 DeviceState (props.deviceState) — the SEMANTIC layer, wired with the SDK's\n // OWN device-bridge collectors. The shell injects none (the R10 payoff): an\n // undeclared/unimplemented domain returns explicit `unknown`s, never a silent\n // undefined. Kept a SEPARATE statement from the SERVER relay — the two\n // reasoning paths never merge.\n setDeviceStateProvider(\n createDeviceState({ connectivity: deviceConnectivity, location: deviceLocation }),\n );\n\n // LOCAL device tools — register the static, host-owned platform tools\n // (device.echo / device.ping) at load, so the device path answers even before\n // any plugin bundle or sign-in: the platform tier deliberately does not depend\n // on the thing being proved. A tenant's EXTERNAL device tools load on\n // session-authenticated, which the host wires to its auth-session subscription\n // via syncDeviceToolsForSession() — ambient, not voice-triggered.\n registerPlatformDeviceTools();\n\n // Plugin/UI-action chips delegate navigation to the host's router.\n setUIActionNavigator(opts.navigateToPlugin);\n\n // Core config + token bridge. URL getters (not snapshots) so the env switch\n // flows through; identity/token bridge owned by the host.\n initAdas({\n coreUrl: opts.urls.core,\n ...(opts.urls.voice ? { voiceUrl: opts.urls.voice } : {}),\n ...(opts.urls.consumerAuth ? { consumerAuthUrl: opts.urls.consumerAuth } : {}),\n ...(opts.onSession ? { onSession: opts.onSession } : {}),\n ...(opts.tenant ? { tenant: opts.tenant } : {}),\n getUser: opts.getUser,\n tokenProvider: opts.tokenProvider,\n attachmentCache,\n });\n\n return { attachmentCache };\n}\n","// Call audio mode for the voice call — see ios/AdaAudioModule.swift for why.\n//\n// requireOptionalNativeModule: on a binary WITHOUT the module (any build before\n// it shipped) this is null and the provider is a no-op, so an OTA carrying this\n// JS can never crash an older binary. Android: no module yet (its WebView echo\n// path is untouched).\nimport { requireOptionalNativeModule } from 'expo-modules-core';\nimport type { CallAudioProvider } from '@ateam-ai-mobile/ui';\n\ninterface AdaAudioNative {\n beginVoiceCall(): boolean;\n endVoiceCall(): boolean;\n}\n\nconst native = requireOptionalNativeModule<AdaAudioNative>('AdaAudio');\n\nexport function createCallAudioProvider(): CallAudioProvider | null {\n if (!native) return null;\n return {\n beginCall: () => { native.beginVoiceCall(); },\n endCall: () => { native.endVoiceCall(); },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BA,SAAS,UAAU,kCAAuF;AAC1G,SAAS,wBAAwB,sBAAsB,mCAA0D;AACjH,SAAS,kBAAkB,sBAAsB,4BAA4B,4BAAgD;;;AC1B7H,SAAS,mCAAmC;AAQ5C,IAAM,SAAS,4BAA4C,UAAU;AAE9D,SAAS,0BAAoD;AAClE,MAAI,CAAC,OAAQ,QAAO;AACpB,SAAO;AAAA,IACL,WAAW,MAAM;AAAE,aAAO,eAAe;AAAA,IAAG;AAAA,IAC5C,SAAS,MAAM;AAAE,aAAO,aAAa;AAAA,IAAG;AAAA,EAC1C;AACF;;;ADqFO,SAAS,kBAAkB,MAA0E;AAG1G,QAAM,EAAE,gBAAgB,IAAI,mBAAmB;AAAA,IAC7C,eAAe,KAAK;AAAA,IACpB,oBAAoB,KAAK,aAAa;AAAA,IACtC,gBAAgB,KAAK,aAAa;AAAA,IAClC,gBAAgB,qBAAqB,EAAE,iBAAiB,KAAK,gBAAgB,CAAC;AAAA,EAChF,CAAC;AAGD,aAAW,UAAU,KAAK,iBAAiB,CAAC,GAAG;AAC7C,eAAW,MAAM,OAAO,IAAK,sBAAqB,IAAI,OAAO,QAAQ;AAAA,EACvE;AAIA,QAAM,QAAQ,KAAK,KAAK;AACxB,6BAA2B,MAAO,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAE;AAIzD,MAAI,KAAK,YAAY;AACnB,QAAI,CAAC,MAAO,OAAM,IAAI,MAAM,gDAAgD;AAC5E,wBAAoB,EAAE,UAAU,OAAO,GAAG,KAAK,WAAW,CAAC;AAAA,EAC7D;AAGA,mBAAiB,wBAAwB,EAAE,mBAAmB,KAAK,kBAAkB,CAAC,CAAC;AAGvF,uBAAqB,wBAAwB,CAAC;AAI9C,MAAI,KAAK,sBAAsB;AAC7B,UAAM,UAAU,KAAK;AACrB,+BAA2B,EAAE,IAAI,MAAM,QAAQ,IAAI,GAAG,MAAM,MAAM,QAAQ,KAAK,EAAE,CAAC;AAAA,EACpF;AAOA;AAAA,IACE,kBAAkB,EAAE,cAAc,sBAAoB,UAAU,iBAAe,CAAC;AAAA,EAClF;AAQA,8BAA4B;AAG5B,uBAAqB,KAAK,gBAAgB;AAI1C,WAAS;AAAA,IACP,SAAS,KAAK,KAAK;AAAA,IACnB,GAAI,KAAK,KAAK,QAAQ,EAAE,UAAU,KAAK,KAAK,MAAM,IAAI,CAAC;AAAA,IACvD,GAAI,KAAK,KAAK,eAAe,EAAE,iBAAiB,KAAK,KAAK,aAAa,IAAI,CAAC;AAAA,IAC5E,GAAI,KAAK,YAAY,EAAE,WAAW,KAAK,UAAU,IAAI,CAAC;AAAA,IACtD,GAAI,KAAK,SAAS,EAAE,QAAQ,KAAK,OAAO,IAAI,CAAC;AAAA,IAC7C,SAAS,KAAK;AAAA,IACd,eAAe,KAAK;AAAA,IACpB;AAAA,EACF,CAAC;AAED,SAAO,EAAE,gBAAgB;AAC3B;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/bootstrap.ts","../src/audio/index.ts"],"sourcesContent":["/**\n * bootstrapExpoAdas — the single, self-contained SDK bootstrap (R10).\n *\n * The final high-level entry point of the \"fat SDK / thin shell\" arc: it folds\n * the ~15 hand-wired seams the host used to assemble in its own adas.ts into ONE\n * call, so the shell stops manually assembling platform providers/collectors/\n * plugins. Internally it initializes, in the order the migrated code established:\n * the Expo providers (haptics/bundle cache/clipboard/attachment cache + the\n * device-primitive provider), the host-bundled native plugins, the plugin-WebView\n * allow-list, native OAuth, the ACS reachability reporter, the L3 DeviceState\n * engine (with the SDK's OWN collectors — the shell injects none), the plugin/\n * UI-action navigator, and finally the core config+token bridge (initAdas).\n *\n * The API is DERIVED from the host's migrated adas.ts, not invented. Everything\n * the host still owns is passed in as a small values-and-getters bag: endpoint\n * getters (the host owns the dev/prod switch), the identity/token bridge, its\n * branded Google client id, its host-bundled plugin resolvers, the native\n * WebView module from its build, and its router callback.\n *\n * A SUBPATH (`@ateam-ai-mobile/expo/bootstrap`), like /device and /oauth: it\n * statically pulls the optional expo native modules (via createDeviceProvider /\n * the device-state collectors / the OAuth provider), so it must not sit on the\n * package's main entry, which a host without those modules still has to build.\n *\n * The two physical reasoning paths stay DISTINCT and are wired as SEPARATE\n * statements — never a merged bridge: LOCAL (the local tool registry + device\n * state the plugin/voice runtime reads) and SERVER (the relay allow-list here;\n * the DeviceBridge relay runtime itself is started by the host lifecycle, out of\n * this module-load bootstrap's scope).\n */\nimport { initAdas, setAcsReachabilityReporter, type TokenProvider, type AdasUser, type AdasSession } from '@ateam-ai-mobile/core';\nimport { setDeviceStateProvider, registerNativePlugin, registerPlatformDeviceTools, setAiLiveProvider, type RegisteredPlugin } from '@ateam-ai-mobile/plugin-runtime';\nimport { setOAuthProvider, setUIActionNavigator, setPluginWebViewExtraHosts, setCallAudioProvider, type UIActionRoute } from '@ateam-ai-mobile/ui';\nimport { createCallAudioProvider } from './audio';\n\nimport { setupExpoProviders, type ExpoAttachmentCache } from './index';\nimport { createDeviceProvider } from './device/createDeviceProvider';\nimport { createAiLiveProvider } from './aiLive/provider';\nimport { createDeviceState } from './device-state';\nimport { createExpoOAuthProvider } from './oauth/expoOAuth';\nimport * as deviceConnectivity from './device-bridge/collectors/connectivity';\nimport * as deviceLocation from './device-bridge/collectors/location';\nimport { configureDeviceSync } from './capabilities/config';\nimport type { SecureKv } from './device-bridge/deviceId';\n\n/** A host-bundled native plugin: one lazy resolver registered under one or more ids. */\nexport interface NativePluginRegistration {\n resolver: () => Promise<RegisteredPlugin>;\n ids: string[];\n}\n\nexport interface BootstrapExpoAdasOptions {\n /**\n * Endpoint GETTERS — the host owns the dev/prod env switch, so these are read\n * live on every SDK request (never snapshotted). `core` is required; the rest\n * are optional (voice/consumer-auth features light up when present).\n */\n urls: {\n core: () => string;\n voice?: () => string;\n consumerAuth?: () => string;\n /** Trusted extra host for plugin WebViews (the relay device-bridge auth flows). */\n relay?: () => string;\n };\n /** The host's token bridge — outcome mapping (transient vs auth_failed) owned by the host. */\n tokenProvider: TokenProvider;\n /** Current user projection for chat routing (host reads its auth store). */\n getUser: () => AdasUser | null;\n /** Active tenant getter (signed-in tenant, falling back to the pre-auth pick). */\n tenant?: () => string;\n /** Adopt a freshly-minted session on tenant switch (host persists tenant-first, then logs in). */\n onSession?: (session: AdasSession) => void | Promise<void>;\n /** The host's bundled Google iOS client id, for the join/open-join OAuth path. */\n googleIosClientId?: string;\n /** Host-bundled native plugins (AuthWebView, ConnectionsPanel, …) — lazy resolvers. */\n nativePlugins?: NativePluginRegistration[];\n /** Native modules remote bundles may require() (e.g. react-native-webview) — from the host build. */\n bundleModules?: Record<string, unknown>;\n /** Pre-SDK AsyncStorage keys, so an existing install keeps its warm caches. */\n storageKeys?: { attachmentIndex?: string; bundleIndex?: string };\n /** Connectivity sink — the SDK reports fetch reachability up/down; the host feeds its banner. */\n onReachabilityChange?: (up: boolean) => void;\n /** Open the host's plugin screen for a UI-action chip (the host owns its router). */\n navigateToPlugin: (route: UIActionRoute) => void;\n /**\n * Reachability probe URL for the device-primitive connectivity API. The host\n * passes this EXPLICITLY (typically `${core}/health`) as a load-time snapshot —\n * deliberately NOT derived from `urls.core()`, so a dev/E2E core override does\n * not silently flow into the health probe (the asymmetry the host relied on).\n */\n reachabilityUrl?: string;\n /**\n * Device sync (the user's device permissions → the relay). Needs `urls.relay`.\n * Leave it out and the capabilities store refuses to start the bridge, by name.\n */\n deviceSync?: {\n /** The relay's shared key, sent as `Authorization: Bearer`. */\n relayKey: string;\n /** Secure storage for the install's device id (Keychain / Keystore). */\n secureStorage: SecureKv;\n };\n}\n\n/**\n * Wire the entire Expo-backed ADAS platform in one call. Run for its side effect\n * at module load, before the router mounts. Returns the attachment cache so the\n * host can hand it to anything that needs it (initAdas already received it).\n */\nexport function bootstrapExpoAdas(opts: BootstrapExpoAdasOptions): { attachmentCache: ExpoAttachmentCache } {\n // Expo providers + the device-primitive implementation (props.device). The SDK\n // owns createDeviceProvider; the shell injects only its reachability URL.\n const { attachmentCache } = setupExpoProviders({\n bundleModules: opts.bundleModules,\n attachmentIndexKey: opts.storageKeys?.attachmentIndex,\n bundleIndexKey: opts.storageKeys?.bundleIndex,\n deviceProvider: createDeviceProvider({ reachabilityUrl: opts.reachabilityUrl }),\n });\n\n // Host-bundled native plugins: register each lazy resolver under its id aliases.\n for (const plugin of opts.nativePlugins ?? []) {\n for (const id of plugin.ids) registerNativePlugin(id, plugin.resolver);\n }\n\n // Plugin WebViews may navigate to the relay (device-bridge auth flows) —\n // whitelist it alongside core/voice. Getter → live across env switches.\n const relay = opts.urls.relay;\n setPluginWebViewExtraHosts(() => (relay ? [relay()] : []));\n\n // Device sync settings for the capabilities store — values only; the bootstrap\n // loads no device-bridge code for this.\n if (opts.deviceSync) {\n if (!relay) throw new Error('bootstrapExpoAdas: deviceSync needs urls.relay');\n configureDeviceSync({ relayUrl: relay, ...opts.deviceSync });\n }\n\n // Native OAuth for the relocated auth screens (the ONLY native OAuth wiring).\n setOAuthProvider(createExpoOAuthProvider({ googleIosClientId: opts.googleIosClientId }));\n\n // The voice call's device audio mode (echo cancellation on the loudspeaker).\n setCallAudioProvider(createCallAudioProvider());\n\n // ACS fetch outcomes feed the host's connectivity banner (any response = up,\n // thrown fetch = down). The host's sink stays host-side (lazy, no load cycle).\n if (opts.onReachabilityChange) {\n const onReach = opts.onReachabilityChange;\n setAcsReachabilityReporter({ up: () => onReach(true), down: () => onReach(false) });\n }\n\n // L3 DeviceState (props.deviceState) — the SEMANTIC layer, wired with the SDK's\n // OWN device-bridge collectors. The shell injects none (the R10 payoff): an\n // undeclared/unimplemented domain returns explicit `unknown`s, never a silent\n // undefined. Kept a SEPARATE statement from the SERVER relay — the two\n // reasoning paths never merge.\n setDeviceStateProvider(\n createDeviceState({ connectivity: deviceConnectivity, location: deviceLocation }),\n );\n\n // props.aiLive — this phone's camera to the workspace's chosen AI. Each use still\n // needs the plugin's `picturesToAi` AND the person's \"Camera pictures to AI\"\n // (the capabilities store installs that half), both checked at start().\n setAiLiveProvider(createAiLiveProvider());\n\n // LOCAL device tools — register the static, host-owned platform tools\n // (device.echo / device.ping) at load, so the device path answers even before\n // any plugin bundle or sign-in: the platform tier deliberately does not depend\n // on the thing being proved. A tenant's EXTERNAL device tools load on\n // session-authenticated, which the host wires to its auth-session subscription\n // via syncDeviceToolsForSession() — ambient, not voice-triggered.\n registerPlatformDeviceTools();\n\n // Plugin/UI-action chips delegate navigation to the host's router.\n setUIActionNavigator(opts.navigateToPlugin);\n\n // Core config + token bridge. URL getters (not snapshots) so the env switch\n // flows through; identity/token bridge owned by the host.\n initAdas({\n coreUrl: opts.urls.core,\n ...(opts.urls.voice ? { voiceUrl: opts.urls.voice } : {}),\n ...(opts.urls.consumerAuth ? { consumerAuthUrl: opts.urls.consumerAuth } : {}),\n ...(opts.onSession ? { onSession: opts.onSession } : {}),\n ...(opts.tenant ? { tenant: opts.tenant } : {}),\n getUser: opts.getUser,\n tokenProvider: opts.tokenProvider,\n attachmentCache,\n });\n\n return { attachmentCache };\n}\n","// Call audio mode for the voice call — see ios/AdaAudioModule.swift for why.\n//\n// requireOptionalNativeModule: on a binary WITHOUT the module (any build before\n// it shipped) this is null and the provider is a no-op, so an OTA carrying this\n// JS can never crash an older binary. Android: no module yet (its WebView echo\n// path is untouched).\nimport { requireOptionalNativeModule } from 'expo-modules-core';\nimport type { CallAudioProvider } from '@ateam-ai-mobile/ui';\n\ninterface AdaAudioNative {\n beginVoiceCall(): boolean;\n endVoiceCall(): boolean;\n}\n\nconst native = requireOptionalNativeModule<AdaAudioNative>('AdaAudio');\n\nexport function createCallAudioProvider(): CallAudioProvider | null {\n if (!native) return null;\n return {\n beginCall: () => { native.beginVoiceCall(); },\n endCall: () => { native.endVoiceCall(); },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BA,SAAS,UAAU,kCAAuF;AAC1G,SAAS,wBAAwB,sBAAsB,6BAA6B,yBAAgD;AACpI,SAAS,kBAAkB,sBAAsB,4BAA4B,4BAAgD;;;AC1B7H,SAAS,mCAAmC;AAQ5C,IAAM,SAAS,4BAA4C,UAAU;AAE9D,SAAS,0BAAoD;AAClE,MAAI,CAAC,OAAQ,QAAO;AACpB,SAAO;AAAA,IACL,WAAW,MAAM;AAAE,aAAO,eAAe;AAAA,IAAG;AAAA,IAC5C,SAAS,MAAM;AAAE,aAAO,aAAa;AAAA,IAAG;AAAA,EAC1C;AACF;;;ADsFO,SAAS,kBAAkB,MAA0E;AAG1G,QAAM,EAAE,gBAAgB,IAAI,mBAAmB;AAAA,IAC7C,eAAe,KAAK;AAAA,IACpB,oBAAoB,KAAK,aAAa;AAAA,IACtC,gBAAgB,KAAK,aAAa;AAAA,IAClC,gBAAgB,qBAAqB,EAAE,iBAAiB,KAAK,gBAAgB,CAAC;AAAA,EAChF,CAAC;AAGD,aAAW,UAAU,KAAK,iBAAiB,CAAC,GAAG;AAC7C,eAAW,MAAM,OAAO,IAAK,sBAAqB,IAAI,OAAO,QAAQ;AAAA,EACvE;AAIA,QAAM,QAAQ,KAAK,KAAK;AACxB,6BAA2B,MAAO,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAE;AAIzD,MAAI,KAAK,YAAY;AACnB,QAAI,CAAC,MAAO,OAAM,IAAI,MAAM,gDAAgD;AAC5E,wBAAoB,EAAE,UAAU,OAAO,GAAG,KAAK,WAAW,CAAC;AAAA,EAC7D;AAGA,mBAAiB,wBAAwB,EAAE,mBAAmB,KAAK,kBAAkB,CAAC,CAAC;AAGvF,uBAAqB,wBAAwB,CAAC;AAI9C,MAAI,KAAK,sBAAsB;AAC7B,UAAM,UAAU,KAAK;AACrB,+BAA2B,EAAE,IAAI,MAAM,QAAQ,IAAI,GAAG,MAAM,MAAM,QAAQ,KAAK,EAAE,CAAC;AAAA,EACpF;AAOA;AAAA,IACE,kBAAkB,EAAE,cAAc,sBAAoB,UAAU,iBAAe,CAAC;AAAA,EAClF;AAKA,oBAAkB,qBAAqB,CAAC;AAQxC,8BAA4B;AAG5B,uBAAqB,KAAK,gBAAgB;AAI1C,WAAS;AAAA,IACP,SAAS,KAAK,KAAK;AAAA,IACnB,GAAI,KAAK,KAAK,QAAQ,EAAE,UAAU,KAAK,KAAK,MAAM,IAAI,CAAC;AAAA,IACvD,GAAI,KAAK,KAAK,eAAe,EAAE,iBAAiB,KAAK,KAAK,aAAa,IAAI,CAAC;AAAA,IAC5E,GAAI,KAAK,YAAY,EAAE,WAAW,KAAK,UAAU,IAAI,CAAC;AAAA,IACtD,GAAI,KAAK,SAAS,EAAE,QAAQ,KAAK,OAAO,IAAI,CAAC;AAAA,IAC7C,SAAS,KAAK;AAAA,IACd,eAAe,KAAK;AAAA,IACpB;AAAA,EACF,CAAC;AAED,SAAO,EAAE,gBAAgB;AAC3B;","names":[]}
|
|
@@ -41,6 +41,9 @@ interface CapabilityState {
|
|
|
41
41
|
}
|
|
42
42
|
interface CapabilitiesState {
|
|
43
43
|
capabilities: CapabilityState[];
|
|
44
|
+
/** The "Camera pictures to AI" switch under Camera: the person's half of the
|
|
45
|
+
* consent props.aiLive needs. Off until they turn it on (default no). */
|
|
46
|
+
picturesToAi: boolean;
|
|
44
47
|
hasCompletedSetup: boolean;
|
|
45
48
|
isLoading: boolean;
|
|
46
49
|
bridgeRunning: boolean;
|
|
@@ -48,6 +51,8 @@ interface CapabilitiesState {
|
|
|
48
51
|
initialize: () => Promise<void>;
|
|
49
52
|
/** Toggle a capability on/off, persist, and update bridge if running */
|
|
50
53
|
toggleCapability: (id: string, enabled: boolean) => Promise<void>;
|
|
54
|
+
/** Set and persist "Camera pictures to AI". The host asks first (PICTURES_TO_AI_ASK). */
|
|
55
|
+
setPicturesToAi: (on: boolean) => Promise<void>;
|
|
51
56
|
/** Update OS permission state for a capability */
|
|
52
57
|
setOsPermission: (id: string, state: PermissionState) => void;
|
|
53
58
|
/** Mark initial setup as complete */
|
|
@@ -69,6 +74,40 @@ interface CapabilitiesState {
|
|
|
69
74
|
}
|
|
70
75
|
declare const useCapabilitiesStore: zustand.UseBoundStore<zustand.StoreApi<CapabilitiesState>>;
|
|
71
76
|
|
|
77
|
+
/**
|
|
78
|
+
* "Camera pictures to AI" — the phone owner's half of a two-sided consent
|
|
79
|
+
* (owner decision 2026-10-25, amending "frames never leave the phone").
|
|
80
|
+
*
|
|
81
|
+
* A camera picture may go to an AI service off the phone only when the
|
|
82
|
+
* solution's developer declared `picturesToAi` in its manifest AND the person on
|
|
83
|
+
* this phone allowed it here. plugin-runtime's mayPicturesLeavePhone() checks
|
|
84
|
+
* both; this half is installed as its consent provider by the capabilities store.
|
|
85
|
+
*
|
|
86
|
+
* Moved from ateam-mobile (branch pictures-to-ai-switch, 9541f22) into the SDK
|
|
87
|
+
* with the store it belongs to. Pure, so tests run it under plain node.
|
|
88
|
+
*/
|
|
89
|
+
interface PicturesToAiInputs {
|
|
90
|
+
/** The switch under Camera in the host's "What Ada can access". */
|
|
91
|
+
picturesToAi: boolean;
|
|
92
|
+
capabilities: ReadonlyArray<{
|
|
93
|
+
id: string;
|
|
94
|
+
enabled: boolean;
|
|
95
|
+
osPermission: string;
|
|
96
|
+
}>;
|
|
97
|
+
}
|
|
98
|
+
/** Derived at read time, never stored: the switch is on AND the camera itself is
|
|
99
|
+
* on and granted by the OS. Anything else answers no. */
|
|
100
|
+
declare function picturesToAiAllowed(s: PicturesToAiInputs): boolean;
|
|
101
|
+
/** What the person is told before allowing it. Apple guideline 5.1.2(i): say
|
|
102
|
+
* where personal data goes before sharing it with an outside AI, and get
|
|
103
|
+
* explicit permission first. */
|
|
104
|
+
declare const PICTURES_TO_AI_ASK: {
|
|
105
|
+
readonly title: "Send camera pictures to AI?";
|
|
106
|
+
readonly message: string;
|
|
107
|
+
readonly allow: "Allow";
|
|
108
|
+
readonly cancel: "Not now";
|
|
109
|
+
};
|
|
110
|
+
|
|
72
111
|
/**
|
|
73
112
|
* Device-sync settings the host provides once (bootstrapExpoAdas `deviceSync`,
|
|
74
113
|
* or configureDeviceSync directly). Kept apart from the store so the bootstrap
|
|
@@ -109,4 +148,4 @@ interface CapabilityCardProps {
|
|
|
109
148
|
/** One capability with its on/off switch and OS-permission badge. */
|
|
110
149
|
declare function CapabilityCard({ capability, onToggle }: CapabilityCardProps): react_jsx_runtime.JSX.Element;
|
|
111
150
|
|
|
112
|
-
export { CapabilitiesSetup, type CapabilitiesSetupProps, CapabilityCard, type CapabilityCardProps, type CapabilityState, type DeviceSyncConfig, configureDeviceSync, useCapabilitiesStore };
|
|
151
|
+
export { CapabilitiesSetup, type CapabilitiesSetupProps, CapabilityCard, type CapabilityCardProps, type CapabilityState, type DeviceSyncConfig, PICTURES_TO_AI_ASK, configureDeviceSync, picturesToAiAllowed, useCapabilitiesStore };
|
|
@@ -41,6 +41,9 @@ interface CapabilityState {
|
|
|
41
41
|
}
|
|
42
42
|
interface CapabilitiesState {
|
|
43
43
|
capabilities: CapabilityState[];
|
|
44
|
+
/** The "Camera pictures to AI" switch under Camera: the person's half of the
|
|
45
|
+
* consent props.aiLive needs. Off until they turn it on (default no). */
|
|
46
|
+
picturesToAi: boolean;
|
|
44
47
|
hasCompletedSetup: boolean;
|
|
45
48
|
isLoading: boolean;
|
|
46
49
|
bridgeRunning: boolean;
|
|
@@ -48,6 +51,8 @@ interface CapabilitiesState {
|
|
|
48
51
|
initialize: () => Promise<void>;
|
|
49
52
|
/** Toggle a capability on/off, persist, and update bridge if running */
|
|
50
53
|
toggleCapability: (id: string, enabled: boolean) => Promise<void>;
|
|
54
|
+
/** Set and persist "Camera pictures to AI". The host asks first (PICTURES_TO_AI_ASK). */
|
|
55
|
+
setPicturesToAi: (on: boolean) => Promise<void>;
|
|
51
56
|
/** Update OS permission state for a capability */
|
|
52
57
|
setOsPermission: (id: string, state: PermissionState) => void;
|
|
53
58
|
/** Mark initial setup as complete */
|
|
@@ -69,6 +74,40 @@ interface CapabilitiesState {
|
|
|
69
74
|
}
|
|
70
75
|
declare const useCapabilitiesStore: zustand.UseBoundStore<zustand.StoreApi<CapabilitiesState>>;
|
|
71
76
|
|
|
77
|
+
/**
|
|
78
|
+
* "Camera pictures to AI" — the phone owner's half of a two-sided consent
|
|
79
|
+
* (owner decision 2026-10-25, amending "frames never leave the phone").
|
|
80
|
+
*
|
|
81
|
+
* A camera picture may go to an AI service off the phone only when the
|
|
82
|
+
* solution's developer declared `picturesToAi` in its manifest AND the person on
|
|
83
|
+
* this phone allowed it here. plugin-runtime's mayPicturesLeavePhone() checks
|
|
84
|
+
* both; this half is installed as its consent provider by the capabilities store.
|
|
85
|
+
*
|
|
86
|
+
* Moved from ateam-mobile (branch pictures-to-ai-switch, 9541f22) into the SDK
|
|
87
|
+
* with the store it belongs to. Pure, so tests run it under plain node.
|
|
88
|
+
*/
|
|
89
|
+
interface PicturesToAiInputs {
|
|
90
|
+
/** The switch under Camera in the host's "What Ada can access". */
|
|
91
|
+
picturesToAi: boolean;
|
|
92
|
+
capabilities: ReadonlyArray<{
|
|
93
|
+
id: string;
|
|
94
|
+
enabled: boolean;
|
|
95
|
+
osPermission: string;
|
|
96
|
+
}>;
|
|
97
|
+
}
|
|
98
|
+
/** Derived at read time, never stored: the switch is on AND the camera itself is
|
|
99
|
+
* on and granted by the OS. Anything else answers no. */
|
|
100
|
+
declare function picturesToAiAllowed(s: PicturesToAiInputs): boolean;
|
|
101
|
+
/** What the person is told before allowing it. Apple guideline 5.1.2(i): say
|
|
102
|
+
* where personal data goes before sharing it with an outside AI, and get
|
|
103
|
+
* explicit permission first. */
|
|
104
|
+
declare const PICTURES_TO_AI_ASK: {
|
|
105
|
+
readonly title: "Send camera pictures to AI?";
|
|
106
|
+
readonly message: string;
|
|
107
|
+
readonly allow: "Allow";
|
|
108
|
+
readonly cancel: "Not now";
|
|
109
|
+
};
|
|
110
|
+
|
|
72
111
|
/**
|
|
73
112
|
* Device-sync settings the host provides once (bootstrapExpoAdas `deviceSync`,
|
|
74
113
|
* or configureDeviceSync directly). Kept apart from the store so the bootstrap
|
|
@@ -109,4 +148,4 @@ interface CapabilityCardProps {
|
|
|
109
148
|
/** One capability with its on/off switch and OS-permission badge. */
|
|
110
149
|
declare function CapabilityCard({ capability, onToggle }: CapabilityCardProps): react_jsx_runtime.JSX.Element;
|
|
111
150
|
|
|
112
|
-
export { CapabilitiesSetup, type CapabilitiesSetupProps, CapabilityCard, type CapabilityCardProps, type CapabilityState, type DeviceSyncConfig, configureDeviceSync, useCapabilitiesStore };
|
|
151
|
+
export { CapabilitiesSetup, type CapabilitiesSetupProps, CapabilityCard, type CapabilityCardProps, type CapabilityState, type DeviceSyncConfig, PICTURES_TO_AI_ASK, configureDeviceSync, picturesToAiAllowed, useCapabilitiesStore };
|
|
@@ -32,15 +32,18 @@ var capabilities_exports2 = {};
|
|
|
32
32
|
__export(capabilities_exports2, {
|
|
33
33
|
CapabilitiesSetup: () => CapabilitiesSetup,
|
|
34
34
|
CapabilityCard: () => CapabilityCard,
|
|
35
|
+
PICTURES_TO_AI_ASK: () => PICTURES_TO_AI_ASK,
|
|
35
36
|
configureDeviceSync: () => configureDeviceSync,
|
|
37
|
+
picturesToAiAllowed: () => picturesToAiAllowed,
|
|
36
38
|
useCapabilitiesStore: () => useCapabilitiesStore
|
|
37
39
|
});
|
|
38
40
|
module.exports = __toCommonJS(capabilities_exports2);
|
|
39
41
|
|
|
40
42
|
// src/capabilities/store.ts
|
|
41
43
|
var import_zustand = require("zustand");
|
|
42
|
-
var
|
|
44
|
+
var import_async_storage4 = __toESM(require("@react-native-async-storage/async-storage"));
|
|
43
45
|
var import_core = require("@ateam-ai-mobile/core");
|
|
46
|
+
var import_plugin_runtime = require("@ateam-ai-mobile/plugin-runtime");
|
|
44
47
|
|
|
45
48
|
// src/device-bridge/relay-client.ts
|
|
46
49
|
var RelayClient = class {
|
|
@@ -1992,7 +1995,8 @@ function getDeviceSyncConfig() {
|
|
|
1992
1995
|
return config;
|
|
1993
1996
|
}
|
|
1994
1997
|
|
|
1995
|
-
// src/capabilities/
|
|
1998
|
+
// src/capabilities/choices.ts
|
|
1999
|
+
var import_async_storage3 = __toESM(require("@react-native-async-storage/async-storage"));
|
|
1996
2000
|
var STORAGE_KEY = "ateam.capabilities";
|
|
1997
2001
|
var SETUP_KEY = "ateam.capabilities.setup";
|
|
1998
2002
|
var DEFAULT_ENABLED = {
|
|
@@ -2010,6 +2014,30 @@ var DEFAULT_ENABLED = {
|
|
|
2010
2014
|
camera: false
|
|
2011
2015
|
};
|
|
2012
2016
|
var HIDDEN_FROM_UI = /* @__PURE__ */ new Set(["notifications"]);
|
|
2017
|
+
async function loadChoices() {
|
|
2018
|
+
const setupDone = await import_async_storage3.default.getItem(SETUP_KEY);
|
|
2019
|
+
const saved = await import_async_storage3.default.getItem(STORAGE_KEY);
|
|
2020
|
+
return { setupDone: setupDone === "true", prefs: saved ? JSON.parse(saved) : {} };
|
|
2021
|
+
}
|
|
2022
|
+
function isEnabled(id, prefs) {
|
|
2023
|
+
return prefs[id] ?? DEFAULT_ENABLED[id] ?? true;
|
|
2024
|
+
}
|
|
2025
|
+
|
|
2026
|
+
// src/capabilities/picturesToAi.ts
|
|
2027
|
+
function picturesToAiAllowed(s) {
|
|
2028
|
+
if (s.picturesToAi !== true) return false;
|
|
2029
|
+
const camera = s.capabilities.find((c) => c.id === "camera");
|
|
2030
|
+
return !!camera && camera.enabled === true && camera.osPermission === "granted";
|
|
2031
|
+
}
|
|
2032
|
+
var PICTURES_TO_AI_ASK = {
|
|
2033
|
+
title: "Send camera pictures to AI?",
|
|
2034
|
+
message: 'Solutions that ask for it may send pictures from your camera to an AI service (OpenAI or Anthropic) through A-Team, to understand what the camera sees. Only while such a solution is open, and "Sending to AI" shows while it does. You can turn this off here at any time.',
|
|
2035
|
+
allow: "Allow",
|
|
2036
|
+
cancel: "Not now"
|
|
2037
|
+
};
|
|
2038
|
+
|
|
2039
|
+
// src/capabilities/store.ts
|
|
2040
|
+
var PICTURES_TO_AI_KEY = "ateam.capabilities.picturesToAi";
|
|
2013
2041
|
var bridge = null;
|
|
2014
2042
|
var bridgeOwner = null;
|
|
2015
2043
|
var startQueue = Promise.resolve();
|
|
@@ -2104,12 +2132,15 @@ var useCapabilitiesStore = (0, import_zustand.create)((set, get) => {
|
|
|
2104
2132
|
};
|
|
2105
2133
|
return {
|
|
2106
2134
|
capabilities: [],
|
|
2135
|
+
picturesToAi: false,
|
|
2107
2136
|
hasCompletedSetup: false,
|
|
2108
2137
|
isLoading: true,
|
|
2109
2138
|
bridgeRunning: false,
|
|
2110
2139
|
initialize: async () => {
|
|
2111
2140
|
try {
|
|
2112
2141
|
builtInCapabilities = capabilities_exports.allBuiltIn().filter((c) => !HIDDEN_FROM_UI.has(c.id));
|
|
2142
|
+
const { setupDone, prefs } = await loadChoices();
|
|
2143
|
+
const picturesToAi = await import_async_storage4.default.getItem(PICTURES_TO_AI_KEY) === "true";
|
|
2113
2144
|
const capStates = builtInCapabilities.map((cap) => ({
|
|
2114
2145
|
id: cap.id,
|
|
2115
2146
|
name: cap.name,
|
|
@@ -2117,21 +2148,16 @@ var useCapabilitiesStore = (0, import_zustand.create)((set, get) => {
|
|
|
2117
2148
|
reason: cap.reason,
|
|
2118
2149
|
icon: cap.icon || cap.id,
|
|
2119
2150
|
requiresPermission: cap.requiresPermission,
|
|
2120
|
-
enabled:
|
|
2151
|
+
enabled: isEnabled(cap.id, prefs),
|
|
2121
2152
|
osPermission: cap.permissionState
|
|
2122
2153
|
}));
|
|
2123
|
-
const setupDone = await import_async_storage3.default.getItem(SETUP_KEY);
|
|
2124
|
-
const saved = await import_async_storage3.default.getItem(STORAGE_KEY);
|
|
2125
|
-
const prefs = saved ? JSON.parse(saved) : {};
|
|
2126
2154
|
set({
|
|
2127
|
-
capabilities: capStates
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
})),
|
|
2131
|
-
hasCompletedSetup: setupDone === "true",
|
|
2155
|
+
capabilities: capStates,
|
|
2156
|
+
picturesToAi,
|
|
2157
|
+
hasCompletedSetup: setupDone,
|
|
2132
2158
|
isLoading: false
|
|
2133
2159
|
});
|
|
2134
|
-
console.log(`[Capabilities] Initialized ${capStates.length} capabilities from device-bridge (setup ${setupDone
|
|
2160
|
+
console.log(`[Capabilities] Initialized ${capStates.length} capabilities from device-bridge (setup ${setupDone ? "done" : "pending"})`);
|
|
2135
2161
|
} catch (err) {
|
|
2136
2162
|
console.error("[Capabilities] Initialize failed:", err);
|
|
2137
2163
|
set({ isLoading: false });
|
|
@@ -2147,7 +2173,10 @@ var useCapabilitiesStore = (0, import_zustand.create)((set, get) => {
|
|
|
2147
2173
|
for (const cap of get().capabilities) {
|
|
2148
2174
|
prefs[cap.id] = cap.id === id ? enabled : cap.enabled;
|
|
2149
2175
|
}
|
|
2150
|
-
await
|
|
2176
|
+
await import_async_storage4.default.setItem(STORAGE_KEY, JSON.stringify(prefs));
|
|
2177
|
+
if (id === "camera" && !enabled && get().picturesToAi) {
|
|
2178
|
+
await get().setPicturesToAi(false);
|
|
2179
|
+
}
|
|
2151
2180
|
if (bridge && get().bridgeRunning) {
|
|
2152
2181
|
if (enabled) {
|
|
2153
2182
|
const builtIn = builtInCapabilities.find((c) => c.id === id);
|
|
@@ -2167,6 +2196,10 @@ var useCapabilitiesStore = (0, import_zustand.create)((set, get) => {
|
|
|
2167
2196
|
}
|
|
2168
2197
|
}
|
|
2169
2198
|
},
|
|
2199
|
+
setPicturesToAi: async (on) => {
|
|
2200
|
+
set({ picturesToAi: on });
|
|
2201
|
+
await import_async_storage4.default.setItem(PICTURES_TO_AI_KEY, on ? "true" : "false");
|
|
2202
|
+
},
|
|
2170
2203
|
setOsPermission: (id, permState) => {
|
|
2171
2204
|
set((s) => ({
|
|
2172
2205
|
capabilities: s.capabilities.map(
|
|
@@ -2175,7 +2208,7 @@ var useCapabilitiesStore = (0, import_zustand.create)((set, get) => {
|
|
|
2175
2208
|
}));
|
|
2176
2209
|
},
|
|
2177
2210
|
completeSetup: async () => {
|
|
2178
|
-
await
|
|
2211
|
+
await import_async_storage4.default.setItem(SETUP_KEY, "true");
|
|
2179
2212
|
set({ hasCompletedSetup: true });
|
|
2180
2213
|
},
|
|
2181
2214
|
startBridge: () => {
|
|
@@ -2218,6 +2251,7 @@ var useCapabilitiesStore = (0, import_zustand.create)((set, get) => {
|
|
|
2218
2251
|
}
|
|
2219
2252
|
};
|
|
2220
2253
|
});
|
|
2254
|
+
(0, import_plugin_runtime.setPicturesToAiConsentProvider)(() => picturesToAiAllowed(useCapabilitiesStore.getState()));
|
|
2221
2255
|
|
|
2222
2256
|
// src/capabilities/CapabilitiesSetup.tsx
|
|
2223
2257
|
var import_react = require("react");
|
|
@@ -2568,7 +2602,9 @@ var styles2 = import_react_native6.StyleSheet.create({
|
|
|
2568
2602
|
0 && (module.exports = {
|
|
2569
2603
|
CapabilitiesSetup,
|
|
2570
2604
|
CapabilityCard,
|
|
2605
|
+
PICTURES_TO_AI_ASK,
|
|
2571
2606
|
configureDeviceSync,
|
|
2607
|
+
picturesToAiAllowed,
|
|
2572
2608
|
useCapabilitiesStore
|
|
2573
2609
|
});
|
|
2574
2610
|
//# sourceMappingURL=index.js.map
|