rhombus-node-mcp 0.1.26 → 0.1.28
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/door-schedule-exception-tool-api.js +27 -20
- package/dist/api/get-entity-tool-api.js +22 -20
- package/dist/logger.js +3 -2
- package/dist/tools/door-schedule-exception-tool.js +20 -3
- package/dist/tools/get-entity-tool.js +7 -3
- package/dist/types/door-schedule-exception-tool-types.js +47 -17
- package/dist/types/get-entity-tool-types.js +10 -7
- package/package.json +1 -1
|
@@ -45,14 +45,15 @@ function buildDateRangeFilter(filter) {
|
|
|
45
45
|
localEndDateRangeEnd,
|
|
46
46
|
};
|
|
47
47
|
}
|
|
48
|
-
async function verifyExceptionConfig(exception, requestModifiers, sessionId) {
|
|
48
|
+
async function verifyExceptionConfig(exception, options, requestModifiers, sessionId) {
|
|
49
49
|
const verified = {
|
|
50
50
|
...exception,
|
|
51
51
|
};
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
52
|
+
const doorUuidsProvided = Array.isArray(exception.doorUuids);
|
|
53
|
+
const cleanedDoorUuids = doorUuidsProvided
|
|
54
|
+
? (exception.doorUuids?.filter((doorUuid) => !!doorUuid) ?? [])
|
|
55
|
+
: undefined;
|
|
56
|
+
if (cleanedDoorUuids !== undefined) {
|
|
56
57
|
verified.doorUuids = cleanedDoorUuids;
|
|
57
58
|
}
|
|
58
59
|
if ((!Array.isArray(exception.intervals) || exception.intervals.length === 0) &&
|
|
@@ -67,27 +68,33 @@ async function verifyExceptionConfig(exception, requestModifiers, sessionId) {
|
|
|
67
68
|
},
|
|
68
69
|
];
|
|
69
70
|
}
|
|
70
|
-
// construct locationToDoorsMap
|
|
71
|
-
|
|
72
|
-
if (cleanedDoorUuids
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
const
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
71
|
+
// construct locationToDoorsMap only when doors are explicitly provided.
|
|
72
|
+
// For update, omitting doorUuids should preserve the existing map.
|
|
73
|
+
if (cleanedDoorUuids !== undefined) {
|
|
74
|
+
const locationToDoorsMap = {};
|
|
75
|
+
if (cleanedDoorUuids.length > 0) {
|
|
76
|
+
const doors = await getAccessControlledDoors(requestModifiers, sessionId);
|
|
77
|
+
const doorsMap = await createUuidMap(doors.accessControlledDoors ?? [], "uuid");
|
|
78
|
+
for (const doorUuid of cleanedDoorUuids) {
|
|
79
|
+
const door = doorsMap.get(doorUuid);
|
|
80
|
+
const locationUuid = door?.locationUuid;
|
|
81
|
+
if (locationUuid) {
|
|
82
|
+
if (!locationToDoorsMap[locationUuid]) {
|
|
83
|
+
locationToDoorsMap[locationUuid] = [];
|
|
84
|
+
}
|
|
85
|
+
locationToDoorsMap[locationUuid].push(doorUuid);
|
|
81
86
|
}
|
|
82
|
-
locationToDoorsMap[locationUuid].push(doorUuid);
|
|
83
87
|
}
|
|
84
88
|
}
|
|
89
|
+
verified.locationToDoorsMap = locationToDoorsMap;
|
|
90
|
+
}
|
|
91
|
+
else if (!options.isUpdate) {
|
|
92
|
+
verified.locationToDoorsMap = {};
|
|
85
93
|
}
|
|
86
|
-
verified.locationToDoorsMap = locationToDoorsMap;
|
|
87
94
|
return verified;
|
|
88
95
|
}
|
|
89
96
|
export async function createDoorScheduleException(exception, requestModifiers, sessionId) {
|
|
90
|
-
const normalizedException = await verifyExceptionConfig(exception, requestModifiers, sessionId);
|
|
97
|
+
const normalizedException = await verifyExceptionConfig(exception, { isUpdate: false }, requestModifiers, sessionId);
|
|
91
98
|
const res = await postApi({
|
|
92
99
|
route: "/accesscontrol/doorScheduleException/createExceptionV2",
|
|
93
100
|
body: {
|
|
@@ -103,7 +110,7 @@ export async function createDoorScheduleException(exception, requestModifiers, s
|
|
|
103
110
|
};
|
|
104
111
|
}
|
|
105
112
|
export async function updateDoorScheduleException(exception, requestModifiers, sessionId) {
|
|
106
|
-
const normalizedException = await verifyExceptionConfig(exception, requestModifiers, sessionId);
|
|
113
|
+
const normalizedException = await verifyExceptionConfig(exception, { isUpdate: true }, requestModifiers, sessionId);
|
|
107
114
|
const res = await postApi({
|
|
108
115
|
route: "/accesscontrol/doorScheduleException/updateExceptionV2",
|
|
109
116
|
body: {
|
|
@@ -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/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,5 +1,5 @@
|
|
|
1
1
|
import { createDoorScheduleException, deleteDoorScheduleException, findDoorScheduleExceptions, findDoorScheduleExceptionsForDoor, findDoorScheduleExceptionsForLocation, getDoorScheduleException, updateDoorScheduleException, } from "../api/door-schedule-exception-tool-api.js";
|
|
2
|
-
import { DoorScheduleExceptionRequestType, OUTPUT_SCHEMA, TOOL_ARGS, } from "../types/door-schedule-exception-tool-types.js";
|
|
2
|
+
import { CREATE_DOOR_SCHEDULE_EXCEPTION_INPUT_SCHEMA, DoorScheduleExceptionRequestType, OUTPUT_SCHEMA, TOOL_ARGS, UPDATE_DOOR_SCHEDULE_EXCEPTION_INPUT_SCHEMA, } from "../types/door-schedule-exception-tool-types.js";
|
|
3
3
|
import { createToolStructuredContent, createToolTextContent, extractFromToolExtra, } from "../util.js";
|
|
4
4
|
const TOOL_NAME = "door-schedule-exception-tool";
|
|
5
5
|
const TOOL_DESCRIPTION = `
|
|
@@ -9,6 +9,10 @@ If a lock/unlock exception is enabled, it will overwrite the existing lock/unloc
|
|
|
9
9
|
A schedule exception allows you to create a custom schedule that is only active for the specified dates/times.
|
|
10
10
|
Once the date/time a schedule exception is set for passes, the original schedule will resume.
|
|
11
11
|
|
|
12
|
+
Door schedule exceptions can be either expired or not expired. If its scheduled date is in the past, then it is expired.
|
|
13
|
+
Users through the web console can toggle whether to see expired door schedule exceptions or not. Please mirror this behavior
|
|
14
|
+
when responding to the user.
|
|
15
|
+
|
|
12
16
|
It has the following modes of operation, determined by the "requestType" parameter:
|
|
13
17
|
- ${DoorScheduleExceptionRequestType.CREATE_EXCEPTION}: Create a door schedule exception. Requires exception (DoorScheduleExceptionType object). If locationUuid is missing but doorUuids are provided, the tool will resolve the location automatically.
|
|
14
18
|
- ${DoorScheduleExceptionRequestType.DELETE_EXCEPTION}: Delete a door schedule exception. Requires exceptionUuid.
|
|
@@ -38,7 +42,13 @@ const TOOL_HANDLER = async (args, _extra) => {
|
|
|
38
42
|
error: "exception is required for create-exception.",
|
|
39
43
|
}));
|
|
40
44
|
}
|
|
41
|
-
const
|
|
45
|
+
const parsedException = CREATE_DOOR_SCHEDULE_EXCEPTION_INPUT_SCHEMA.safeParse(args.exception);
|
|
46
|
+
if (!parsedException.success) {
|
|
47
|
+
return createToolTextContent(JSON.stringify({
|
|
48
|
+
error: parsedException.error.issues[0]?.message ?? "Invalid exception payload for create-exception.",
|
|
49
|
+
}));
|
|
50
|
+
}
|
|
51
|
+
const created = await createDoorScheduleException(parsedException.data, requestModifiers, sessionId);
|
|
42
52
|
return createToolStructuredContent(created);
|
|
43
53
|
}
|
|
44
54
|
case DoorScheduleExceptionRequestType.DELETE_EXCEPTION: {
|
|
@@ -87,7 +97,14 @@ const TOOL_HANDLER = async (args, _extra) => {
|
|
|
87
97
|
error: "exception is required for update-exception.",
|
|
88
98
|
}));
|
|
89
99
|
}
|
|
90
|
-
const
|
|
100
|
+
const parsedException = UPDATE_DOOR_SCHEDULE_EXCEPTION_INPUT_SCHEMA.safeParse(args.exception);
|
|
101
|
+
if (!parsedException.success) {
|
|
102
|
+
return createToolTextContent(JSON.stringify({
|
|
103
|
+
error: parsedException.error.issues[0]?.message ??
|
|
104
|
+
"Invalid exception payload for update-exception.",
|
|
105
|
+
}));
|
|
106
|
+
}
|
|
107
|
+
const updated = await updateDoorScheduleException(parsedException.data, requestModifiers, sessionId);
|
|
91
108
|
return createToolStructuredContent(updated);
|
|
92
109
|
}
|
|
93
110
|
}
|
|
@@ -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
|
});
|
|
@@ -11,29 +11,29 @@ export var DoorScheduleExceptionRequestType;
|
|
|
11
11
|
DoorScheduleExceptionRequestType["GET_EXCEPTION"] = "get-exception";
|
|
12
12
|
DoorScheduleExceptionRequestType["UPDATE_EXCEPTION"] = "update-exception";
|
|
13
13
|
})(DoorScheduleExceptionRequestType || (DoorScheduleExceptionRequestType = {}));
|
|
14
|
-
|
|
14
|
+
const DOOR_INTERVAL_SCHEMA = z.object({
|
|
15
|
+
localEndDateTime: z.string().nullable(),
|
|
16
|
+
localStartDateTime: z.string().nullable(),
|
|
17
|
+
state: z.enum(AccessControlledDoorStateEnumType),
|
|
18
|
+
});
|
|
19
|
+
const DOOR_SCHEDULE_EXCEPTION_BASE_SCHEMA = z
|
|
15
20
|
.object({
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
21
|
+
uuid: z.string().nullable().optional(),
|
|
22
|
+
createdAtMillis: z.number().nullable().optional(),
|
|
23
|
+
defaultState: z.enum(AccessControlledDoorStateEnumType).nullable().optional(),
|
|
24
|
+
description: z.string().nullable().optional(),
|
|
19
25
|
doorUuids: z.array(z.string().nullable()).nullable().optional(),
|
|
20
|
-
intervals: z
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
localStartDateTime: z.string().nullable(),
|
|
24
|
-
state: z.enum(AccessControlledDoorStateEnumType),
|
|
25
|
-
}))
|
|
26
|
-
.nullable(),
|
|
27
|
-
localEndDate: z.string().nullable(),
|
|
28
|
-
localStartDate: z.string().nullable(),
|
|
26
|
+
intervals: z.array(DOOR_INTERVAL_SCHEMA).nullable().optional(),
|
|
27
|
+
localEndDate: z.string().nullable().optional(),
|
|
28
|
+
localStartDate: z.string().nullable().optional(),
|
|
29
29
|
locationToDoorsMap: z
|
|
30
30
|
.record(z.string(), z.array(z.string().nullable()).nullable())
|
|
31
31
|
.nullable()
|
|
32
32
|
.optional(),
|
|
33
|
-
name: z.string().nullable(),
|
|
34
|
-
updatedAtMillis: z.number().nullable(),
|
|
35
|
-
})
|
|
36
|
-
|
|
33
|
+
name: z.string().nullable().optional(),
|
|
34
|
+
updatedAtMillis: z.number().nullable().optional(),
|
|
35
|
+
});
|
|
36
|
+
export const CREATE_DOOR_SCHEDULE_EXCEPTION_INPUT_SCHEMA = DOOR_SCHEDULE_EXCEPTION_BASE_SCHEMA.superRefine((value, ctx) => {
|
|
37
37
|
if (!value.name) {
|
|
38
38
|
ctx.addIssue({
|
|
39
39
|
code: z.ZodIssueCode.custom,
|
|
@@ -74,6 +74,36 @@ export const DOOR_SCHEDULE_EXCEPTION_INPUT_SCHEMA = z
|
|
|
74
74
|
});
|
|
75
75
|
}
|
|
76
76
|
});
|
|
77
|
+
export const UPDATE_DOOR_SCHEDULE_EXCEPTION_INPUT_SCHEMA = DOOR_SCHEDULE_EXCEPTION_BASE_SCHEMA.superRefine((value, ctx) => {
|
|
78
|
+
if (!value.uuid) {
|
|
79
|
+
ctx.addIssue({
|
|
80
|
+
code: z.ZodIssueCode.custom,
|
|
81
|
+
message: "exception.uuid is required for update-exception.",
|
|
82
|
+
path: ["uuid"],
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
const hasMutableField = [
|
|
86
|
+
value.name,
|
|
87
|
+
value.description,
|
|
88
|
+
value.defaultState,
|
|
89
|
+
value.localStartDate,
|
|
90
|
+
value.localEndDate,
|
|
91
|
+
value.intervals,
|
|
92
|
+
value.doorUuids,
|
|
93
|
+
value.locationToDoorsMap,
|
|
94
|
+
].some((field) => field !== undefined);
|
|
95
|
+
if (!hasMutableField) {
|
|
96
|
+
ctx.addIssue({
|
|
97
|
+
code: z.ZodIssueCode.custom,
|
|
98
|
+
message: "exception update must provide at least one mutable field (for example name, description, dates, intervals, doorUuids, or locationToDoorsMap).",
|
|
99
|
+
path: [],
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
export const DOOR_SCHEDULE_EXCEPTION_INPUT_SCHEMA = z.union([
|
|
104
|
+
CREATE_DOOR_SCHEDULE_EXCEPTION_INPUT_SCHEMA,
|
|
105
|
+
UPDATE_DOOR_SCHEDULE_EXCEPTION_INPUT_SCHEMA,
|
|
106
|
+
]);
|
|
77
107
|
export const TOOL_ARGS = {
|
|
78
108
|
requestType: z
|
|
79
109
|
.nativeEnum(DoorScheduleExceptionRequestType)
|
|
@@ -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."),
|