@camstack/server 1.2.393 → 1.2.394

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.
@@ -61,6 +61,12 @@ under [Non-commercial models](#non-commercial-models).
61
61
  https://github.com/ShiqiYu/libfacedetection.train.
62
62
  Trained on WIDER FACE, whose images are CC BY-NC-ND.
63
63
  - **AuraFace v1** — fal.ai, Apache-2.0. https://huggingface.co/fal/AuraFace-v1
64
+ - **SigLIP 2** — © Google LLC, Apache-2.0 (`Apache-2.0.txt`).
65
+ https://huggingface.co/google/siglip2-base-patch16-224 ·
66
+ https://github.com/google-research/big_vision. CamStack's SigLIP 2 files are
67
+ modified: the vision input scaling `2x - 1` is baked into the graph, the text
68
+ graph slices its input to the model's 64 positions, the tokenizer lower-cases,
69
+ and the towers are converted to ONNX, OpenVINO IR and CoreML FP16.
64
70
  - **EasyOCR** — JaidedAI, Apache-2.0. https://github.com/JaidedAI/EasyOCR
65
71
  - **U²-Net** — Xuebin Qin et al., Apache-2.0. https://github.com/xuebinqin/U-2-Net
66
72
  - **YAMNet** — © Google LLC, Apache-2.0.
@@ -202,6 +208,8 @@ commercial use**:
202
208
  | --- | --- | --- | --- | --- | --- |
203
209
  | `mobileclip-s1`, `mobileclip-s2` (image) | Apple `ml-mobileclip` | MIT / **Apple Machine Learning Research Model License** | per Apple | Model Derivative: converted to OpenVINO IR and CoreML FP16 | Mirror `clip/mobileclip-s1`, `clip/mobileclip-s2` |
204
210
  | `mobileclip-s1-text`, `mobileclip-s2-text` | Apple `ml-mobileclip`, with the CLIP tokenizer | MIT / **Apple Machine Learning Research Model License** | per Apple | Model Derivative: quantised to INT8 ONNX and converted to OpenVINO IR | Mirror `clip/mobileclip-s1`, `clip/mobileclip-s2` |
211
+ | `siglip2-b16-224` (image) | Google SigLIP 2 base patch16-224 (`google/siglip2-base-patch16-224`) | Apache-2.0 / Apache-2.0 | WebLI (Google internal, not released) | input scaling `y = 2x - 1` baked ahead of the patch embedding; converted to OpenVINO IR and CoreML FP16 (an FP32 ONNX is hosted as the verification reference) (`scripts/build-siglip2-model.py`) | Mirror `clip/siglip2` |
212
+ | `siglip2-b16-224-text` | Google SigLIP 2 base patch16-224, with its Gemma tokenizer | Apache-2.0 / Apache-2.0 | WebLI (Google internal, not released) | input sliced to the model's 64 positions in the graph; ONNX weights FP16, OpenVINO IR and CoreML FP16; a `Lowercase` normalizer prepended to the tokenizer | Mirror `clip/siglip2` |
205
213
 
206
214
  ### Segmentation
207
215
 
@@ -319,8 +319,32 @@ function unreachableSourceRow(addonId, reason) {
319
319
  availability: { state: 'unreachable', reason },
320
320
  };
321
321
  }
