rhombus-node-mcp 0.1.27 → 0.1.29
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/api/events-tool-api.js +65 -0
- package/dist/api/get-entity-tool-api.js +22 -20
- package/dist/createServer.js +1 -1
- package/dist/logger.js +3 -2
- package/dist/tools/events-tool.js +29 -2
- package/dist/tools/get-entity-tool.js +7 -3
- package/dist/types/access-control-tool-types.js +1 -1
- package/dist/types/events-tools-types.js +49 -0
- package/dist/types/get-entity-tool-types.js +10 -7
- package/package.json +1 -1
|
@@ -75,6 +75,71 @@ async function getAccessControlEventsForDoor(doorUuid, startTime, endTime, timeZ
|
|
|
75
75
|
}
|
|
76
76
|
return allEvents;
|
|
77
77
|
}
|
|
78
|
+
export async function getBrivoAccessControlEvents(startTime, endTime, timeZone, requestModifiers, sessionId) {
|
|
79
|
+
// Step 1: fetch Brivo integration config to get configured doors and their location UUIDs
|
|
80
|
+
const integrationResponse = await postApi({
|
|
81
|
+
route: "/integrations/accessControl/getBrivoIntegrationV2",
|
|
82
|
+
body: {},
|
|
83
|
+
modifiers: requestModifiers,
|
|
84
|
+
sessionId,
|
|
85
|
+
});
|
|
86
|
+
const brivoSettings = integrationResponse.orgIntegrationV2;
|
|
87
|
+
const integrationEnabled = brivoSettings?.enabled ?? false;
|
|
88
|
+
const doorInfoMap = brivoSettings?.doorInfoMap ?? {};
|
|
89
|
+
const brivoDoors = Object.entries(doorInfoMap)
|
|
90
|
+
.filter(([, info]) => info != null)
|
|
91
|
+
.map(([brivoDoornId, info]) => ({
|
|
92
|
+
brivoDoornId,
|
|
93
|
+
doorName: info.doorName ?? undefined,
|
|
94
|
+
locationUuid: info.locationUuid ?? undefined,
|
|
95
|
+
}));
|
|
96
|
+
if (brivoDoors.length === 0) {
|
|
97
|
+
return {
|
|
98
|
+
integrationEnabled,
|
|
99
|
+
brivoDoorsConfigured: 0,
|
|
100
|
+
brivoDoors: [],
|
|
101
|
+
events: [],
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
// Step 2: collect unique location UUIDs from configured Brivo doors
|
|
105
|
+
const locationUuids = [...new Set(brivoDoors.map(d => d.locationUuid).filter((id) => !!id))];
|
|
106
|
+
// Step 3: query CredentialReceivedEvents for each location
|
|
107
|
+
const MAX_LIMIT = 1000;
|
|
108
|
+
const allEvents = [];
|
|
109
|
+
await Promise.all(locationUuids.map(async (locationUuid) => {
|
|
110
|
+
const body = {
|
|
111
|
+
locationUuid,
|
|
112
|
+
typeFilter: ["CredentialReceivedEvent"],
|
|
113
|
+
...(startTime ? { createdAfterMs: startTime } : {}),
|
|
114
|
+
...(endTime ? { createdBeforeMs: endTime } : {}),
|
|
115
|
+
limit: MAX_LIMIT,
|
|
116
|
+
};
|
|
117
|
+
const response = await postApi({
|
|
118
|
+
route: "/component/findComponentEventsByLocation",
|
|
119
|
+
body,
|
|
120
|
+
modifiers: requestModifiers,
|
|
121
|
+
sessionId,
|
|
122
|
+
});
|
|
123
|
+
const mapped = (response.componentEvents || []).map(event => mapAccessControlEvent(event, timeZone));
|
|
124
|
+
allEvents.push(...mapped);
|
|
125
|
+
}));
|
|
126
|
+
allEvents.sort((a, b) => (b.timestampMs || 0) - (a.timestampMs || 0));
|
|
127
|
+
return {
|
|
128
|
+
integrationEnabled,
|
|
129
|
+
brivoDoorsConfigured: brivoDoors.length,
|
|
130
|
+
brivoDoors,
|
|
131
|
+
events: allEvents.map(e => ({
|
|
132
|
+
authenticationResult: e.authenticationResult ?? undefined,
|
|
133
|
+
authorizationResult: e.authorizationResult ?? undefined,
|
|
134
|
+
doorUuid: e.doorUuid ?? undefined,
|
|
135
|
+
locationUuid: e.locationUuid ?? undefined,
|
|
136
|
+
user: e.user ?? undefined,
|
|
137
|
+
credSource: e.credSource ?? undefined,
|
|
138
|
+
timestampMs: e.timestampMs ?? undefined,
|
|
139
|
+
datetime: e.datetime,
|
|
140
|
+
})),
|
|
141
|
+
};
|
|
142
|
+
}
|
|
78
143
|
export async function getFaceEvents(_locationUuid, timeZone, requestModifiers, sessionId) {
|
|
79
144
|
const nowMs = Date.now();
|
|
80
145
|
const rangeStartMs = nowMs - THREE_HOURS_MS;
|
|
@@ -3,23 +3,25 @@ import { postApi } from "../network/network.js";
|
|
|
3
3
|
import { formatTimestamp } from "../util.js";
|
|
4
4
|
import { tempFunc } from "../utils/temp.js";
|
|
5
5
|
export async function getCameraList(requestModifiers, sessionId) {
|
|
6
|
+
const body = await postApi({
|
|
7
|
+
route: "/camera/getMinimalCameraStateList",
|
|
8
|
+
body: {},
|
|
9
|
+
modifiers: requestModifiers,
|
|
10
|
+
sessionId,
|
|
11
|
+
});
|
|
6
12
|
return {
|
|
7
|
-
cameras: (
|
|
8
|
-
route: "/camera/getMinimalCameraStateList",
|
|
9
|
-
body: {},
|
|
10
|
-
modifiers: requestModifiers,
|
|
11
|
-
sessionId,
|
|
12
|
-
})).cameraStates.filter((camera) => !!camera.locationUuid),
|
|
13
|
+
cameras: (body.cameraStates ?? []).filter((camera) => !!camera.locationUuid),
|
|
13
14
|
};
|
|
14
15
|
}
|
|
15
16
|
export async function getDoorbellCameras(requestModifiers, sessionId) {
|
|
17
|
+
const body = await postApi({
|
|
18
|
+
route: "/doorbellcamera/getMinimalStateList",
|
|
19
|
+
body: {},
|
|
20
|
+
modifiers: requestModifiers,
|
|
21
|
+
sessionId,
|
|
22
|
+
});
|
|
16
23
|
return {
|
|
17
|
-
doorbellCameras: (
|
|
18
|
-
route: "/doorbellcamera/getMinimalStateList",
|
|
19
|
-
body: {},
|
|
20
|
-
modifiers: requestModifiers,
|
|
21
|
-
sessionId,
|
|
22
|
-
})).minimalStates.filter((doorbellCamera) => !!doorbellCamera.locationUuid),
|
|
24
|
+
doorbellCameras: (body.minimalStates ?? []).filter((doorbellCamera) => !!doorbellCamera.locationUuid),
|
|
23
25
|
};
|
|
24
26
|
}
|
|
25
27
|
export async function getBadgeReaders(requestModifiers, sessionId) {
|
|
@@ -30,7 +32,7 @@ export async function getBadgeReaders(requestModifiers, sessionId) {
|
|
|
30
32
|
sessionId,
|
|
31
33
|
}).then((response) => {
|
|
32
34
|
return {
|
|
33
|
-
badgeReaders: response.minimalStates.filter((badgeReader) => !!badgeReader.locationUuid),
|
|
35
|
+
badgeReaders: (response.minimalStates ?? []).filter((badgeReader) => !!badgeReader.locationUuid),
|
|
34
36
|
};
|
|
35
37
|
});
|
|
36
38
|
}
|
|
@@ -65,7 +67,7 @@ export async function getAudioGateways(timeZone, requestModifiers, sessionId) {
|
|
|
65
67
|
sessionId,
|
|
66
68
|
}).then((response) => {
|
|
67
69
|
return {
|
|
68
|
-
audioGateways: response.audioGatewayStates
|
|
70
|
+
audioGateways: (response.audioGatewayStates ?? [])
|
|
69
71
|
.filter((camera) => !!camera.locationUuid)
|
|
70
72
|
.map((gateway) => ({
|
|
71
73
|
...gateway,
|
|
@@ -84,7 +86,7 @@ export async function getDoorSensors(requestModifiers, sessionId) {
|
|
|
84
86
|
sessionId,
|
|
85
87
|
}).then((response) => {
|
|
86
88
|
return {
|
|
87
|
-
doorStates: response.doorStates.filter((door) => !!door.locationUuid),
|
|
89
|
+
doorStates: (response.doorStates ?? []).filter((door) => !!door.locationUuid),
|
|
88
90
|
};
|
|
89
91
|
});
|
|
90
92
|
}
|
|
@@ -97,7 +99,7 @@ export async function getEnvironmentalSensors(timeZone, tempUnit, requestModifie
|
|
|
97
99
|
}).then((response) => {
|
|
98
100
|
logger.info("Using tempUnit: ", tempUnit);
|
|
99
101
|
return {
|
|
100
|
-
climateStates: response.climateStates
|
|
102
|
+
climateStates: (response.climateStates ?? [])
|
|
101
103
|
.filter((sensor) => !!sensor.locationUuid)
|
|
102
104
|
.map((_sensor) => {
|
|
103
105
|
const { temperatureCelcius, ...sensor } = _sensor;
|
|
@@ -120,7 +122,7 @@ export async function getMotionSensors(requestModifiers, sessionId) {
|
|
|
120
122
|
sessionId,
|
|
121
123
|
}).then((response) => {
|
|
122
124
|
return {
|
|
123
|
-
occupancySensorStates: response.occupancySensorStates.filter((occupancySensor) => !!occupancySensor.locationUuid),
|
|
125
|
+
occupancySensorStates: (response.occupancySensorStates ?? []).filter((occupancySensor) => !!occupancySensor.locationUuid),
|
|
124
126
|
};
|
|
125
127
|
});
|
|
126
128
|
}
|
|
@@ -132,7 +134,7 @@ export async function getButtons(timeZone, requestModifiers, sessionId) {
|
|
|
132
134
|
sessionId,
|
|
133
135
|
}).then((response) => {
|
|
134
136
|
return {
|
|
135
|
-
buttonStates: response.states
|
|
137
|
+
buttonStates: (response.states ?? [])
|
|
136
138
|
.filter((button) => !!button.locationUuid)
|
|
137
139
|
.map((button) => ({
|
|
138
140
|
...button,
|
|
@@ -151,7 +153,7 @@ export async function getKeypads(requestModifiers, sessionId) {
|
|
|
151
153
|
sessionId,
|
|
152
154
|
}).then((response) => {
|
|
153
155
|
return {
|
|
154
|
-
keypadStates: response.keypads.filter((keypad) => !!keypad.locationUuid),
|
|
156
|
+
keypadStates: (response.keypads ?? []).filter((keypad) => !!keypad.locationUuid),
|
|
155
157
|
};
|
|
156
158
|
});
|
|
157
159
|
}
|
|
@@ -163,7 +165,7 @@ export async function getEnvironmentalGateways(timeZone, requestModifiers, sessi
|
|
|
163
165
|
sessionId,
|
|
164
166
|
}).then((response) => {
|
|
165
167
|
return {
|
|
166
|
-
minimalEnvironmentalGatewayStates: response.minimalEnvironmentalGatewayStates
|
|
168
|
+
minimalEnvironmentalGatewayStates: (response.minimalEnvironmentalGatewayStates ?? [])
|
|
167
169
|
.filter((gateway) => !!gateway.locationUuid)
|
|
168
170
|
.map((gateway) => ({
|
|
169
171
|
...gateway,
|
package/dist/createServer.js
CHANGED
package/dist/logger.js
CHANGED
|
@@ -17,7 +17,7 @@ catch (error) {
|
|
|
17
17
|
const appenders = {
|
|
18
18
|
// stderr for terminal visibility (always available)
|
|
19
19
|
stderr: { type: "stderr" },
|
|
20
|
-
//
|
|
20
|
+
// production stderr: hide trace/debug (e.g. full response snippets); still shows info+ like [POSTAPI] REQUEST
|
|
21
21
|
stderrInfo: {
|
|
22
22
|
type: "logLevelFilter",
|
|
23
23
|
appender: "stderr",
|
|
@@ -36,7 +36,8 @@ if (fileLoggingEnabled) {
|
|
|
36
36
|
layout: { type: "basic" },
|
|
37
37
|
};
|
|
38
38
|
}
|
|
39
|
-
const
|
|
39
|
+
const isProduction = process.env.NODE_ENV === "production";
|
|
40
|
+
const stderrAppender = isProduction ? "stderrInfo" : "stderr";
|
|
40
41
|
// Configure categories based on available appenders
|
|
41
42
|
const categories = {
|
|
42
43
|
default: {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getAccessControlEvents, getEventsForEnvironmentalGateway, getClimateEventsForSensor, getComponentEventsByLocation, getHumanMotionEvents, getButtonPressEvents, getOccupancyEvents, getProximityEvents, getDoorbellEvents, } from "../api/events-tool-api.js";
|
|
1
|
+
import { getAccessControlEvents, getBrivoAccessControlEvents, getEventsForEnvironmentalGateway, getClimateEventsForSensor, getComponentEventsByLocation, getHumanMotionEvents, getButtonPressEvents, getOccupancyEvents, getProximityEvents, getDoorbellEvents, } from "../api/events-tool-api.js";
|
|
2
2
|
import { EventsToolRequestType, OUTPUT_SCHEMA, TOOL_ARGS, } from "../types/events-tools-types.js";
|
|
3
3
|
import { createToolStructuredContent } from "../util.js";
|
|
4
4
|
import { getLogger } from "../logger.js";
|
|
@@ -9,7 +9,27 @@ const TOOL_NAME = "events-tool";
|
|
|
9
9
|
const TOOL_DESCRIPTION = `
|
|
10
10
|
**Scope:** This tool returns **raw, event-level data** (individual events with timestamps). Use **report-tool** when you need aggregated counts, time-series summaries, or analytics over intervals.
|
|
11
11
|
|
|
12
|
-
This tool has
|
|
12
|
+
This tool has multiple modes, set by "eventType": access-control, brivo-access-control, environmental-gateway, climate-sensor, component-events, camera. Use it when the user asks for specific events (unlocks, badge ins, credentials, arrivals, environmental readings, climate data, camera motion, or other component events). It can return large result sets; keep time ranges narrow. For ranges spanning more than ~24 hours, prefer report-tool for aggregates. For maximum flexibility across event types at a location, use eventType "component-events".
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
When eventType is "brivo-access-control":
|
|
17
|
+
|
|
18
|
+
Retrieves badge/credential events from Brivo-integrated doors. Automatically fetches the Brivo integration configuration to determine which locations have Brivo doors mapped. No door UUIDs are required.
|
|
19
|
+
|
|
20
|
+
Use this when the user asks specifically about Brivo events, Brivo badge ins, Brivo access control, or events from Brivo doors.
|
|
21
|
+
|
|
22
|
+
Arguments:
|
|
23
|
+
* **startTime (string):** Start of the time range (ISO 8601).
|
|
24
|
+
* **endTime (string):** End of the time range (ISO 8601).
|
|
25
|
+
|
|
26
|
+
Returns:
|
|
27
|
+
* **integrationEnabled:** Whether the Brivo integration is currently enabled.
|
|
28
|
+
* **brivoDoorsConfigured:** Number of Brivo doors configured in the integration.
|
|
29
|
+
* **brivoDoors:** List of Brivo doors with their IDs, names, and associated Rhombus location UUIDs.
|
|
30
|
+
* **events:** Credential received events from all locations that have Brivo doors configured, sorted newest first.
|
|
31
|
+
|
|
32
|
+
Note: Events are fetched at the location level, so results may include events from all access-controlled doors at locations where Brivo is configured.
|
|
13
33
|
|
|
14
34
|
---
|
|
15
35
|
|
|
@@ -92,6 +112,13 @@ const TOOL_HANDLER = async (args, extra) => {
|
|
|
92
112
|
const { eventType, accessControlledDoorUuids, deviceUuid, sensorUuid, locationUuid, componentEventTypes, startTime, endTime, limit, timeZone, tempUnit, cameraUuid, duration, buttonSensorUuid, occupancySensorUuid, proximityTagUuids, doorbellCameraUuid, } = args;
|
|
93
113
|
logger.debug(`eventType: ${eventType}`);
|
|
94
114
|
switch (eventType) {
|
|
115
|
+
case EventsToolRequestType.BRIVO_ACCESS_CONTROL: {
|
|
116
|
+
const result = await getBrivoAccessControlEvents(startTime ? new Date(startTime).getTime() : undefined, endTime ? new Date(endTime).getTime() : undefined, timeZone, extra._meta?.requestModifiers, extra.sessionId);
|
|
117
|
+
return createToolStructuredContent({
|
|
118
|
+
eventType: "brivo-access-control",
|
|
119
|
+
brivoAccessControlEvents: result,
|
|
120
|
+
});
|
|
121
|
+
}
|
|
95
122
|
case "access-control": {
|
|
96
123
|
if (!accessControlledDoorUuids || accessControlledDoorUuids.length === 0) {
|
|
97
124
|
return createToolStructuredContent({
|
|
@@ -14,7 +14,9 @@ includes a "connected" boolean field indicating whether it is currently online (
|
|
|
14
14
|
When asked about device health, offline devices, or connectivity issues, use this tool to fetch all device
|
|
15
15
|
types and check the "connected" field to identify which devices are offline or unreachable.`;
|
|
16
16
|
const TOOL_HANDLER = async (args, extra) => {
|
|
17
|
-
const { entityTypes, timeZone,
|
|
17
|
+
const { entityTypes, timeZone, tempUnit } = args;
|
|
18
|
+
const filterBy = args.filterBy ?? { locationUuids: null };
|
|
19
|
+
const locationFilter = filterBy.locationUuids;
|
|
18
20
|
const { requestModifiers, sessionId } = extractFromToolExtra(extra);
|
|
19
21
|
const promises = [];
|
|
20
22
|
if (entityTypes.includes(DeviceType.CAMERA)) {
|
|
@@ -61,8 +63,10 @@ const TOOL_HANDLER = async (args, extra) => {
|
|
|
61
63
|
// then filter
|
|
62
64
|
response[key] = value.filter((item) => {
|
|
63
65
|
let pass = true;
|
|
64
|
-
if (item.locationUuid &&
|
|
65
|
-
|
|
66
|
+
if (item.locationUuid &&
|
|
67
|
+
locationFilter &&
|
|
68
|
+
locationFilter.length > 0) {
|
|
69
|
+
pass = pass && locationFilter.includes(item.locationUuid);
|
|
66
70
|
}
|
|
67
71
|
return pass;
|
|
68
72
|
});
|
|
@@ -13,7 +13,7 @@ export var AccessControlRequestType;
|
|
|
13
13
|
AccessControlRequestType["GET_REMOTE_UNLOCK_USERS"] = "get-remote-unlock-users";
|
|
14
14
|
})(AccessControlRequestType || (AccessControlRequestType = {}));
|
|
15
15
|
export const TOOL_ARGS = {
|
|
16
|
-
requestType: z.
|
|
16
|
+
requestType: z.nativeEnum(AccessControlRequestType).describe("The type of access control request to make."),
|
|
17
17
|
doorUuid: z
|
|
18
18
|
.string()
|
|
19
19
|
.nullable()
|
|
@@ -6,6 +6,7 @@ import { TempUnit } from "../utils/temp.js";
|
|
|
6
6
|
export var EventsToolRequestType;
|
|
7
7
|
(function (EventsToolRequestType) {
|
|
8
8
|
EventsToolRequestType["ACCESS_CONTROL"] = "access-control";
|
|
9
|
+
EventsToolRequestType["BRIVO_ACCESS_CONTROL"] = "brivo-access-control";
|
|
9
10
|
EventsToolRequestType["ENVIRONMENTAL_GATEWAY"] = "environmental-gateway";
|
|
10
11
|
EventsToolRequestType["CLIMATE_SENSOR"] = "climate-sensor";
|
|
11
12
|
EventsToolRequestType["COMPONENT_EVENTS"] = "component-events";
|
|
@@ -20,6 +21,7 @@ export const TOOL_ARGS = {
|
|
|
20
21
|
.nativeEnum(EventsToolRequestType)
|
|
21
22
|
.describe("The type of events to retrieve. " +
|
|
22
23
|
"access-control: Access control events like unlocks, badge ins, credentials, arrivals. " +
|
|
24
|
+
"brivo-access-control: Badge/credential events from Brivo-integrated doors. Does not require door UUIDs — automatically looks up which doors are configured via the Brivo integration. " +
|
|
23
25
|
"environmental-gateway: Environmental gateway events with sensor readings and derived values. " +
|
|
24
26
|
"climate-sensor: Climate sensor events with temperature, humidity, air quality readings. " +
|
|
25
27
|
"component-events: All types of component events for a location (most flexible option). " +
|
|
@@ -143,6 +145,7 @@ export const OUTPUT_SCHEMA = z.object({
|
|
|
143
145
|
eventType: z
|
|
144
146
|
.enum([
|
|
145
147
|
"access-control",
|
|
148
|
+
"brivo-access-control",
|
|
146
149
|
"environmental-gateway",
|
|
147
150
|
"climate-sensor",
|
|
148
151
|
"component-events",
|
|
@@ -153,6 +156,52 @@ export const OUTPUT_SCHEMA = z.object({
|
|
|
153
156
|
"doorbell",
|
|
154
157
|
])
|
|
155
158
|
.optional(),
|
|
159
|
+
brivoAccessControlEvents: z.optional(z
|
|
160
|
+
.object({
|
|
161
|
+
integrationEnabled: z.boolean().describe("Whether the Brivo integration is enabled"),
|
|
162
|
+
brivoDoorsConfigured: z
|
|
163
|
+
.number()
|
|
164
|
+
.describe("Number of Brivo doors configured in the integration"),
|
|
165
|
+
brivoDoors: z
|
|
166
|
+
.array(z.object({
|
|
167
|
+
brivoDoornId: z.string().describe("Brivo's door ID"),
|
|
168
|
+
doorName: z.string().optional().describe("Brivo door name"),
|
|
169
|
+
locationUuid: z.string().optional().describe("Rhombus location UUID for this door"),
|
|
170
|
+
}))
|
|
171
|
+
.describe("List of Brivo doors configured in the integration"),
|
|
172
|
+
events: z
|
|
173
|
+
.array(z.object({
|
|
174
|
+
authenticationResult: z
|
|
175
|
+
.string()
|
|
176
|
+
.optional()
|
|
177
|
+
.describe("The result of the authentication process"),
|
|
178
|
+
authorizationResult: z
|
|
179
|
+
.string()
|
|
180
|
+
.optional()
|
|
181
|
+
.describe("The result of the authorization process"),
|
|
182
|
+
doorUuid: z
|
|
183
|
+
.string()
|
|
184
|
+
.optional()
|
|
185
|
+
.describe("The Rhombus access controlled door UUID"),
|
|
186
|
+
locationUuid: z
|
|
187
|
+
.string()
|
|
188
|
+
.optional()
|
|
189
|
+
.describe("The Rhombus location UUID where the event occurred"),
|
|
190
|
+
user: z.string().optional().describe("Username of the person who triggered the event"),
|
|
191
|
+
credSource: z
|
|
192
|
+
.string()
|
|
193
|
+
.optional()
|
|
194
|
+
.describe("The source of the credential (e.g. WIEGAND, NFC, BLE_WAVE, REMOTE)"),
|
|
195
|
+
timestampMs: z
|
|
196
|
+
.number()
|
|
197
|
+
.optional()
|
|
198
|
+
.describe("Timestamp in milliseconds when the event occurred"),
|
|
199
|
+
datetime: z.string().optional().describe("Formatted datetime string of the event"),
|
|
200
|
+
}))
|
|
201
|
+
.describe("Credential received events from locations that have Brivo doors configured, sorted by timestamp (newest first)"),
|
|
202
|
+
})
|
|
203
|
+
.nullable()
|
|
204
|
+
.describe("Brivo access control events. Fetches credential events from all locations that have Brivo doors configured in the integration.")),
|
|
156
205
|
accessControlEvents: z.optional(z
|
|
157
206
|
.array(z.object({
|
|
158
207
|
authenticationResult: z
|
|
@@ -2,18 +2,21 @@ import { z } from "zod";
|
|
|
2
2
|
import { createUuidSchema } from "../types.js";
|
|
3
3
|
import DeviceType from "./deviceType.js";
|
|
4
4
|
import { TempUnit } from "../utils/temp.js";
|
|
5
|
+
const filterByObjectSchema = z.object({
|
|
6
|
+
locationUuids: z
|
|
7
|
+
.array(createUuidSchema())
|
|
8
|
+
.nullish()
|
|
9
|
+
.describe("The UUIDs of the locations to filter by. Set to null or an empty array to not filter by location."),
|
|
10
|
+
});
|
|
5
11
|
export const TOOL_ARGS = {
|
|
6
12
|
entityTypes: z
|
|
7
13
|
.array(z.nativeEnum(DeviceType).describe("The entity type to retreive"))
|
|
8
14
|
.describe("What type of entities to retrieve."),
|
|
9
15
|
filterBy: z
|
|
10
|
-
.
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
.describe("The UUIDs of the locations to filter by. Set to null or an enmpty array to not filter by location."),
|
|
15
|
-
})
|
|
16
|
-
.describe("Additional filters that can be applied to the result."),
|
|
16
|
+
.union([filterByObjectSchema, z.null()])
|
|
17
|
+
.optional()
|
|
18
|
+
.transform((v) => v ?? { locationUuids: null })
|
|
19
|
+
.describe("Additional filters that can be applied to the result. Omit or pass null for no filtering."),
|
|
17
20
|
timeZone: z
|
|
18
21
|
.string()
|
|
19
22
|
.describe("The timezone for formatting timestamps. This is necessary for the tool to produce accurate formatted timestamps."),
|