@camstack/addon-ai 0.4.4 → 0.4.6
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/addon.js +124 -12
- package/dist/addon.mjs +124 -12
- package/package.json +1 -1
package/dist/addon.js
CHANGED
|
@@ -11021,6 +11021,8 @@ var QueryFilterSchema = object({
|
|
|
11021
11021
|
where: record(string(), unknown()).optional(),
|
|
11022
11022
|
whereIn: record(string(), array(unknown())).optional(),
|
|
11023
11023
|
whereBetween: record(string(), tuple([unknown(), unknown()])).optional(),
|
|
11024
|
+
/** NULL-safe exclusion: matches rows whose field is NULL OR != the value. */
|
|
11025
|
+
whereNot: record(string(), unknown()).optional(),
|
|
11024
11026
|
orderBy: object({
|
|
11025
11027
|
field: string(),
|
|
11026
11028
|
direction: _enum(["asc", "desc"])
|
|
@@ -11040,7 +11042,8 @@ var QueryFilterSchema = object({
|
|
|
11040
11042
|
var MutationFilterSchema = object({
|
|
11041
11043
|
where: record(string(), unknown()).optional(),
|
|
11042
11044
|
whereIn: record(string(), array(unknown())).optional(),
|
|
11043
|
-
whereBetween: record(string(), tuple([unknown(), unknown()])).optional()
|
|
11045
|
+
whereBetween: record(string(), tuple([unknown(), unknown()])).optional(),
|
|
11046
|
+
whereNot: record(string(), unknown()).optional()
|
|
11044
11047
|
});
|
|
11045
11048
|
/** A single stored record: `{ id, data }`. */
|
|
11046
11049
|
var SettingsRecordSchema = object({
|
|
@@ -16997,7 +17000,10 @@ var RecentTracksQueryInput = object({
|
|
|
16997
17000
|
* Encodes the (lastSeen, trackId) sort position — treat as opaque. */
|
|
16998
17001
|
cursor: string().optional(),
|
|
16999
17002
|
/** See {@link TrackProjectionSchema}. Default `full`. */
|
|
17000
|
-
projection: TrackProjectionSchema.optional()
|
|
17003
|
+
projection: TrackProjectionSchema.optional(),
|
|
17004
|
+
/** Include stationary-promoted rows (parked objects). Default false: the
|
|
17005
|
+
* feed lists passages; parking records live on the stationary registry. */
|
|
17006
|
+
includeStationary: boolean().optional()
|
|
17001
17007
|
});
|
|
17002
17008
|
var RecentTracksPageSchema = object({
|
|
17003
17009
|
/** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
|
|
@@ -17215,7 +17221,11 @@ DeviceType.Camera, method(object({ deviceId: number$1() }), array(TrackSchema).r
|
|
|
17215
17221
|
zone: TrackZoneFilterSchema.optional(),
|
|
17216
17222
|
/** See {@link TrackProjectionSchema}. Default `full` (backward
|
|
17217
17223
|
* compatible — omitting the field keeps today's exact behaviour). */
|
|
17218
|
-
projection: TrackProjectionSchema.optional()
|
|
17224
|
+
projection: TrackProjectionSchema.optional(),
|
|
17225
|
+
/** Include stationary-promoted rows (parked objects handed to the
|
|
17226
|
+
* stationary registry). Default false: the timeline lists passages,
|
|
17227
|
+
* not parking records (operator decision, 2026-08-15). */
|
|
17228
|
+
includeStationary: boolean().optional()
|
|
17219
17229
|
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(object({ deviceId: number$1() }), _void(), {
|
|
17220
17230
|
kind: "mutation",
|
|
17221
17231
|
auth: "admin"
|
|
@@ -17379,11 +17389,16 @@ DeviceType.Camera, method(object({ deviceId: number$1() }), array(TrackSchema).r
|
|
|
17379
17389
|
auth: "admin"
|
|
17380
17390
|
}), method(object({
|
|
17381
17391
|
eventId: string(),
|
|
17382
|
-
kind: MediaFileKindEnum.optional()
|
|
17392
|
+
kind: MediaFileKindEnum.optional(),
|
|
17393
|
+
deviceId: number$1()
|
|
17394
|
+
}), array(MediaFileSchema).readonly()), method(object({
|
|
17395
|
+
trackId: string(),
|
|
17396
|
+
kinds: array(MediaFileKindEnum).optional(),
|
|
17397
|
+
deviceId: number$1()
|
|
17383
17398
|
}), array(MediaFileSchema).readonly()), method(object({
|
|
17384
17399
|
trackId: string(),
|
|
17385
|
-
|
|
17386
|
-
}), array(
|
|
17400
|
+
deviceId: number$1()
|
|
17401
|
+
}), array(MediaFileInfoSchema).readonly()), method(SearchObjectEventsInput, array(ScoredObjectEventSchema).readonly()), method(object({}), WipeObjectEmbeddingsResultSchema, {
|
|
17387
17402
|
kind: "mutation",
|
|
17388
17403
|
auth: "admin"
|
|
17389
17404
|
}), method(RebuildObjectEmbeddingsInput, RebuildObjectEmbeddingsResultSchema, {
|
|
@@ -19332,7 +19347,31 @@ DeviceType.Camera, method(object({
|
|
|
19332
19347
|
lastCapturedAt: number$1().nullable(),
|
|
19333
19348
|
cacheAgeMs: number$1().nullable(),
|
|
19334
19349
|
etag: string().nullable()
|
|
19335
|
-
}))), systemMethod(object({
|
|
19350
|
+
}))), systemMethod(object({ deviceId: number$1() }), object({
|
|
19351
|
+
/** The battery slice as read, or null when the device has none. */
|
|
19352
|
+
battery: object({
|
|
19353
|
+
sleeping: boolean(),
|
|
19354
|
+
lastUpdated: number$1(),
|
|
19355
|
+
lastContactAt: number$1().optional()
|
|
19356
|
+
}).nullable(),
|
|
19357
|
+
/** The resolved snapshot state (what the overlay decision used). */
|
|
19358
|
+
state: object({
|
|
19359
|
+
isBattery: boolean(),
|
|
19360
|
+
reason: _enum([
|
|
19361
|
+
"disabled",
|
|
19362
|
+
"sleeping",
|
|
19363
|
+
"unreachable",
|
|
19364
|
+
"waking"
|
|
19365
|
+
]).nullable()
|
|
19366
|
+
}),
|
|
19367
|
+
/** The cached frame behind the next paint. */
|
|
19368
|
+
frame: object({
|
|
19369
|
+
capturedAt: number$1().nullable(),
|
|
19370
|
+
ageMs: number$1().nullable()
|
|
19371
|
+
}),
|
|
19372
|
+
/** A wake window is currently open (the Waking overlay's source). */
|
|
19373
|
+
waking: boolean()
|
|
19374
|
+
})), systemMethod(object({
|
|
19336
19375
|
/** The tiles a surface is actually rendering. One entry per (device,
|
|
19337
19376
|
* width) the caller will paint — the width is snapped to the server's
|
|
19338
19377
|
* ladder and becomes part of the link's SIGNED identity. */
|
|
@@ -19362,7 +19401,16 @@ targets: array(object({
|
|
|
19362
19401
|
/** A sleeping battery camera: the frame is deliberately stale and will
|
|
19363
19402
|
* NOT refresh in the background. A surface should say so rather than
|
|
19364
19403
|
* present it as current. */
|
|
19365
|
-
sleeping: boolean()
|
|
19404
|
+
sleeping: boolean(),
|
|
19405
|
+
/** Current device state rendered over the cached frame. State images
|
|
19406
|
+
* remain authoritative even when their photographic background is
|
|
19407
|
+
* old; null means the link must carry a current camera frame. */
|
|
19408
|
+
stateReason: _enum([
|
|
19409
|
+
"disabled",
|
|
19410
|
+
"sleeping",
|
|
19411
|
+
"unreachable",
|
|
19412
|
+
"waking"
|
|
19413
|
+
]).nullable()
|
|
19366
19414
|
})));
|
|
19367
19415
|
/**
|
|
19368
19416
|
* `sso-bridge` — internal hub-only cap that lets SSO-style auth
|
|
@@ -20884,6 +20932,25 @@ var BatteryStatusSchema = object({
|
|
|
20884
20932
|
/** Ms epoch of the last observation. Lets consumers reason about freshness. */
|
|
20885
20933
|
lastUpdated: number$1(),
|
|
20886
20934
|
/**
|
|
20935
|
+
* Ms epoch of the last time the device PROVED it was reachable — a
|
|
20936
|
+
* completed firmware round-trip, an observed wake, or an inbound push
|
|
20937
|
+
* (firmware event, email). `0`/absent = never since this slice was born.
|
|
20938
|
+
*
|
|
20939
|
+
* This is the ONLY input that separates "asleep" from "gone", and it is
|
|
20940
|
+
* fed exclusively by PASSIVE signals: nothing may write it by reaching
|
|
20941
|
+
* for the radio, because a poll that confirms reachability is the same
|
|
20942
|
+
* poll that drains the battery. See {@link deriveBatteryPresence} — the
|
|
20943
|
+
* single derivation every consumer must use; no surface computes its own.
|
|
20944
|
+
*
|
|
20945
|
+
* It is deliberately NOT a clock in the
|
|
20946
|
+
* `scripts/check-runtime-state-durability.ts` sense: it is the
|
|
20947
|
+
* observation itself, and it is the only thing a 30-hour silence is
|
|
20948
|
+
* visible in. Writers quantise it (see `CONTACT_WRITE_QUANTUM_MS` in the
|
|
20949
|
+
* Reolink provider) so a value that means "recently" cannot cost a
|
|
20950
|
+
* SQLite commit per round-trip.
|
|
20951
|
+
*/
|
|
20952
|
+
lastContactAt: number$1().optional(),
|
|
20953
|
+
/**
|
|
20887
20954
|
* True when the source is a BINARY low-battery indicator (HA
|
|
20888
20955
|
* `binary_sensor` device_class=battery / `LOW_BAT`) that has no real
|
|
20889
20956
|
* charge level — `percentage` is then a coarse stand-in (100 = normal,
|
|
@@ -25161,6 +25228,16 @@ var CamStreamDescriptorSchema = object({
|
|
|
25161
25228
|
/** Transport-specific opaque metadata (e.g. rfc4571 SDP). */
|
|
25162
25229
|
metadata: record(string(), unknown()).optional()
|
|
25163
25230
|
});
|
|
25231
|
+
object({
|
|
25232
|
+
/** The descriptors as last built from a real camera response. Never a guess:
|
|
25233
|
+
* a failed or refused build writes NOTHING, so a restored catalog is always
|
|
25234
|
+
* one the camera itself once produced. */
|
|
25235
|
+
descriptors: array(CamStreamDescriptorSchema),
|
|
25236
|
+
/** Ms epoch of the build that produced {@link descriptors}. Lets the wake
|
|
25237
|
+
* path decide whether the camera's own awake window is worth spending on a
|
|
25238
|
+
* re-read. */
|
|
25239
|
+
lastFetchedAt: number$1()
|
|
25240
|
+
});
|
|
25164
25241
|
DeviceType.Camera, method(object({ deviceId: number$1().int().nonnegative() }), array(CamStreamDescriptorSchema).readonly());
|
|
25165
25242
|
/** One of the camera's stream profiles. */
|
|
25166
25243
|
var StreamProfileSchema = _enum([
|
|
@@ -30509,6 +30586,12 @@ Object.freeze({
|
|
|
30509
30586
|
addonId: null,
|
|
30510
30587
|
access: "view"
|
|
30511
30588
|
},
|
|
30589
|
+
"snapshot.getDebugState": {
|
|
30590
|
+
capName: "snapshot",
|
|
30591
|
+
capScope: "device",
|
|
30592
|
+
addonId: null,
|
|
30593
|
+
access: "view"
|
|
30594
|
+
},
|
|
30512
30595
|
"snapshot.getSnapshot": {
|
|
30513
30596
|
capName: "snapshot",
|
|
30514
30597
|
capScope: "device",
|
|
@@ -32591,6 +32674,11 @@ Object.freeze({
|
|
|
32591
32674
|
form: "single",
|
|
32592
32675
|
optional: false
|
|
32593
32676
|
}],
|
|
32677
|
+
"pipelineAnalytics.getEventMedia": [{
|
|
32678
|
+
name: "deviceId",
|
|
32679
|
+
form: "single",
|
|
32680
|
+
optional: false
|
|
32681
|
+
}],
|
|
32594
32682
|
"pipelineAnalytics.getKeyEvents": [{
|
|
32595
32683
|
name: "deviceId",
|
|
32596
32684
|
form: "single",
|
|
@@ -32621,6 +32709,11 @@ Object.freeze({
|
|
|
32621
32709
|
form: "single",
|
|
32622
32710
|
optional: false
|
|
32623
32711
|
}],
|
|
32712
|
+
"pipelineAnalytics.getTrackMedia": [{
|
|
32713
|
+
name: "deviceId",
|
|
32714
|
+
form: "single",
|
|
32715
|
+
optional: false
|
|
32716
|
+
}],
|
|
32624
32717
|
"pipelineAnalytics.getTrainingExportSummary": [{
|
|
32625
32718
|
name: "deviceIds",
|
|
32626
32719
|
form: "array",
|
|
@@ -32656,6 +32749,11 @@ Object.freeze({
|
|
|
32656
32749
|
form: "array",
|
|
32657
32750
|
optional: true
|
|
32658
32751
|
}],
|
|
32752
|
+
"pipelineAnalytics.listTrackMedia": [{
|
|
32753
|
+
name: "deviceId",
|
|
32754
|
+
form: "single",
|
|
32755
|
+
optional: false
|
|
32756
|
+
}],
|
|
32659
32757
|
"pipelineAnalytics.listTracks": [{
|
|
32660
32758
|
name: "deviceId",
|
|
32661
32759
|
form: "single",
|
|
@@ -33091,11 +33189,22 @@ Object.freeze({
|
|
|
33091
33189
|
form: "single",
|
|
33092
33190
|
optional: false
|
|
33093
33191
|
}],
|
|
33192
|
+
"snapshot.getDebugState": [{
|
|
33193
|
+
name: "deviceId",
|
|
33194
|
+
form: "single",
|
|
33195
|
+
optional: false
|
|
33196
|
+
}],
|
|
33094
33197
|
"snapshot.getSnapshot": [{
|
|
33095
33198
|
name: "deviceId",
|
|
33096
33199
|
form: "single",
|
|
33097
33200
|
optional: false
|
|
33098
33201
|
}],
|
|
33202
|
+
"snapshot.getSnapshotLinks": [{
|
|
33203
|
+
name: "targets",
|
|
33204
|
+
form: "object-array",
|
|
33205
|
+
optional: false,
|
|
33206
|
+
itemField: "deviceId"
|
|
33207
|
+
}],
|
|
33099
33208
|
"snapshot.getSnapshotOverview": [{
|
|
33100
33209
|
name: "deviceIds",
|
|
33101
33210
|
form: "array",
|
|
@@ -72400,7 +72509,9 @@ var TestChatImageRefSchema = discriminatedUnion("kind", [object({
|
|
|
72400
72509
|
deviceId: number$1().int().positive()
|
|
72401
72510
|
}), object({
|
|
72402
72511
|
kind: literal("track"),
|
|
72403
|
-
trackId: string().min(1)
|
|
72512
|
+
trackId: string().min(1),
|
|
72513
|
+
/** Owning device — `getTrackMedia` requires it as the read's scope. */
|
|
72514
|
+
deviceId: number$1().int().positive()
|
|
72404
72515
|
})]);
|
|
72405
72516
|
/**
|
|
72406
72517
|
* `.strict()`, and it is load-bearing.
|
|
@@ -72626,7 +72737,7 @@ async function resolveImage(deps, ref) {
|
|
|
72626
72737
|
}
|
|
72627
72738
|
let rows;
|
|
72628
72739
|
try {
|
|
72629
|
-
rows = await deps.getTrackMedia(ref.trackId, TRACK_MEDIA_PREFERENCE);
|
|
72740
|
+
rows = await deps.getTrackMedia(ref.trackId, TRACK_MEDIA_PREFERENCE, ref.deviceId);
|
|
72630
72741
|
} catch (cause) {
|
|
72631
72742
|
const message = cause instanceof Error ? cause.message : String(cause);
|
|
72632
72743
|
deps.logger.warn("ai test chat: track media read failed — turn dropped", { meta: {
|
|
@@ -73221,9 +73332,10 @@ var AiAddon = class extends BaseAddon {
|
|
|
73221
73332
|
});
|
|
73222
73333
|
},
|
|
73223
73334
|
getSnapshot: (deviceId) => api.snapshot.getSnapshot.query({ deviceId }),
|
|
73224
|
-
getTrackMedia: (trackId, kinds) => api.pipelineAnalytics.getTrackMedia.query({
|
|
73335
|
+
getTrackMedia: (trackId, kinds, deviceId) => api.pipelineAnalytics.getTrackMedia.query({
|
|
73225
73336
|
trackId,
|
|
73226
|
-
kinds: [...kinds]
|
|
73337
|
+
kinds: [...kinds],
|
|
73338
|
+
deviceId
|
|
73227
73339
|
}),
|
|
73228
73340
|
recordUsage: (row) => usage.record(row),
|
|
73229
73341
|
logger,
|
package/dist/addon.mjs
CHANGED
|
@@ -11047,6 +11047,8 @@ var QueryFilterSchema = object({
|
|
|
11047
11047
|
where: record(string(), unknown()).optional(),
|
|
11048
11048
|
whereIn: record(string(), array(unknown())).optional(),
|
|
11049
11049
|
whereBetween: record(string(), tuple([unknown(), unknown()])).optional(),
|
|
11050
|
+
/** NULL-safe exclusion: matches rows whose field is NULL OR != the value. */
|
|
11051
|
+
whereNot: record(string(), unknown()).optional(),
|
|
11050
11052
|
orderBy: object({
|
|
11051
11053
|
field: string(),
|
|
11052
11054
|
direction: _enum(["asc", "desc"])
|
|
@@ -11066,7 +11068,8 @@ var QueryFilterSchema = object({
|
|
|
11066
11068
|
var MutationFilterSchema = object({
|
|
11067
11069
|
where: record(string(), unknown()).optional(),
|
|
11068
11070
|
whereIn: record(string(), array(unknown())).optional(),
|
|
11069
|
-
whereBetween: record(string(), tuple([unknown(), unknown()])).optional()
|
|
11071
|
+
whereBetween: record(string(), tuple([unknown(), unknown()])).optional(),
|
|
11072
|
+
whereNot: record(string(), unknown()).optional()
|
|
11070
11073
|
});
|
|
11071
11074
|
/** A single stored record: `{ id, data }`. */
|
|
11072
11075
|
var SettingsRecordSchema = object({
|
|
@@ -17023,7 +17026,10 @@ var RecentTracksQueryInput = object({
|
|
|
17023
17026
|
* Encodes the (lastSeen, trackId) sort position — treat as opaque. */
|
|
17024
17027
|
cursor: string().optional(),
|
|
17025
17028
|
/** See {@link TrackProjectionSchema}. Default `full`. */
|
|
17026
|
-
projection: TrackProjectionSchema.optional()
|
|
17029
|
+
projection: TrackProjectionSchema.optional(),
|
|
17030
|
+
/** Include stationary-promoted rows (parked objects). Default false: the
|
|
17031
|
+
* feed lists passages; parking records live on the stationary registry. */
|
|
17032
|
+
includeStationary: boolean().optional()
|
|
17027
17033
|
});
|
|
17028
17034
|
var RecentTracksPageSchema = object({
|
|
17029
17035
|
/** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
|
|
@@ -17241,7 +17247,11 @@ DeviceType.Camera, method(object({ deviceId: number$1() }), array(TrackSchema).r
|
|
|
17241
17247
|
zone: TrackZoneFilterSchema.optional(),
|
|
17242
17248
|
/** See {@link TrackProjectionSchema}. Default `full` (backward
|
|
17243
17249
|
* compatible — omitting the field keeps today's exact behaviour). */
|
|
17244
|
-
projection: TrackProjectionSchema.optional()
|
|
17250
|
+
projection: TrackProjectionSchema.optional(),
|
|
17251
|
+
/** Include stationary-promoted rows (parked objects handed to the
|
|
17252
|
+
* stationary registry). Default false: the timeline lists passages,
|
|
17253
|
+
* not parking records (operator decision, 2026-08-15). */
|
|
17254
|
+
includeStationary: boolean().optional()
|
|
17245
17255
|
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(object({ deviceId: number$1() }), _void(), {
|
|
17246
17256
|
kind: "mutation",
|
|
17247
17257
|
auth: "admin"
|
|
@@ -17405,11 +17415,16 @@ DeviceType.Camera, method(object({ deviceId: number$1() }), array(TrackSchema).r
|
|
|
17405
17415
|
auth: "admin"
|
|
17406
17416
|
}), method(object({
|
|
17407
17417
|
eventId: string(),
|
|
17408
|
-
kind: MediaFileKindEnum.optional()
|
|
17418
|
+
kind: MediaFileKindEnum.optional(),
|
|
17419
|
+
deviceId: number$1()
|
|
17420
|
+
}), array(MediaFileSchema).readonly()), method(object({
|
|
17421
|
+
trackId: string(),
|
|
17422
|
+
kinds: array(MediaFileKindEnum).optional(),
|
|
17423
|
+
deviceId: number$1()
|
|
17409
17424
|
}), array(MediaFileSchema).readonly()), method(object({
|
|
17410
17425
|
trackId: string(),
|
|
17411
|
-
|
|
17412
|
-
}), array(
|
|
17426
|
+
deviceId: number$1()
|
|
17427
|
+
}), array(MediaFileInfoSchema).readonly()), method(SearchObjectEventsInput, array(ScoredObjectEventSchema).readonly()), method(object({}), WipeObjectEmbeddingsResultSchema, {
|
|
17413
17428
|
kind: "mutation",
|
|
17414
17429
|
auth: "admin"
|
|
17415
17430
|
}), method(RebuildObjectEmbeddingsInput, RebuildObjectEmbeddingsResultSchema, {
|
|
@@ -19358,7 +19373,31 @@ DeviceType.Camera, method(object({
|
|
|
19358
19373
|
lastCapturedAt: number$1().nullable(),
|
|
19359
19374
|
cacheAgeMs: number$1().nullable(),
|
|
19360
19375
|
etag: string().nullable()
|
|
19361
|
-
}))), systemMethod(object({
|
|
19376
|
+
}))), systemMethod(object({ deviceId: number$1() }), object({
|
|
19377
|
+
/** The battery slice as read, or null when the device has none. */
|
|
19378
|
+
battery: object({
|
|
19379
|
+
sleeping: boolean(),
|
|
19380
|
+
lastUpdated: number$1(),
|
|
19381
|
+
lastContactAt: number$1().optional()
|
|
19382
|
+
}).nullable(),
|
|
19383
|
+
/** The resolved snapshot state (what the overlay decision used). */
|
|
19384
|
+
state: object({
|
|
19385
|
+
isBattery: boolean(),
|
|
19386
|
+
reason: _enum([
|
|
19387
|
+
"disabled",
|
|
19388
|
+
"sleeping",
|
|
19389
|
+
"unreachable",
|
|
19390
|
+
"waking"
|
|
19391
|
+
]).nullable()
|
|
19392
|
+
}),
|
|
19393
|
+
/** The cached frame behind the next paint. */
|
|
19394
|
+
frame: object({
|
|
19395
|
+
capturedAt: number$1().nullable(),
|
|
19396
|
+
ageMs: number$1().nullable()
|
|
19397
|
+
}),
|
|
19398
|
+
/** A wake window is currently open (the Waking overlay's source). */
|
|
19399
|
+
waking: boolean()
|
|
19400
|
+
})), systemMethod(object({
|
|
19362
19401
|
/** The tiles a surface is actually rendering. One entry per (device,
|
|
19363
19402
|
* width) the caller will paint — the width is snapped to the server's
|
|
19364
19403
|
* ladder and becomes part of the link's SIGNED identity. */
|
|
@@ -19388,7 +19427,16 @@ targets: array(object({
|
|
|
19388
19427
|
/** A sleeping battery camera: the frame is deliberately stale and will
|
|
19389
19428
|
* NOT refresh in the background. A surface should say so rather than
|
|
19390
19429
|
* present it as current. */
|
|
19391
|
-
sleeping: boolean()
|
|
19430
|
+
sleeping: boolean(),
|
|
19431
|
+
/** Current device state rendered over the cached frame. State images
|
|
19432
|
+
* remain authoritative even when their photographic background is
|
|
19433
|
+
* old; null means the link must carry a current camera frame. */
|
|
19434
|
+
stateReason: _enum([
|
|
19435
|
+
"disabled",
|
|
19436
|
+
"sleeping",
|
|
19437
|
+
"unreachable",
|
|
19438
|
+
"waking"
|
|
19439
|
+
]).nullable()
|
|
19392
19440
|
})));
|
|
19393
19441
|
/**
|
|
19394
19442
|
* `sso-bridge` — internal hub-only cap that lets SSO-style auth
|
|
@@ -20910,6 +20958,25 @@ var BatteryStatusSchema = object({
|
|
|
20910
20958
|
/** Ms epoch of the last observation. Lets consumers reason about freshness. */
|
|
20911
20959
|
lastUpdated: number$1(),
|
|
20912
20960
|
/**
|
|
20961
|
+
* Ms epoch of the last time the device PROVED it was reachable — a
|
|
20962
|
+
* completed firmware round-trip, an observed wake, or an inbound push
|
|
20963
|
+
* (firmware event, email). `0`/absent = never since this slice was born.
|
|
20964
|
+
*
|
|
20965
|
+
* This is the ONLY input that separates "asleep" from "gone", and it is
|
|
20966
|
+
* fed exclusively by PASSIVE signals: nothing may write it by reaching
|
|
20967
|
+
* for the radio, because a poll that confirms reachability is the same
|
|
20968
|
+
* poll that drains the battery. See {@link deriveBatteryPresence} — the
|
|
20969
|
+
* single derivation every consumer must use; no surface computes its own.
|
|
20970
|
+
*
|
|
20971
|
+
* It is deliberately NOT a clock in the
|
|
20972
|
+
* `scripts/check-runtime-state-durability.ts` sense: it is the
|
|
20973
|
+
* observation itself, and it is the only thing a 30-hour silence is
|
|
20974
|
+
* visible in. Writers quantise it (see `CONTACT_WRITE_QUANTUM_MS` in the
|
|
20975
|
+
* Reolink provider) so a value that means "recently" cannot cost a
|
|
20976
|
+
* SQLite commit per round-trip.
|
|
20977
|
+
*/
|
|
20978
|
+
lastContactAt: number$1().optional(),
|
|
20979
|
+
/**
|
|
20913
20980
|
* True when the source is a BINARY low-battery indicator (HA
|
|
20914
20981
|
* `binary_sensor` device_class=battery / `LOW_BAT`) that has no real
|
|
20915
20982
|
* charge level — `percentage` is then a coarse stand-in (100 = normal,
|
|
@@ -25187,6 +25254,16 @@ var CamStreamDescriptorSchema = object({
|
|
|
25187
25254
|
/** Transport-specific opaque metadata (e.g. rfc4571 SDP). */
|
|
25188
25255
|
metadata: record(string(), unknown()).optional()
|
|
25189
25256
|
});
|
|
25257
|
+
object({
|
|
25258
|
+
/** The descriptors as last built from a real camera response. Never a guess:
|
|
25259
|
+
* a failed or refused build writes NOTHING, so a restored catalog is always
|
|
25260
|
+
* one the camera itself once produced. */
|
|
25261
|
+
descriptors: array(CamStreamDescriptorSchema),
|
|
25262
|
+
/** Ms epoch of the build that produced {@link descriptors}. Lets the wake
|
|
25263
|
+
* path decide whether the camera's own awake window is worth spending on a
|
|
25264
|
+
* re-read. */
|
|
25265
|
+
lastFetchedAt: number$1()
|
|
25266
|
+
});
|
|
25190
25267
|
DeviceType.Camera, method(object({ deviceId: number$1().int().nonnegative() }), array(CamStreamDescriptorSchema).readonly());
|
|
25191
25268
|
/** One of the camera's stream profiles. */
|
|
25192
25269
|
var StreamProfileSchema = _enum([
|
|
@@ -30535,6 +30612,12 @@ Object.freeze({
|
|
|
30535
30612
|
addonId: null,
|
|
30536
30613
|
access: "view"
|
|
30537
30614
|
},
|
|
30615
|
+
"snapshot.getDebugState": {
|
|
30616
|
+
capName: "snapshot",
|
|
30617
|
+
capScope: "device",
|
|
30618
|
+
addonId: null,
|
|
30619
|
+
access: "view"
|
|
30620
|
+
},
|
|
30538
30621
|
"snapshot.getSnapshot": {
|
|
30539
30622
|
capName: "snapshot",
|
|
30540
30623
|
capScope: "device",
|
|
@@ -32617,6 +32700,11 @@ Object.freeze({
|
|
|
32617
32700
|
form: "single",
|
|
32618
32701
|
optional: false
|
|
32619
32702
|
}],
|
|
32703
|
+
"pipelineAnalytics.getEventMedia": [{
|
|
32704
|
+
name: "deviceId",
|
|
32705
|
+
form: "single",
|
|
32706
|
+
optional: false
|
|
32707
|
+
}],
|
|
32620
32708
|
"pipelineAnalytics.getKeyEvents": [{
|
|
32621
32709
|
name: "deviceId",
|
|
32622
32710
|
form: "single",
|
|
@@ -32647,6 +32735,11 @@ Object.freeze({
|
|
|
32647
32735
|
form: "single",
|
|
32648
32736
|
optional: false
|
|
32649
32737
|
}],
|
|
32738
|
+
"pipelineAnalytics.getTrackMedia": [{
|
|
32739
|
+
name: "deviceId",
|
|
32740
|
+
form: "single",
|
|
32741
|
+
optional: false
|
|
32742
|
+
}],
|
|
32650
32743
|
"pipelineAnalytics.getTrainingExportSummary": [{
|
|
32651
32744
|
name: "deviceIds",
|
|
32652
32745
|
form: "array",
|
|
@@ -32682,6 +32775,11 @@ Object.freeze({
|
|
|
32682
32775
|
form: "array",
|
|
32683
32776
|
optional: true
|
|
32684
32777
|
}],
|
|
32778
|
+
"pipelineAnalytics.listTrackMedia": [{
|
|
32779
|
+
name: "deviceId",
|
|
32780
|
+
form: "single",
|
|
32781
|
+
optional: false
|
|
32782
|
+
}],
|
|
32685
32783
|
"pipelineAnalytics.listTracks": [{
|
|
32686
32784
|
name: "deviceId",
|
|
32687
32785
|
form: "single",
|
|
@@ -33117,11 +33215,22 @@ Object.freeze({
|
|
|
33117
33215
|
form: "single",
|
|
33118
33216
|
optional: false
|
|
33119
33217
|
}],
|
|
33218
|
+
"snapshot.getDebugState": [{
|
|
33219
|
+
name: "deviceId",
|
|
33220
|
+
form: "single",
|
|
33221
|
+
optional: false
|
|
33222
|
+
}],
|
|
33120
33223
|
"snapshot.getSnapshot": [{
|
|
33121
33224
|
name: "deviceId",
|
|
33122
33225
|
form: "single",
|
|
33123
33226
|
optional: false
|
|
33124
33227
|
}],
|
|
33228
|
+
"snapshot.getSnapshotLinks": [{
|
|
33229
|
+
name: "targets",
|
|
33230
|
+
form: "object-array",
|
|
33231
|
+
optional: false,
|
|
33232
|
+
itemField: "deviceId"
|
|
33233
|
+
}],
|
|
33125
33234
|
"snapshot.getSnapshotOverview": [{
|
|
33126
33235
|
name: "deviceIds",
|
|
33127
33236
|
form: "array",
|
|
@@ -72426,7 +72535,9 @@ var TestChatImageRefSchema = discriminatedUnion("kind", [object({
|
|
|
72426
72535
|
deviceId: number$1().int().positive()
|
|
72427
72536
|
}), object({
|
|
72428
72537
|
kind: literal("track"),
|
|
72429
|
-
trackId: string().min(1)
|
|
72538
|
+
trackId: string().min(1),
|
|
72539
|
+
/** Owning device — `getTrackMedia` requires it as the read's scope. */
|
|
72540
|
+
deviceId: number$1().int().positive()
|
|
72430
72541
|
})]);
|
|
72431
72542
|
/**
|
|
72432
72543
|
* `.strict()`, and it is load-bearing.
|
|
@@ -72652,7 +72763,7 @@ async function resolveImage(deps, ref) {
|
|
|
72652
72763
|
}
|
|
72653
72764
|
let rows;
|
|
72654
72765
|
try {
|
|
72655
|
-
rows = await deps.getTrackMedia(ref.trackId, TRACK_MEDIA_PREFERENCE);
|
|
72766
|
+
rows = await deps.getTrackMedia(ref.trackId, TRACK_MEDIA_PREFERENCE, ref.deviceId);
|
|
72656
72767
|
} catch (cause) {
|
|
72657
72768
|
const message = cause instanceof Error ? cause.message : String(cause);
|
|
72658
72769
|
deps.logger.warn("ai test chat: track media read failed — turn dropped", { meta: {
|
|
@@ -73247,9 +73358,10 @@ var AiAddon = class extends BaseAddon {
|
|
|
73247
73358
|
});
|
|
73248
73359
|
},
|
|
73249
73360
|
getSnapshot: (deviceId) => api.snapshot.getSnapshot.query({ deviceId }),
|
|
73250
|
-
getTrackMedia: (trackId, kinds) => api.pipelineAnalytics.getTrackMedia.query({
|
|
73361
|
+
getTrackMedia: (trackId, kinds, deviceId) => api.pipelineAnalytics.getTrackMedia.query({
|
|
73251
73362
|
trackId,
|
|
73252
|
-
kinds: [...kinds]
|
|
73363
|
+
kinds: [...kinds],
|
|
73364
|
+
deviceId
|
|
73253
73365
|
}),
|
|
73254
73366
|
recordUsage: (row) => usage.record(row),
|
|
73255
73367
|
logger,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-ai",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.6",
|
|
4
4
|
"description": "AI addon for CamStack — the `llm` collection provider (cloud, LAN, and camstack-managed local llama.cpp profiles) plus the per-node `llm-runtime` managed executor.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"camstack",
|