@ateam-ai-mobile/ui 0.1.3 → 0.1.4

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.d.mts CHANGED
@@ -177,8 +177,10 @@ declare const useLightboxStore: zustand.UseBoundStore<zustand.StoreApi<LightboxS
177
177
  interface Props {
178
178
  visible: boolean;
179
179
  onClose: () => void;
180
+ /** Optional skill to hand the mic to on connect (voice /session → takeMic). */
181
+ skillSlug?: string;
180
182
  }
181
- declare function VoiceCallSheet({ visible, onClose }: Props): react_jsx_runtime.JSX.Element | null;
183
+ declare function VoiceCallSheet({ visible, onClose, skillSlug }: Props): react_jsx_runtime.JSX.Element | null;
182
184
 
183
185
  interface TranscriptEntry {
184
186
  role: 'user' | 'ai' | 'tool';
@@ -186,7 +188,9 @@ interface TranscriptEntry {
186
188
  ts: number;
187
189
  }
188
190
  type CallState = 'idle' | 'connecting' | 'connected' | 'error';
189
- declare function useVoiceCall(): {
191
+ declare function useVoiceCall({ skillSlug }?: {
192
+ skillSlug?: string;
193
+ }): {
190
194
  callState: CallState;
191
195
  sessionId: string | null;
192
196
  error: string | null;
@@ -194,7 +198,7 @@ declare function useVoiceCall(): {
194
198
  aiPartial: string;
195
199
  userPartial: string;
196
200
  muted: boolean;
197
- startCall: () => void;
201
+ startCall: () => Promise<void>;
198
202
  stopCall: () => void;
199
203
  toggleMute: () => void;
200
204
  handleWebViewMessage: (event: any) => void;
package/dist/index.d.ts CHANGED
@@ -177,8 +177,10 @@ declare const useLightboxStore: zustand.UseBoundStore<zustand.StoreApi<LightboxS
177
177
  interface Props {
178
178
  visible: boolean;
179
179
  onClose: () => void;
180
+ /** Optional skill to hand the mic to on connect (voice /session → takeMic). */
181
+ skillSlug?: string;
180
182
  }
181
- declare function VoiceCallSheet({ visible, onClose }: Props): react_jsx_runtime.JSX.Element | null;
183
+ declare function VoiceCallSheet({ visible, onClose, skillSlug }: Props): react_jsx_runtime.JSX.Element | null;
182
184
 
183
185
  interface TranscriptEntry {
184
186
  role: 'user' | 'ai' | 'tool';
@@ -186,7 +188,9 @@ interface TranscriptEntry {
186
188
  ts: number;
187
189
  }
188
190
  type CallState = 'idle' | 'connecting' | 'connected' | 'error';
189
- declare function useVoiceCall(): {
191
+ declare function useVoiceCall({ skillSlug }?: {
192
+ skillSlug?: string;
193
+ }): {
190
194
  callState: CallState;
191
195
  sessionId: string | null;
192
196
  error: string | null;
@@ -194,7 +198,7 @@ declare function useVoiceCall(): {
194
198
  aiPartial: string;
195
199
  userPartial: string;
196
200
  muted: boolean;
197
- startCall: () => void;
201
+ startCall: () => Promise<void>;
198
202
  stopCall: () => void;
199
203
  toggleMute: () => void;
200
204
  handleWebViewMessage: (event: any) => void;
package/dist/index.js CHANGED
@@ -2088,6 +2088,20 @@ var import_plugin_runtime9 = require("@ateam-ai-mobile/plugin-runtime");
2088
2088
  // src/voice/useVoiceCall.ts
2089
2089
  var import_react12 = require("react");
2090
2090
  var import_core16 = require("@ateam-ai-mobile/core");
2091
+ var TOKEN_REFRESH_SKEW_MS = 9e4;
2092
+ function tokenNeedsRefresh(token) {
2093
+ if (!token) return true;
2094
+ try {
2095
+ const payloadB64 = token.split(".")[1];
2096
+ const padded = payloadB64.replace(/-/g, "+").replace(/_/g, "/");
2097
+ const json = typeof atob === "function" ? atob(padded) : Buffer.from(padded, "base64").toString("utf8");
2098
+ const exp = JSON.parse(json)?.exp;
2099
+ if (typeof exp !== "number") return false;
2100
+ return Date.now() >= exp * 1e3 - TOKEN_REFRESH_SKEW_MS;
2101
+ } catch {
2102
+ return false;
2103
+ }
2104
+ }
2091
2105
  var INJECT_TRACK_HOOK = `
2092
2106
  (function() {
2093
2107
  if (window._adaTrackHookInstalled) return;
@@ -2178,7 +2192,7 @@ var buildMuteScript = (muted) => `
2178
2192
  console.log('[ada-mute]', muted ? 'MUTED' : 'UNMUTED', 'tracks=', n);
2179
2193
  })(${muted}); true;
2180
2194
  `;
2181
- function useVoiceCall() {
2195
+ function useVoiceCall({ skillSlug } = {}) {
2182
2196
  const [callState, setCallState] = (0, import_react12.useState)("idle");
2183
2197
  const [sessionId, setSessionId] = (0, import_react12.useState)(null);
2184
2198
  const [error, setError] = (0, import_react12.useState)(null);
@@ -2219,12 +2233,18 @@ function useVoiceCall() {
2219
2233
  } catch {
2220
2234
  }
2221
2235
  }, []);
2222
- const startCall = (0, import_react12.useCallback)(() => {
2223
- setCallState("connecting");
2236
+ const startCall = (0, import_react12.useCallback)(async () => {
2224
2237
  setError(null);
2225
2238
  setTranscript([]);
2226
2239
  setAiPartial("");
2227
2240
  setUserPartial("");
2241
+ try {
2242
+ if (tokenNeedsRefresh((0, import_core16.getToken)())) {
2243
+ await (0, import_core16.refreshToken)();
2244
+ }
2245
+ } catch {
2246
+ }
2247
+ setCallState("connecting");
2228
2248
  }, []);
2229
2249
  const stopCall = (0, import_react12.useCallback)(() => {
2230
2250
  webViewRef.current?.injectJavaScript?.("window.hangUp && window.hangUp(); true;");
@@ -2244,10 +2264,11 @@ function useVoiceCall() {
2244
2264
  const token = (0, import_core16.getToken)();
2245
2265
  const tenant = (0, import_core16.getTenant)();
2246
2266
  const actorId = (0, import_core16.getUser)()?.actorId || "";
2267
+ const skillParam = skillSlug ? `&skillSlug=${encodeURIComponent(skillSlug)}` : "";
2247
2268
  return {
2248
- uri: `${(0, import_core16.getVoiceApiUrl)()}/app?mode=mini&embedded=rn&authToken=${encodeURIComponent(token || "")}&tenant=${encodeURIComponent(tenant)}&actorId=${encodeURIComponent(actorId)}`
2269
+ uri: `${(0, import_core16.getVoiceApiUrl)()}/app?mode=mini&embedded=rn&authToken=${encodeURIComponent(token || "")}&tenant=${encodeURIComponent(tenant)}&actorId=${encodeURIComponent(actorId)}${skillParam}`
2249
2270
  };
2250
- }, []);
2271
+ }, [skillSlug]);
2251
2272
  return {
2252
2273
  callState,
2253
2274
  sessionId,
@@ -2314,7 +2335,7 @@ function HighlightedText({
2314
2335
  const segments = (0, import_react13.useMemo)(() => highlightSegments(text), [text]);
2315
2336
  return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_react_native14.Text, { style: baseStyle, children: segments.map((seg, i) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_react_native14.Text, { style: seg.important ? importantStyle : void 0, children: seg.text }, i)) });
2316
2337
  }
2317
- function VoiceCallSheet({ visible, onClose }) {
2338
+ function VoiceCallSheet({ visible, onClose, skillSlug }) {
2318
2339
  const {
2319
2340
  callState,
2320
2341
  aiPartial,
@@ -2329,7 +2350,7 @@ function VoiceCallSheet({ visible, onClose }) {
2329
2350
  getWebViewSource,
2330
2351
  webViewRef,
2331
2352
  injectedTrackHook
2332
- } = useVoiceCall();
2353
+ } = useVoiceCall({ skillSlug });
2333
2354
  const scrollRef = (0, import_react13.useRef)(null);
2334
2355
  (0, import_react13.useEffect)(() => {
2335
2356
  if (visible && callState === "idle") startCall();