@camstack/system 1.1.49 → 1.1.50

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.
Files changed (47) hide show
  1. package/dist/addon-runner.js +2 -2
  2. package/dist/addon-runner.mjs +2 -2
  3. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
  4. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
  5. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
  6. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
  7. package/dist/builtins/alerts/alerts.addon.js +1 -1
  8. package/dist/builtins/alerts/alerts.addon.mjs +1 -1
  9. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +1 -1
  10. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +1 -1
  11. package/dist/builtins/console-logging/index.js +1 -1
  12. package/dist/builtins/console-logging/index.mjs +1 -1
  13. package/dist/builtins/device-manager/device-manager.addon.js +1 -1
  14. package/dist/builtins/device-manager/device-manager.addon.mjs +1 -1
  15. package/dist/builtins/hub-forwarder/index.js +1 -1
  16. package/dist/builtins/hub-forwarder/index.mjs +1 -1
  17. package/dist/builtins/local-auth/local-auth.addon.js +1 -1
  18. package/dist/builtins/local-auth/local-auth.addon.mjs +1 -1
  19. package/dist/builtins/local-network/local-network.addon.js +1 -1
  20. package/dist/builtins/local-network/local-network.addon.mjs +1 -1
  21. package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
  22. package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
  23. package/dist/builtins/platform-probe/coral-accelerators.d.ts +22 -0
  24. package/dist/builtins/platform-probe/index.js +67 -2
  25. package/dist/builtins/platform-probe/index.mjs +67 -2
  26. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
  27. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
  28. package/dist/builtins/snapshot/index.js +1 -1
  29. package/dist/builtins/snapshot/index.mjs +1 -1
  30. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
  31. package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
  32. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +1 -1
  33. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +1 -1
  34. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +1 -1
  35. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1 -1
  36. package/dist/builtins/system-config/system-config.addon.js +1 -1
  37. package/dist/builtins/system-config/system-config.addon.mjs +1 -1
  38. package/dist/builtins/winston-logging/index.js +1 -1
  39. package/dist/builtins/winston-logging/index.mjs +1 -1
  40. package/dist/{dist-8phgmJ6b.mjs → dist-CC3E-_3h.mjs} +153 -7
  41. package/dist/{dist-BDV1WKRg.js → dist-CQYo6Zp8.js} +164 -6
  42. package/dist/index.js +5 -3
  43. package/dist/index.mjs +5 -3
  44. package/dist/kernel/hwaccel/hwaccel-resolver.d.ts +2 -0
  45. package/dist/{manifest-python-deps-B09I9ems.mjs → manifest-python-deps-DqATCsK0.mjs} +31 -4
  46. package/dist/{manifest-python-deps-DAA0ULwT.js → manifest-python-deps-Wy8dNJpr.js} +31 -4
  47. package/package.json +1 -1
@@ -1,5 +1,5 @@
1
1
  import { z } from "zod";
2
- //#region ../types/dist/sleep-DkhOVOjW.mjs
2
+ //#region ../types/dist/sleep-_sv7WKkq.mjs
3
3
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
4
4
  EventCategory["SystemBoot"] = "system.boot";
5
5
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -430,6 +430,14 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
430
430
  EventCategory["PipelineAnalyticsDetectionEvent"] = "pipeline-analytics.detection-event";
431
431
  EventCategory["PipelineAnalyticsFrameTracked"] = "pipeline-analytics.frame-tracked";
432
432
  /**
433
+ * Fired by `addon-post-analysis` when a parked (stationary) object appears
434
+ * (a track was promoted to a stationary-registry entry) or departs (the
435
+ * object moved / was removed). Telemetry (D8): lossy, drives a UI refresh of
436
+ * the dedicated "Stationary" section — never the live event feed. Payload:
437
+ * `{ deviceId, entryId, className, phase:'appeared'|'departed', timestamp }`.
438
+ */
439
+ EventCategory["PipelineAnalyticsStationaryChanged"] = "pipeline-analytics.stationary-changed";
440
+ /**
433
441
  * Fired by `addon-post-analysis` whenever a gallery face row changes:
434
442
  * `kind:'buffered'` a new detected face was persisted, `'assigned'` /
435
443
  * `'unassigned'` its identity link changed, `'deleted'` the row was
@@ -2980,6 +2988,15 @@ var ModelCatalogEntrySchema = z.object({
2980
2988
  width: z.number(),
2981
2989
  height: z.number()
2982
2990
  }),
2991
+ /**
2992
+ * Channel count of the model input tensor. Omit ⇒ 3 (RGB), the default for
2993
+ * every detector / classifier / embedder. Set to 1 for a grayscale CTC text
2994
+ * recognizer (EasyOCR VGG plate-OCR: input `[N,1,H,W]`) so the preprocess
2995
+ * feeds a single-channel, EasyOCR-normalized tensor instead of the default
2996
+ * 3-channel RGB one. Threaded through `PoolModelConfig.inputChannels` to the
2997
+ * Python inference pool.
2998
+ */
2999
+ inputChannels: z.number().int().positive().optional(),
2983
3000
  labels: z.array(LabelDefinitionSchema).readonly(),
2984
3001
  inputLayout: z.enum(["nchw", "nhwc"]).optional(),
2985
3002
  inputNormalization: z.enum([
@@ -2989,6 +3006,16 @@ var ModelCatalogEntrySchema = z.object({
2989
3006
  ]).optional(),
2990
3007
  preprocessMode: z.enum(["letterbox", "resize"]).optional(),
2991
3008
  /**
3009
+ * Per-MODEL postprocessor override. Absent ⇒ the step's own
3010
+ * `StepDefinition.postprocessor` applies (the normal case — every model in a
3011
+ * step shares its decode). Set it when a step hosts models with DIFFERENT raw
3012
+ * output layouts under one slot: e.g. object-detection is `'yolo'` by default,
3013
+ * but a Coral SSD MobileNet build emits the `TFLite_Detection_PostProcess`
3014
+ * 4-tensor layout and needs `'ssd'`. Threaded into `PoolModelConfig.postprocessor`
3015
+ * by the engine factory (`modelEntry.postprocessor ?? def.postprocessor`).
3016
+ */
3017
+ postprocessor: z.custom().optional(),
3018
+ /**
2992
3019
  * When true, the executor produces a landmark-aligned crop (similarity warp
2993
3020
  * onto the canonical template) before this step runs, instead of a plain
2994
3021
  * axis-aligned bbox crop. Required for face-recognition embedders (ArcFace):
@@ -7980,7 +8007,8 @@ var EngineProvisioningSchema = z.object({
7980
8007
  runtimeId: z.enum([
7981
8008
  "onnx",
7982
8009
  "openvino",
7983
- "coreml"
8010
+ "coreml",
8011
+ "edgetpu"
7984
8012
  ]).nullable(),
7985
8013
  device: z.string().nullable(),
7986
8014
  state: z.enum([
@@ -10806,6 +10834,36 @@ var ZoneScopeBreakdownSchema = PerScopeBreakdownSchema.extend({
10806
10834
  * with the per-track detail panel and live overlay. */
10807
10835
  trackIds: z.array(z.string()).readonly()
10808
10836
  });
