@ateam-ai-mobile/plugin-runtime 0.1.10 → 0.1.12

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.
@@ -2181,7 +2181,58 @@ var _provider = {};
2181
2181
  function setDeviceStateProvider(state) {
2182
2182
  _provider = state || {};
2183
2183
  }
2184
- function gateDeviceState(declared) {
2184
+ var holds = /* @__PURE__ */ new Map();
2185
+ function holdersOf(domain) {
2186
+ let s = holds.get(domain);
2187
+ if (!s) {
2188
+ s = /* @__PURE__ */ new Set();
2189
+ holds.set(domain, s);
2190
+ }
2191
+ return s;
2192
+ }
2193
+ function withHolds(domain, engine, holder) {
2194
+ if (!engine || typeof engine.start !== "function" || typeof engine.stop !== "function") return engine;
2195
+ return Object.assign(Object.create(engine), {
2196
+ async start(options) {
2197
+ const s = holdersOf(domain);
2198
+ const fresh = !s.has(holder);
2199
+ s.add(holder);
2200
+ let result;
2201
+ try {
2202
+ result = await engine.start(options);
2203
+ } catch (e) {
2204
+ if (fresh && s.delete(holder) && s.size === 0) await stopQuietly(engine);
2205
+ throw e;
2206
+ }
2207
+ if (!s.has(holder) && s.size === 0) await stopQuietly(engine);
2208
+ return result;
2209
+ },
2210
+ async stop() {
2211
+ const s = holdersOf(domain);
2212
+ if (!s.has(holder)) return;
2213
+ s.delete(holder);
2214
+ if (s.size === 0) await engine.stop();
2215
+ }
2216
+ });
2217
+ }
2218
+ async function stopQuietly(engine) {
2219
+ try {
2220
+ await engine?.stop?.();
2221
+ } catch {
2222
+ }
2223
+ }
2224
+ async function releaseDeviceStateHolds(holder, keep = []) {
2225
+ for (const [domain, s] of holds) {
2226
+ if (keep.includes(domain)) continue;
2227
+ if (!s.delete(holder) || s.size > 0) continue;
2228
+ await stopQuietly(_provider[domain]);
2229
+ }
2230
+ }
2231
+ function deviceStateHolders(domain) {
2232
+ return [...holds.get(domain) || []];
2233
+ }
2234
+ function gateDeviceState(declared, holder) {
2235
+ if (!holder) throw new Error("gateDeviceState: a holder is required \u2014 who would release a session it starts?");
2185
2236
  const allowed = new Set(declared || []);
2186
2237
  const out = {};
2187
2238
  for (const domain of ALL_DOMAINS) {
@@ -2193,7 +2244,7 @@ function gateDeviceState(declared) {
2193
2244
  continue;
2194
2245
  }
2195
2246
  const engine = _provider[domain];
2196
- out[domain] = engine ?? deniedDomain(
2247
+ out[domain] = engine ? withHolds(domain, engine, holder) : deniedDomain(
2197
2248
  domain,
2198
2249
  "no engine in this build \u2014 the native side does not exist yet. See docs/DEVICE_API_STATUS.md."
2199
2250
  );
@@ -2228,7 +2279,9 @@ function defaultContext(pluginId, capabilities, stateDomains) {
2228
2279
  return {
2229
2280
  bridge: createNativeBridge(pluginId),
2230
2281
  native: gatePluginNative(getPluginNative(), capabilities, pluginId),
2231
- deviceState: gateDeviceState(stateDomains)
2282
+ // A tool call has no lifetime of its own: what it starts is held for the
2283
+ // plugin's tools, and released when the plugin's tools are unregistered.
2284
+ deviceState: gateDeviceState(stateDomains, toolHolder(pluginId))
2232
2285
  };
2233
2286
  }
2234
2287
  function registerDeviceTools(pluginId, tools, capabilities, stateDomains) {
@@ -2253,10 +2306,14 @@ function registerDeviceTools(pluginId, tools, capabilities, stateDomains) {
2253
2306
  }
2254
2307
  return accepted;
2255
2308
  }
2309
+ function toolHolder(pluginId) {
2310
+ return `tools:${pluginId}`;
2311
+ }
2256
2312
  function unregisterDeviceTools(pluginId) {
2257
2313
  for (const [name, entry] of registry.entries()) {
2258
2314
  if (entry.pluginId === pluginId) registry.delete(name);
2259
2315
  }
2316
+ void releaseDeviceStateHolds(toolHolder(pluginId));
2260
2317
  }
2261
2318
  function hasDeviceTool(name, pluginId) {
2262
2319
  const entry = registry.get(name);
@@ -2994,10 +3051,10 @@ function resolvePluginGrants(src) {
2994
3051
  const stateDomains = trusted?.stateDomains ? [...trusted.stateDomains] : void 0;
2995
3052
  return { capabilities: mergeCaps(trusted), stateDomains };
2996
3053
  }
2997
- function resolvePluginRuntimeProps(src) {
3054
+ function resolvePluginRuntimeProps(src, holder = src.pluginId) {
2998
3055
  const { capabilities, stateDomains } = resolvePluginGrants(src);
2999
3056
  const native = gatePluginNative(getPluginNative(), capabilities, src.pluginId);
3000
- const deviceState = gateDeviceState(stateDomains);
3057
+ const deviceState = gateDeviceState(stateDomains, holder);
3001
3058
  const voice = gateVoice(!!capabilities?.voice, src.pluginId);
3002
3059
  return { device: native, native, deviceState, voice };
3003
3060
  }
@@ -3149,6 +3206,8 @@ export {
3149
3206
  useApi,
3150
3207
  PluginSDK,
3151
3208
  setDeviceStateProvider,
3209
+ releaseDeviceStateHolds,
3210
+ deviceStateHolders,
3152
3211
  gateDeviceState,
3153
3212
  implementedStateDomains,
3154
3213
  setVoiceProvider,
@@ -3188,4 +3247,4 @@ export {
3188
3247
  ensureDeviceToolsLoaded,
3189
3248
  resetDeviceToolLoader
3190
3249
  };
3191
- //# sourceMappingURL=chunk-SICFDA5K.mjs.map
3250
+ //# sourceMappingURL=chunk-P43IKNZE.mjs.map