@camstack/addon-model-studio 1.1.182 → 1.1.184

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 (18) hide show
  1. package/dist/{MotionZonesSettings-DB-47cOo.mjs → MotionZonesSettings-CLIRob-J.mjs} +2 -2
  2. package/dist/{PrivacyMaskSettings-BIzb0D_0.mjs → PrivacyMaskSettings-exV6L1j_.mjs} +4 -4
  3. package/dist/{SceneMonitorEditor-IaL6eXRr.mjs → SceneMonitorEditor-icoLBztR.mjs} +3 -3
  4. package/dist/_stub.js +14 -14
  5. package/dist/{_virtual_mf-localSharedImportMap___mfe_internal__addon_model_studio_page-CsOTOHLQ.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_model_studio_page-DQxc1RfH.mjs} +3 -3
  6. package/dist/_virtual_mf___mfe_internal__addon_model_studio_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-D3PT9fEx.mjs +26 -0
  7. package/dist/{hostInit-Bl24UlY4.mjs → hostInit-C9yJIB1e.mjs} +2 -2
  8. package/dist/model-studio.addon.js +313 -202
  9. package/dist/model-studio.addon.mjs +313 -202
  10. package/dist/{player-overlays-CISEjNtj.mjs → player-overlays-DwfCWVUG.mjs} +1 -1
  11. package/dist/remoteEntry.js +1 -1
  12. package/dist/{responsive-CUot36ya.mjs → responsive-BRO7smWV.mjs} +1 -1
  13. package/dist/{scene-monitor-copy-J64_2zC1.mjs → scene-monitor-copy--wZxxF0G.mjs} +1 -1
  14. package/dist/{square-CDSkPKBQ.mjs → square-BfZLUXuN.mjs} +1 -1
  15. package/dist/{trash-2-C1NZwuGu.mjs → trash-2-0kWm0Lcw.mjs} +1 -1
  16. package/dist/{virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_model_studio_page__remoteEntry_js-DcHcLEYl.mjs → virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_model_studio_page__remoteEntry_js-JOrjSbrc.mjs} +1 -1
  17. package/package.json +1 -1
  18. package/dist/_virtual_mf___mfe_internal__addon_model_studio_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-BmwlvTun.mjs +0 -26
