@ateam-ai-mobile/expo 0.1.21 → 0.1.23
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 +10 -4
- package/dist/aiLive/provider.d.ts +10 -4
- package/dist/aiLive/provider.js +119 -43
- package/dist/aiLive/provider.js.map +1 -1
- package/dist/aiLive/provider.mjs +5 -3
- package/dist/bootstrap.js +120 -46
- package/dist/bootstrap.js.map +1 -1
- package/dist/bootstrap.mjs +4 -4
- package/dist/capabilities/index.js +19 -1
- package/dist/capabilities/index.js.map +1 -1
- package/dist/capabilities/index.mjs +21 -3
- package/dist/capabilities/index.mjs.map +1 -1
- package/dist/{chunk-BAZFMTCC.mjs → chunk-4HJ5FO3S.mjs} +2 -2
- package/dist/{chunk-C62NQA4F.mjs → chunk-GGEFDRQQ.mjs} +2 -2
- package/dist/chunk-GGEFDRQQ.mjs.map +1 -0
- package/dist/{chunk-OEX4OKYQ.mjs → chunk-NH3CHSLR.mjs} +2 -2
- package/dist/{chunk-JUBLG3PN.mjs → chunk-PV2EHH2P.mjs} +119 -44
- package/dist/chunk-PV2EHH2P.mjs.map +1 -0
- package/dist/device/createDeviceProvider.mjs +3 -3
- package/dist/device-bridge/index.js +1 -1
- package/dist/device-bridge/index.js.map +1 -1
- package/dist/device-bridge/index.mjs +2 -2
- package/dist/push/silentSync.js.map +1 -1
- package/dist/push/silentSync.mjs +1 -1
- package/package.json +4 -4
- package/src/aiLive/provider.ts +138 -49
- package/src/aiLive/streamProtocol.ts +2 -2
- package/src/capabilities/store.ts +21 -1
- package/src/device-bridge/capabilities.ts +2 -1
- package/dist/chunk-C62NQA4F.mjs.map +0 -1
- package/dist/chunk-JUBLG3PN.mjs.map +0 -1
- /package/dist/{chunk-BAZFMTCC.mjs.map → chunk-4HJ5FO3S.mjs.map} +0 -0
- /package/dist/{chunk-OEX4OKYQ.mjs.map → chunk-NH3CHSLR.mjs.map} +0 -0
package/dist/bootstrap.js
CHANGED
|
@@ -176,7 +176,7 @@ __export(bootstrap_exports, {
|
|
|
176
176
|
});
|
|
177
177
|
module.exports = __toCommonJS(bootstrap_exports);
|
|
178
178
|
var import_core3 = require("@ateam-ai-mobile/core");
|
|
179
|
-
var
|
|
179
|
+
var import_plugin_runtime4 = require("@ateam-ai-mobile/plugin-runtime");
|
|
180
180
|
var import_ui2 = require("@ateam-ai-mobile/ui");
|
|
181
181
|
|
|
182
182
|
// src/audio/index.ts
|
|
@@ -2925,6 +2925,7 @@ function createDeviceProvider(config2) {
|
|
|
2925
2925
|
|
|
2926
2926
|
// src/aiLive/provider.ts
|
|
2927
2927
|
var import_core2 = require("@ateam-ai-mobile/core");
|
|
2928
|
+
var import_plugin_runtime3 = require("@ateam-ai-mobile/plugin-runtime");
|
|
2928
2929
|
|
|
2929
2930
|
// src/aiLive/streamProtocol.ts
|
|
2930
2931
|
var STREAM_PATH = "/ws/stream";
|
|
@@ -2953,8 +2954,8 @@ function encodeFrame({ seq, tCapture, payload }) {
|
|
|
2953
2954
|
out.set(payload, HEADER_BYTES);
|
|
2954
2955
|
return out;
|
|
2955
2956
|
}
|
|
2956
|
-
function openMessage(kind) {
|
|
2957
|
-
return JSON.stringify({ type: "open", kind });
|
|
2957
|
+
function openMessage(kind, params) {
|
|
2958
|
+
return JSON.stringify(params ? { type: "open", kind, params } : { type: "open", kind });
|
|
2958
2959
|
}
|
|
2959
2960
|
var CLOSE_MESSAGE = JSON.stringify({ type: "close" });
|
|
2960
2961
|
function parseServerEvent(text2) {
|
|
@@ -3002,22 +3003,14 @@ function base64ToBytes(b64) {
|
|
|
3002
3003
|
}
|
|
3003
3004
|
|
|
3004
3005
|
// src/aiLive/provider.ts
|
|
3005
|
-
var PHONE_SLICE_USD = 0.5;
|
|
3006
3006
|
var LIVE_KIND = "ai-models.live";
|
|
3007
3007
|
var FRESH_MS2 = 3e3;
|
|
3008
3008
|
var MAX_BUFFERED = 512 * 1024;
|
|
3009
3009
|
var DEFAULT_CAMERA = { fps: 1, maxPx: 768 };
|
|
3010
|
-
var
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
if (res?.error) throw new Error(res.error.message || "AI Models refused the request");
|
|
3014
|
-
const out = (0, import_core2.unwrapMcpResult)(res?.result);
|
|
3015
|
-
if (res?.result?.isError) throw new Error(typeof out === "string" ? out : out?.message || out?.error || "AI Models refused the request");
|
|
3016
|
-
if (out && typeof out === "object" && out.ok === false) throw new Error(out.message || out.error || "AI Models refused the request");
|
|
3017
|
-
return out;
|
|
3018
|
-
}
|
|
3010
|
+
var OPEN_TIMEOUT_MS = 2e4;
|
|
3011
|
+
var CLOSE_WAIT_MS = 3e3;
|
|
3012
|
+
var isEpisode = (d) => !!d && typeof d === "object" && typeof d.type === "string" && typeof d.class === "string" && typeof d.episodeId === "string" && typeof d.actorId === "string" && d.actorId.length > 0 && Number.isFinite(d.at);
|
|
3019
3013
|
var defaultAiLiveDeps = () => ({
|
|
3020
|
-
callCp: defaultCallCp,
|
|
3021
3014
|
WebSocketImpl: globalThis.WebSocket,
|
|
3022
3015
|
wsBase: import_core2.getCoreWsUrl,
|
|
3023
3016
|
token: import_core2.getToken,
|
|
@@ -3025,7 +3018,9 @@ var defaultAiLiveDeps = () => ({
|
|
|
3025
3018
|
jpegById,
|
|
3026
3019
|
now: Date.now,
|
|
3027
3020
|
setInterval: (fn, ms) => setInterval(fn, ms),
|
|
3028
|
-
clearInterval: (h) => clearInterval(h)
|
|
3021
|
+
clearInterval: (h) => clearInterval(h),
|
|
3022
|
+
setTimeout: (fn, ms) => setTimeout(fn, ms),
|
|
3023
|
+
clearTimeout: (h) => clearTimeout(h)
|
|
3029
3024
|
});
|
|
3030
3025
|
var idle = () => ({ state: "idle", camera: null, sent: 0, skipped: 0, lastEpisode: null, lastError: null });
|
|
3031
3026
|
function createAiLiveProvider(overrides = {}) {
|
|
@@ -3035,7 +3030,11 @@ function createAiLiveProvider(overrides = {}) {
|
|
|
3035
3030
|
let ws = null;
|
|
3036
3031
|
let loop = null;
|
|
3037
3032
|
let visual = null;
|
|
3038
|
-
let
|
|
3033
|
+
let allowed = () => false;
|
|
3034
|
+
let stopReason = null;
|
|
3035
|
+
let tearingDown = null;
|
|
3036
|
+
const waitingToStart = /* @__PURE__ */ new Map();
|
|
3037
|
+
const closedOf = /* @__PURE__ */ new WeakMap();
|
|
3039
3038
|
let closingOnPurpose = false;
|
|
3040
3039
|
let seq = 0;
|
|
3041
3040
|
let busy = false;
|
|
@@ -3088,6 +3087,12 @@ function createAiLiveProvider(overrides = {}) {
|
|
|
3088
3087
|
const g = gen;
|
|
3089
3088
|
const sock = ws;
|
|
3090
3089
|
const current = () => g === gen && ws === sock && sock?.readyState === 1;
|
|
3090
|
+
const consentGone = () => {
|
|
3091
|
+
if (allowed()) return false;
|
|
3092
|
+
if (g === gen) void teardown("stopped", import_plugin_runtime3.CONSENT_TAKEN_BACK);
|
|
3093
|
+
return true;
|
|
3094
|
+
};
|
|
3095
|
+
if (consentGone()) return;
|
|
3091
3096
|
if (busy || !current()) {
|
|
3092
3097
|
set2({ skipped: snap.skipped + 1 });
|
|
3093
3098
|
return;
|
|
@@ -3108,7 +3113,7 @@ function createAiLiveProvider(overrides = {}) {
|
|
|
3108
3113
|
return;
|
|
3109
3114
|
}
|
|
3110
3115
|
const b64 = await deps.jpegById(id, camera.maxPx, 0.7);
|
|
3111
|
-
if (!current()) return;
|
|
3116
|
+
if (!current() || consentGone()) return;
|
|
3112
3117
|
const frame = encodeFrame({ seq: mySeq, tCapture: t, payload: base64ToBytes(b64) });
|
|
3113
3118
|
sock.send(frame.buffer);
|
|
3114
3119
|
lastFrameId = id;
|
|
@@ -3132,22 +3137,42 @@ function createAiLiveProvider(overrides = {}) {
|
|
|
3132
3137
|
const sock = new deps.WebSocketImpl(url, [SUBPROTOCOL, `adas.bearer.${token}`]);
|
|
3133
3138
|
ws = sock;
|
|
3134
3139
|
sock.binaryType = "arraybuffer";
|
|
3140
|
+
let markClosed = () => {
|
|
3141
|
+
};
|
|
3142
|
+
closedOf.set(sock, new Promise((r) => {
|
|
3143
|
+
markClosed = r;
|
|
3144
|
+
}));
|
|
3145
|
+
const gaveUp = deps.setTimeout(() => {
|
|
3146
|
+
if (opened) return;
|
|
3147
|
+
reject(new Error("Core did not answer in time. Try again."));
|
|
3148
|
+
try {
|
|
3149
|
+
sock.close();
|
|
3150
|
+
} catch {
|
|
3151
|
+
}
|
|
3152
|
+
}, OPEN_TIMEOUT_MS);
|
|
3135
3153
|
sock.onopen = () => {
|
|
3136
3154
|
try {
|
|
3137
|
-
sock.send(openMessage(LIVE_KIND));
|
|
3155
|
+
sock.send(openMessage(LIVE_KIND, { session: "own", source: "phone" }));
|
|
3138
3156
|
} catch (e) {
|
|
3139
3157
|
reject(e);
|
|
3140
3158
|
}
|
|
3141
3159
|
};
|
|
3142
3160
|
sock.onmessage = (m) => {
|
|
3161
|
+
if (ws !== sock) return;
|
|
3143
3162
|
const ev = parseServerEvent(m?.data);
|
|
3144
3163
|
if (!ev) return;
|
|
3164
|
+
if (ev.event === "session" && !opened) {
|
|
3165
|
+
const c = ev.data?.camera;
|
|
3166
|
+
camera = c && Number(c.fps) > 0 && Number(c.maxPx) > 0 ? { fps: Number(c.fps), maxPx: Number(c.maxPx) } : DEFAULT_CAMERA;
|
|
3167
|
+
return;
|
|
3168
|
+
}
|
|
3145
3169
|
if (ev.event === "opened" && !opened) {
|
|
3146
3170
|
opened = true;
|
|
3171
|
+
deps.clearTimeout(gaveUp);
|
|
3147
3172
|
resolve();
|
|
3148
3173
|
return;
|
|
3149
3174
|
}
|
|
3150
|
-
if (ev.event === "episode" && ev.data
|
|
3175
|
+
if (ev.event === "episode" && isEpisode(ev.data)) {
|
|
3151
3176
|
const episode = ev.data;
|
|
3152
3177
|
set2({ lastEpisode: episode });
|
|
3153
3178
|
for (const cb of owner && episodeCbs.get(owner) || []) {
|
|
@@ -3161,8 +3186,10 @@ function createAiLiveProvider(overrides = {}) {
|
|
|
3161
3186
|
sock.onerror = () => {
|
|
3162
3187
|
};
|
|
3163
3188
|
sock.onclose = (c) => {
|
|
3189
|
+
markClosed();
|
|
3164
3190
|
const why = describeClose(Number(c?.code), c?.reason);
|
|
3165
3191
|
if (!opened) {
|
|
3192
|
+
deps.clearTimeout(gaveUp);
|
|
3166
3193
|
reject(new Error(why));
|
|
3167
3194
|
return;
|
|
3168
3195
|
}
|
|
@@ -3171,9 +3198,20 @@ function createAiLiveProvider(overrides = {}) {
|
|
|
3171
3198
|
};
|
|
3172
3199
|
});
|
|
3173
3200
|
}
|
|
3174
|
-
|
|
3175
|
-
|
|
3176
|
-
|
|
3201
|
+
function teardown(state, lastError) {
|
|
3202
|
+
if (tearingDown) return tearingDown;
|
|
3203
|
+
const p = teardownNow(state, lastError);
|
|
3204
|
+
tearingDown = p;
|
|
3205
|
+
void p.then(() => {
|
|
3206
|
+
}, () => {
|
|
3207
|
+
}).then(() => {
|
|
3208
|
+
if (tearingDown === p) tearingDown = null;
|
|
3209
|
+
});
|
|
3210
|
+
return p;
|
|
3211
|
+
}
|
|
3212
|
+
async function teardownNow(state, lastError) {
|
|
3213
|
+
stopReason = lastError;
|
|
3214
|
+
allowed = () => false;
|
|
3177
3215
|
gen++;
|
|
3178
3216
|
stopTimers();
|
|
3179
3217
|
const sock = ws;
|
|
@@ -3190,21 +3228,40 @@ function createAiLiveProvider(overrides = {}) {
|
|
|
3190
3228
|
closingOnPurpose = false;
|
|
3191
3229
|
const v = visual;
|
|
3192
3230
|
visual = null;
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
}
|
|
3202
|
-
|
|
3231
|
+
let gaveUp = null;
|
|
3232
|
+
const closed = sock && closedOf.get(sock);
|
|
3233
|
+
await Promise.all([
|
|
3234
|
+
(async () => {
|
|
3235
|
+
try {
|
|
3236
|
+
await v?.stop?.();
|
|
3237
|
+
} catch {
|
|
3238
|
+
}
|
|
3239
|
+
})(),
|
|
3240
|
+
closed ? Promise.race([closed, new Promise((r) => {
|
|
3241
|
+
gaveUp = deps.setTimeout(r, CLOSE_WAIT_MS);
|
|
3242
|
+
})]) : Promise.resolve()
|
|
3243
|
+
]);
|
|
3244
|
+
if (gaveUp != null) deps.clearTimeout(gaveUp);
|
|
3203
3245
|
owner = null;
|
|
3204
3246
|
set2({ state, lastError });
|
|
3205
3247
|
}
|
|
3206
3248
|
return {
|
|
3207
3249
|
async start(opts, who, ctx) {
|
|
3250
|
+
if (tearingDown) {
|
|
3251
|
+
const wait = { cancelled: false };
|
|
3252
|
+
waitingToStart.set(who, wait);
|
|
3253
|
+
try {
|
|
3254
|
+
while (tearingDown) {
|
|
3255
|
+
try {
|
|
3256
|
+
await tearingDown;
|
|
3257
|
+
} catch {
|
|
3258
|
+
}
|
|
3259
|
+
}
|
|
3260
|
+
} finally {
|
|
3261
|
+
if (waitingToStart.get(who) === wait) waitingToStart.delete(who);
|
|
3262
|
+
}
|
|
3263
|
+
if (wait.cancelled) throw Object.assign(new Error("aiLive: stopped before it started."), { code: "STOPPED" });
|
|
3264
|
+
}
|
|
3208
3265
|
if (owner && owner !== who) throw Object.assign(new Error("aiLive: another screen is sending to AI right now. Close it first."), { code: "CONFLICT" });
|
|
3209
3266
|
if (owner === who) return snap;
|
|
3210
3267
|
const cam = opts?.camera === "front" ? "front" : "back";
|
|
@@ -3212,35 +3269,52 @@ function createAiLiveProvider(overrides = {}) {
|
|
|
3212
3269
|
owner = who;
|
|
3213
3270
|
lastOwner = who;
|
|
3214
3271
|
visual = ctx.visual;
|
|
3272
|
+
allowed = typeof ctx.allowed === "function" ? ctx.allowed : () => false;
|
|
3215
3273
|
gen++;
|
|
3216
3274
|
seq = 0;
|
|
3217
3275
|
lastFrameId = null;
|
|
3218
3276
|
busy = false;
|
|
3277
|
+
const g = gen;
|
|
3278
|
+
const cameraOfScreen = ctx.visual;
|
|
3219
3279
|
snap = { ...idle(), camera: cam };
|
|
3220
3280
|
set2({ state: "starting" });
|
|
3281
|
+
const stillStarting = async () => {
|
|
3282
|
+
if (g === gen && !allowed()) await teardown("stopped", import_plugin_runtime3.CONSENT_TAKEN_BACK);
|
|
3283
|
+
if (g !== gen) throw Object.assign(new Error(stopReason || "aiLive: stopped before it started sending."), { code: "STOPPED" });
|
|
3284
|
+
};
|
|
3221
3285
|
try {
|
|
3222
|
-
|
|
3223
|
-
|
|
3224
|
-
|
|
3225
|
-
startedSession = true;
|
|
3226
|
-
}
|
|
3227
|
-
const c = session?.camera;
|
|
3228
|
-
camera = c && Number(c.fps) > 0 && Number(c.maxPx) > 0 ? { fps: Number(c.fps), maxPx: Number(c.maxPx) } : DEFAULT_CAMERA;
|
|
3229
|
-
await visual.start({ intent: "stream", facing: cam });
|
|
3286
|
+
await stillStarting();
|
|
3287
|
+
camera = DEFAULT_CAMERA;
|
|
3288
|
+
if (g !== gen) throw Object.assign(new Error(stopReason || "aiLive: stopped before it started sending."), { code: "STOPPED" });
|
|
3230
3289
|
await openSocket();
|
|
3290
|
+
await stillStarting();
|
|
3291
|
+
await cameraOfScreen.start({ intent: "stream", facing: cam });
|
|
3292
|
+
if (g !== gen) {
|
|
3293
|
+
try {
|
|
3294
|
+
await cameraOfScreen.stop?.();
|
|
3295
|
+
} catch {
|
|
3296
|
+
}
|
|
3297
|
+
}
|
|
3298
|
+
await stillStarting();
|
|
3299
|
+
if (g !== gen) throw Object.assign(new Error(stopReason || "aiLive: stopped before it started sending."), { code: "STOPPED" });
|
|
3231
3300
|
loop = deps.setInterval(() => {
|
|
3232
3301
|
void slot();
|
|
3233
3302
|
}, Math.max(200, Math.round(1e3 / camera.fps)));
|
|
3234
3303
|
set2({ state: "sending" });
|
|
3235
3304
|
return snap;
|
|
3236
3305
|
} catch (e) {
|
|
3306
|
+
if (g !== gen) {
|
|
3307
|
+
throw e?.code === "STOPPED" ? e : Object.assign(new Error(stopReason || "aiLive: stopped before it started sending."), { code: "STOPPED" });
|
|
3308
|
+
}
|
|
3237
3309
|
await teardown("error", String(e?.message || e));
|
|
3238
3310
|
throw e;
|
|
3239
3311
|
}
|
|
3240
3312
|
},
|
|
3241
|
-
async stop(who) {
|
|
3313
|
+
async stop(who, why) {
|
|
3314
|
+
const waiting = waitingToStart.get(who);
|
|
3315
|
+
if (waiting) waiting.cancelled = true;
|
|
3242
3316
|
if (owner !== who) return;
|
|
3243
|
-
await teardown("stopped", null);
|
|
3317
|
+
await teardown("stopped", why ?? null);
|
|
3244
3318
|
},
|
|
3245
3319
|
getSnapshot: (who) => lastOwner === who ? snap : idle(),
|
|
3246
3320
|
onEpisode: (cb, who) => add(episodeCbs, who, cb),
|
|
@@ -3342,7 +3416,7 @@ function bootstrapExpoAdas(opts) {
|
|
|
3342
3416
|
deviceProvider: createDeviceProvider({ reachabilityUrl: opts.reachabilityUrl })
|
|
3343
3417
|
});
|
|
3344
3418
|
for (const plugin of opts.nativePlugins ?? []) {
|
|
3345
|
-
for (const id of plugin.ids) (0,
|
|
3419
|
+
for (const id of plugin.ids) (0, import_plugin_runtime4.registerNativePlugin)(id, plugin.resolver);
|
|
3346
3420
|
}
|
|
3347
3421
|
const relay = opts.urls.relay;
|
|
3348
3422
|
(0, import_ui2.setPluginWebViewExtraHosts)(() => relay ? [relay()] : []);
|
|
@@ -3356,11 +3430,11 @@ function bootstrapExpoAdas(opts) {
|
|
|
3356
3430
|
const onReach = opts.onReachabilityChange;
|
|
3357
3431
|
(0, import_core3.setAcsReachabilityReporter)({ up: () => onReach(true), down: () => onReach(false) });
|
|
3358
3432
|
}
|
|
3359
|
-
(0,
|
|
3433
|
+
(0, import_plugin_runtime4.setDeviceStateProvider)(
|
|
3360
3434
|
createDeviceState({ connectivity: connectivity_exports, location: location_exports })
|
|
3361
3435
|
);
|
|
3362
|
-
(0,
|
|
3363
|
-
(0,
|
|
3436
|
+
(0, import_plugin_runtime4.setAiLiveProvider)(createAiLiveProvider());
|
|
3437
|
+
(0, import_plugin_runtime4.registerPlatformDeviceTools)();
|
|
3364
3438
|
(0, import_ui2.setUIActionNavigator)(opts.navigateToPlugin);
|
|
3365
3439
|
(0, import_core3.initAdas)({
|
|
3366
3440
|
coreUrl: opts.urls.core,
|