322
+ /**
323
+ * The fan-out methods whose failure BECOMES a row rather than an absence.
324
+ *
325
+ * `listSources` is the D554 convention for every device-collection cap. A cap
326
+ * whose own listing is what a surface claims ABSENCE from adds its method here
327
+ * with the row its schema declares for it: `device-extension.listSlots`
328
+ * (D648), because "this camera has no extensions" read off a provider that
329
+ * threw is exactly the D315 lie — and it must hold on a one-owner device too,
330
+ * which is why {@link failureRowFor} is consulted on the single-source path as
331
+ * well (for these methods only; `listSources` keeps its one-source verbatim
332
+ * behaviour, D554 decision 6).
333
+ */
334
+ const CAP_FAILURE_ROWS = {
335
+ [types_1.deviceExtensionCapability.name]: {
336
+ [types_1.EXTENSION_SLOT_LISTING_METHOD]: types_1.unreachableExtensionSlotRow,
337
+ },
338
+ };
339
+ function failureRowFor(capName, method) {
340
+ const own = CAP_FAILURE_ROWS[capName]?.[method];
341
+ if (own !== undefined)
342
+ return own;
343
+ return method === exports.SOURCE_LISTING_METHOD ? unreachableSourceRow : null;
344
+ }
322
345
  async function fanOut(sources, method, input, capName, deviceId, logger) {
323
346
  const isSourceListing = method === exports.SOURCE_LISTING_METHOD;
347
+ const failureRow = failureRowFor(capName, method);
324
348
  const settled = await Promise.allSettled(sources.map(async (source) => await callSource(source, method, input, capName, deviceId)));
325
349
  const rows = [];
326
350
  for (const [index, result] of settled.entries()) {
@@ -335,8 +359,8 @@ async function fanOut(sources, method, input, capName, deviceId, logger) {
335
359
  tags: { deviceId, addonId: source.addonId },
336
360
  meta: { capability: capName, method, reason },
337
361
  });
338
- if (isSourceListing)
339
- rows.push(unreachableSourceRow(source.addonId, reason));
362
+ if (failureRow !== null)
363
+ rows.push(failureRow(source.addonId, reason));
340
364
  continue;
341
365
  }
342
366
  if (!Array.isArray(result.value)) {
@@ -547,6 +571,12 @@ function requireDeviceCollection(registry, capName, logger) {
547
571
  // before this dispatcher existed (D554 decision 6). Only the
548
572
  // listing rows are finished, and only to carry the addon stamp.
549
573
  if (sources.length === 1 && first !== undefined) {
574
+ if (CAP_FAILURE_ROWS[capName]?.[prop] !== undefined) {
575
+ // A cap-declared failure row holds on a ONE-owner device too:
576
+ // the fan-out's isolation is what turns a throw into a row, so
577
+ // the lone source takes the fan-out.
578
+ return await fanOut(sources, prop, input, capName, deviceId, logger);
579
+ }
550
580
  const answered = await callSource(first, prop, input, capName, deviceId);
551
581
  if (!Array.isArray(answered))
552
582
  return answered;
@@ -2,7 +2,7 @@
2
2
  // AUTO-GENERATED by scripts/generate-cap-mounts.ts — DO NOT EDIT
3
3
  // Re-run: npx tsx scripts/generate-cap-mounts.ts
4
4
  //
5
- // Mounted: 157 Skipped (legacy): 3
5
+ // Mounted: 158 Skipped (legacy): 3
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
7
  exports.LEGACY_SHAPE_SKIP = void 0;
8
8
  exports.mountAllCaps = mountAllCaps;
@@ -185,6 +185,7 @@ function mountAllCaps(services) {
185
185
  listExposedDevices: (0, cap_mount_helpers_js_1.concatCollection)(providers, 'listExposedDevices'),
186
186
  };
187
187
  }, remoteCapProxy),
188
+ deviceExtension: (0, generated_cap_routers_js_1.createCapRouter_deviceExtension)((_ctx) => (0, device_collection_dispatch_js_1.requireDeviceCollection)(reg, 'device-extension'), remoteCapProxy),
188
189
  deviceManager: (0, generated_cap_routers_js_1.createCapRouter_deviceManager)((_ctx) => reg?.getSingleton('device-manager') ?? null, remoteCapProxy),
189
190
  deviceOps: (0, generated_cap_routers_js_1.createCapRouter_deviceOps)((_ctx) => (0, cap_mount_helpers_js_1.requireDeviceScoped)(reg, 'device-ops'), remoteCapProxy),
190
191
  deviceProvider: (0, generated_cap_routers_js_1.createCapRouter_deviceProvider)((_ctx, addonId) => {