@camera.ui/browser 0.0.189 → 0.0.191
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +36 -0
- package/dist/index.js +98 -65
- package/package.json +4 -4
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { AssistantToolReference } from '@camera.ui/sdk';
|
|
1
2
|
import { AudioProperty } from '@camera.ui/sdk';
|
|
2
3
|
import { AudioSensorProperties } from '@camera.ui/sdk';
|
|
3
4
|
import type { BaseCamera } from '@camera.ui/sdk';
|
|
@@ -41,6 +42,7 @@ import { HumidityProperty } from '@camera.ui/sdk';
|
|
|
41
42
|
import { IlluminanceInfoProperties } from '@camera.ui/sdk';
|
|
42
43
|
import { IlluminanceProperty } from '@camera.ui/sdk';
|
|
43
44
|
import { InjectionKey } from 'vue';
|
|
45
|
+
import type { JSONSchema } from '@tanstack/ai';
|
|
44
46
|
import { LeakProperty } from '@camera.ui/sdk';
|
|
45
47
|
import { LeakSensorProperties } from '@camera.ui/sdk';
|
|
46
48
|
import { LicensePlateDetection } from '@camera.ui/sdk';
|
|
@@ -130,6 +132,36 @@ declare interface ActivityModeState {
|
|
|
130
132
|
readonly hasActivity: Ref<boolean>;
|
|
131
133
|
}
|
|
132
134
|
|
|
135
|
+
declare interface AssistantAccess {
|
|
136
|
+
allowed: boolean;
|
|
137
|
+
model: string | null;
|
|
138
|
+
vision: boolean | null;
|
|
139
|
+
language: string | null;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
declare interface AssistantAskRequest {
|
|
143
|
+
pluginId: string;
|
|
144
|
+
prompt: string;
|
|
145
|
+
system?: string;
|
|
146
|
+
images?: { data: Uint8Array; mimeType: string }[];
|
|
147
|
+
outputSchema?: JSONSchema;
|
|
148
|
+
timeoutMs?: number;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
declare type AssistantAskResult =
|
|
152
|
+
| { ok: true; text: string; json?: unknown; usage: { promptTokens: number; completionTokens: number } }
|
|
153
|
+
| { ok: false; reason: 'not_allowed' | 'unconfigured' | 'timeout' | 'error'; message: string };
|
|
154
|
+
|
|
155
|
+
declare interface AssistantPost {
|
|
156
|
+
userId: string;
|
|
157
|
+
threadId: string;
|
|
158
|
+
title?: string;
|
|
159
|
+
text: string;
|
|
160
|
+
label?: string;
|
|
161
|
+
image?: { data: string; mimeType: string };
|
|
162
|
+
references?: AssistantToolReference[];
|
|
163
|
+
}
|
|
164
|
+
|
|
133
165
|
/* Excluded from this release type: AudioProperty */
|
|
134
166
|
|
|
135
167
|
/* Excluded from this release type: AudioSensorProperties */
|
|
@@ -296,6 +328,9 @@ export declare interface CoreManagerInterface {
|
|
|
296
328
|
getPlugin(pluginName: string): Promise<HostPluginInfo | undefined>;
|
|
297
329
|
getPluginsByInterface(interfaceName: PluginInterface): Promise<HostPluginInfo[]>;
|
|
298
330
|
getFloorPlan(): Promise<FloorPlan>;
|
|
331
|
+
assistantAsk(request: AssistantAskRequest): Promise<AssistantAskResult>;
|
|
332
|
+
assistantAccess(pluginId: string): Promise<AssistantAccess>;
|
|
333
|
+
assistantPost(post: AssistantPost): Promise<boolean>;
|
|
299
334
|
}
|
|
300
335
|
|
|
301
336
|
export declare interface CoreManagerNamespaces {
|
|
@@ -1043,6 +1078,7 @@ export declare interface ReactiveSmokeSensor extends ReactiveSensor<SmokeSensorP
|
|
|
1043
1078
|
|
|
1044
1079
|
export declare interface ReactiveStorage {
|
|
1045
1080
|
readonly proxy: Promisify<StorageRPC>;
|
|
1081
|
+
readonly client: RPCClient;
|
|
1046
1082
|
readonly config: ShallowRef<SchemaConfig | undefined>;
|
|
1047
1083
|
readonly isLoading: Ref<boolean>;
|
|
1048
1084
|
readonly error: Ref<Error | undefined>;
|
package/dist/index.js
CHANGED
|
@@ -430,9 +430,7 @@ function fetchSnapshotShared(deviceManager, id, forceFresh = false) {
|
|
|
430
430
|
const device = await acquireCameraDevice(deviceManager, id);
|
|
431
431
|
try {
|
|
432
432
|
if (!device) return void 0;
|
|
433
|
-
|
|
434
|
-
if (result) setSnapshot(id, result);
|
|
435
|
-
return result ?? void 0;
|
|
433
|
+
return await device.fetchSnapshot(void 0, forceFresh ? true : void 0) ?? void 0;
|
|
436
434
|
} finally {
|
|
437
435
|
if (device) releaseCameraDevice(id);
|
|
438
436
|
}
|
|
@@ -445,28 +443,32 @@ function hookReconnectRefresh(cameraUi, deviceManager) {
|
|
|
445
443
|
if (reconnectHooked) return;
|
|
446
444
|
reconnectHooked = true;
|
|
447
445
|
cameraUi.on("reconnected", () => {
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
446
|
+
setTimeout(() => {
|
|
447
|
+
let delay = 0;
|
|
448
|
+
for (const id of subscribers.keys()) {
|
|
449
|
+
if ((subscribers.get(id)?.size ?? 0) === 0) continue;
|
|
450
|
+
const cameraId = id;
|
|
451
|
+
setTimeout(() => {
|
|
452
|
+
if ((subscribers.get(cameraId)?.size ?? 0) === 0) return;
|
|
453
|
+
fetchSnapshotShared(deviceManager, cameraId).catch(() => void 0);
|
|
454
|
+
}, delay);
|
|
455
|
+
delay += 150;
|
|
456
|
+
}
|
|
457
|
+
}, 0);
|
|
458
458
|
});
|
|
459
459
|
}
|
|
460
460
|
function deferRevoke(url) {
|
|
461
461
|
setTimeout(() => URL.revokeObjectURL(url), REVOKE_DELAY_MS);
|
|
462
462
|
}
|
|
463
463
|
function setSnapshot(cameraId, data, fetchedAt) {
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
464
|
+
if (snapshotCache.get(cameraId) !== data) {
|
|
465
|
+
const oldUrl = urlCache.get(cameraId);
|
|
466
|
+
if (oldUrl) {
|
|
467
|
+
deferRevoke(oldUrl);
|
|
468
|
+
urlCache.delete(cameraId);
|
|
469
|
+
}
|
|
470
|
+
snapshotCache.set(cameraId, data);
|
|
468
471
|
}
|
|
469
|
-
snapshotCache.set(cameraId, data);
|
|
470
472
|
if (fetchedAt !== void 0) timestampCache.set(cameraId, fetchedAt);
|
|
471
473
|
notify(cameraId);
|
|
472
474
|
}
|
|
@@ -715,7 +717,7 @@ async function createReactiveCameraDevice(rpcOrContext, initialCamera) {
|
|
|
715
717
|
case "frameWorkerState":
|
|
716
718
|
frameWorkerConnected.value = event.data;
|
|
717
719
|
break;
|
|
718
|
-
case "snapshot:updated": setSnapshot(initialCamera._id, event.data.snapshot,
|
|
720
|
+
case "snapshot:updated": setSnapshot(initialCamera._id, event.data.snapshot, event.data.fetchedAt);
|
|
719
721
|
}
|
|
720
722
|
}
|
|
721
723
|
function handleSensorEvent(event) {
|
|
@@ -1808,7 +1810,7 @@ async function resolvePluginId(rpcRef, pluginName) {
|
|
|
1808
1810
|
}
|
|
1809
1811
|
//#endregion
|
|
1810
1812
|
//#region src/composables/useStorage.ts
|
|
1811
|
-
function createReactiveStorage(proxy) {
|
|
1813
|
+
function createReactiveStorage(proxy, client) {
|
|
1812
1814
|
const config = shallowRef();
|
|
1813
1815
|
const isLoading = ref(false);
|
|
1814
1816
|
const error = ref();
|
|
@@ -1872,6 +1874,7 @@ function createReactiveStorage(proxy) {
|
|
|
1872
1874
|
}
|
|
1873
1875
|
return {
|
|
1874
1876
|
proxy,
|
|
1877
|
+
client,
|
|
1875
1878
|
config,
|
|
1876
1879
|
isLoading,
|
|
1877
1880
|
error,
|
|
@@ -1891,10 +1894,10 @@ function getCameraStorageKey(pluginId, cameraId) {
|
|
|
1891
1894
|
function getSensorStorageKey(pluginId, sensorId) {
|
|
1892
1895
|
return `plugin:${pluginId}:sensor:${sensorId}`;
|
|
1893
1896
|
}
|
|
1894
|
-
function acquireStorage(key, createProxy) {
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1897
|
+
function acquireStorage(key, client, createProxy) {
|
|
1898
|
+
const cached = storageCache.get(key);
|
|
1899
|
+
if (cached && cached.client !== client) storageCache.forceRelease(key);
|
|
1900
|
+
return storageCache.acquire(key, () => createReactiveStorage(createProxy(), client));
|
|
1898
1901
|
}
|
|
1899
1902
|
function releaseStorage(key) {
|
|
1900
1903
|
storageCache.release(key);
|
|
@@ -1918,10 +1921,23 @@ function cleanupStorage(state, isConnected, config) {
|
|
|
1918
1921
|
state.cachedStorage = void 0;
|
|
1919
1922
|
config.value = void 0;
|
|
1920
1923
|
}
|
|
1924
|
+
function bindStorage(state, storageKey, client, config, createProxy) {
|
|
1925
|
+
if (state.currentStorageKey === storageKey && state.cachedStorage?.client === client) return;
|
|
1926
|
+
if (state.currentStorageKey && state.currentStorageKey !== storageKey) {
|
|
1927
|
+
releaseStorage(state.currentStorageKey);
|
|
1928
|
+
config.value = void 0;
|
|
1929
|
+
}
|
|
1930
|
+
state.currentStorageKey = storageKey;
|
|
1931
|
+
state.cachedStorage = acquireStorage(storageKey, client, createProxy);
|
|
1932
|
+
}
|
|
1921
1933
|
var GET_CONFIG_RETRY_DELAYS = [
|
|
1922
1934
|
2e3,
|
|
1923
1935
|
5e3,
|
|
1924
1936
|
1e4,
|
|
1937
|
+
15e3,
|
|
1938
|
+
15e3,
|
|
1939
|
+
15e3,
|
|
1940
|
+
15e3,
|
|
1925
1941
|
15e3
|
|
1926
1942
|
];
|
|
1927
1943
|
function sleep(ms) {
|
|
@@ -2017,7 +2033,8 @@ function createStorageOperations(state, config, isLoading, error) {
|
|
|
2017
2033
|
};
|
|
2018
2034
|
}
|
|
2019
2035
|
function usePluginStorage(pluginName) {
|
|
2020
|
-
const
|
|
2036
|
+
const cameraUi = useCameraUi();
|
|
2037
|
+
const { rpc, isConnected: clientConnected } = cameraUi;
|
|
2021
2038
|
const config = shallowRef();
|
|
2022
2039
|
const _isLoading = ref(false);
|
|
2023
2040
|
const initialSetupDone = ref(false);
|
|
@@ -2026,16 +2043,14 @@ function usePluginStorage(pluginName) {
|
|
|
2026
2043
|
const state = createStorageState();
|
|
2027
2044
|
const operations = createStorageOperations(state, config, _isLoading, error);
|
|
2028
2045
|
async function connect(name) {
|
|
2029
|
-
|
|
2046
|
+
const client = rpc.value;
|
|
2047
|
+
if (!client || !clientConnected.value) return false;
|
|
2030
2048
|
try {
|
|
2031
2049
|
const pluginId = await resolvePluginId(rpc, name);
|
|
2032
2050
|
if (!pluginId) throw new Error(`Plugin "${name}" not found`);
|
|
2033
|
-
|
|
2034
|
-
if (state.currentStorageKey && state.currentStorageKey !== storageKey) releaseStorage(state.currentStorageKey);
|
|
2035
|
-
state.currentStorageKey = storageKey;
|
|
2036
|
-
state.cachedStorage = acquireStorage(storageKey, () => {
|
|
2051
|
+
bindStorage(state, getPluginStorageKey(pluginId), client, config, () => {
|
|
2037
2052
|
const namespaces = NamespaceManager.pluginNamespaces(pluginId);
|
|
2038
|
-
return
|
|
2053
|
+
return client.createProxy(namespaces.pluginStorageRpc);
|
|
2039
2054
|
});
|
|
2040
2055
|
isConnected.value = true;
|
|
2041
2056
|
return true;
|
|
@@ -2053,14 +2068,20 @@ function usePluginStorage(pluginName) {
|
|
|
2053
2068
|
}
|
|
2054
2069
|
return operations.getConfig();
|
|
2055
2070
|
}
|
|
2056
|
-
|
|
2057
|
-
|
|
2071
|
+
async function sync() {
|
|
2072
|
+
const name = toValue(pluginName);
|
|
2073
|
+
if (clientConnected.value && name) {
|
|
2058
2074
|
await connect(name);
|
|
2059
2075
|
operations.getConfig();
|
|
2060
2076
|
} else cleanupStorage(state, isConnected, config);
|
|
2061
2077
|
initialSetupDone.value = true;
|
|
2062
|
-
}
|
|
2063
|
-
|
|
2078
|
+
}
|
|
2079
|
+
watch([clientConnected, () => toValue(pluginName)], sync, { immediate: true });
|
|
2080
|
+
cameraUi.on("reconnected", sync);
|
|
2081
|
+
tryOnScopeDispose(() => {
|
|
2082
|
+
cameraUi.off("reconnected", sync);
|
|
2083
|
+
cleanupStorage(state, isConnected, config);
|
|
2084
|
+
});
|
|
2064
2085
|
return {
|
|
2065
2086
|
config,
|
|
2066
2087
|
isLoading: computed(() => _isLoading.value || !initialSetupDone.value),
|
|
@@ -2073,7 +2094,8 @@ function usePluginStorage(pluginName) {
|
|
|
2073
2094
|
};
|
|
2074
2095
|
}
|
|
2075
2096
|
function useCameraStorage(camera, pluginName) {
|
|
2076
|
-
const
|
|
2097
|
+
const cameraUi = useCameraUi();
|
|
2098
|
+
const { rpc, isConnected: clientConnected } = cameraUi;
|
|
2077
2099
|
const config = shallowRef();
|
|
2078
2100
|
const _isLoading = ref(false);
|
|
2079
2101
|
const initialSetupDone = ref(false);
|
|
@@ -2082,16 +2104,14 @@ function useCameraStorage(camera, pluginName) {
|
|
|
2082
2104
|
const state = createStorageState();
|
|
2083
2105
|
const operations = createStorageOperations(state, config, _isLoading, error);
|
|
2084
2106
|
async function connect(cameraId, name) {
|
|
2085
|
-
|
|
2107
|
+
const client = rpc.value;
|
|
2108
|
+
if (!client || !clientConnected.value) return false;
|
|
2086
2109
|
try {
|
|
2087
2110
|
const pluginId = await resolvePluginId(rpc, name);
|
|
2088
2111
|
if (!pluginId) throw new Error(`Plugin "${name}" not found`);
|
|
2089
|
-
|
|
2090
|
-
if (state.currentStorageKey && state.currentStorageKey !== storageKey) releaseStorage(state.currentStorageKey);
|
|
2091
|
-
state.currentStorageKey = storageKey;
|
|
2092
|
-
state.cachedStorage = acquireStorage(storageKey, () => {
|
|
2112
|
+
bindStorage(state, getCameraStorageKey(pluginId, cameraId), client, config, () => {
|
|
2093
2113
|
const namespaces = NamespaceManager.pluginCameraNamespaces(pluginId, cameraId);
|
|
2094
|
-
return
|
|
2114
|
+
return client.createProxy(namespaces.cameraStorageRpc);
|
|
2095
2115
|
});
|
|
2096
2116
|
isConnected.value = true;
|
|
2097
2117
|
return true;
|
|
@@ -2110,18 +2130,25 @@ function useCameraStorage(camera, pluginName) {
|
|
|
2110
2130
|
}
|
|
2111
2131
|
return operations.getConfig();
|
|
2112
2132
|
}
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
(
|
|
2117
|
-
], async ([connected, cameraId, name]) => {
|
|
2118
|
-
if (connected && cameraId && name) {
|
|
2133
|
+
async function sync() {
|
|
2134
|
+
const cameraId = extractCameraId(toValue(camera));
|
|
2135
|
+
const name = toValue(pluginName);
|
|
2136
|
+
if (clientConnected.value && cameraId && name) {
|
|
2119
2137
|
await connect(cameraId, name);
|
|
2120
2138
|
operations.getConfig();
|
|
2121
2139
|
} else cleanupStorage(state, isConnected, config);
|
|
2122
2140
|
initialSetupDone.value = true;
|
|
2123
|
-
}
|
|
2124
|
-
|
|
2141
|
+
}
|
|
2142
|
+
watch([
|
|
2143
|
+
clientConnected,
|
|
2144
|
+
() => extractCameraId(toValue(camera)),
|
|
2145
|
+
() => toValue(pluginName)
|
|
2146
|
+
], sync, { immediate: true });
|
|
2147
|
+
cameraUi.on("reconnected", sync);
|
|
2148
|
+
tryOnScopeDispose(() => {
|
|
2149
|
+
cameraUi.off("reconnected", sync);
|
|
2150
|
+
cleanupStorage(state, isConnected, config);
|
|
2151
|
+
});
|
|
2125
2152
|
return {
|
|
2126
2153
|
config,
|
|
2127
2154
|
isLoading: computed(() => _isLoading.value || !initialSetupDone.value),
|
|
@@ -2134,7 +2161,8 @@ function useCameraStorage(camera, pluginName) {
|
|
|
2134
2161
|
};
|
|
2135
2162
|
}
|
|
2136
2163
|
function useSensorStorage(sensorId, pluginId) {
|
|
2137
|
-
const
|
|
2164
|
+
const cameraUi = useCameraUi();
|
|
2165
|
+
const { rpc, isConnected: clientConnected } = cameraUi;
|
|
2138
2166
|
const config = shallowRef();
|
|
2139
2167
|
const _isLoading = ref(false);
|
|
2140
2168
|
const initialSetupDone = ref(false);
|
|
@@ -2143,14 +2171,12 @@ function useSensorStorage(sensorId, pluginId) {
|
|
|
2143
2171
|
const state = createStorageState();
|
|
2144
2172
|
const operations = createStorageOperations(state, config, _isLoading, error);
|
|
2145
2173
|
function connect(senId, plugId) {
|
|
2146
|
-
|
|
2174
|
+
const client = rpc.value;
|
|
2175
|
+
if (!client || !clientConnected.value) return false;
|
|
2147
2176
|
try {
|
|
2148
|
-
|
|
2149
|
-
if (state.currentStorageKey && state.currentStorageKey !== storageKey) releaseStorage(state.currentStorageKey);
|
|
2150
|
-
state.currentStorageKey = storageKey;
|
|
2151
|
-
state.cachedStorage = acquireStorage(storageKey, () => {
|
|
2177
|
+
bindStorage(state, getSensorStorageKey(plugId, senId), client, config, () => {
|
|
2152
2178
|
const namespaces = NamespaceManager.pluginSensorNamespaces(plugId, senId);
|
|
2153
|
-
return
|
|
2179
|
+
return client.createProxy(namespaces.sensorStorageRpc);
|
|
2154
2180
|
});
|
|
2155
2181
|
isConnected.value = true;
|
|
2156
2182
|
return true;
|
|
@@ -2169,18 +2195,25 @@ function useSensorStorage(sensorId, pluginId) {
|
|
|
2169
2195
|
}
|
|
2170
2196
|
return operations.getConfig();
|
|
2171
2197
|
}
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
(
|
|
2176
|
-
], ([connected, senId, plugId]) => {
|
|
2177
|
-
if (connected && senId && plugId) {
|
|
2198
|
+
function sync() {
|
|
2199
|
+
const senId = toValue(sensorId);
|
|
2200
|
+
const plugId = toValue(pluginId);
|
|
2201
|
+
if (clientConnected.value && senId && plugId) {
|
|
2178
2202
|
connect(senId, plugId);
|
|
2179
2203
|
operations.getConfig();
|
|
2180
2204
|
} else cleanupStorage(state, isConnected, config);
|
|
2181
2205
|
initialSetupDone.value = true;
|
|
2182
|
-
}
|
|
2183
|
-
|
|
2206
|
+
}
|
|
2207
|
+
watch([
|
|
2208
|
+
clientConnected,
|
|
2209
|
+
() => toValue(sensorId),
|
|
2210
|
+
() => toValue(pluginId)
|
|
2211
|
+
], sync, { immediate: true });
|
|
2212
|
+
cameraUi.on("reconnected", sync);
|
|
2213
|
+
tryOnScopeDispose(() => {
|
|
2214
|
+
cameraUi.off("reconnected", sync);
|
|
2215
|
+
cleanupStorage(state, isConnected, config);
|
|
2216
|
+
});
|
|
2184
2217
|
return {
|
|
2185
2218
|
config,
|
|
2186
2219
|
isLoading: computed(() => _isLoading.value || !initialSetupDone.value),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camera.ui/browser",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.191",
|
|
4
4
|
"description": "camera.ui browser client",
|
|
5
5
|
"author": "seydx (https://github.com/cameraui/clients)",
|
|
6
6
|
"type": "module",
|
|
@@ -39,14 +39,14 @@
|
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@camera.ui/logger": "file:../../packages/logger",
|
|
41
41
|
"@camera.ui/rpc": "^1.0.12",
|
|
42
|
-
"@camera.ui/sdk": "~1.2.
|
|
42
|
+
"@camera.ui/sdk": "~1.2.38",
|
|
43
43
|
"@camera.ui/transport": "file:../../packages/transport",
|
|
44
44
|
"@eneris/push-receiver": "^4.3.1",
|
|
45
45
|
"@microsoft/api-extractor": "^7.59.1",
|
|
46
46
|
"@stylistic/eslint-plugin": "^5.10.0",
|
|
47
47
|
"@types/webrtc": "^0.0.47",
|
|
48
48
|
"@typescript-eslint/parser": "^8.70.0",
|
|
49
|
-
"@vitejs/plugin-vue": "^6.0.
|
|
49
|
+
"@vitejs/plugin-vue": "^6.0.9",
|
|
50
50
|
"@vue/eslint-config-prettier": "^10.2.0",
|
|
51
51
|
"@vue/eslint-config-typescript": "^14.9.0",
|
|
52
52
|
"@vue/language-core": "^3.3.11",
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
"unplugin-dts": "^1.1.0",
|
|
64
64
|
"updates": "^18.1.0",
|
|
65
65
|
"vite": "^8.3.0",
|
|
66
|
-
"vitest": "^5.0.
|
|
66
|
+
"vitest": "^5.0.1",
|
|
67
67
|
"vue": "^3.5.42",
|
|
68
68
|
"vue-tsc": "^3.3.11"
|
|
69
69
|
},
|