@@ -5941,7 +5941,7 @@ var ZodIssueCode = {
5941
5941
  var ZodFirstPartyTypeKind;
5942
5942
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5943
5943
  //#endregion
5944
- //#region ../types/dist/sleep-DlrgY4Qb.mjs
5944
+ //#region ../types/dist/sleep-C-v96WpE.mjs
5945
5945
  /**
5946
5946
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5947
5947
  * window to float samples (D455).
@@ -8051,7 +8051,59 @@ var DeviceRole = /* @__PURE__ */ function(DeviceRole) {
8051
8051
  return DeviceRole;
8052
8052
  }({});
8053
8053
  //#endregion
8054
- //#region ../types/dist/composition-BK-GTFYb.mjs
8054
+ //#region ../types/dist/composition-Dq42XWp0.mjs
8055
+ /**
8056
+ * The ffmpeg build every CamStack node downloads, per platform and arch.
8057
+ *
8058
+ * ## Why a download, on every node, including the container
8059
+ *
8060
+ * The version of ffmpeg used to be CODE: baked into the image, changeable only
8061
+ * by rebuilding and rolling it. Now it is DATA — this file states the release,
8062
+ * and a node that boots with a different one downloads it. Changing ffmpeg is a
8063
+ * framework bump, not an image rebuild.
8064
+ *
8065
+ * It also settles the licence question by removing it. FFmpeg's licence is
8066
+ * chosen at compile time: the core is LGPL 2.1+, `--enable-gpl` makes it GPL
8067
+ * (for x264/x265), `--enable-version3` makes that v3, and `--enable-nonfree`
8068
+ * makes the result undistributable. These are GPL v3 builds, and we do not
8069
+ * distribute them: the user's own node fetches the archive from the project
8070
+ * that publishes it, so we convey no GPL work and inherit none of the
8071
+ * obligations that come with conveying one. That is the whole reason the image
8072
+ * no longer installs ffmpeg at all — not a technical preference.
8073
+ *
8074
+ * ## Why jellyfin-ffmpeg
8075
+ *
8076
+ * One vendor covering linux-amd64, linux-arm64, darwin-arm64 and darwin-x64
8077
+ * from one release, with the widest hardware surface of anything maintained:
8078
+ * VAAPI, QSV, NVENC/NVDEC, AMF, Vulkan, OpenCL and DRM on amd64, plus Rockchip
8079
+ * MPP on arm64. It reaches the vendor libraries through dlopen trampolines,
8080
+ * so the binary is not linked against a driver stack it may not find.
8081
+ *
8082
+ * **What it still needs from the host, measured 2026-09-19.** On the Unraid
8083
+ * HOST, which has no libva, `-vaapi_device` aborts the process outright —
8084
+ * `implib-gen: libva-drm.so.2: failed to load library ... Assertion '0 &&
8085
+ * "Assertion in generated code"' failed`. Inside our container, which installs
8086
+ * libva plus the iHD driver, the same command encodes: verified end to end with
8087
+ * `testsrc → format=nv12,hwupload → h264_vaapi`. So the image drops ffmpeg and
8088
+ * KEEPS the Intel media stack; the drivers are the part a binary cannot bring.
8089
+ *
8090
+ * ## Why each artifact carries a checksum and a claim
8091
+ *
8092
+ * The download is now the only source, so `sha256` is verified before anything
8093
+ * is extracted — jellyfin publishes no checksums on its release assets, so
8094
+ * these are ours, taken at the version bump. And `expectedHwaccels` is what the
8095
+ * build is supposed to be able to do: a binary that probes short of its own
8096
+ * claim is a source that changed under us, which is precisely what went
8097
+ * unnoticed for months when a static build turned out to carry no VAAPI at all
8098
+ * (D536).
8099
+ */
8100
+ /** The pinned jellyfin-ffmpeg release. Changing this is the version change. */
8101
+ var FFMPEG_RELEASE = "8.1.2-5";
8102
+ var BASE = `https://github.com/jellyfin/jellyfin-ffmpeg/releases/download/v${FFMPEG_RELEASE}`;
8103
+ function portable(target) {
8104
+ return `${BASE}/jellyfin-ffmpeg_${FFMPEG_RELEASE}_portable_${target}-gpl.tar.xz`;
8105
+ }
8106
+ portable("linux64"), portable("linuxarm64"), portable("macarm64"), portable("mac64");
8055
8107
  /**
8056
8108
  * LA tabella "quale booleano di questo tipo di device conta come ALTO", e il
8057
8109
  * valutatore puro del suo FRONTE.
@@ -8855,7 +8907,6 @@ var CompositionSchema = object({
8855
8907
  });
8856
8908
  new Set([
8857
8909
  "track",
8858
- "summary",
8859
8910
  "face",
8860
8911
  "identity",
8861
8912
  "plate",
@@ -13629,6 +13680,70 @@ var CompositionBlockStateSchema = object({
13629
13680
  reason: string().optional(),
13630
13681
  fields: array(CompositionFieldStateSchema)
13631
13682
  });
13683
+ var NUMBER = {
13684
+ kind: "fixed",
13685
+ result: ["number"]
13686
+ };
13687
+ var BOOLEAN = {
13688
+ kind: "fixed",
13689
+ result: ["boolean"]
13690
+ };
13691
+ Object.freeze({
13692
+ min: NUMBER,
13693
+ max: NUMBER,
13694
+ abs: NUMBER,
13695
+ floor: NUMBER,
13696
+ ceil: NUMBER,
13697
+ sqrt: NUMBER,
13698
+ round: NUMBER,
13699
+ pow: NUMBER,
13700
+ clamp: NUMBER,
13701
+ avg: NUMBER,
13702
+ sum: NUMBER,
13703
+ age: NUMBER,
13704
+ convert: NUMBER,
13705
+ coalesce: { kind: "coalesce" },
13706
+ any: BOOLEAN,
13707
+ all: BOOLEAN,
13708
+ within: BOOLEAN,
13709
+ latest: {
13710
+ kind: "fixed",
13711
+ result: ["number", "null"]
13712
+ },
13713
+ number: {
13714
+ kind: "fixed",
13715
+ result: ["number", "null"]
13716
+ },
13717
+ rose: {
13718
+ kind: "fixed",
13719
+ result: ["number", "null"]
13720
+ },
13721
+ count: NUMBER
13722
+ });
13723
+ `${COMPOSED_DEVICE_STABLE_ID_PREFIX}`;
13724
+ /**
13725
+ * What a composition may BUILD on a device type (G2, D676): the caps a new
13726
+ * device of that type, or an existing one that lacks them, can be given. The
13727
+ * blockers are the validator's own refusal codes, and a spec compares this
13728
+ * listing with `planComposition` for every capability — the editor can never
13729
+ * offer a feature the save would refuse for the same reason.
13730
+ */
13731
+ var ComposableFieldSchema = object({
13732
+ path: string(),
13733
+ kind: CompositionFieldKindSchema,
13734
+ nullable: boolean(),
13735
+ required: boolean(),
13736
+ enumValues: array(string()).optional()
13737
+ });
13738
+ var ComposableCapabilitiesSchema = object({ caps: array(object({
13739
+ cap: string(),
13740
+ fields: array(ComposableFieldSchema),
13741
+ /** Present for an item-array cap (`consumables.items`). */
13742
+ itemArray: object({
13743
+ path: string(),
13744
+ keyField: string()
13745
+ }).optional()
13746
+ })) });
13632
13747
  /** Where a block runs. The operator chooses — a block driving a device on an
13633
13748
  * agent is the reason placement is not fixed to the hub. */
13634
13749
  var CoreBlockPlacementSchema = union([literal("hub"), string().min(1)]);
@@ -13793,7 +13908,7 @@ method(object({}), object({ blocks: array(CoreBlockSchema) }), { auth: "admin" }
13793
13908
  }), method(object({ blockId: string() }), CompositionGetReadSchema, { auth: "admin" }), method(object({}), CompositionListReadSchema, { auth: "admin" }), method(object({
13794
13909
  addonId: string().min(1),
13795
13910
  stableId: string().min(1)
13796
- }), CompositionCustomizationReadSchema, { auth: "admin" }), method(object({
13911
+ }), CompositionCustomizationReadSchema, { auth: "admin" }), method(object({ deviceType: _enum(DeviceType) }), ComposableCapabilitiesSchema, { auth: "admin" }), method(object({
13797
13912
  composition: CompositionSchema,
13798
13913
  blockId: string().optional()
13799
13914
  }), CompositionValidationSchema, {
@@ -20697,6 +20812,102 @@ var OauthIntegrationDescriptorSchema = object({
20697
20812
  });
20698
20813
  method(_void(), OauthIntegrationDescriptorSchema, { auth: "admin" });
20699
20814
  /**
20815
+ * What started a camera's onboard motion (D672). `camera` is the camera's own
20816
+ * firmware; `sensor` is a device the operator ATTACHED to it. Absent on the
20817
+ * wire means the camera: only the camera-sensors bridge ever says `sensor`.
20818
+ */
20819
+ var MotionTriggeredBySchema = discriminatedUnion("kind", [object({ kind: literal("camera") }), object({
20820
+ kind: literal("sensor"),
20821
+ deviceId: number().int().positive()
20822
+ })]);
20823
+ Object.freeze({ kind: "camera" });
20824
+ var CameraSensorRefSchema = object({
20825
+ addonId: string().min(1),
20826
+ stableId: string().min(1)
20827
+ });
20828
+ function cameraSensorRefKey(ref) {
20829
+ return `${ref.addonId}/${ref.stableId}`;
20830
+ }
20831
+ /** CS-1 accepts exactly one mode; CS-2 (D673) widens it to confirm / replace. */
20832
+ var CameraSensorsModeSchema = _enum(["in-addition"]);
20833
+ var CameraSensorsConfigSchema = object({
20834
+ mode: CameraSensorsModeSchema,
20835
+ sensors: array(CameraSensorRefSchema).min(1).max(8)
20836
+ }).superRefine((value, ctx) => {
20837
+ const seen = /* @__PURE__ */ new Set();
20838
+ value.sensors.forEach((ref, index) => {
20839
+ const key = cameraSensorRefKey(ref);
20840
+ if (seen.has(key)) ctx.addIssue({
20841
+ code: "custom",
20842
+ path: ["sensors", index],
20843
+ message: `duplicate camera sensor ${key}`
20844
+ });
20845
+ seen.add(key);
20846
+ });
20847
+ });
20848
+ var RefFields = {
20849
+ addonId: string(),
20850
+ stableId: string()
20851
+ };
20852
+ var CameraSensorAttachmentSchema = discriminatedUnion("state", [
20853
+ object({
20854
+ ...RefFields,
20855
+ state: literal("ready"),
20856
+ deviceId: number(),
20857
+ name: string(),
20858
+ caps: array(string()).readonly()
20859
+ }),
20860
+ object({
20861
+ ...RefFields,
20862
+ state: literal("offline"),
20863
+ deviceId: number(),
20864
+ name: string(),
20865
+ reason: _enum(["offline", "disabled"])
20866
+ }),
20867
+ object({
20868
+ ...RefFields,
20869
+ state: literal("missing"),
20870
+ reason: string()
20871
+ }),
20872
+ object({
20873
+ ...RefFields,
20874
+ state: literal("unsupported"),
20875
+ deviceId: number(),
20876
+ name: string(),
20877
+ reason: string()
20878
+ }),
20879
+ object({
20880
+ ...RefFields,
20881
+ state: literal("unreadable"),
20882
+ reason: string()
20883
+ })
20884
+ ]);
20885
+ /**
20886
+ * Why a configured camera forwards NOTHING from its sensors, however ready they
20887
+ * are (D672): it does not list `onboard` in `motionSources` (attaching a sensor
20888
+ * does not add it), or it has no active detection config at all (the bridge
20889
+ * reads the active config). Absent = forwarded, or an older node that does not
20890
+ * say.
20891
+ */
20892
+ var CameraSensorsNotForwardedSchema = _enum(["onboard-not-listed", "no-active-detection"]);
20893
+ var CameraSensorsStatusSchema = discriminatedUnion("state", [
20894
+ object({ state: literal("not-configured") }),
20895
+ object({
20896
+ state: literal("unreadable"),
20897
+ reason: string()
20898
+ }),
20899
+ object({
20900
+ state: literal("configured"),
20901
+ mode: CameraSensorsModeSchema,
20902
+ sensors: array(CameraSensorAttachmentSchema).readonly(),
20903
+ notForwarded: CameraSensorsNotForwardedSchema.optional()
20904
+ })
20905
+ ]);
20906
+ Object.freeze({
20907
+ state: "unreadable",
20908
+ reason: "camera sensor mappings not loaded"
20909
+ });
20910
+ /**
20700
20911
  * A model choice has a SCOPE, and a scope change has a workflow.
20701
20912
  *
20702
20913
  * ## The two scopes
@@ -21445,6 +21656,12 @@ var MotionEventSchema = object({
21445
21656
  /** Populated by B5 (recording playback URL for this event). */
21446
21657
  mediaUrl: string().optional(),
21447
21658
  /**
21659
+ * The FIRST trigger of an `onboard` episode, written once at open (D672).
21660
+ * Absent = not recorded (a row written before D672, or an analyzer /
21661
+ * device-activity episode) — never read as "the camera" (D393).
21662
+ */
21663
+ triggeredBy: MotionTriggeredBySchema.optional(),
21664
+ /**
21448
21665
  * One row per motion EPISODE, not one per push (D475). `null` while the
21449
21666
  * episode is still open — a further rising edge extends it in place rather
21450
21667
  * than inserting a new row. Set once, at close, to `lastOnAt - startedAt`
@@ -21603,6 +21820,21 @@ var ObjectEventSchema = object({
21603
21820
  keyFrameMediaId: number().int().optional(),
21604
21821
  /** Populated by B5 (recording playback URL for this event). */
21605
21822
  mediaUrl: string().optional(),
21823
+ /**
21824
+ * When the change this row records HAPPENED, epoch ms, when that is earlier
21825
+ * than {@link timestamp} and the producer could date it (D684).
21826
+ *
21827
+ * Set on a package PICK-UP row only: its `timestamp` is when the departure
21828
+ * was CONCLUDED — five minutes of unseen observed time after the parcel went
21829
+ * — and a notification's footage has to be cut around the pick-up, not the
21830
+ * empty doormat after it (D682). Stored so every path that rebuilds a
21831
+ * notification subject from the row (the boot reconcile, a dry-run) anchors
21832
+ * on the same instant the live hook did.
21833
+ *
21834
+ * `timestamp` keeps its meaning. Absent on every other row and on every
21835
+ * pick-up written before D684 — UNKNOWN, never 0 and never `timestamp`.
21836
+ */
21837
+ observedAt: number().optional(),
21606
21838
  /** The parent track's key-event importance [0,1], propagated to every object
21607
21839
  * event of the track (so an event row can be sorted by importance without a
21608
21840
  * track join). Absent on legacy rows / before the track was scored. */
@@ -21938,131 +22170,6 @@ var RecentTracksQueryInput = object({
21938
22170
  /** See {@link ExcludeSourcesDoc}. */
21939
22171
  excludeSources: array(TrackSourceSchema).optional()
21940
22172
  });
21941
- /**
21942
- * A Summary (D359): the per-camera session envelope that references tracks.
21943
- * `groupShotMediaId` is the media ROW id of its group shot (`ownerKind:
21944
- * 'summary'`, served by the event-media plane at `/m/<id>`), null until the
21945
- * first frame with a member visible has been materialised (D482 — it was the
21946
- * row's composite key, which embedded the owner and could name another table's
21947
- * row once event ids became per-table rowids).
21948
- */
21949
- var SummarySchema = object({
21950
- id: string(),
21951
- deviceId: number(),
21952
- openedAt: number(),
21953
- lastActiveAt: number(),
21954
- sealedAt: number().nullable(),
21955
- memberCount: number().int().nonnegative(),
21956
- groupShotMediaId: number().int().nullable()
21957
- });
21958
- var SummariesQueryInput = object({
21959
- deviceIds: array(number()).min(1),
21960
- since: number().optional(),
21961
- until: number().optional(),
21962
- limit: number().int().min(1).max(200).default(50),
21963
- /** The same member-wise filter {@link listRecentSummaries} takes — one
21964
- * meaning of "dog" on every summary surface. */
21965
- classes: array(string().min(1).max(60)).max(40).optional()
21966
- });
21967
- var SummaryDetailSchema = object({
21968
- summary: SummarySchema,
21969
- /** Members in absorption order, oldest join first. */
21970
- members: array(object({
21971
- trackId: string(),
21972
- /**
21973
- * The track's class at the time it JOINED, or `null` when it was unresolved
21974
- * and the track no longer exists to fill it.
21975
- *
21976
- * The join, not the latest opinion: class voting can re-decide a track's
21977
- * class afterwards, and a group's composition is the history of who came
21978
- * together. A consumer counts these to badge a thumbnail — "two people and a
21979
- * dog" — rather than being handed a second, denormalised tally that would
21980
- * drift from the members it claims to describe.
21981
- */
21982
- className: string().nullable(),
21983
- /** `primary` is the one member that carries the group's identity. */
21984
- role: _enum([
21985
- "primary",
21986
- "sibling",
21987
- "child"
21988
- ]).nullable(),
21989
- joinedAt: number(),
21990
- /** Tier 1 — the sub-class (`dog`, `van`), resolved from the member's track
21991
- * at read time. Absent when nothing resolved, never an empty string. */
21992
- label: string().optional(),
21993
- /** Tier 2 — the instance: a person's name, a plate. Absent when the pipeline
21994
- * recognised nobody, and absent for a member whose track has been pruned —
21995
- * a thumbnail that names the wrong person is worse than one naming nobody. */
21996
- subLabel: string().optional()
21997
- })).readonly()
21998
- });
21999
- /**
22000
- * What a LIST of groups carries: the envelope plus what it is MADE OF.
22001
- *
22002
- * Coarse on purpose — the operator's rule is "only the rough data on the list,
22003
- * we extend when we notice we need more". Enough to draw the card ("two people
22004
- * and a dog") and no more. The MEMBERS, their names and the per-member links
22005
- * are on {@link getSummary}: shipping every member of every group so a client
22006
- * can count them turns a page of two hundred groups into a thousand records to
22007
- * draw two hundred badges.
22008
- */
22009
- var SummaryListItemSchema = object({
22010
- summary: SummarySchema,
22011
- /** Class counts, most numerous first; `className: null` is a member whose
22012
- * class never resolved, counted so the counts add up to `memberCount`. */
22013
- classes: array(object({
22014
- className: string().nullable(),
22015
- count: number().int().positive()
22016
- })).readonly()
22017
- });
22018
- var SummariesPageSchema = object({ summaries: array(SummaryListItemSchema).readonly() });
22019
- /**
22020
- * The paged feed, deliberately the SAME shape as {@link RecentTracksQueryInput}.
22021
- *
22022
- * The reel on the cameras page and the Events gallery both ride a cursor, so a
22023
- * summaries feed that could only answer "the last N for these cameras"
22024
- * (`listSummaries`) would make groups available in the timeline and nowhere
22025
- * else. Two feeds with different ordering contracts would be two ideas of what
22026
- * "newest" means, on one screen.
22027
- */
22028
- var RecentSummariesQueryInput = object({
22029
- /** Devices to merge. An empty array yields an empty page. */
22030
- deviceIds: array(number()),
22031
- /** Window lower bound on `lastActiveAt` (inclusive). */
22032
- since: number().optional(),
22033
- /** Window upper bound on `lastActiveAt` (inclusive). */
22034
- until: number().optional(),
22035
- limit: number().int().min(1).max(500).default(100),
22036
- /** Opaque continuation cursor from a previous page's `nextCursor`. */
22037
- cursor: string().optional(),
22038
- /**
22039
- * Restrict to these classes — THE SAME FIELD `listRecentTracks` takes, and
22040
- * deliberately the same name: the events filter tree emits one list of ticked
22041
- * taxonomy nodes, and a summaries feed that called it something else would
22042
- * make the operator's one filter component produce two shapes.
22043
- *
22044
- * A question about the MEMBERS: a group matches when ANY of them does. "Show
22045
- * me the arrivals with a dog" has to return the group of four people who had
22046
- * one with them; a filter on the group's own fields could only ever answer
22047
- * about its primary.
22048
- *
22049
- * Matched against all THREE tiers of a member — the class (`animal`), the
22050
- * sub-class (`dog`) and the instance (a name, a plate) — because which tier a
22051
- * ticked node lives on is the taxonomy's business, not the caller's. `dog` is
22052
- * an event kind in the tree and a tier-1 label on an `animal` track; a filter
22053
- * that read only the class would answer "animal" and never "dog".
22054
- *
22055
- * ABSENT or EMPTY means no filter — absent is not a selection of none.
22056
- */
22057
- classes: array(string().min(1).max(60)).max(40).optional()
22058
- });
22059
- var RecentSummariesPageSchema = object({
22060
- /** Ordered by (`lastActiveAt` DESC, id DESC). Same light item as
22061
- * {@link listSummaries} — one list shape, so a card renders the same
22062
- * whichever feed drew it. */
22063
- summaries: array(SummaryListItemSchema).readonly(),
22064
- nextCursor: string().nullable()
22065
- });
22066
22173
  var RecentTracksPageSchema = object({
22067
22174
  /** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
22068
22175
  tracks: array(TrackSchema).readonly(),
@@ -22574,7 +22681,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
22574
22681
  classes: array(string()).optional(),
22575
22682
  /** See {@link ExcludeSourcesDoc}. */
22576
22683
  excludeSources: array(TrackSourceSchema).optional()
22577
- }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(SummariesQueryInput, SummariesPageSchema), method(RecentSummariesQueryInput, RecentSummariesPageSchema), method(object({ id: string() }), SummaryDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
22684
+ }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(object({ deviceId: number() }), _void(), {
22578
22685
  kind: "mutation",
22579
22686
  auth: "admin"
22580
22687
  }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({ deviceId: number() }), array(EventKindDescriptorSchema).readonly()), method(object({ deviceIds: array(number()).min(1).max(200) }), array(EventKindsForDeviceSchema).readonly()), method(object({
@@ -23754,6 +23861,23 @@ var MotionSourceEnum = _enum([
23754
23861
  */
23755
23862
  var MotionSourcesSchema = array(MotionSourceEnum);
23756
23863
  /**
23864
+ * The operator-facing name of each MOTION source (D672: `onboard` = the
23865
+ * camera's sensors — its own motion plus any sensor attached to it). The wire
23866
+ * value stays `onboard`; only the label changed. `detectionSources: 'onboard'`
23867
+ * ("Camera onboard AI") and the notification source filter keep their labels.
23868
+ */
23869
+ var MOTION_SOURCE_LABELS = {
23870
+ analyzer: "Frame-diff Analyzer (motion addon)",
23871
+ onboard: "Camera sensors",
23872
+ "device-activity": "Device activity (the device says it is working)"
23873
+ };
23874
+ /** The order the motion-source picker offers them in (not the enum's order). */
23875
+ var MOTION_SOURCE_PICKER_ORDER = [
23876
+ "analyzer",
23877
+ "onboard",
23878
+ "device-activity"
23879
+ ];
23880
+ /**
23757
23881
  * Which root detector a camera runs — EXACTLY ONE.
23758
23882
  *
23759
23883
  * Deliberately the SAME vocabulary post-analysis already tags every detection
@@ -24100,7 +24224,14 @@ var RunnerCameraConfigSchema = object({
24100
24224
  */
24101
24225
  inferenceDevices: array(RunnerInferenceDeviceSchema).readonly().optional()
24102
24226
  });
24103
- motionFpsField.min, motionFpsField.max, motionFpsField.step, motionFpsField.default, detectionFpsField.min, detectionFpsField.max, detectionFpsField.step, detectionFpsField.default, motionCooldownMsField.min, motionCooldownMsField.max, motionCooldownMsField.step, motionCooldownMsField.default, maxSessionHoldMsField.min, maxSessionHoldMsField.max, maxSessionHoldMsField.step, maxSessionHoldMsField.default, audioMotionWindowMsField.min, audioMotionWindowMsField.max, audioMotionWindowMsField.step, audioMotionWindowMsField.default, preRollInferenceFramesField.min, preRollInferenceFramesField.max, preRollInferenceFramesField.step, preRollInferenceFramesField.default, occupancyRecheckSecField.min, occupancyRecheckSecField.max, occupancyRecheckSecField.step, occupancyRecheckSecField.default, occupancyRecheckFramesField.min, occupancyRecheckFramesField.max, occupancyRecheckFramesField.step, occupancyRecheckFramesField.default;
24227
+ MOTION_SOURCE_PICKER_ORDER.map((value) => value === "onboard" ? {
24228
+ value,
24229
+ label: MOTION_SOURCE_LABELS[value],
24230
+ description: "The camera's own motion, plus any sensor attached to it"
24231
+ } : {
24232
+ value,
24233
+ label: MOTION_SOURCE_LABELS[value]
24234
+ }), motionFpsField.min, motionFpsField.max, motionFpsField.step, motionFpsField.default, detectionFpsField.min, detectionFpsField.max, detectionFpsField.step, detectionFpsField.default, motionCooldownMsField.min, motionCooldownMsField.max, motionCooldownMsField.step, motionCooldownMsField.default, maxSessionHoldMsField.min, maxSessionHoldMsField.max, maxSessionHoldMsField.step, maxSessionHoldMsField.default, audioMotionWindowMsField.min, audioMotionWindowMsField.max, audioMotionWindowMsField.step, audioMotionWindowMsField.default, preRollInferenceFramesField.min, preRollInferenceFramesField.max, preRollInferenceFramesField.step, preRollInferenceFramesField.default, occupancyRecheckSecField.min, occupancyRecheckSecField.max, occupancyRecheckSecField.step, occupancyRecheckSecField.default, occupancyRecheckFramesField.min, occupancyRecheckFramesField.max, occupancyRecheckFramesField.step, occupancyRecheckFramesField.default;
24104
24235
  /**
24105
24236
  * Runtime load summary returned by `getLocalLoad`. Used by the orchestrator's
24106
24237
  * load-balancing levels (L2 capacity-based, L3 hardware-aware) to decide
@@ -24674,6 +24805,11 @@ var CameraStatusSchema = object({
24674
24805
  */
24675
24806
  switchedOff: array(CameraSwitchIdSchema).readonly(),
24676
24807
  /**
24808
+ * The camera's attached sensors (D672). Optional only for a status composed
24809
+ * by an orchestrator older than D672; this orchestrator always sets it.
24810
+ */
24811
+ cameraSensors: CameraSensorsStatusSchema.optional(),
24812
+ /**
24677
24813
  * Stages of the bounded fan-out that were CUT SHORT — a timeout or a
24678
24814
  * rejection — and whose block is therefore `null` because we could not
24679
24815
  * READ it, not because there is nothing there.
@@ -24766,6 +24902,28 @@ var NodeInferenceDevicesSchema = object({
24766
24902
  reachable: boolean(),
24767
24903
  devices: array(NodeInferenceDeviceSchema).readonly()
24768
24904
  });
24905
+ /**
24906
+ * Pipeline Orchestrator capability — global load balancer + camera dispatcher.
24907
+ *
24908
+ * Lives on the hub. Tracks the camera-to-agent assignment map, listens to
24909
+ * device lifecycle events, queries each runner's capacity + hardware
24910
+ * profile, and dispatches `attachCamera` / `detachCamera` cap calls to the
24911
+ * appropriate runner instances. Persists assignments via the multi-level
24912
+ * settings store so they survive hub restarts.
24913
+ *
24914
+ * Strictly the control plane: never sees a frame, never calls inference,
24915
+ * never drains queues. The runner does that work locally on each agent.
24916
+ */
24917
+ /**
24918
+ * The input of `setCameraSensors` (G5, D676): the ONE typed write path of a
24919
+ * camera's attached sensors (D672). `config: null` removes the attachment —
24920
+ * the camera reads `not-configured` again, never `unreadable`.
24921
+ */
24922
+ var SetCameraSensorsInputSchema = object({
24923
+ deviceId: number().int().nonnegative(),
24924
+ /** `null` removes the attachment: the camera goes back to `not-configured`. */
24925
+ config: CameraSensorsConfigSchema.nullable()
24926
+ });
24769
24927
  method(StorageMigrationLeaseInputSchema, object({ paused: literal(true) }), {
24770
24928
  kind: "mutation",
24771
24929
  auth: "admin"
@@ -24920,7 +25078,10 @@ method(StorageMigrationLeaseInputSchema, object({ paused: literal(true) }), {
24920
25078
  }), CameraSwitchGroupSchema, {
24921
25079
  kind: "mutation",
24922
25080
  auth: "admin"
24923
- }), method(object({ deviceId: number() }), CameraStatusSchema), method(object({ deviceIds: array(number()).optional() }), array(CameraStatusSchema).readonly()), method(_void(), DiskReconcileJobSchema, {
25081
+ }), method(object({ deviceId: number() }), CameraStatusSchema), method(object({ deviceIds: array(number()).optional() }), array(CameraStatusSchema).readonly()), method(SetCameraSensorsInputSchema, object({ success: literal(true) }), {
25082
+ kind: "mutation",
25083
+ auth: "admin"
25084
+ }), method(_void(), DiskReconcileJobSchema, {
24924
25085
  kind: "mutation",
24925
25086
  auth: "admin"
24926
25087
  }), method(_void(), DiskReconcileJobSchema, { auth: "admin" }), method(_void(), array(PipelineTemplateSchema).readonly()), method(object({
@@ -30745,7 +30906,9 @@ object({
30745
30906
  detected: boolean(),
30746
30907
  timestamp: number(),
30747
30908
  source: MotionSourceEnum,
30748
- regions: array(MotionRegionSchema).readonly().optional()
30909
+ regions: array(MotionRegionSchema).readonly().optional(),
30910
+ /** Who started it (D672). Absent = the camera itself. Only `onboard` carries `sensor`. */
30911
+ triggeredBy: MotionTriggeredBySchema.optional()
30749
30912
  });
30750
30913
  DeviceType.Camera, DeviceType.Sensor, method(object({ deviceId: number() }), boolean());
30751
30914
  object({
@@ -35819,47 +35982,6 @@ DeviceType.Camera, method(object({
35819
35982
  detection: array(ZoneRuleSchema).readonly(),
35820
35983
  package: array(ZoneRuleSchema).readonly()
35821
35984
  });
35822
- var NUMBER = {
35823
- kind: "fixed",
35824
- result: ["number"]
35825
- };
35826
- var BOOLEAN = {
35827
- kind: "fixed",
35828
- result: ["boolean"]
35829
- };
35830
- Object.freeze({
35831
- min: NUMBER,
35832
- max: NUMBER,
35833
- abs: NUMBER,
35834
- floor: NUMBER,
35835
- ceil: NUMBER,
35836
- sqrt: NUMBER,
35837
- round: NUMBER,
35838
- pow: NUMBER,
35839
- clamp: NUMBER,
35840
- avg: NUMBER,
35841
- sum: NUMBER,
35842
- age: NUMBER,
35843
- convert: NUMBER,
35844
- coalesce: { kind: "coalesce" },
35845
- any: BOOLEAN,
35846
- all: BOOLEAN,
35847
- within: BOOLEAN,
35848
- latest: {
35849
- kind: "fixed",
35850
- result: ["number", "null"]
35851
- },
35852
- number: {
35853
- kind: "fixed",
35854
- result: ["number", "null"]
35855
- },
35856
- rose: {
35857
- kind: "fixed",
35858
- result: ["number", "null"]
35859
- },
35860
- count: NUMBER
35861
- });
35862
- `${COMPOSED_DEVICE_STABLE_ID_PREFIX}`;
35863
35985
  /**
35864
35986
  * Accessory device helpers — shared across drivers.
35865
35987
  *
@@ -38282,6 +38404,12 @@ Object.freeze({
38282
38404
  addonId: null,
38283
38405
  access: "view"
38284
38406
  },
38407
+ "coreBlocks.listComposableCaps": {
38408
+ capName: "core-blocks",
38409
+ capScope: "system",
38410
+ addonId: null,
38411
+ access: "view"
38412
+ },
38285
38413
  "coreBlocks.listCompositions": {
38286
38414
  capName: "core-blocks",
38287
38415
  capScope: "system",
@@ -41252,12 +41380,6 @@ Object.freeze({
41252
41380
  addonId: null,
41253
41381
  access: "view"
41254
41382
  },
41255
- "pipelineAnalytics.getSummary": {
41256
- capName: "pipeline-analytics",
41257
- capScope: "device",
41258
- addonId: null,
41259
- access: "view"
41260
- },
41261
41383
  "pipelineAnalytics.getTrack": {
41262
41384
  capName: "pipeline-analytics",
41263
41385
  capScope: "device",
@@ -41318,12 +41440,6 @@ Object.freeze({
41318
41440
  addonId: null,
41319
41441
  access: "view"
41320
41442
  },
41321
- "pipelineAnalytics.listRecentSummaries": {
41322
- capName: "pipeline-analytics",
41323
- capScope: "device",
41324
- addonId: null,
41325
- access: "view"
41326
- },
41327
41443
  "pipelineAnalytics.listRecentTracks": {
41328
41444
  capName: "pipeline-analytics",
41329
41445
  capScope: "device",
@@ -41354,12 +41470,6 @@ Object.freeze({
41354
41470
  addonId: null,
41355
41471
  access: "view"
41356
41472
  },
41357
- "pipelineAnalytics.listSummaries": {
41358
- capName: "pipeline-analytics",
41359
- capScope: "device",
41360
- addonId: null,
41361
- access: "view"
41362
- },
41363
41473
  "pipelineAnalytics.listTrackMedia": {
41364
41474
  capName: "pipeline-analytics",
41365
41475
  capScope: "device",
@@ -41984,6 +42094,12 @@ Object.freeze({
41984
42094
  addonId: null,
41985
42095
  access: "create"
41986
42096
  },
42097
+ "pipelineOrchestrator.setCameraSensors": {
42098
+ capName: "pipeline-orchestrator",
42099
+ capScope: "system",
42100
+ addonId: null,
42101
+ access: "create"
42102
+ },
41987
42103
  "pipelineOrchestrator.setCameraStepOverride": {
41988
42104
  capName: "pipeline-orchestrator",
41989
42105
  capScope: "system",
@@ -45529,11 +45645,6 @@ Object.freeze({
45529
45645
  form: "single",
45530
45646
  optional: true
45531
45647
  }],
45532
- "pipelineAnalytics.listRecentSummaries": [{
45533
- name: "deviceIds",
45534
- form: "array",
45535
- optional: false
45536
- }],
45537
45648
  "pipelineAnalytics.listRecentTracks": [{
45538
45649
  name: "deviceIds",
45539
45650
  form: "array",
@@ -45544,11 +45655,6 @@ Object.freeze({
45544
45655
  form: "array",
45545
45656
  optional: true
45546
45657
  }],
45547
- "pipelineAnalytics.listSummaries": [{
45548
- name: "deviceIds",
45549
- form: "array",
45550
- optional: false
45551
- }],
45552
45658
  "pipelineAnalytics.listTrackMedia": [{
45553
45659
  name: "deviceId",
45554
45660
  form: "single",
@@ -45704,6 +45810,11 @@ Object.freeze({
45704
45810
  form: "single",
45705
45811
  optional: false
45706
45812
  }],
45813
+ "pipelineOrchestrator.setCameraSensors": [{
45814
+ name: "deviceId",
45815
+ form: "single",
45816
+ optional: false
45817
+ }],
45707
45818
  "pipelineOrchestrator.setCameraStepOverride": [{
45708
45819
  name: "deviceId",
45709
45820
  form: "single",