10837
+ /**
10838
+ * A parked ("stationary") object surfaced alongside occupancy — an object that
10839
+ * settled and stopped moving. It is NO LONGER a tracked object (the tracker was
10840
+ * told to forget it so it stops re-spawning tracks/events), but it IS still
10841
+ * physically present, so it keeps counting toward `frame` occupancy and is
10842
+ * listed here so the UI can show it in a dedicated "Stationary" section instead
10843
+ * of flooding the live event feed.
10844
+ */
10845
+ var StationaryObjectSchema = z.object({
10846
+ id: z.string(),
10847
+ className: z.string(),
10848
+ bbox: z.object({
10849
+ x: z.number(),
10850
+ y: z.number(),
10851
+ w: z.number(),
10852
+ h: z.number()
10853
+ }),
10854
+ frameWidth: z.number().int().nonnegative(),
10855
+ frameHeight: z.number().int().nonnegative(),
10856
+ /** When the source track was first seen. */
10857
+ firstSeenAt: z.number().int(),
10858
+ /** When the object was recognised as parked (promotion time). */
10859
+ becameStationaryAt: z.number().int(),
10860
+ /** Last frame a detection confirmed the object is still there. */
10861
+ lastConfirmedAt: z.number().int(),
10862
+ /** Enrichment label carried from the source track (identity / plate). */
10863
+ label: z.string().optional(),
10864
+ /** Native-resolution key-frame media key for the parked object's best image. */
10865
+ keyFrameMediaKey: z.string().optional()
10866
+ });
10809
10867
  var CameraOccupancySnapshotSchema = z.object({
10810
10868
  /** Frame timestamp of the inference result that produced this snapshot. */
10811
10869
  ts: z.number().int(),
@@ -10814,10 +10872,15 @@ var CameraOccupancySnapshotSchema = z.object({
10814
10872
  frameHeight: z.number().int().nonnegative(),
10815
10873
  /** Per-zone breakdown — one entry per defined zone (user + onboard). */
10816
10874
  zones: z.array(ZoneScopeBreakdownSchema).readonly(),
10817
- /** Frame-wide aggregate (everywhere, regardless of zone membership). */
10875
+ /** Frame-wide aggregate (everywhere, regardless of zone membership).
10876
+ * INCLUDES currently-confirmed stationary objects (they are still present). */
10818
10877
  frame: PerScopeBreakdownSchema,
10819
10878
  /** Detections that landed outside every zone. Empty when no zones defined. */
10820
- unzoned: PerScopeBreakdownSchema
10879
+ unzoned: PerScopeBreakdownSchema,
10880
+ /** Parked objects on this camera (additive — absent on legacy snapshots).
10881
+ * Surfaced separately so the UI shows them in a dedicated section rather
10882
+ * than as repeated tracks/events. */
10883
+ stationaryObjects: z.array(StationaryObjectSchema).readonly().optional()
10821
10884
  });
10822
10885
  /**
10823
10886
  * Time-series resolution. The history methods return one bucket per
@@ -12801,6 +12864,64 @@ function looseSchema(schema) {
12801
12864
  const loose = schema.loose;
12802
12865
  return typeof loose === "function" ? loose.call(schema) : schema;
12803
12866
  }
12867
+ /**
12868
+ * Derive a COLLECTION-cap routing `addonId` from a NON-array mutation input
12869
+ * when the caller did NOT supply the top-level `{ addonId }` selector.
12870
+ *
12871
+ * Background: a `scope:'system', mode:'collection'` cap fans its ARRAY methods
12872
+ * (`listTargets`, `listTargetKinds`, …) across every provider, but routes each
12873
+ * single-object method (`send` / CRUD) to ONE provider. The runtime router
12874
+ * strips a TOP-LEVEL `addonId` selector and routes it via
12875
+ * `getProviderByAddonId`; absent that selector it falls through to the FIRST
12876
+ * registered provider — which misroutes (or hard-crashes on a partial provider)
12877
+ * when the target is owned by a DIFFERENT provider. See
12878
+ * `notification-output.cap.ts` (`Target.addonId` / `TargetKind.addonId` are
12879
+ * "stamped by each provider so the concat-fanned catalog stays routable").
12880
+ *
12881
+ * That routing `addonId` is ALREADY carried inside the mutation payload the
12882
+ * caller sends — e.g. `upsertTarget({ target: { …, addonId } })`. This helper
12883
+ * recovers it: it scans the input's DIRECT child object properties (bounded to
12884
+ * one level, first match wins) for a string `addonId`. Mirrors the child-side
12885
+ * `extractArgsAddonId` fallback in `child-cap-dispatch.ts`, which reads a
12886
+ * top-level `addonId` off the raw args; this covers the one-level-nested case
12887
+ * the top-level scan misses.
12888
+ *
12889
+ * Only used for non-array collection methods (array fan-out is never rerouted),
12890
+ * so it can never collapse a catalog aggregation onto a single provider. `null`
12891
+ * / non-object inputs yield `undefined` (fall back to the first provider,
12892
+ * preserving single-provider and id-only-payload back-compat).
12893
+ */
12894
+ function extractNestedAddonId(input) {
12895
+ if (input === null || typeof input !== "object") return void 0;
12896
+ for (const value of Object.values(input)) if (value !== null && typeof value === "object") {
12897
+ const nested = value.addonId;
12898
+ if (typeof nested === "string") return nested;
12899
+ }
12900
+ }
12901
+ /**
12902
+ * True when an OBJECT input schema declares a top-level `addonId` field.
12903
+ *
12904
+ * Such a cap method routes explicitly via the top-level `{ addonId }` selector
12905
+ * (the `llm.generate` / `deleteProfile` posture). The runtime router therefore
12906
+ * MUST NOT also fall back to {@link extractNestedAddonId} for it — that would
12907
+ * let an incidental nested `addonId` (e.g. a key inside a free-form `jsonSchema`
12908
+ * record) hijack routing. Nested recovery is reserved for methods whose input
12909
+ * carries NO top-level selector but embeds the owning `addonId` inside a domain
12910
+ * entity (`upsertTarget({ target: { addonId } })`, `upsertProfile({ profile })`).
12911
+ *
12912
+ * Accepts both Zod 4 (`.shape` / `_def.shape`) and legacy shapes; returns false
12913
+ * for non-object schemas.
12914
+ */
12915
+ function objectInputDeclaresAddonId(schema) {
12916
+ if (schema === null || typeof schema !== "object" && typeof schema !== "function") return false;
12917
+ const direct = schema.shape;
12918
+ const shape = direct !== void 0 && direct !== null ? direct : resolveDefShape(schema._def?.shape);
12919
+ return shape !== void 0 && shape !== null && typeof shape === "object" && Object.prototype.hasOwnProperty.call(shape, "addonId");
12920
+ }
12921
+ /** `_def.shape` may be a thunk (Zod defers object-shape evaluation) or a plain record. */
12922
+ function resolveDefShape(defShape) {
12923
+ return typeof defShape === "function" ? defShape() : defShape;
12924
+ }
12804
12925
  /** Auth level → base-procedure key. `superAdmin` collapses to `admin`. */
12805
12926
  function procedureAuthKey(auth) {
12806
12927
  if (auth === "public") return "public";
@@ -15531,6 +15652,22 @@ var TrackSnapshotSchema = z.object({
15531
15652
  /** MediaStore key; resolve via `getTrackMedia({ trackId })`. */
15532
15653
  mediaKey: z.string()
15533
15654
  });
15655
+ /**
15656
+ * One audio-classification label heard on the track's camera while the
15657
+ * track was alive, aggregated per label. An "episode" is one persisted
15658
+ * audio event (the confident-classification path: score ≥ the device's
15659
+ * `classificationMinScore`, class-change-or-heartbeat coalesced) — NOT
15660
+ * one 32 ms inference chunk, so counts stay human-scaled.
15661
+ */
15662
+ var TrackAudioLabelSchema = z.object({
15663
+ label: z.string(),
15664
+ /** Highest classification score observed across the label's episodes. */
15665
+ peakScore: z.number(),
15666
+ /** Number of coalesced audio-event episodes carrying this label. */
15667
+ count: z.number(),
15668
+ firstAt: z.number(),
15669
+ lastAt: z.number()
15670
+ });
15534
15671
  var TrackSchema = z.object({
15535
15672
  trackId: z.string(),
15536
15673
  deviceId: z.number(),
@@ -15562,7 +15699,11 @@ var TrackSchema = z.object({
15562
15699
  bestEventId: z.string().optional(),
15563
15700
  /** Tag of the importance sub-signal that dominated the score
15564
15701
  * (identity|dwell|proximity|class|confidence|travel|zone). */
15565
- importanceReason: z.string().optional()
15702
+ importanceReason: z.string().optional(),
15703
+ /** Audio-classification labels heard on the camera during the track's
15704
+ * life (score ≥ device `classificationMinScore`), aggregated per label.
15705
+ * Absent on legacy rows / tracks with no confident audio. */
15706
+ audioLabels: z.array(TrackAudioLabelSchema).readonly().optional()
15566
15707
  });
15567
15708
  var BaseEventFields = {
15568
15709
  id: z.string(),
@@ -20139,6 +20280,10 @@ var GpuInfoSchema = z.object({
20139
20280
  memoryMB: z.number().optional()
20140
20281
  });
20141
20282
  var NpuInfoSchema = z.object({ type: z.enum(["apple-ane", "intel-npu"]) });
20283
+ var CoralInfoSchema = z.object({
20284
+ type: z.literal("coral-edgetpu"),
20285
+ bus: z.string().optional()
20286
+ });
20142
20287
  var HardwareInfoSchema = z.object({
20143
20288
  platform: HardwarePlatformSchema,
20144
20289
  arch: HardwareArchSchema,
@@ -20147,7 +20292,8 @@ var HardwareInfoSchema = z.object({
20147
20292
  totalRAM_MB: z.number(),
20148
20293
  availableRAM_MB: z.number(),
20149
20294
  gpu: GpuInfoSchema.nullable(),
20150
- npu: NpuInfoSchema.nullable()
20295
+ npu: NpuInfoSchema.nullable(),
20296
+ coral: CoralInfoSchema.nullable().optional()
20151
20297
  });
20152
20298
  var PlatformScoreSchema = z.object({
20153
20299
  runtime: z.enum(["node", "python"]),
@@ -26172,4 +26318,4 @@ function scoreRuntimes(hw) {
26172
26318
  };
26173
26319
  }
26174
26320
  //#endregion
26175
- export { validateExpressionSource as $, isObjectInput as A, parseStreamParamsFormPatch as B, enumerateItemArrayFields as C, readinessKey as Ct, getByPath as D, filesystemBrowseCapability as E, sleep as Et, logDestinationCapability as F, setByPath as G, procedureAuthKey as H, looseSchema as I, storageCapability as J, settingsStoreCapability as K, metricsProviderCapability as L, kebabToCamel as M, lifecycleJobSchema as N, isArrayOutputSchema as O, localNetworkCapability as P, userManagementCapability as Q, nodePin as R, deviceStatusCapability as S, parseJsonUnknown as St, evaluateLinkExpression as T, scopeKey as Tt, readNodePin as U, platformProbeCapability as V, scoreRuntimes as W, streamQualityLabel as X, storageProviderCapability as Y, toExpressionValue as Z, authProviderCapability as _, emitReadiness as _t, DeviceStatusSchema as a, DeviceFeature as at, deviceManagerCapability as b, isDeviceConfigCap as bt, STREAM_PROFILE_META as c, EventCategory as ct, UserRecordSchema as d, WELL_KNOWN_TAB_MAP as dt, errMsg as et, addonPagesCapability as f, asJsonObject as ft, applyTransform as g, emitDownForOwnedCaps as gt, alertsCapability as h, createEvent as ht, CAP_NAMES_WITH_STATUS as i, DEVICE_STATUS_METHOD as it, isVoidInput as j, isCollectionArrayMethod as k, ScopedTokenSchema as l, ReadinessRegistry as lt, addonWidgetsCapability as m, asString as mt, AlertSchema as n, DATAPLANE_SECRET_HEADER as nt, METHOD_ACCESS_MAP as o, DeviceRole as ot, addonSettingsCapability as p, asNumber as pt, snapshotCapability as q, ApiKeyRecordSchema as r, DEVICE_SETTINGS_CONTRIBUTION_METHODS as rt, RUNTIME_DEFAULTS as s, DeviceType as st, ALL_CAPABILITY_DEFINITIONS as t, BaseAddon as tt, StorageLocationTypeSchema as u, ReadinessTimeoutError as ut, backupCapability as v, expandCapMethods as vt, enumerateSchemaFields as w, resolveCapMount as wt, deviceStateCapability as x, parseJsonObject as xt, buildStreamParamsConfigSchema as y, hydrateSchema as yt, normalizeUnit as z };
26321
+ export { toExpressionValue as $, isCollectionArrayMethod as A, normalizeUnit as B, enumerateItemArrayFields as C, parseJsonObject as Ct, filesystemBrowseCapability as D, scopeKey as Dt, extractNestedAddonId as E, resolveCapMount as Et, localNetworkCapability as F, readNodePin as G, parseStreamParamsFormPatch as H, logDestinationCapability as I, settingsStoreCapability as J, scoreRuntimes as K, looseSchema as L, isVoidInput as M, kebabToCamel as N, getByPath as O, sleep as Ot, lifecycleJobSchema as P, streamQualityLabel as Q, metricsProviderCapability as R, deviceStatusCapability as S, isDeviceConfigCap as St, evaluateLinkExpression as T, readinessKey as Tt, platformProbeCapability as U, objectInputDeclaresAddonId as V, procedureAuthKey as W, storageCapability as X, snapshotCapability as Y, storageProviderCapability as Z, authProviderCapability as _, createEvent as _t, DeviceStatusSchema as a, DEVICE_SETTINGS_CONTRIBUTION_METHODS as at, deviceManagerCapability as b, expandCapMethods as bt, STREAM_PROFILE_META as c, DeviceRole as ct, UserRecordSchema as d, ReadinessRegistry as dt, userManagementCapability as et, addonPagesCapability as f, ReadinessTimeoutError as ft, applyTransform as g, asString as gt, alertsCapability as h, asNumber as ht, CAP_NAMES_WITH_STATUS as i, DATAPLANE_SECRET_HEADER as it, isObjectInput as j, isArrayOutputSchema as k, ScopedTokenSchema as l, DeviceType as lt, addonWidgetsCapability as m, asJsonObject as mt, AlertSchema as n, errMsg as nt, METHOD_ACCESS_MAP as o, DEVICE_STATUS_METHOD as ot, addonSettingsCapability as p, WELL_KNOWN_TAB_MAP as pt, setByPath as q, ApiKeyRecordSchema as r, BaseAddon as rt, RUNTIME_DEFAULTS as s, DeviceFeature as st, ALL_CAPABILITY_DEFINITIONS as t, validateExpressionSource as tt, StorageLocationTypeSchema as u, EventCategory as ut, backupCapability as v, emitDownForOwnedCaps as vt, enumerateSchemaFields as w, parseJsonUnknown as wt, deviceStateCapability as x, hydrateSchema as xt, buildStreamParamsConfigSchema as y, emitReadiness as yt, nodePin as z };
@@ -1,5 +1,5 @@
1
1
  let zod = require("zod");
2
- //#region ../types/dist/sleep-DkhOVOjW.mjs
2
+ //#region ../types/dist/sleep-_sv7WKkq.mjs
3
3
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
4
4
  EventCategory["SystemBoot"] = "system.boot";
5
5
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -430,6 +430,14 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
430
430
  EventCategory["PipelineAnalyticsDetectionEvent"] = "pipeline-analytics.detection-event";
431
431
  EventCategory["PipelineAnalyticsFrameTracked"] = "pipeline-analytics.frame-tracked";
432
432
  /**
433
+ * Fired by `addon-post-analysis` when a parked (stationary) object appears
434
+ * (a track was promoted to a stationary-registry entry) or departs (the
435
+ * object moved / was removed). Telemetry (D8): lossy, drives a UI refresh of
436
+ * the dedicated "Stationary" section — never the live event feed. Payload:
437
+ * `{ deviceId, entryId, className, phase:'appeared'|'departed', timestamp }`.
438
+ */
439
+ EventCategory["PipelineAnalyticsStationaryChanged"] = "pipeline-analytics.stationary-changed";
440
+ /**
433
441
  * Fired by `addon-post-analysis` whenever a gallery face row changes:
434
442
  * `kind:'buffered'` a new detected face was persisted, `'assigned'` /
435
443
  * `'unassigned'` its identity link changed, `'deleted'` the row was
@@ -2980,6 +2988,15 @@ var ModelCatalogEntrySchema = zod.z.object({
2980
2988
  width: zod.z.number(),
2981
2989
  height: zod.z.number()
2982
2990
  }),
2991
+ /**
2992
+ * Channel count of the model input tensor. Omit ⇒ 3 (RGB), the default for
2993
+ * every detector / classifier / embedder. Set to 1 for a grayscale CTC text
2994
+ * recognizer (EasyOCR VGG plate-OCR: input `[N,1,H,W]`) so the preprocess
2995
+ * feeds a single-channel, EasyOCR-normalized tensor instead of the default
2996
+ * 3-channel RGB one. Threaded through `PoolModelConfig.inputChannels` to the
2997
+ * Python inference pool.
2998
+ */
2999
+ inputChannels: zod.z.number().int().positive().optional(),
2983
3000
  labels: zod.z.array(LabelDefinitionSchema).readonly(),
2984
3001
  inputLayout: zod.z.enum(["nchw", "nhwc"]).optional(),
2985
3002
  inputNormalization: zod.z.enum([
@@ -2989,6 +3006,16 @@ var ModelCatalogEntrySchema = zod.z.object({
2989
3006
  ]).optional(),
2990
3007
  preprocessMode: zod.z.enum(["letterbox", "resize"]).optional(),
2991
3008
  /**
3009
+ * Per-MODEL postprocessor override. Absent ⇒ the step's own
3010
+ * `StepDefinition.postprocessor` applies (the normal case — every model in a
3011
+ * step shares its decode). Set it when a step hosts models with DIFFERENT raw
3012
+ * output layouts under one slot: e.g. object-detection is `'yolo'` by default,
3013
+ * but a Coral SSD MobileNet build emits the `TFLite_Detection_PostProcess`
3014
+ * 4-tensor layout and needs `'ssd'`. Threaded into `PoolModelConfig.postprocessor`
3015
+ * by the engine factory (`modelEntry.postprocessor ?? def.postprocessor`).
3016
+ */
3017
+ postprocessor: zod.z.custom().optional(),
3018
+ /**
2992
3019
  * When true, the executor produces a landmark-aligned crop (similarity warp
2993
3020
  * onto the canonical template) before this step runs, instead of a plain
2994
3021
  * axis-aligned bbox crop. Required for face-recognition embedders (ArcFace):
@@ -7980,7 +8007,8 @@ var EngineProvisioningSchema = zod.z.object({
7980
8007
  runtimeId: zod.z.enum([
7981
8008
  "onnx",
7982
8009
  "openvino",
7983
- "coreml"
8010
+ "coreml",
8011
+ "edgetpu"
7984
8012
  ]).nullable(),
7985
8013
  device: zod.z.string().nullable(),
7986
8014
  state: zod.z.enum([
@@ -10806,6 +10834,36 @@ var ZoneScopeBreakdownSchema = PerScopeBreakdownSchema.extend({
10806
10834
  * with the per-track detail panel and live overlay. */
10807
10835
  trackIds: zod.z.array(zod.z.string()).readonly()
10808
10836
  });
10837
+ /**
10838
+ * A parked ("stationary") object surfaced alongside occupancy — an object that
10839
+ * settled and stopped moving. It is NO LONGER a tracked object (the tracker was
10840
+ * told to forget it so it stops re-spawning tracks/events), but it IS still
10841
+ * physically present, so it keeps counting toward `frame` occupancy and is
10842
+ * listed here so the UI can show it in a dedicated "Stationary" section instead
10843
+ * of flooding the live event feed.
10844
+ */
10845
+ var StationaryObjectSchema = zod.z.object({
10846
+ id: zod.z.string(),
10847
+ className: zod.z.string(),
10848
+ bbox: zod.z.object({
10849
+ x: zod.z.number(),
10850
+ y: zod.z.number(),
10851
+ w: zod.z.number(),
10852
+ h: zod.z.number()
10853
+ }),
10854
+ frameWidth: zod.z.number().int().nonnegative(),
10855
+ frameHeight: zod.z.number().int().nonnegative(),
10856
+ /** When the source track was first seen. */
10857
+ firstSeenAt: zod.z.number().int(),
10858
+ /** When the object was recognised as parked (promotion time). */
10859
+ becameStationaryAt: zod.z.number().int(),
10860
+ /** Last frame a detection confirmed the object is still there. */
10861
+ lastConfirmedAt: zod.z.number().int(),
10862
+ /** Enrichment label carried from the source track (identity / plate). */
10863
+ label: zod.z.string().optional(),
10864
+ /** Native-resolution key-frame media key for the parked object's best image. */
10865
+ keyFrameMediaKey: zod.z.string().optional()
10866
+ });
10809
10867
  var CameraOccupancySnapshotSchema = zod.z.object({
10810
10868
  /** Frame timestamp of the inference result that produced this snapshot. */
10811
10869
  ts: zod.z.number().int(),
@@ -10814,10 +10872,15 @@ var CameraOccupancySnapshotSchema = zod.z.object({
10814
10872
  frameHeight: zod.z.number().int().nonnegative(),
10815
10873
  /** Per-zone breakdown — one entry per defined zone (user + onboard). */
10816
10874
  zones: zod.z.array(ZoneScopeBreakdownSchema).readonly(),
10817
- /** Frame-wide aggregate (everywhere, regardless of zone membership). */
10875
+ /** Frame-wide aggregate (everywhere, regardless of zone membership).
10876
+ * INCLUDES currently-confirmed stationary objects (they are still present). */
10818
10877
  frame: PerScopeBreakdownSchema,
10819
10878
  /** Detections that landed outside every zone. Empty when no zones defined. */
10820
- unzoned: PerScopeBreakdownSchema
10879
+ unzoned: PerScopeBreakdownSchema,
10880
+ /** Parked objects on this camera (additive — absent on legacy snapshots).
10881
+ * Surfaced separately so the UI shows them in a dedicated section rather
10882
+ * than as repeated tracks/events. */
10883
+ stationaryObjects: zod.z.array(StationaryObjectSchema).readonly().optional()
10821
10884
  });
10822
10885
  /**
10823
10886
  * Time-series resolution. The history methods return one bucket per
@@ -12801,6 +12864,64 @@ function looseSchema(schema) {
12801
12864
  const loose = schema.loose;
12802
12865
  return typeof loose === "function" ? loose.call(schema) : schema;
12803
12866
  }
12867
+ /**
12868
+ * Derive a COLLECTION-cap routing `addonId` from a NON-array mutation input
12869
+ * when the caller did NOT supply the top-level `{ addonId }` selector.
12870
+ *
12871
+ * Background: a `scope:'system', mode:'collection'` cap fans its ARRAY methods
12872
+ * (`listTargets`, `listTargetKinds`, …) across every provider, but routes each
12873
+ * single-object method (`send` / CRUD) to ONE provider. The runtime router
12874
+ * strips a TOP-LEVEL `addonId` selector and routes it via
12875
+ * `getProviderByAddonId`; absent that selector it falls through to the FIRST
12876
+ * registered provider — which misroutes (or hard-crashes on a partial provider)
12877
+ * when the target is owned by a DIFFERENT provider. See
12878
+ * `notification-output.cap.ts` (`Target.addonId` / `TargetKind.addonId` are
12879
+ * "stamped by each provider so the concat-fanned catalog stays routable").
12880
+ *
12881
+ * That routing `addonId` is ALREADY carried inside the mutation payload the
12882
+ * caller sends — e.g. `upsertTarget({ target: { …, addonId } })`. This helper
12883
+ * recovers it: it scans the input's DIRECT child object properties (bounded to
12884
+ * one level, first match wins) for a string `addonId`. Mirrors the child-side
12885
+ * `extractArgsAddonId` fallback in `child-cap-dispatch.ts`, which reads a
12886
+ * top-level `addonId` off the raw args; this covers the one-level-nested case
12887
+ * the top-level scan misses.
12888
+ *
12889
+ * Only used for non-array collection methods (array fan-out is never rerouted),
12890
+ * so it can never collapse a catalog aggregation onto a single provider. `null`
12891
+ * / non-object inputs yield `undefined` (fall back to the first provider,
12892
+ * preserving single-provider and id-only-payload back-compat).
12893
+ */
12894
+ function extractNestedAddonId(input) {
12895
+ if (input === null || typeof input !== "object") return void 0;
12896
+ for (const value of Object.values(input)) if (value !== null && typeof value === "object") {
12897
+ const nested = value.addonId;
12898
+ if (typeof nested === "string") return nested;
12899
+ }
12900
+ }
12901
+ /**
12902
+ * True when an OBJECT input schema declares a top-level `addonId` field.
12903
+ *
12904
+ * Such a cap method routes explicitly via the top-level `{ addonId }` selector
12905
+ * (the `llm.generate` / `deleteProfile` posture). The runtime router therefore
12906
+ * MUST NOT also fall back to {@link extractNestedAddonId} for it — that would
12907
+ * let an incidental nested `addonId` (e.g. a key inside a free-form `jsonSchema`
12908
+ * record) hijack routing. Nested recovery is reserved for methods whose input
12909
+ * carries NO top-level selector but embeds the owning `addonId` inside a domain
12910
+ * entity (`upsertTarget({ target: { addonId } })`, `upsertProfile({ profile })`).
12911
+ *
12912
+ * Accepts both Zod 4 (`.shape` / `_def.shape`) and legacy shapes; returns false
12913
+ * for non-object schemas.
12914
+ */
12915
+ function objectInputDeclaresAddonId(schema) {
12916
+ if (schema === null || typeof schema !== "object" && typeof schema !== "function") return false;
12917
+ const direct = schema.shape;
12918
+ const shape = direct !== void 0 && direct !== null ? direct : resolveDefShape(schema._def?.shape);
12919
+ return shape !== void 0 && shape !== null && typeof shape === "object" && Object.prototype.hasOwnProperty.call(shape, "addonId");
12920
+ }
12921
+ /** `_def.shape` may be a thunk (Zod defers object-shape evaluation) or a plain record. */
12922
+ function resolveDefShape(defShape) {
12923
+ return typeof defShape === "function" ? defShape() : defShape;
12924
+ }
12804
12925
  /** Auth level → base-procedure key. `superAdmin` collapses to `admin`. */
12805
12926
  function procedureAuthKey(auth) {
12806
12927
  if (auth === "public") return "public";
@@ -15531,6 +15652,22 @@ var TrackSnapshotSchema = zod.z.object({
15531
15652
  /** MediaStore key; resolve via `getTrackMedia({ trackId })`. */
15532
15653
  mediaKey: zod.z.string()
15533
15654
  });
15655
+ /**
15656
+ * One audio-classification label heard on the track's camera while the
15657
+ * track was alive, aggregated per label. An "episode" is one persisted
15658
+ * audio event (the confident-classification path: score ≥ the device's
15659
+ * `classificationMinScore`, class-change-or-heartbeat coalesced) — NOT
15660
+ * one 32 ms inference chunk, so counts stay human-scaled.
15661
+ */
15662
+ var TrackAudioLabelSchema = zod.z.object({
15663
+ label: zod.z.string(),
15664
+ /** Highest classification score observed across the label's episodes. */
15665
+ peakScore: zod.z.number(),
15666
+ /** Number of coalesced audio-event episodes carrying this label. */
15667
+ count: zod.z.number(),
15668
+ firstAt: zod.z.number(),
15669
+ lastAt: zod.z.number()
15670
+ });
15534
15671
  var TrackSchema = zod.z.object({
15535
15672
  trackId: zod.z.string(),
15536
15673
  deviceId: zod.z.number(),
@@ -15562,7 +15699,11 @@ var TrackSchema = zod.z.object({
15562
15699
  bestEventId: zod.z.string().optional(),
15563
15700
  /** Tag of the importance sub-signal that dominated the score
15564
15701
  * (identity|dwell|proximity|class|confidence|travel|zone). */
15565
- importanceReason: zod.z.string().optional()
15702
+ importanceReason: zod.z.string().optional(),
15703
+ /** Audio-classification labels heard on the camera during the track's
15704
+ * life (score ≥ device `classificationMinScore`), aggregated per label.
15705
+ * Absent on legacy rows / tracks with no confident audio. */
15706
+ audioLabels: zod.z.array(TrackAudioLabelSchema).readonly().optional()
15566
15707
  });
15567
15708
  var BaseEventFields = {
15568
15709
  id: zod.z.string(),
@@ -20139,6 +20280,10 @@ var GpuInfoSchema = zod.z.object({
20139
20280
  memoryMB: zod.z.number().optional()
20140
20281
  });
20141
20282
  var NpuInfoSchema = zod.z.object({ type: zod.z.enum(["apple-ane", "intel-npu"]) });
20283
+ var CoralInfoSchema = zod.z.object({
20284
+ type: zod.z.literal("coral-edgetpu"),
20285
+ bus: zod.z.string().optional()
20286
+ });
20142
20287
  var HardwareInfoSchema = zod.z.object({
20143
20288
  platform: HardwarePlatformSchema,
20144
20289
  arch: HardwareArchSchema,
@@ -20147,7 +20292,8 @@ var HardwareInfoSchema = zod.z.object({
20147
20292
  totalRAM_MB: zod.z.number(),
20148
20293
  availableRAM_MB: zod.z.number(),
20149
20294
  gpu: GpuInfoSchema.nullable(),
20150
- npu: NpuInfoSchema.nullable()
20295
+ npu: NpuInfoSchema.nullable(),
20296
+ coral: CoralInfoSchema.nullable().optional()
20151
20297
  });
20152
20298
  var PlatformScoreSchema = zod.z.object({
20153
20299
  runtime: zod.z.enum(["node", "python"]),
@@ -26436,6 +26582,12 @@ Object.defineProperty(exports, "expandCapMethods", {
26436
26582
  return expandCapMethods;
26437
26583
  }
26438
26584
  });
26585
+ Object.defineProperty(exports, "extractNestedAddonId", {
26586
+ enumerable: true,
26587
+ get: function() {
26588
+ return extractNestedAddonId;
26589
+ }
26590
+ });
26439
26591
  Object.defineProperty(exports, "filesystemBrowseCapability", {
26440
26592
  enumerable: true,
26441
26593
  get: function() {
@@ -26532,6 +26684,12 @@ Object.defineProperty(exports, "normalizeUnit", {
26532
26684
  return normalizeUnit;
26533
26685
  }
26534
26686
  });
26687
+ Object.defineProperty(exports, "objectInputDeclaresAddonId", {
26688
+ enumerable: true,
26689
+ get: function() {
26690
+ return objectInputDeclaresAddonId;
26691
+ }
26692
+ });
26535
26693
  Object.defineProperty(exports, "parseJsonObject", {
26536
26694
  enumerable: true,
26537
26695
  get: function() {
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_chunk = require("./chunk-Cek0wNdY.js");
3
- const require_dist = require("./dist-BDV1WKRg.js");
3
+ const require_dist = require("./dist-CQYo6Zp8.js");
4
4
  const require_model_download_service = require("./model-download-service-D-Umz4-L.js");
5
5
  const require_resource_monitor = require("./resource-monitor-DNNomR-i.js");
6
6
  const require_builtins_sqlite_storage_filesystem_storage_addon = require("./builtins/sqlite-storage/filesystem-storage.addon.js");
@@ -21,7 +21,7 @@ const require_builtins_local_auth_local_auth_addon = require("./builtins/local-a
21
21
  require("./builtins/local-auth/index.js");
22
22
  const require_builtins_device_manager_device_manager_addon = require("./builtins/device-manager/device-manager.addon.js");
23
23
  require("./builtins/device-manager/index.js");
24
- const require_manifest_python_deps = require("./manifest-python-deps-DAA0ULwT.js");
24
+ const require_manifest_python_deps = require("./manifest-python-deps-Wy8dNJpr.js");
25
25
  const require_custom_action_registry = require("./custom-action-registry-vLYEFTtv.js");
26
26
  let _camstack_types_node = require("@camstack/types/node");
27
27
  let zod = require("zod");
@@ -5121,7 +5121,9 @@ function buildOneCapRouter(def, primitives, services) {
5121
5121
  if (isCollection) {
5122
5122
  const { rest, picked } = stripKeys(input, ["nodeId", "addonId"]);
5123
5123
  const nodeId = typeof picked.nodeId === "string" ? picked.nodeId : void 0;
5124
- const addonId = typeof picked.addonId === "string" ? picked.addonId : void 0;
5124
+ const topLevelAddonId = typeof picked.addonId === "string" ? picked.addonId : void 0;
5125
+ const canRecoverNestedAddonId = !require_dist.isArrayOutputSchema(method.schema.output) && !require_dist.objectInputDeclaresAddonId(method.schema.input);
5126
+ const addonId = topLevelAddonId ?? (canRecoverNestedAddonId ? require_dist.extractNestedAddonId(rest) : void 0);
5125
5127
  return resolveProviderForCall(capName, nodeId, () => getLocal(ctx, addonId), services)[method.name]?.(rest);
5126
5128
  }
5127
5129
  const { rest, picked } = stripKeys(input, ["nodeId"]);
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { A as isObjectInput, Ct as readinessKey, H as procedureAuthKey, I as looseSchema, M as kebabToCamel, N as lifecycleJobSchema, O as isArrayOutputSchema, St as parseJsonUnknown$1, Tt as scopeKey, ct as EventCategory$1, et as errMsg$1, ft as asJsonObject$1, gt as emitDownForOwnedCaps, ht as createEvent, it as DEVICE_STATUS_METHOD, j as isVoidInput, k as isCollectionArrayMethod, lt as ReadinessRegistry, mt as asString$1, nt as DATAPLANE_SECRET_HEADER$1, o as METHOD_ACCESS_MAP, p as addonSettingsCapability, pt as asNumber, rt as DEVICE_SETTINGS_CONTRIBUTION_METHODS, s as RUNTIME_DEFAULTS, t as ALL_CAPABILITY_DEFINITIONS, ut as ReadinessTimeoutError, vt as expandCapMethods, wt as resolveCapMount, xt as parseJsonObject } from "./dist-8phgmJ6b.mjs";
1
+ import { A as isCollectionArrayMethod, Ct as parseJsonObject, Dt as scopeKey, E as extractNestedAddonId, Et as resolveCapMount, L as looseSchema, M as isVoidInput, N as kebabToCamel, P as lifecycleJobSchema, Tt as readinessKey, V as objectInputDeclaresAddonId, W as procedureAuthKey, _t as createEvent, at as DEVICE_SETTINGS_CONTRIBUTION_METHODS, bt as expandCapMethods, dt as ReadinessRegistry, ft as ReadinessTimeoutError, gt as asString$1, ht as asNumber, it as DATAPLANE_SECRET_HEADER$1, j as isObjectInput, k as isArrayOutputSchema, mt as asJsonObject$1, nt as errMsg$1, o as METHOD_ACCESS_MAP, ot as DEVICE_STATUS_METHOD, p as addonSettingsCapability, s as RUNTIME_DEFAULTS, t as ALL_CAPABILITY_DEFINITIONS, ut as EventCategory$1, vt as emitDownForOwnedCaps, wt as parseJsonUnknown$1 } from "./dist-CC3E-_3h.mjs";
2
2
  import { a as downloadModel, c as getModelFilePath, d as contentTypeFor, f as createAuthenticatedFileServer, h as resolveFilePath, i as downloadFile, l as isModelDownloaded, m as parseTokenizedUrl, n as collectModelFiles, o as ensureModel, p as parseRangeHeader, r as deleteModelFromDisk, s as fetchJson, t as ModelDownloadService, u as createFileDataPlaneHandler } from "./model-download-service-C-IHWnXx.mjs";
3
3
  import { n as getSinglePidStats, t as getPidStats } from "./resource-monitor-Le3l0qS2.mjs";
4
4
  import { FilesystemStorageAddon, t as FilesystemStorageProvider } from "./builtins/sqlite-storage/filesystem-storage.addon.mjs";
@@ -19,7 +19,7 @@ import { LocalAuthAddon, a as require_ms, c as __esmMin, d as __toCommonJS, f as
19
19
  import "./builtins/local-auth/index.mjs";
20
20
  import { DeviceManagerAddon } from "./builtins/device-manager/device-manager.addon.mjs";
21
21
  import "./builtins/device-manager/index.mjs";
22
- import { $ as buildUdsNativeCapProxy, A as createParentUnownedCallHandler, B as AGENT_CAP_FWD_SERVICE, C as buildLinkChain, D as HUB_CAP_FWD_ACTION, E as localProviderLink, F as createUdsLoggerWithControl, G as createLocalTransport, H as CapRouteError, I as LocalChildClient, J as SocketChannel, K as UdsLocalTransportClient, L as LocalChildRegistry, M as createUdsEventBus, N as udsChildLogToWorkerEntry, O as HUB_CAP_FWD_SERVICE, P as createUdsLogger, Q as buildNativeCapProxy, R as UDS_NO_ROUTE_PREFIX, S as brokerTransportLink, T as ipcParentLink, U as classifyCapRoute, V as CapRouteResolver, W as callWithServiceDiscovery, X as FrameDecoder, Y as localEndpointPath, Z as encodeFrame, _ as resolveHwAccel, _t as CapabilityUnavailableError, a as getWorkerDeviceRegistry, at as createAddonService, b as getCapUsageRegistry, c as setHubConnected, ct as capActionName, d as getMoleculerEventStats, dt as capServiceName, et as createBrokerDeviceManagerApi, f as registerEventBusService, ft as parseCapAction, g as createKernelHwAccel, gt as CapabilityHandle, h as AddonDepsManager, ht as DeviceRegistry, i as createUdsAddonContext, j as createUdsEventBridge, k as createHubCapForwardService, l as EVENT_TOPIC_PREFIX, lt as capActionSuffix, m as subscribePassthrough, mt as serializeTypedArrays, n as adaptBrokerToCluster, o as getOrInitReadinessRegistry, ot as validateProviderRegistrations, p as setNodeEventInterest, pt as deserializeTypedArrays, q as UdsLocalTransportServer, r as createAddonContext, rt as mountNativeCapService, s as getOrInitReadinessRegistryForClient, st as NATIVE_PROVIDER_SERVICE_INFIX, t as installManifestPythonDeps, u as getBrokerEventBus, ut as capBareAction, v as CapUsageRegistry, vt as installManifestNativeDeps, w as ipcChildLink, x as brokerCallForCap, y as __resetCapUsageRegistryForTests, yt as resolveAddonClass, z as AGENT_CAP_FWD_ACTION } from "./manifest-python-deps-B09I9ems.mjs";
22
+ import { $ as buildUdsNativeCapProxy, A as createParentUnownedCallHandler, B as AGENT_CAP_FWD_SERVICE, C as buildLinkChain, D as HUB_CAP_FWD_ACTION, E as localProviderLink, F as createUdsLoggerWithControl, G as createLocalTransport, H as CapRouteError, I as LocalChildClient, J as SocketChannel, K as UdsLocalTransportClient, L as LocalChildRegistry, M as createUdsEventBus, N as udsChildLogToWorkerEntry, O as HUB_CAP_FWD_SERVICE, P as createUdsLogger, Q as buildNativeCapProxy, R as UDS_NO_ROUTE_PREFIX, S as brokerTransportLink, T as ipcParentLink, U as classifyCapRoute, V as CapRouteResolver, W as callWithServiceDiscovery, X as FrameDecoder, Y as localEndpointPath, Z as encodeFrame, _ as resolveHwAccel, _t as CapabilityUnavailableError, a as getWorkerDeviceRegistry, at as createAddonService, b as getCapUsageRegistry, c as setHubConnected, ct as capActionName, d as getMoleculerEventStats, dt as capServiceName, et as createBrokerDeviceManagerApi, f as registerEventBusService, ft as parseCapAction, g as createKernelHwAccel, gt as CapabilityHandle, h as AddonDepsManager, ht as DeviceRegistry, i as createUdsAddonContext, j as createUdsEventBridge, k as createHubCapForwardService, l as EVENT_TOPIC_PREFIX, lt as capActionSuffix, m as subscribePassthrough, mt as serializeTypedArrays, n as adaptBrokerToCluster, o as getOrInitReadinessRegistry, ot as validateProviderRegistrations, p as setNodeEventInterest, pt as deserializeTypedArrays, q as UdsLocalTransportServer, r as createAddonContext, rt as mountNativeCapService, s as getOrInitReadinessRegistryForClient, st as NATIVE_PROVIDER_SERVICE_INFIX, t as installManifestPythonDeps, u as getBrokerEventBus, ut as capBareAction, v as CapUsageRegistry, vt as installManifestNativeDeps, w as ipcChildLink, x as brokerCallForCap, y as __resetCapUsageRegistryForTests, yt as resolveAddonClass, z as AGENT_CAP_FWD_ACTION } from "./manifest-python-deps-DqATCsK0.mjs";
23
23
  import { t as CustomActionRegistry } from "./custom-action-registry-BEXwC-oo.mjs";
24
24
  import { PYTHON_VERSION, buildBinaryPath, downloadBinary, ensureBinary, ensureFfmpeg, ensurePython, findInPath, getFfmpegDownloadUrl, getPlatformInfo, getPythonDownloadUrl, installPythonPackages, installPythonRequirements } from "@camstack/types/node";
25
25
  import { z } from "zod";
@@ -5113,7 +5113,9 @@ function buildOneCapRouter(def, primitives, services) {
5113
5113
  if (isCollection) {
5114
5114
  const { rest, picked } = stripKeys(input, ["nodeId", "addonId"]);
5115
5115
  const nodeId = typeof picked.nodeId === "string" ? picked.nodeId : void 0;
5116
- const addonId = typeof picked.addonId === "string" ? picked.addonId : void 0;
5116
+ const topLevelAddonId = typeof picked.addonId === "string" ? picked.addonId : void 0;
5117
+ const canRecoverNestedAddonId = !isArrayOutputSchema(method.schema.output) && !objectInputDeclaresAddonId(method.schema.input);
5118
+ const addonId = topLevelAddonId ?? (canRecoverNestedAddonId ? extractNestedAddonId(rest) : void 0);
5117
5119
  return resolveProviderForCall(capName, nodeId, () => getLocal(ctx, addonId), services)[method.name]?.(rest);
5118
5120
  }
5119
5121
  const { rest, picked } = stripKeys(input, ["nodeId"]);
@@ -8,6 +8,8 @@ export interface PlatformSignals {
8
8
  readonly hasRenderNode: boolean;
9
9
  /** Intel NPU (Meteor Lake / Core Ultra "AI Boost") — exposed as /dev/accel/accel0. */
10
10
  readonly hasIntelNpu: boolean;
11
+ /** Coral USB Edge TPU — a discrete USB accelerator (gates the `edgetpu` runtime). */
12
+ readonly hasCoral: boolean;
11
13
  }
12
14
  export declare function probePlatform(): PlatformSignals;
13
15
  /**
@@ -1,4 +1,4 @@
1
- import { U as readNodePin } from "./dist-8phgmJ6b.mjs";
1
+ import { G as readNodePin } from "./dist-CC3E-_3h.mjs";
2
2
  import { ensureBinary, ensureFfmpeg, ensurePython, installPythonPackages, installPythonRequirements } from "@camstack/types/node";
3
3
  import { createServer } from "node:http";
4
4
  import * as fs from "node:fs";
@@ -5583,6 +5583,30 @@ function safeExistsSync(path) {
5583
5583
  return false;
5584
5584
  }
5585
5585
  }
5586
+ /**
5587
+ * Detect a Coral USB Edge TPU: a matching USB device (`1a6e:089a` pre-init or
5588
+ * `18d1:9302` post-init) OR the installed libedgetpu delegate (the hub
5589
+ * provisions it out-of-band; its presence is a reliable "Coral is wired"
5590
+ * signal even where the container's `/sys` USB view is limited).
5591
+ */
5592
+ function detectCoralUsb() {
5593
+ const CORAL_IDS = [{
5594
+ vendor: "1a6e",
5595
+ product: "089a"
5596
+ }, {
5597
+ vendor: "18d1",
5598
+ product: "9302"
5599
+ }];
5600
+ try {
5601
+ for (const device of fs.readdirSync("/sys/bus/usb/devices")) try {
5602
+ const base = `/sys/bus/usb/devices/${device}`;
5603
+ const vendor = fs.readFileSync(`${base}/idVendor`, "utf8").trim().toLowerCase();
5604
+ const product = fs.readFileSync(`${base}/idProduct`, "utf8").trim().toLowerCase();
5605
+ if (CORAL_IDS.some((id) => id.vendor === vendor && id.product === product)) return true;
5606
+ } catch {}
5607
+ } catch {}
5608
+ return safeExistsSync(process.env["CAMSTACK_EDGETPU_LIB"] ?? "/data/deps/edgetpu/lib/libedgetpu.so.1");
5609
+ }
5586
5610
  /** Probe Linux GPU vendors by parsing /proc/bus/pci/devices or /sys/class/drm. */
5587
5611
  function probeLinuxGpus() {
5588
5612
  const signals = {
@@ -5590,7 +5614,8 @@ function probeLinuxGpus() {
5590
5614
  hasAmdGpu: false,
5591
5615
  hasIntelGpu: false,
5592
5616
  hasRenderNode: false,
5593
- hasIntelNpu: safeExistsSync("/dev/accel/accel0")
5617
+ hasIntelNpu: safeExistsSync("/dev/accel/accel0"),
5618
+ hasCoral: detectCoralUsb()
5594
5619
  };
5595
5620
  signals.hasRenderNode = safeExistsSync("/dev/dri/renderD128");
5596
5621
  if (safeExistsSync("/dev/nvidia0") || safeExistsSync("/proc/driver/nvidia/version")) signals.hasNvidiaGpu = true;
@@ -5623,7 +5648,8 @@ function probePlatform() {
5623
5648
  hasAmdGpu: false,
5624
5649
  hasIntelGpu: false,
5625
5650
  hasRenderNode: false,
5626
- hasIntelNpu: false
5651
+ hasIntelNpu: false,
5652
+ hasCoral: safeExistsSync(process.env["CAMSTACK_EDGETPU_LIB"] ?? "/data/deps/edgetpu/lib/libedgetpu.so.1")
5627
5653
  };
5628
5654
  }
5629
5655
  function pickBackendsForPlatform(signals) {
@@ -5708,7 +5734,8 @@ function createKernelHwAccel() {
5708
5734
  function mapSignalsToInferenceHardware(signals) {
5709
5735
  return {
5710
5736
  gpu: signals.hasNvidiaGpu ? { type: "nvidia" } : signals.hasIntelGpu || signals.hasRenderNode ? { type: "intel" } : null,
5711
- npu: signals.platform === "darwin" && signals.arch === "arm64" ? { type: "apple-ane" } : signals.hasIntelNpu ? { type: "intel-npu" } : null
5737
+ npu: signals.platform === "darwin" && signals.arch === "arm64" ? { type: "apple-ane" } : signals.hasIntelNpu ? { type: "intel-npu" } : null,
5738
+ coral: signals.hasCoral ? { type: "coral-edgetpu" } : null
5712
5739
  };
5713
5740
  }
5714
5741
  /**