@ateam-ai-mobile/ui 0.1.9 → 0.1.11

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/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/AdasChatScreen.tsx
2
- import { useCallback as useCallback5, useEffect as useEffect6, useMemo as useMemo3, useRef as useRef4, useState as useState6 } from "react";
2
+ import { useCallback as useCallback5, useEffect as useEffect7, useMemo as useMemo3, useRef as useRef4, useState as useState6 } from "react";
3
3
  import {
4
4
  FlatList,
5
5
  KeyboardAvoidingView,
@@ -215,6 +215,13 @@ function setOAuthProvider(oauth) {
215
215
  function getOAuthProvider() {
216
216
  return _oauth;
217
217
  }
218
+ var _callAudio = null;
219
+ function setCallAudioProvider(callAudio) {
220
+ _callAudio = callAudio;
221
+ }
222
+ function getCallAudioProvider() {
223
+ return _callAudio;
224
+ }
218
225
  var _clipboard = null;
219
226
  function setClipboardProvider(clipboard) {
220
227
  _clipboard = clipboard;
@@ -238,13 +245,13 @@ function getPluginWebViewExtraHosts() {
238
245
  }
239
246
 
240
247
  // src/plugin/WidgetHost.tsx
241
- import { useEffect as useEffect4 } from "react";
248
+ import { useEffect as useEffect5 } from "react";
242
249
  import { create } from "zustand";
243
250
  import { pluginCommandEmitter as pluginCommandEmitter2 } from "@ateam-ai-mobile/core";
244
251
  import { useSurfaceStore } from "@ateam-ai-mobile/plugin-runtime";
245
252
 
246
253
  // src/plugin/PluginSurface.tsx
247
- import { useEffect as useEffect3, useState as useState3 } from "react";
254
+ import { useEffect as useEffect4, useState as useState3 } from "react";
248
255
  import { View as View4, ActivityIndicator as ActivityIndicator3 } from "react-native";
249
256
  import { ada as ada3 } from "@ateam-ai-mobile/core";
250
257
  import {
@@ -265,7 +272,7 @@ import {
265
272
  } from "@ateam-ai-mobile/plugin-runtime";
266
273
 
267
274
  // src/plugin/EmbeddedPluginWebView.tsx
268
- import { useState as useState2, useMemo, useCallback as useCallback2 } from "react";
275
+ import { useState as useState2, useMemo, useCallback as useCallback2, useEffect as useEffect3 } from "react";
269
276
  import { View as View2, Text as Text2, ActivityIndicator, StyleSheet as StyleSheet2, Platform } from "react-native";
270
277
  import { WebView } from "react-native-webview";
271
278
  import { getConfig, getCoreApiUrl, getVoiceApiUrl, getTenant as getTenant2, getToken, ada as ada2 } from "@ateam-ai-mobile/core";
@@ -596,6 +603,9 @@ function EmbeddedPluginWebView({ pluginId, manifest, commandBufferRef }) {
596
603
  const tenant = getTenant2();
597
604
  const { webViewRef, sendInit, handleMessage } = usePluginBridge(pluginId, manifest._connectorId, commandBufferRef);
598
605
  const url = resolvePluginUrl(manifest, tenant || void 0);
606
+ useEffect3(() => {
607
+ setError(null);
608
+ }, [url]);
599
609
  const bridgeJS = buildPluginBridgeJS(token || "", tenant || "");
600
610
  const computeAllowedHosts = useCallback2(() => {
601
611
  const hosts = /* @__PURE__ */ new Set();
@@ -833,7 +843,7 @@ import { jsx as jsx4 } from "react/jsx-runtime";
833
843
  function PluginSurface({ pluginId, surface, dismiss, props }) {
834
844
  const [manifest, setManifest] = useState3(null);
835
845
  const [error, setError] = useState3(null);
836
- useEffect3(() => {
846
+ useEffect4(() => {
837
847
  let cancelled = false;
838
848
  getPlugin(pluginId).then((m) => {
839
849
  if (!cancelled) m ? setManifest(m) : setError("Plugin not found");
@@ -892,7 +902,7 @@ function WidgetHost() {
892
902
  const pluginId = useWidgetHostStore((s) => s.pluginId);
893
903
  const props = useWidgetHostStore((s) => s.props);
894
904
  const close = useWidgetHostStore((s) => s.close);
895
- useEffect4(() => {
905
+ useEffect5(() => {
896
906
  return pluginCommandEmitter2.on("focus-plugin", (data) => {
897
907
  if (data?.pluginId) openWidget(String(data.pluginId), data.props);
898
908
  });
@@ -1600,7 +1610,7 @@ var styles8 = StyleSheet8.create({
1600
1610
  });
1601
1611
 
1602
1612
  // src/chat/ChatInput.tsx
1603
- import { useState as useState5, useRef as useRef3, useCallback as useCallback4, useEffect as useEffect5 } from "react";
1613
+ import { useState as useState5, useRef as useRef3, useCallback as useCallback4, useEffect as useEffect6 } from "react";
1604
1614
  import {
1605
1615
  View as View10,
1606
1616
  TextInput,
@@ -1616,7 +1626,7 @@ function ChatInput({ onSend, onCallStart, loading, prefill, placeholder }) {
1616
1626
  const [text, setText] = useState5("");
1617
1627
  const [height, setHeight] = useState5(40);
1618
1628
  const inputRef = useRef3(null);
1619
- useEffect5(() => {
1629
+ useEffect6(() => {
1620
1630
  if (prefill) {
1621
1631
  setText(prefill);
1622
1632
  inputRef.current?.focus();
@@ -1777,10 +1787,10 @@ function AdasChatScreen({
1777
1787
  const listRef = useRef4(null);
1778
1788
  const [refreshing, setRefreshing] = useState6(false);
1779
1789
  const [prefill, setPrefill] = useState6("");
1780
- useEffect6(() => {
1790
+ useEffect7(() => {
1781
1791
  if (!conversationLoaded) loadConversation();
1782
1792
  }, [conversationLoaded, loadConversation]);
1783
- useEffect6(() => {
1793
+ useEffect7(() => {
1784
1794
  const unsub = pluginCommandEmitter3.on("prepare-chat-message", ({ text }) => {
1785
1795
  if (text) setPrefill(text);
1786
1796
  });
@@ -2004,7 +2014,7 @@ var styles12 = StyleSheet12.create({
2004
2014
  });
2005
2015
 
2006
2016
  // src/TenantPicker.tsx
2007
- import { useEffect as useEffect7, useState as useState8 } from "react";
2017
+ import { useEffect as useEffect8, useState as useState8 } from "react";
2008
2018
  import { View as View14, Text as Text10, Pressable as Pressable8, ActivityIndicator as ActivityIndicator5, StyleSheet as StyleSheet13, Platform as Platform9 } from "react-native";
2009
2019
  import { ada as ada10, fontSize as fontSize6, borderRadius as borderRadius4, listMyTenants, switchTenant, getTenant as getTenant4 } from "@ateam-ai-mobile/core";
2010
2020
  import { jsx as jsx15, jsxs as jsxs11 } from "react/jsx-runtime";
@@ -2014,7 +2024,7 @@ function TenantPicker({ onSwitched, onSelect, currentTenantId }) {
2014
2024
  const [error, setError] = useState8(null);
2015
2025
  const [switching, setSwitching] = useState8(null);
2016
2026
  const active = currentTenantId ?? getTenant4();
2017
- useEffect7(() => {
2027
+ useEffect8(() => {
2018
2028
  let cancelled = false;
2019
2029
  listMyTenants().then((list) => {
2020
2030
  if (!cancelled) setTenants(list);
@@ -2185,7 +2195,7 @@ var styles14 = StyleSheet14.create({
2185
2195
  });
2186
2196
 
2187
2197
  // src/auth/HandoffScreen.tsx
2188
- import { useEffect as useEffect8, useRef as useRef5, useState as useState9 } from "react";
2198
+ import { useEffect as useEffect9, useRef as useRef5, useState as useState9 } from "react";
2189
2199
  import { View as View16, Text as Text12, Pressable as Pressable9, StyleSheet as StyleSheet15, Platform as Platform10, ActivityIndicator as ActivityIndicator6 } from "react-native";
2190
2200
  import { exchangeHandoff, ada as ada12 } from "@ateam-ai-mobile/core";
2191
2201
  import { AdaOrb as AdaOrb3 } from "@ateam-ai-mobile/plugin-runtime";
@@ -2193,7 +2203,6 @@ import { AdaOrb as AdaOrb3 } from "@ateam-ai-mobile/plugin-runtime";
2193
2203
  // src/auth/handoffExchange.ts
2194
2204
  async function runHandoffExchange(code, deps) {
2195
2205
  const res = await deps.exchange(code);
2196
- if (res.tenant) await deps.onAdoptTenant(res.tenant);
2197
2206
  await deps.onSignedIn(res.jwt);
2198
2207
  deps.onDone();
2199
2208
  }
@@ -2208,14 +2217,14 @@ function handoffErrorMessage(msg) {
2208
2217
  // src/auth/HandoffScreen.tsx
2209
2218
  import { Fragment as Fragment3, jsx as jsx17, jsxs as jsxs13 } from "react/jsx-runtime";
2210
2219
  var fontFam7 = Platform10.OS === "ios" ? "SF Pro Rounded" : void 0;
2211
- function HandoffScreen({ code, onAdoptTenant, onSignedIn, onDone, onCancel }) {
2220
+ function HandoffScreen({ code, onSignedIn, onDone, onCancel }) {
2212
2221
  const [err, setErr] = useState9(null);
2213
2222
  const startedForRef = useRef5(null);
2214
- useEffect8(() => {
2223
+ useEffect9(() => {
2215
2224
  if (!code || startedForRef.current === code) return;
2216
2225
  startedForRef.current = code;
2217
- runHandoffExchange(code, { exchange: exchangeHandoff, onAdoptTenant, onSignedIn, onDone }).catch((e) => setErr(handoffErrorMessage(e?.message)));
2218
- }, [code, onAdoptTenant, onSignedIn, onDone]);
2226
+ runHandoffExchange(code, { exchange: exchangeHandoff, onSignedIn, onDone }).catch((e) => setErr(handoffErrorMessage(e?.message)));
2227
+ }, [code, onSignedIn, onDone]);
2219
2228
  return /* @__PURE__ */ jsx17(View16, { style: styles15.container, children: /* @__PURE__ */ jsxs13(View16, { style: styles15.center, children: [
2220
2229
  /* @__PURE__ */ jsx17(AdaOrb3, { size: 72, state: err ? "idle" : "thinking" }),
2221
2230
  !err ? /* @__PURE__ */ jsxs13(Fragment3, { children: [
@@ -2238,7 +2247,7 @@ var styles15 = StyleSheet15.create({
2238
2247
  });
2239
2248
 
2240
2249
  // src/auth/OpenJoinScreen.tsx
2241
- import { useEffect as useEffect9, useState as useState10 } from "react";
2250
+ import { useEffect as useEffect10, useState as useState10 } from "react";
2242
2251
  import { View as View17, Text as Text13, Pressable as Pressable10, StyleSheet as StyleSheet16, ActivityIndicator as ActivityIndicator7, Platform as Platform11, TextInput as TextInput2 } from "react-native";
2243
2252
  import { openJoinWithGoogle, openJoinWithApple, ada as ada13, spacing as spacing3 } from "@ateam-ai-mobile/core";
2244
2253
  import { AdaOrb as AdaOrb4 } from "@ateam-ai-mobile/plugin-runtime";
@@ -2247,7 +2256,6 @@ import { AdaOrb as AdaOrb4 } from "@ateam-ai-mobile/plugin-runtime";
2247
2256
  async function completeOpenJoin(slug, idToken, deps) {
2248
2257
  if (!idToken) return false;
2249
2258
  const consumer = await deps.join(slug, idToken);
2250
- await deps.onAdoptTenant(slug);
2251
2259
  await deps.onSignedIn(consumer.jwt);
2252
2260
  return true;
2253
2261
  }
@@ -2265,12 +2273,12 @@ function openJoinErrorMessage(msg) {
2265
2273
  // src/auth/OpenJoinScreen.tsx
2266
2274
  import { jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
2267
2275
  var fontFam8 = Platform11.OS === "ios" ? "SF Pro Rounded" : void 0;
2268
- function OpenJoinScreen({ onAdoptTenant, onSignedIn, onBack }) {
2276
+ function OpenJoinScreen({ onSignedIn, onBack }) {
2269
2277
  const [team, setTeam] = useState10("");
2270
2278
  const [busy, setBusy] = useState10(false);
2271
2279
  const [err, setErr] = useState10(null);
2272
2280
  const [appleAvailable, setAppleAvailable] = useState10(false);
2273
- useEffect9(() => {
2281
+ useEffect10(() => {
2274
2282
  getOAuthProvider()?.isAppleAvailable().then(setAppleAvailable).catch(() => setAppleAvailable(false));
2275
2283
  }, []);
2276
2284
  const slug = team.trim().toLowerCase();
@@ -2286,7 +2294,7 @@ function OpenJoinScreen({ onAdoptTenant, onSignedIn, onBack }) {
2286
2294
  setBusy(true);
2287
2295
  try {
2288
2296
  const idToken = await acquire(oauth);
2289
- await completeOpenJoin(slug, idToken, { join, onAdoptTenant, onSignedIn });
2297
+ await completeOpenJoin(slug, idToken, { join, onSignedIn });
2290
2298
  } catch (e) {
2291
2299
  setErr(openJoinErrorMessage(e?.message));
2292
2300
  } finally {
@@ -2369,7 +2377,7 @@ var styles16 = StyleSheet16.create({
2369
2377
  });
2370
2378
 
2371
2379
  // src/auth/JoinScreen.tsx
2372
- import { useEffect as useEffect10, useMemo as useMemo5, useState as useState11 } from "react";
2380
+ import { useEffect as useEffect11, useMemo as useMemo5, useState as useState11 } from "react";
2373
2381
  import { View as View18, Text as Text14, Pressable as Pressable11, StyleSheet as StyleSheet17, ActivityIndicator as ActivityIndicator8, Platform as Platform12 } from "react-native";
2374
2382
  import {
2375
2383
  previewInvite,
@@ -2402,13 +2410,13 @@ function JoinScreen({ code, onSignedIn, onDone, onCancel }) {
2402
2410
  const [busy, setBusy] = useState11(false);
2403
2411
  const [err, setErr] = useState11(null);
2404
2412
  const [appleAvailable, setAppleAvailable] = useState11(false);
2405
- useEffect10(() => {
2413
+ useEffect11(() => {
2406
2414
  if (!code) return;
2407
2415
  setPreview(null);
2408
2416
  setLoadErr(null);
2409
2417
  previewInvite(code).then(setPreview).catch((e) => setLoadErr(e?.message || "Could not load invite"));
2410
2418
  }, [code]);
2411
- useEffect10(() => {
2419
+ useEffect11(() => {
2412
2420
  getOAuthProvider()?.isAppleAvailable().then(setAppleAvailable).catch(() => setAppleAvailable(false));
2413
2421
  }, []);
2414
2422
  const orgLine = useMemo5(() => inviteHeadline(preview), [preview]);
@@ -2487,8 +2495,8 @@ var styles17 = StyleSheet17.create({
2487
2495
  });
2488
2496
 
2489
2497
  // src/auth/LoginScreen.tsx
2490
- import { useEffect as useEffect11, useMemo as useMemo6, useState as useState12 } from "react";
2491
- import { View as View19, Text as Text15, Pressable as Pressable12, StyleSheet as StyleSheet18, Platform as Platform13, ActivityIndicator as ActivityIndicator9 } from "react-native";
2498
+ import { useEffect as useEffect12, useMemo as useMemo6, useState as useState12 } from "react";
2499
+ import { View as View19, Text as Text15, Pressable as Pressable12, StyleSheet as StyleSheet18, Platform as Platform13, ActivityIndicator as ActivityIndicator9, TextInput as TextInput3 } from "react-native";
2492
2500
  import { fetchConsumerConfig, signInWithGoogle, signInWithApple, ada as ada15 } from "@ateam-ai-mobile/core";
2493
2501
  import { AdaOrb as AdaOrb6 } from "@ateam-ai-mobile/plugin-runtime";
2494
2502
 
@@ -2500,8 +2508,8 @@ function googleClientIds(config) {
2500
2508
  iosClientId: g.ios_client_id || ""
2501
2509
  };
2502
2510
  }
2503
- function shouldRecoverToDefaultTenant(errorMsg, currentTenant, defaultTenant) {
2504
- return /capability not enabled/i.test(errorMsg || "") && currentTenant !== defaultTenant;
2511
+ function isConsumerDisabled(errorMsg) {
2512
+ return /capability not enabled/i.test(errorMsg || "");
2505
2513
  }
2506
2514
  async function completeProviderSignIn(idToken, deps) {
2507
2515
  if (!idToken) return false;
@@ -2513,21 +2521,32 @@ async function completeProviderSignIn(idToken, deps) {
2513
2521
  // src/auth/LoginScreen.tsx
2514
2522
  import { Fragment as Fragment5, jsx as jsx20, jsxs as jsxs16 } from "react/jsx-runtime";
2515
2523
  var fontFam10 = Platform13.OS === "ios" ? "SF Pro Rounded" : void 0;
2516
- function LoginScreen({ activeTenant, defaultTenant, onConsumerDisabled, onSignedIn, onJoinTeam }) {
2524
+ function LoginScreen({ activeTenant, onPickTenant, onConsumerDisabled, onSignedIn, onJoinTeam }) {
2517
2525
  const [config, setConfig] = useState12(null);
2518
2526
  const [error, setError] = useState12(null);
2519
- useEffect11(() => {
2527
+ const [disabledTeam, setDisabledTeam] = useState12(null);
2528
+ const [askTeam, setAskTeam] = useState12(false);
2529
+ const askingTeam = !activeTenant || askTeam;
2530
+ const pick = async (tenant) => {
2531
+ setAskTeam(false);
2532
+ setDisabledTeam(null);
2533
+ await onPickTenant(tenant);
2534
+ };
2535
+ useEffect12(() => {
2520
2536
  setConfig(null);
2521
2537
  setError(null);
2538
+ if (!activeTenant) return;
2522
2539
  fetchConsumerConfig().then(setConfig).catch(async (err) => {
2523
2540
  const msg = err?.message || "Failed to load sign-in config";
2524
- if (shouldRecoverToDefaultTenant(msg, activeTenant, defaultTenant)) {
2541
+ if (isConsumerDisabled(msg)) {
2542
+ setDisabledTeam(activeTenant);
2543
+ setAskTeam(true);
2525
2544
  await onConsumerDisabled();
2526
2545
  return;
2527
2546
  }
2528
2547
  setError(msg);
2529
2548
  });
2530
- }, [activeTenant, defaultTenant, onConsumerDisabled]);
2549
+ }, [activeTenant, onConsumerDisabled]);
2531
2550
  return /* @__PURE__ */ jsxs16(View19, { style: styles18.container, children: [
2532
2551
  /* @__PURE__ */ jsxs16(View19, { style: styles18.hero, children: [
2533
2552
  /* @__PURE__ */ jsx20(AdaOrb6, { size: 140 }),
@@ -2535,20 +2554,51 @@ function LoginScreen({ activeTenant, defaultTenant, onConsumerDisabled, onSigned
2535
2554
  /* @__PURE__ */ jsx20(Text15, { style: styles18.tagline, children: "Your private personal AI-Team" })
2536
2555
  ] }),
2537
2556
  /* @__PURE__ */ jsxs16(View19, { style: styles18.buttonSection, children: [
2538
- !config && !error && /* @__PURE__ */ jsx20(ActivityIndicator9, { color: ada15.ink }),
2539
- !!error && /* @__PURE__ */ jsx20(Text15, { style: styles18.errorText, children: error }),
2540
- !!config && /* @__PURE__ */ jsx20(SignInButtons, { config, onSignedIn }),
2557
+ askingTeam && /* @__PURE__ */ jsx20(TeamField, { notice: disabledTeam, onPick: pick }),
2558
+ !askingTeam && !config && !error && /* @__PURE__ */ jsx20(ActivityIndicator9, { color: ada15.ink }),
2559
+ !askingTeam && !!error && /* @__PURE__ */ jsx20(Text15, { style: styles18.errorText, children: error }),
2560
+ !askingTeam && !!config && /* @__PURE__ */ jsx20(SignInButtons, { config, onSignedIn }),
2561
+ !askingTeam && /* @__PURE__ */ jsx20(Pressable12, { onPress: () => setAskTeam(true), hitSlop: 8, style: { paddingVertical: 4 }, children: /* @__PURE__ */ jsx20(Text15, { style: styles18.joinLink, children: "Use a different team" }) }),
2541
2562
  onJoinTeam && /* @__PURE__ */ jsx20(Pressable12, { onPress: onJoinTeam, hitSlop: 8, style: { paddingVertical: 8 }, children: /* @__PURE__ */ jsx20(Text15, { style: styles18.joinLink, children: "Join a team by name" }) }),
2542
2563
  /* @__PURE__ */ jsx20(Text15, { style: styles18.disclaimer, children: "By continuing you agree to Ada's Terms and Privacy Policy." })
2543
2564
  ] })
2544
2565
  ] });
2545
2566
  }
2567
+ function TeamField({ notice, onPick }) {
2568
+ const [team, setTeam] = useState12("");
2569
+ const slug = team.trim().toLowerCase();
2570
+ const submit = () => {
2571
+ if (slug) void onPick(slug);
2572
+ };
2573
+ return /* @__PURE__ */ jsxs16(Fragment5, { children: [
2574
+ !!notice && /* @__PURE__ */ jsxs16(Text15, { style: styles18.errorText, children: [
2575
+ "\u201C",
2576
+ notice,
2577
+ "\u201D doesn't have app sign-in. Try another team."
2578
+ ] }),
2579
+ /* @__PURE__ */ jsx20(
2580
+ TextInput3,
2581
+ {
2582
+ style: styles18.teamInput,
2583
+ value: team,
2584
+ onChangeText: setTeam,
2585
+ placeholder: "your team (e.g. acme)",
2586
+ placeholderTextColor: ada15.inkMuted,
2587
+ autoCapitalize: "none",
2588
+ autoCorrect: false,
2589
+ returnKeyType: "go",
2590
+ onSubmitEditing: submit
2591
+ }
2592
+ ),
2593
+ /* @__PURE__ */ jsx20(Pressable12, { style: [styles18.signInBtn, !slug && styles18.signInBtnDisabled], onPress: submit, disabled: !slug, children: /* @__PURE__ */ jsx20(Text15, { style: styles18.signInText, children: "Continue" }) })
2594
+ ] });
2595
+ }
2546
2596
  function SignInButtons({ config, onSignedIn }) {
2547
2597
  const [busy, setBusy] = useState12(false);
2548
2598
  const [error, setError] = useState12(null);
2549
2599
  const [appleAvailable, setAppleAvailable] = useState12(false);
2550
2600
  const { webClientId, iosClientId } = useMemo6(() => googleClientIds(config), [config]);
2551
- useEffect11(() => {
2601
+ useEffect12(() => {
2552
2602
  getOAuthProvider()?.isAppleAvailable().then(setAppleAvailable).catch(() => setAppleAvailable(false));
2553
2603
  }, []);
2554
2604
  const handleGoogleLogin = async () => {
@@ -2636,13 +2686,24 @@ var styles18 = StyleSheet18.create({
2636
2686
  signInGlyph: { fontSize: 18, fontWeight: "700", color: ada15.paper, fontFamily: fontFam10 },
2637
2687
  signInText: { fontSize: 16, fontWeight: "600", color: ada15.paper, letterSpacing: -0.2, fontFamily: fontFam10 },
2638
2688
  appleBtn: { width: "100%", height: 52 },
2689
+ teamInput: {
2690
+ width: "100%",
2691
+ backgroundColor: ada15.paperSoft,
2692
+ borderWidth: 1,
2693
+ borderColor: ada15.border,
2694
+ borderRadius: 14,
2695
+ paddingHorizontal: 16,
2696
+ paddingVertical: 14,
2697
+ fontSize: 16,
2698
+ color: ada15.ink
2699
+ },
2639
2700
  errorText: { fontSize: 13, color: "#c43d3d", textAlign: "center", paddingHorizontal: 16 },
2640
2701
  disclaimer: { fontSize: 12, color: ada15.inkMuted, textAlign: "center", marginTop: 8, lineHeight: 18, fontFamily: fontFam10 },
2641
2702
  joinLink: { fontSize: 14, fontWeight: "600", color: ada15.orangeDeep, textAlign: "center", fontFamily: fontFam10 }
2642
2703
  });
2643
2704
 
2644
2705
  // src/voice/VoiceCallSheet.tsx
2645
- import { useEffect as useEffect13, useRef as useRef6, useMemo as useMemo7 } from "react";
2706
+ import { useEffect as useEffect14, useRef as useRef6, useMemo as useMemo7 } from "react";
2646
2707
  import {
2647
2708
  View as View20,
2648
2709
  Text as Text16,
@@ -2656,7 +2717,7 @@ import { ada as ada16 } from "@ateam-ai-mobile/core";
2656
2717
  import { AdaOrb as AdaOrb7, SurfaceFullscreen as SurfaceFullscreen2 } from "@ateam-ai-mobile/plugin-runtime";
2657
2718
 
2658
2719
  // src/voice/useVoiceCall.ts
2659
- import { useCallback as useCallback6, useEffect as useEffect12, useReducer } from "react";
2720
+ import { useCallback as useCallback6, useEffect as useEffect13, useReducer } from "react";
2660
2721
 
2661
2722
  // src/voice/voiceSession.ts
2662
2723
  import { getVoiceApiUrl as getVoiceApiUrl2, getToken as getToken2, getTenant as getTenant5, getUser as getUser2, refreshToken } from "@ateam-ai-mobile/core";
@@ -2810,6 +2871,9 @@ function originOf(url) {
2810
2871
  const m = /^([a-z][a-z0-9+.-]*:\/\/[^/?#]+)/i.exec(url);
2811
2872
  return m ? m[1].toLowerCase() : null;
2812
2873
  }
2874
+ function isLiveCall(state) {
2875
+ return state === "connecting" || state === "connected";
2876
+ }
2813
2877
  var IDLE = {
2814
2878
  callState: "idle",
2815
2879
  sessionId: null,
@@ -3264,9 +3328,22 @@ var VoiceSessionManager = class {
3264
3328
  }
3265
3329
  // ── internals ────────────────────────────────────────────────
3266
3330
  setState(partial) {
3331
+ const wasLive = isLiveCall(this.state.callState);
3267
3332
  this.state = { ...this.state, ...partial };
3333
+ const isLive = isLiveCall(this.state.callState);
3334
+ if (wasLive !== isLive) this.setCallAudio(isLive);
3268
3335
  this.emit({ type: "state" });
3269
3336
  }
3337
+ setCallAudio(on) {
3338
+ const audio = getCallAudioProvider();
3339
+ if (!audio) return;
3340
+ try {
3341
+ if (on) audio.beginCall();
3342
+ else audio.endCall();
3343
+ } catch (e) {
3344
+ console.warn("[voiceSession] call audio mode failed:", e?.message || String(e));
3345
+ }
3346
+ }
3270
3347
  appendTranscript(entry) {
3271
3348
  this.state = { ...this.state, transcript: [...this.state.transcript, entry] };
3272
3349
  this.emit({ type: "transcript" });
@@ -3325,7 +3402,7 @@ var voiceSession = new VoiceSessionManager();
3325
3402
  // src/voice/useVoiceCall.ts
3326
3403
  function useVoiceCall({ skillSlug } = {}) {
3327
3404
  const [, force] = useReducer((x) => x + 1, 0);
3328
- useEffect12(() => {
3405
+ useEffect13(() => {
3329
3406
  const sub = voiceSession.subscribe(() => force());
3330
3407
  return () => sub.unsubscribe();
3331
3408
  }, []);
@@ -3414,10 +3491,10 @@ function VoiceCallSheet({ visible, onClose, skillSlug }) {
3414
3491
  toggleMute
3415
3492
  } = useVoiceCall({ skillSlug });
3416
3493
  const scrollRef = useRef6(null);
3417
- useEffect13(() => {
3494
+ useEffect14(() => {
3418
3495
  if (visible && callState === "idle") startCall();
3419
3496
  }, [visible]);
3420
- useEffect13(() => {
3497
+ useEffect14(() => {
3421
3498
  scrollRef.current?.scrollToEnd?.({ animated: true });
3422
3499
  }, [transcript.length, aiPartial, userPartial]);
3423
3500
  const handleHangUp = () => {
@@ -3610,14 +3687,14 @@ var styles19 = StyleSheet19.create({
3610
3687
  });
3611
3688
 
3612
3689
  // src/voice/VoiceSessionHost.tsx
3613
- import { useCallback as useCallback7, useEffect as useEffect14, useReducer as useReducer2, useRef as useRef7 } from "react";
3690
+ import { useCallback as useCallback7, useEffect as useEffect15, useReducer as useReducer2, useRef as useRef7 } from "react";
3614
3691
  import { View as View21, StyleSheet as StyleSheet20 } from "react-native";
3615
3692
  import { WebView as WebView3 } from "react-native-webview";
3616
3693
  import { jsx as jsx22 } from "react/jsx-runtime";
3617
3694
  function VoiceSessionHost() {
3618
3695
  const [, force] = useReducer2((x) => x + 1, 0);
3619
3696
  const lastSig = useRef7("");
3620
- useEffect14(() => {
3697
+ useEffect15(() => {
3621
3698
  const sub = voiceSession.subscribe(() => {
3622
3699
  const s2 = voiceSession.getInternal();
3623
3700
  const sig = `${s2.mounted}|${s2.webViewSource?.uri || ""}`;
@@ -3663,7 +3740,7 @@ var styles20 = StyleSheet20.create({
3663
3740
  });
3664
3741
 
3665
3742
  // src/voice/VoiceMicIndicator.tsx
3666
- import { useEffect as useEffect15, useReducer as useReducer3, useRef as useRef8 } from "react";
3743
+ import { useEffect as useEffect16, useReducer as useReducer3, useRef as useRef8 } from "react";
3667
3744
  import { View as View22, Text as Text17, Animated as Animated2, StyleSheet as StyleSheet21, Platform as Platform15 } from "react-native";
3668
3745
  import { ada as ada17 } from "@ateam-ai-mobile/core";
3669
3746
  import { jsx as jsx23, jsxs as jsxs18 } from "react/jsx-runtime";
@@ -3671,13 +3748,13 @@ var fontFam12 = Platform15.OS === "ios" ? "SF Pro Rounded" : void 0;
3671
3748
  function VoiceMicIndicator({ topInset = 8 }) {
3672
3749
  const [, force] = useReducer3((x) => x + 1, 0);
3673
3750
  const pulse = useRef8(new Animated2.Value(0.4)).current;
3674
- useEffect15(() => {
3751
+ useEffect16(() => {
3675
3752
  const sub = voiceSession.subscribe(() => force());
3676
3753
  return () => sub.unsubscribe();
3677
3754
  }, []);
3678
3755
  const snap = voiceSession.getSnapshot();
3679
3756
  const live = snap.state === "connecting" || snap.state === "connected";
3680
- useEffect15(() => {
3757
+ useEffect16(() => {
3681
3758
  if (!live) return;
3682
3759
  const loop = Animated2.loop(
3683
3760
  Animated2.sequence([
@@ -3762,14 +3839,15 @@ export {
3762
3839
  googleClientIds,
3763
3840
  handoffErrorMessage,
3764
3841
  inviteHeadline,
3842
+ isConsumerDisabled,
3765
3843
  openJoinErrorMessage,
3766
3844
  openWidget,
3767
3845
  runHandoffExchange,
3846
+ setCallAudioProvider,
3768
3847
  setClipboardProvider,
3769
3848
  setOAuthProvider,
3770
3849
  setPluginWebViewExtraHosts,
3771
3850
  setUIActionNavigator,
3772
- shouldRecoverToDefaultTenant,
3773
3851
  useLightboxStore,
3774
3852
  usePluginBridge,
3775
3853
  useVoiceCall,