web-sdk-pp-detection 0.1.0 → 0.1.1

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.ts CHANGED
@@ -607,7 +607,7 @@ declare class IndexedDBModelCache implements ModelCache {
607
607
  declare global {
608
608
  var __PPDETECTION_SCRIPT_URL__: string | undefined;
609
609
  }
610
- declare const CURRENT_SDK_VERSION = "0.1.0";
610
+ declare const CURRENT_SDK_VERSION = "0.1.1";
611
611
 
612
612
  declare function probePPDetectionCapabilities(options?: CapabilityProbeOptions): DetectionCapabilities;
613
613
 
package/dist/index.js CHANGED
@@ -1687,14 +1687,15 @@ function now3() {
1687
1687
  function mapError(error, phase) {
1688
1688
  if (error instanceof PPDetectionError) return error;
1689
1689
  const message = error instanceof Error ? error.message : String(error);
1690
+ const details = { phase, causeMessage: message };
1690
1691
  if (/abort|cancel/i.test(message))
1691
- return new PPDetectionError("ABORTED", "\u63A8\u7406\u5DF2\u53D6\u6D88", { phase }, { cause: error });
1692
+ return new PPDetectionError("ABORTED", "\u63A8\u7406\u5DF2\u53D6\u6D88", details, { cause: error });
1692
1693
  if (/memory|out.of.memory|allocation/i.test(message))
1693
- return new PPDetectionError("OUT_OF_MEMORY", "\u8FD0\u884C\u65F6\u5185\u5B58\u4E0D\u8DB3", { phase }, { cause: error });
1694
+ return new PPDetectionError("OUT_OF_MEMORY", "\u8FD0\u884C\u65F6\u5185\u5B58\u4E0D\u8DB3", details, { cause: error });
1694
1695
  return new PPDetectionError(
1695
1696
  phase === "create" ? "SESSION_CREATE_FAILED" : "INFERENCE_FAILED",
1696
1697
  phase === "create" ? "\u521B\u5EFA ONNX Runtime \u4F1A\u8BDD\u5931\u8D25" : "ONNX Runtime \u63A8\u7406\u5931\u8D25",
1697
- { phase },
1698
+ details,
1698
1699
  { cause: error }
1699
1700
  );
1700
1701
  }
@@ -1852,14 +1853,13 @@ function probeCapabilities(options = {}) {
1852
1853
  function fail(code, message, details) {
1853
1854
  throw new PPDetectionError(code, message, details);
1854
1855
  }
1855
- function candidatesForBackend(requested, capabilities, allowFallback) {
1856
+ function candidatesForBackend(requested, capabilities) {
1856
1857
  if (requested === "wasm") return ["wasm"];
1857
1858
  if (requested === "webgpu")
1858
1859
  return capabilities.webgpu ? ["webgpu"] : fail("CAPABILITY_UNSUPPORTED", "\u8BF7\u6C42\u7684 webgpu \u4E0D\u53EF\u7528", { requestedBackend: requested });
1859
1860
  const available = [];
1860
1861
  if (capabilities.webgpu) available.push("webgpu");
1861
1862
  available.push("wasm");
1862
- if (!allowFallback) return available.slice(0, 1);
1863
1863
  return available;
1864
1864
  }
1865
1865
  function selectExecutionPlan(options, capabilities, manifest) {
@@ -1877,19 +1877,18 @@ function selectExecutionPlan(options, capabilities, manifest) {
1877
1877
  requestedPrecision
1878
1878
  });
1879
1879
  }
1880
- const candidates = candidatesForBackend(
1881
- requestedBackend,
1882
- capabilities,
1883
- options.allowFallback === true
1884
- ).filter((backend) => variant3.backends.includes(backend));
1885
- if (candidates.length === 0) {
1880
+ const candidates = candidatesForBackend(requestedBackend, capabilities).filter(
1881
+ (backend) => variant3.backends.includes(backend)
1882
+ );
1883
+ const selectedCandidates = options.allowFallback === true ? candidates : candidates.slice(0, 1);
1884
+ if (selectedCandidates.length === 0) {
1886
1885
  fail("CAPABILITY_UNSUPPORTED", "\u6CA1\u6709\u4E0E\u6A21\u578B\u53D8\u4F53\u5339\u914D\u7684\u53EF\u7528\u540E\u7AEF", {
1887
1886
  requestedBackend,
1888
1887
  requestedPrecision,
1889
1888
  availableBackends: variant3.backends
1890
1889
  });
1891
1890
  }
1892
- const actualBackend = candidates[0];
1891
+ const actualBackend = selectedCandidates[0];
1893
1892
  return {
1894
1893
  variantId: variant3.id,
1895
1894
  requestedBackend,
@@ -1897,7 +1896,7 @@ function selectExecutionPlan(options, capabilities, manifest) {
1897
1896
  requestedPrecision,
1898
1897
  actualPrecision: variant3.precision,
1899
1898
  executionMode,
1900
- candidates: candidates.map((backend) => ({
1899
+ candidates: selectedCandidates.map((backend) => ({
1901
1900
  variantId: variant3.id,
1902
1901
  backend,
1903
1902
  precision: variant3.precision,
@@ -2052,7 +2051,7 @@ var WorkerBridge = class {
2052
2051
  };
2053
2052
 
2054
2053
  // src/index.ts
2055
- var CURRENT_SDK_VERSION = "0.1.0";
2054
+ var CURRENT_SDK_VERSION = "0.1.1";
2056
2055
  function probePPDetectionCapabilities(options = {}) {
2057
2056
  return probeCapabilities(options);
2058
2057
  }
@@ -2178,7 +2177,6 @@ async function createPPDetection(options = {}) {
2178
2177
  cache: options.cache === false ? false : options.cache === "memory" ? "memory" : void 0
2179
2178
  });
2180
2179
  let executor;
2181
- let activeBridge;
2182
2180
  try {
2183
2181
  const loadStartedAt = now4();
2184
2182
  options.onProgress?.({ phase: "model", status: "start" });
@@ -2211,29 +2209,16 @@ async function createPPDetection(options = {}) {
2211
2209
  }
2212
2210
  options.onProgress?.({ phase: "model", status: "complete" });
2213
2211
  const fallbacks = [];
2214
- let selectedPlan = plan;
2215
- let sessionMs = 0;
2216
- for (const candidate of plan.candidates) {
2217
- const candidatePlan = {
2218
- ...plan,
2219
- variantId: candidate.variantId,
2220
- actualBackend: candidate.backend,
2221
- actualPrecision: candidate.precision,
2222
- executionMode: candidate.executionMode,
2223
- candidates: [candidate]
2224
- };
2212
+ const createExecutorForPlan = async (candidatePlan) => {
2225
2213
  options.onProgress?.({ phase: "session", status: "start" });
2214
+ let bridge;
2226
2215
  try {
2227
- if (candidate.executionMode === "worker") {
2216
+ if (candidatePlan.executionMode === "worker") {
2228
2217
  if (typeof Worker !== "function")
2229
2218
  throw new PPDetectionError("CAPABILITY_UNSUPPORTED", "\u5F53\u524D\u73AF\u5883\u4E0D\u652F\u6301 Worker");
2230
- const worker = new Worker(workerUrl(), {
2231
- type: "module"
2232
- });
2233
- const bridge = new WorkerBridge(worker);
2234
- activeBridge = bridge;
2235
- const workerModelBytes = modelBytes.slice(0);
2236
- await bridge.load(workerModelBytes, candidatePlan, {
2219
+ const worker = new Worker(workerUrl(), { type: "module" });
2220
+ bridge = new WorkerBridge(worker);
2221
+ await bridge.load(modelBytes.slice(0), candidatePlan, {
2237
2222
  onProgress: (event) => options.onProgress?.({
2238
2223
  phase: "session",
2239
2224
  status: event.status
@@ -2243,35 +2228,65 @@ async function createPPDetection(options = {}) {
2243
2228
  numThreads: options.ort?.wasm?.numThreads
2244
2229
  }
2245
2230
  });
2246
- executor = {
2247
- run(input, signal) {
2248
- return bridge.run(
2249
- { [input.inputName]: { data: input.data, dims: input.dims } },
2250
- { signal }
2251
- );
2252
- },
2253
- dispose: () => bridge.dispose()
2254
- };
2255
- activeBridge = void 0;
2256
- } else {
2257
- const session = await createOrtSession(modelBytes, candidatePlan, {
2258
- ort: options.ort?.module,
2259
- wasmPaths: options.ort?.wasm?.paths,
2260
- numThreads: options.ort?.wasm?.numThreads
2261
- });
2262
- sessionMs = session.sessionMs;
2263
- executor = {
2231
+ const activeBridge = bridge;
2232
+ options.onProgress?.({ phase: "session", status: "complete" });
2233
+ return {
2264
2234
  run(input, signal) {
2265
- return session.run(
2235
+ return activeBridge.run(
2266
2236
  { [input.inputName]: { data: input.data, dims: input.dims } },
2267
2237
  { signal }
2268
2238
  );
2269
2239
  },
2270
- dispose: () => session.dispose()
2240
+ dispose: () => activeBridge.dispose()
2271
2241
  };
2272
2242
  }
2273
- selectedPlan = candidatePlan;
2243
+ const session = await createOrtSession(modelBytes, candidatePlan, {
2244
+ ort: options.ort?.module,
2245
+ wasmPaths: options.ort?.wasm?.paths,
2246
+ numThreads: options.ort?.wasm?.numThreads
2247
+ });
2248
+ sessionMs = session.sessionMs;
2274
2249
  options.onProgress?.({ phase: "session", status: "complete" });
2250
+ return {
2251
+ run(input, signal) {
2252
+ return session.run(
2253
+ { [input.inputName]: { data: input.data, dims: input.dims } },
2254
+ { signal }
2255
+ );
2256
+ },
2257
+ dispose: () => session.dispose()
2258
+ };
2259
+ } catch (error) {
2260
+ try {
2261
+ await bridge?.dispose();
2262
+ } catch {
2263
+ }
2264
+ if (error instanceof PPDetectionError) throw error;
2265
+ const message = error instanceof Error ? error.message : String(error);
2266
+ throw new PPDetectionError(
2267
+ "SESSION_CREATE_FAILED",
2268
+ "\u521B\u5EFA ONNX Runtime \u4F1A\u8BDD\u5931\u8D25",
2269
+ { phase: "create", causeMessage: message },
2270
+ { cause: error }
2271
+ );
2272
+ }
2273
+ };
2274
+ let selectedPlan = plan;
2275
+ let sessionMs = 0;
2276
+ let selectedCandidateIndex = -1;
2277
+ for (const [candidateIndex, candidate] of plan.candidates.entries()) {
2278
+ const candidatePlan = {
2279
+ ...plan,
2280
+ variantId: candidate.variantId,
2281
+ actualBackend: candidate.backend,
2282
+ actualPrecision: candidate.precision,
2283
+ executionMode: candidate.executionMode,
2284
+ candidates: [candidate]
2285
+ };
2286
+ try {
2287
+ executor = await createExecutorForPlan(candidatePlan);
2288
+ selectedPlan = candidatePlan;
2289
+ selectedCandidateIndex = candidateIndex;
2275
2290
  break;
2276
2291
  } catch (error) {
2277
2292
  const mapped = error instanceof PPDetectionError ? error : new PPDetectionError("SESSION_CREATE_FAILED", String(error));
@@ -2281,11 +2296,6 @@ async function createPPDetection(options = {}) {
2281
2296
  } catch {
2282
2297
  }
2283
2298
  executor = void 0;
2284
- try {
2285
- await activeBridge?.dispose();
2286
- } catch {
2287
- }
2288
- activeBridge = void 0;
2289
2299
  if (!hasNext) {
2290
2300
  throw mapped;
2291
2301
  }
@@ -2303,22 +2313,67 @@ async function createPPDetection(options = {}) {
2303
2313
  }
2304
2314
  }
2305
2315
  if (!executor) throw new PPDetectionError("SESSION_CREATE_FAILED", "\u65E0\u6CD5\u521B\u5EFA\u68C0\u6D4B Session");
2306
- const loadedExecutor = executor;
2316
+ const runtime = {
2317
+ requestedBackend: options.backend ?? "auto",
2318
+ backend: selectedPlan.actualBackend,
2319
+ precision: selectedPlan.actualPrecision,
2320
+ mode: selectedPlan.executionMode,
2321
+ fallbacks,
2322
+ capabilities
2323
+ };
2324
+ let activeExecutor = executor;
2325
+ const fallbackExecutor = {
2326
+ async run(input, signal) {
2327
+ try {
2328
+ return await activeExecutor.run(input, signal);
2329
+ } catch (error) {
2330
+ if (options.allowFallback !== true || selectedCandidateIndex < 0 || selectedCandidateIndex >= plan.candidates.length - 1) {
2331
+ throw error;
2332
+ }
2333
+ const failedCandidate = plan.candidates[selectedCandidateIndex];
2334
+ const mapped = error instanceof PPDetectionError ? error : new PPDetectionError("INFERENCE_FAILED", String(error), {}, { cause: error });
2335
+ if (mapped.code === "ABORTED") throw mapped;
2336
+ const nextCandidate = plan.candidates[selectedCandidateIndex + 1];
2337
+ const nextPlan = {
2338
+ ...plan,
2339
+ variantId: nextCandidate.variantId,
2340
+ actualBackend: nextCandidate.backend,
2341
+ actualPrecision: nextCandidate.precision,
2342
+ executionMode: nextCandidate.executionMode,
2343
+ candidates: [nextCandidate]
2344
+ };
2345
+ await activeExecutor.dispose();
2346
+ const nextExecutor = await createExecutorForPlan(nextPlan);
2347
+ activeExecutor = nextExecutor;
2348
+ selectedCandidateIndex += 1;
2349
+ selectedPlan = nextPlan;
2350
+ runtime.backend = nextPlan.actualBackend;
2351
+ runtime.precision = nextPlan.actualPrecision;
2352
+ runtime.mode = nextPlan.executionMode;
2353
+ const fallback = {
2354
+ cause: mapped.cause ?? mapped,
2355
+ code: mapped.code,
2356
+ message: mapped.message,
2357
+ precision: failedCandidate.precision,
2358
+ provider: failedCandidate.backend,
2359
+ stage: "inference",
2360
+ variantId: failedCandidate.variantId
2361
+ };
2362
+ fallbacks.push(fallback);
2363
+ options.onProgress?.({ phase: "fallback", status: "complete", fallback });
2364
+ return activeExecutor.run(input, signal);
2365
+ }
2366
+ },
2367
+ dispose: () => activeExecutor.dispose()
2368
+ };
2307
2369
  loadTimings = { ...loadTimings, sessionMs, totalMs: now4() - loadStartedAt };
2308
2370
  const detector = new PPDetectionDetectorImplementation({
2309
2371
  capabilities,
2310
2372
  manifest: runtimeManifest,
2311
2373
  model: modelInfo(runtimeManifest, variant3.id, actualSource),
2312
- runtime: {
2313
- requestedBackend: options.backend ?? "auto",
2314
- backend: selectedPlan.actualBackend,
2315
- precision: selectedPlan.actualPrecision,
2316
- mode: selectedPlan.executionMode,
2317
- fallbacks,
2318
- capabilities
2319
- },
2374
+ runtime,
2320
2375
  loadTimings,
2321
- loadExecutor: () => Promise.resolve(loadedExecutor),
2376
+ loadExecutor: () => Promise.resolve(fallbackExecutor),
2322
2377
  onProgress: options.onProgress,
2323
2378
  clearCurrentModelCache: () => modelManager.clearCurrentModelCache(),
2324
2379
  clearAllCache: () => modelManager.clearAllCache(),
@@ -2333,10 +2388,6 @@ async function createPPDetection(options = {}) {
2333
2388
  await executor?.dispose();
2334
2389
  } catch {
2335
2390
  }
2336
- try {
2337
- await activeBridge?.dispose();
2338
- } catch {
2339
- }
2340
2391
  try {
2341
2392
  await modelManager.dispose();
2342
2393
  } catch {