rhombus-node-mcp 0.1.15 → 0.1.17

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 (80) hide show
  1. package/README.md +9 -1
  2. package/dist/api/camera-tool-api.js +161 -0
  3. package/dist/api/clips-tool-api.js +36 -0
  4. package/dist/api/create-camera-policy-tool-api.js +9 -0
  5. package/dist/api/create-tool-api.js +53 -0
  6. package/dist/api/entity-lookup-tool-api.js +65 -0
  7. package/dist/api/events-tool-api.js +320 -0
  8. package/dist/api/faces-tool-api.js +110 -0
  9. package/dist/api/get-entity-tool-api.js +176 -0
  10. package/dist/api/get-org-information-tool-api.js +9 -0
  11. package/dist/api/location-tool-api.js +9 -0
  12. package/dist/api/lpr-tool-api.js +68 -0
  13. package/dist/api/policy-alerts-tool-api.js +42 -0
  14. package/dist/api/reboot-cameras-tool-api.js +34 -0
  15. package/dist/api/report-tool-api.js +426 -0
  16. package/dist/api/time-tool-api.js +90 -0
  17. package/dist/api/update-tool-api.js +148 -0
  18. package/dist/createServer.js +7 -1
  19. package/dist/disabled-tools/endpoint-to-keys-tool.js +84 -0
  20. package/dist/disabled-tools/semantic-search-tool.js +90 -0
  21. package/dist/index.js +3 -5
  22. package/dist/logger.js +4 -3
  23. package/dist/network.js +42 -15
  24. package/dist/resources/routes.json.js +1 -1
  25. package/dist/services/embedding-service.js +153 -0
  26. package/dist/services/faiss-search-service.js +261 -0
  27. package/dist/tools/camera-tool.js +100 -0
  28. package/dist/tools/clips-tool.js +23 -37
  29. package/dist/tools/count-tool.js +25 -0
  30. package/dist/tools/create-camera-policy-tool.js +214 -0
  31. package/dist/tools/create-tool.js +25 -74
  32. package/dist/tools/entity-lookup-tool.js +36 -0
  33. package/dist/tools/events-tool.js +188 -92
  34. package/dist/tools/faces-tool.js +59 -132
  35. package/dist/tools/get-entity-tool.js +78 -0
  36. package/dist/tools/get-org-information-tool.js +18 -0
  37. package/dist/tools/location-tool.js +24 -31
  38. package/dist/tools/lpr-tool.js +79 -0
  39. package/dist/tools/policy-alerts-tool.js +34 -42
  40. package/dist/tools/reboot-cameras-tool.js +34 -0
  41. package/dist/tools/report-tool.js +190 -0
  42. package/dist/tools/time-conversion-tool.js +43 -0
  43. package/dist/tools/time-tool.js +17 -57
  44. package/dist/tools/update-tool.js +262 -0
  45. package/dist/transports/streamable-http.js +160 -57
  46. package/dist/{tools/devices/camera-tool/types.js → types/camera-tool-types.js} +52 -0
  47. package/dist/types/clips-tool-types.js +41 -0
  48. package/dist/types/create-camera-policy-tool-types.js +44 -0
  49. package/dist/types/create-tool-types.js +8 -0
  50. package/dist/types/deviceType.js +1 -0
  51. package/dist/types/endpoint-to-keys-tool-types.js +7 -0
  52. package/dist/types/entity-lookup-tool-types.js +70 -0
  53. package/dist/types/events-tools-types.js +257 -0
  54. package/dist/types/faces-tools-types.js +143 -0
  55. package/dist/types/get-entity-tool-types.js +25 -0
  56. package/dist/types/get-org-information-tool-types.js +3 -0
  57. package/dist/types/location-tool-types.js +11 -0
  58. package/dist/types/lpr-tool-types.js +97 -0
  59. package/dist/types/policy-alerts-tool-types.js +74 -0
  60. package/dist/types/reboot-cameras-tool-types.js +8 -0
  61. package/dist/types/report-tool-types.js +268 -0
  62. package/dist/types/schema-components.js +7093 -0
  63. package/dist/types/schema.js +1 -0
  64. package/dist/types/semantic-search-tool-types.js +5 -0
  65. package/dist/types/time-conversion-tool-types.js +8 -0
  66. package/dist/types/time-tool-types.js +11 -0
  67. package/dist/types/update-tool-types.js +186 -0
  68. package/dist/types/zod-schemas.js +21315 -0
  69. package/dist/types.js +17 -7
  70. package/dist/util.js +94 -2
  71. package/dist/utils/confirmation.js +1 -1
  72. package/dist/utils/reduce-output.js +35 -0
  73. package/dist/utils/remove-nulls.js +28 -0
  74. package/dist/utils/temp.js +8 -0
  75. package/dist/utils/timestampInput.js +12 -0
  76. package/package.json +23 -3
  77. package/dist/tools/devices/camera-tool/camera-tool.js +0 -218
  78. package/dist/tools/devices/get-entity-tool.js +0 -118
  79. package/dist/tools/get-org-information.js +0 -17
  80. package/dist/tools/reboot-cameras.js +0 -62
@@ -0,0 +1,7 @@
1
+ import { z } from "zod";
2
+ export const TOOL_ARGS = {
3
+ endpoint: z
4
+ .string()
5
+ .describe("The API endpoint to get output keys for (e.g., 'POST /api/camera/getMinimalCameraStateList')"),
6
+ };
7
+ const TOOL_ARGS_SCHEMA = z.object(TOOL_ARGS);
@@ -0,0 +1,70 @@
1
+ import { z } from "zod";
2
+ import { createUuidSchema } from "../types.js";
3
+ import { TempUnit } from "../utils/temp.js";
4
+ export const TOOL_ARGS = {
5
+ deviceUuids: z.array(createUuidSchema()).describe("The UUIDs of the devices to look up."),
6
+ timeZone: z
7
+ .string()
8
+ .describe("The timezone for formatting timestamps. This is necessary for the tool to produce accurate formatted timestamps."),
9
+ tempUnit: z
10
+ .nativeEnum(TempUnit)
11
+ .nullable()
12
+ .describe("The unit of temperature to return, if applicable. Default is Celsius."),
13
+ };
14
+ const TOOL_ARGS_SCHEMA = z.object(TOOL_ARGS);
15
+ export const OUTPUT_SCHEMA = z.object({
16
+ // Device arrays with their counts
17
+ cameras: z.array(z.any()).optional().describe("List of cameras matching the provided UUIDs"),
18
+ camerasCount: z.number().optional().describe("Number of cameras found"),
19
+ doorbellCameras: z
20
+ .array(z.any())
21
+ .optional()
22
+ .describe("List of doorbell cameras matching the provided UUIDs"),
23
+ doorbellCamerasCount: z.number().optional().describe("Number of doorbell cameras found"),
24
+ badgeReaders: z
25
+ .array(z.any())
26
+ .optional()
27
+ .describe("List of badge readers matching the provided UUIDs"),
28
+ badgeReadersCount: z.number().optional().describe("Number of badge readers found"),
29
+ accessControlledDoors: z
30
+ .array(z.any())
31
+ .optional()
32
+ .describe("List of access controlled doors matching the provided UUIDs"),
33
+ accessControlledDoorsCount: z
34
+ .number()
35
+ .optional()
36
+ .describe("Number of access controlled doors found"),
37
+ audioGateways: z
38
+ .array(z.any())
39
+ .optional()
40
+ .describe("List of audio gateways matching the provided UUIDs"),
41
+ audioGatewaysCount: z.number().optional().describe("Number of audio gateways found"),
42
+ doorStates: z
43
+ .array(z.any())
44
+ .optional()
45
+ .describe("List of door sensors matching the provided UUIDs"),
46
+ doorStatesCount: z.number().optional().describe("Number of door sensors found"),
47
+ climateStates: z
48
+ .array(z.any())
49
+ .optional()
50
+ .describe("List of environmental sensors matching the provided UUIDs"),
51
+ climateStatesCount: z.number().optional().describe("Number of environmental sensors found"),
52
+ occupancySensorStates: z
53
+ .array(z.any())
54
+ .optional()
55
+ .describe("List of motion sensors matching the provided UUIDs"),
56
+ occupancySensorStatesCount: z.number().optional().describe("Number of motion sensors found"),
57
+ buttonStates: z.array(z.any()).optional().describe("List of buttons matching the provided UUIDs"),
58
+ buttonStatesCount: z.number().optional().describe("Number of buttons found"),
59
+ keypadStates: z.array(z.any()).optional().describe("List of keypads matching the provided UUIDs"),
60
+ keypadStatesCount: z.number().optional().describe("Number of keypads found"),
61
+ minimalEnvironmentalGatewayStates: z
62
+ .array(z.any())
63
+ .optional()
64
+ .describe("List of environmental gateways matching the provided UUIDs"),
65
+ minimalEnvironmentalGatewayStatesCount: z
66
+ .number()
67
+ .optional()
68
+ .describe("Number of environmental gateways found"),
69
+ error: z.string().optional().describe("An error message if the request failed."),
70
+ });
@@ -0,0 +1,257 @@
1
+ import { z } from "zod";
2
+ import { ISOTimestampFormatDescription } from "../utils/timestampInput.js";
3
+ import { ComponentEventEnumType } from "./schema-components.js";
4
+ import { HumanEvent } from "../api/events-tool-api.js";
5
+ import { TempUnit } from "../utils/temp.js";
6
+ export var EventsToolRequestType;
7
+ (function (EventsToolRequestType) {
8
+ EventsToolRequestType["ACCESS_CONTROL"] = "access-control";
9
+ EventsToolRequestType["ENVIRONMENTAL_GATEWAY"] = "environmental-gateway";
10
+ EventsToolRequestType["CLIMATE_SENSOR"] = "climate-sensor";
11
+ EventsToolRequestType["COMPONENT_EVENTS"] = "component-events";
12
+ EventsToolRequestType["CAMERA"] = "camera";
13
+ })(EventsToolRequestType || (EventsToolRequestType = {}));
14
+ export const TOOL_ARGS = {
15
+ eventType: z
16
+ .nativeEnum(EventsToolRequestType)
17
+ .describe("The type of events to retrieve. " +
18
+ "access-control: Access control events like unlocks, badge ins, credentials, arrivals. " +
19
+ "environmental-gateway: Environmental gateway events with sensor readings and derived values. " +
20
+ "climate-sensor: Climate sensor events with temperature, humidity, air quality readings. " +
21
+ "component-events: All types of component events for a location (most flexible option). " +
22
+ "camera: Human motion events detected by cameras."),
23
+ startTime: z
24
+ .string()
25
+ .datetime({ message: "Invalid datetime string. Expected ISO 8601 format.", offset: true })
26
+ .describe("A timestamp representing when to start the search for access control events." +
27
+ ISOTimestampFormatDescription),
28
+ endTime: z
29
+ .string()
30
+ .datetime({ message: "Invalid datetime string. Expected ISO 8601 format.", offset: true })
31
+ .describe("A timestamp representing when to end the search for access control events." +
32
+ ISOTimestampFormatDescription),
33
+ accessControlledDoorUuids: z
34
+ .array(z.string())
35
+ .nullable()
36
+ .describe("The UUIDs (array) of the access controlled doors. Required when eventType is 'access-control'."),
37
+ deviceUuid: z
38
+ .string()
39
+ .nullable()
40
+ .describe("The UUID of the environmental gateway device. Required when eventType is 'environmental-gateway' Can be obtained from the get-entity-tool for ENVIRONMENTAL_GATEWAY."),
41
+ sensorUuid: z
42
+ .string()
43
+ .nullable()
44
+ .describe("The UUID of the climate sensor. Required when eventType is 'climate-sensor'. Can be obtained from the get-entity-tool for SENSOR."),
45
+ limit: z
46
+ .number()
47
+ .int()
48
+ .positive()
49
+ .nullable()
50
+ .describe("Maximum number of climate events to return. Only applicable when eventType is 'climate-sensor'. Default is 1000. Pass null for other event types."),
51
+ locationUuid: z
52
+ .string()
53
+ .nullable()
54
+ .describe("The UUID of the location. Required when eventType is 'component-events'."),
55
+ componentEventTypes: z
56
+ .array(z.nativeEnum(ComponentEventEnumType))
57
+ .nullable()
58
+ .describe("Array of component event types to filter by. Only applicable when eventType is 'component-events'. " +
59
+ "If empty or null, returns all event types. Valid values: " +
60
+ "DoorbellEvent, DoorReaderStateChangeEvent, DoorRelayStateChangeEvent, DoorPositionIndicatorStateChangeEvent, " +
61
+ "RequestToExitStateChangeEvent, CredentialReceivedEvent, ButtonEvent, GenericInputStateChangeEvent, " +
62
+ "GenericRelayStateChangeEvent, AccessControlUnitTamperEvent, AccessControlUnitLocationLockdownStateEvent, " +
63
+ "DoorLocationLockdownStateEvent, PanicButtonEvent, AccessControlUnitBatteryStateChangeEvent, " +
64
+ "WaveToUnlockIntentExpiredEvent, DoorStateChangeEvent, DoorAuthFirstInStateEvent, DoorScheduleFirstInStateEvent, " +
65
+ "AccessControlUnitDoorFirstInStateEvent, AperioDoorExtensionStateEvent, AperioGatewayStateEvent, " +
66
+ "AperioGatewayConnectionStateChangeEvent, AperioDtcEvent, AperioTamperStateEvent."),
67
+ timeZone: z
68
+ .string()
69
+ .describe("The timezone of the requested locations or devices. This is necessary for the tool to produce accurate formatted timestamps."),
70
+ cameraUuid: z
71
+ .string()
72
+ .nullable()
73
+ .describe("The unique identifier for the camera. Required when eventType is 'camera'. Can be obtained from the get-entity-tool for CAMERA."),
74
+ duration: z
75
+ .number()
76
+ .int()
77
+ .positive()
78
+ .nullable()
79
+ .describe("Duration in seconds to search for human motion events. Required when eventType is 'camera'. Default is 3600 (1 hour)."),
80
+ tempUnit: z
81
+ .nativeEnum(TempUnit)
82
+ .nullable()
83
+ .describe("The unit of temperature to return. Default is Celsius."),
84
+ };
85
+ const TOOL_ARGS_SCHEMA = z.object(TOOL_ARGS);
86
+ const StrippedEnvironmentalEvent = z.object({
87
+ timestampString: z.string().optional().describe("Human-readable formatted timestamp"),
88
+ temp: z.number().optional().describe("Temperature from CO2 sensor in Celsius"),
89
+ probeTemp: z.number().optional().describe("Temperature from probe sensor in Celsius"),
90
+ humidity: z.number().optional().describe("Relative humidity percentage"),
91
+ pm25: z.number().optional().describe("PM2.5 particulate matter reading"),
92
+ co2: z.number().optional().describe("CO2 concentration in PPM"),
93
+ vapeDetected: z.boolean().optional().describe("Whether vape was detected"),
94
+ });
95
+ const ClimateSensorEvent = z.object({
96
+ timestampString: z.string().optional().describe("Human-readable formatted timestamp"),
97
+ timestampMs: z.number().optional().describe("Timestamp in milliseconds"),
98
+ temp: z.number().optional().describe("Temperature reading in Celsius"),
99
+ probeTemp: z.number().optional().describe("Temperature from probe sensor"),
100
+ // probeTempC: z.number().optional().describe("Temperature from probe sensor in Celsius"),
101
+ humidity: z.number().optional().describe("Relative humidity percentage"),
102
+ pm25: z.number().optional().describe("PM2.5 particulate matter reading"),
103
+ co2: z.number().optional().describe("CO2 concentration in PPM"),
104
+ tvoc: z.number().optional().describe("Total Volatile Organic Compounds"),
105
+ iaq: z.number().optional().describe("Indoor Air Quality index"),
106
+ ethanol: z.number().optional().describe("Ethanol concentration"),
107
+ heatIndexDegF: z.number().optional().describe("Heat index in Fahrenheit"),
108
+ heatIndexRangeWarning: z.string().optional().describe("Heat index warning level"),
109
+ vapeSmokeDetected: z.boolean().optional().describe("Whether vape or smoke was detected"),
110
+ vapeSmokePercent: z.number().optional().describe("Vape/smoke confidence percentage"),
111
+ thcDetected: z.boolean().optional().describe("Whether THC was detected"),
112
+ thcPercent: z.number().optional().describe("THC confidence percentage"),
113
+ tampered: z.boolean().optional().describe("Whether the sensor was tampered with"),
114
+ batteryPercentage: z.number().optional().describe("Battery level percentage"),
115
+ locationUuid: z.string().optional().describe("Location UUID"),
116
+ orgUuid: z.string().optional().describe("Organization UUID"),
117
+ });
118
+ export const OUTPUT_SCHEMA = z.object({
119
+ eventType: z
120
+ .enum([
121
+ "access-control",
122
+ "environmental-gateway",
123
+ "climate-sensor",
124
+ "component-events",
125
+ "camera",
126
+ ])
127
+ .optional(),
128
+ accessControlEvents: z.optional(z
129
+ .array(z.object({
130
+ authenticationResult: z
131
+ .string()
132
+ .optional()
133
+ .describe("The result of the authentication process"),
134
+ authorizationResult: z
135
+ .string()
136
+ .optional()
137
+ .describe("The result of the authorization process"),
138
+ doorUuid: z
139
+ .string()
140
+ .optional()
141
+ .describe("The unique identifier for the access controlled door"),
142
+ locationUuid: z
143
+ .string()
144
+ .optional()
145
+ .describe("The unique identifier for the location where the event occurred"),
146
+ user: z
147
+ .string()
148
+ .optional()
149
+ .describe("The username of the person who triggered the event"),
150
+ credSource: z
151
+ .string()
152
+ .optional()
153
+ .describe("The source of the credential. Is what generated the event. " +
154
+ "BLE_WAVE is a user badging in by physically waving their hand over the reader. " +
155
+ "NFC is a user badging in by tapping their badge or their phone on the reader. " +
156
+ "REMOTE is unlocking the door remotely through the Rhombus app."),
157
+ datetime: z.string().optional().describe("Datetime string of when the event occurred"),
158
+ }))
159
+ .nullable()
160
+ .describe("Access control events data including badge ins, credentials, arrivals, etc.")),
161
+ environmentalGatewayEvents: z.optional(z
162
+ .object({
163
+ events: z
164
+ .array(StrippedEnvironmentalEvent)
165
+ .optional()
166
+ .describe("An array where each object represents a single environmental event containing sensor readings and derived values"),
167
+ lastEvaluatedKey: z
168
+ .string()
169
+ .optional()
170
+ .describe("A key for pagination if more results are available"),
171
+ })
172
+ .nullable()
173
+ .describe("Environmental gateway events data including sensor readings and derived values")),
174
+ climateSensorEvents: z.optional(z
175
+ .array(ClimateSensorEvent)
176
+ .nullable()
177
+ .describe("Climate sensor events data including temperature, humidity, air quality, and other readings")),
178
+ componentEvents: z.optional(z
179
+ .array(z.object({
180
+ eventType: z
181
+ .string()
182
+ .optional()
183
+ .describe("The type of component event (e.g., DoorbellEvent, CredentialReceivedEvent, etc.)"),
184
+ componentUuid: z
185
+ .string()
186
+ .optional()
187
+ .describe("The unique identifier for the component that generated the event"),
188
+ locationUuid: z
189
+ .string()
190
+ .optional()
191
+ .describe("The unique identifier for the location where the event occurred"),
192
+ orgUuid: z.string().optional().describe("The unique identifier for the organization"),
193
+ correlationId: z
194
+ .string()
195
+ .optional()
196
+ .describe("A correlation ID for tracking related events"),
197
+ ownerDeviceUuid: z
198
+ .string()
199
+ .optional()
200
+ .describe("The unique identifier for the device that owns this component"),
201
+ datetime: z
202
+ .string()
203
+ .optional()
204
+ .describe("Human-readable datetime string of when the event occurred"),
205
+ timestampMs: z
206
+ .number()
207
+ .optional()
208
+ .describe("Timestamp in milliseconds when the event occurred"),
209
+ uuid: z.string().optional().describe("The unique identifier for this specific event"),
210
+ // Event-specific fields
211
+ authenticationResult: z
212
+ .string()
213
+ .optional()
214
+ .describe("The result of the authentication process (for credential events)"),
215
+ authorizationResult: z
216
+ .string()
217
+ .optional()
218
+ .describe("The result of the authorization process (for credential events)"),
219
+ user: z
220
+ .string()
221
+ .optional()
222
+ .describe("The username of the person who triggered the event (for credential events)"),
223
+ credSource: z
224
+ .string()
225
+ .optional()
226
+ .describe("The source of the credential (for credential events)"),
227
+ doorUuid: z
228
+ .string()
229
+ .optional()
230
+ .describe("The unique identifier for the door (for door-related events)"),
231
+ doorbellCameraUuid: z
232
+ .string()
233
+ .optional()
234
+ .describe("The unique identifier for the doorbell camera (for doorbell events)"),
235
+ previousState: z
236
+ .string()
237
+ .optional()
238
+ .describe("The previous state before the change (for state change events)"),
239
+ newState: z
240
+ .string()
241
+ .optional()
242
+ .describe("The new state after the change (for state change events)"),
243
+ reason: z.string().optional().describe("The reason for the state change or event"),
244
+ buttonState: z
245
+ .string()
246
+ .optional()
247
+ .describe("The state of the button (for button events)"),
248
+ }))
249
+ .nullable()
250
+ .describe("Component events data for all types of access control events at a location, sorted by timestamp (newest first)")),
251
+ cameraEvents: z
252
+ .array(HumanEvent)
253
+ .optional()
254
+ .describe(`Camera events data, as requested with requestType ${EventsToolRequestType.CAMERA}`),
255
+ needUserInput: z.boolean().optional(),
256
+ commandForUser: z.string().optional(),
257
+ });
@@ -0,0 +1,143 @@
1
+ import { z } from "zod";
2
+ import { ISOTimestampFormatDescription } from "../utils/timestampInput.js";
3
+ import { createUuidSchema } from "../types.js";
4
+ export var RequestType;
5
+ (function (RequestType) {
6
+ RequestType["GET_FACE_EVENTS"] = "get-face-events";
7
+ RequestType["GET_REGISTERED_FACES"] = "get-registered-faces";
8
+ })(RequestType || (RequestType = {}));
9
+ export const GetRegisteredFacesArgsSchema = z.object({
10
+ requestType: z.literal(RequestType.GET_REGISTERED_FACES),
11
+ });
12
+ export const GetFaceEventsArgs = z.object({
13
+ pageRequest: z
14
+ .object({
15
+ lastEvaluatedKey: z
16
+ .string()
17
+ .nullable()
18
+ .describe("The last evaluated key from a previous pagination request"),
19
+ maxPageSize: z
20
+ .number()
21
+ .nullable()
22
+ .describe("Maximum number of results to return per page. Default to around 200. Caution against setting this to a lower number, it may make you miss information."),
23
+ })
24
+ .nullable()
25
+ .describe("Pagination parameters for the request"),
26
+ searchFilter: z
27
+ .object({
28
+ // TODO: this is causing the AI to call the tool incorrectly and always pass in deviceUUIDs. We'll leave
29
+ // the filtering of this to the AI for now.
30
+ // deviceUuids: z
31
+ // .array(z.string())
32
+ // .describe(
33
+ // "Optional filter by a set of device UUIDs. Only face events from these devices will be returned. An empty array will be the same as omitting the filter. The strings are always 22 characters long."
34
+ // ),
35
+ faceNameContains: z
36
+ .string()
37
+ .nullable()
38
+ .describe("Optional filter for face events where the detected face's name contains this substring. The search is performed only if the value is at least 3 characters long after trimming spaces. This takes precedence over 'faceNames' if both are specified. This is case-sensitive."),
39
+ faceNames: z.array(z.string()).describe(`Optional filter by a set of specific person names. Only face events associated with these names will be returned. An empty array will be the same as omitting the filter.
40
+ This is case-sensitive.`),
41
+ hasEmbedding: z
42
+ .boolean()
43
+ .nullable()
44
+ .describe("Optional filter by the presence (true) or absence (false) of a face embedding associated with the event."),
45
+ hasName: z
46
+ .boolean()
47
+ .nullable()
48
+ .describe("Optional filter by the presence (true) or absence (false) of a person name associated with the face event."),
49
+ labels: z
50
+ .array(z.string())
51
+ .describe("Optional filter by a set of labels associated with the face event. An empty array will be the same as omitting the filter."),
52
+ locationUuids: z
53
+ .array(createUuidSchema())
54
+ .describe("Optional filter by a set of location UUIDs. Only face events from these locations will be returned. An empty array will be the same as omitting the filter."),
55
+ personUuids: z
56
+ .array(createUuidSchema())
57
+ .describe("Optional filter by a set of person UUIDs. Only face events associated with these specific people will be returned. An empty array will be the same as omitting the filter."),
58
+ timestampFilter: z
59
+ .object({
60
+ rangeEnd: z
61
+ .string()
62
+ .datetime({
63
+ message: "Invalid datetime string. Expected ISO 8601 format.",
64
+ offset: true,
65
+ })
66
+ .nullable()
67
+ .describe("The end of the time range (inclusive) for filtering face events. If not specified, the filter defaults to the last 7 days." +
68
+ ISOTimestampFormatDescription),
69
+ rangeStart: z
70
+ .string()
71
+ .datetime({
72
+ message: "Invalid datetime string. Expected ISO 8601 format.",
73
+ offset: true,
74
+ })
75
+ .nullable()
76
+ .describe("The start of the time range (inclusive) for filtering face events. If not specified, the filter defaults to the last 7 days." +
77
+ ISOTimestampFormatDescription),
78
+ })
79
+ .nullable()
80
+ .describe("Time range filter for face events"),
81
+ })
82
+ .nullable()
83
+ .describe("Search criteria for filtering face events. Only applies to tool calls with requestType 'get-face-events'."),
84
+ });
85
+ export const TOOL_ARGS = {
86
+ requestType: z.nativeEnum(RequestType),
87
+ faceEventFilter: GetFaceEventsArgs,
88
+ timeZone: z
89
+ .string()
90
+ .describe("The timezone for formatting timestamps which should come from the location of the camera for the face event. This is necessary for the tool to produce accurate formatted timestamps."),
91
+ };
92
+ const TOOL_ARGS_SCHEMA = z.object(TOOL_ARGS);
93
+ export const OUTPUT_SCHEMA = z.object({
94
+ requestType: z.nativeEnum(RequestType),
95
+ getFaceEventsResponse: z
96
+ .optional(z.array(z.object({
97
+ deviceUuid: z.optional(z.string()),
98
+ eventTimestampMs: z.number().describe("The timestamp of the face event in milliseconds."),
99
+ eventTimestamp: z
100
+ .optional(z.string())
101
+ .describe("The timestamp of the face event in human readable format."),
102
+ faceName: z
103
+ .optional(z.string())
104
+ .describe("If the face matches somebody that has been registered in our system, this is the name of the person that was detected."),
105
+ locationUuid: z
106
+ .optional(z.string())
107
+ .describe("The UUID of the location where the face event occurred."),
108
+ personUuid: z.optional(z.string()).describe("The UUID of the person that was detected."),
109
+ // selectedPersonMatch: z.optional(
110
+ // z.object({
111
+ // confidence: z.number(),
112
+ // faceId: z.optional(z.string()),
113
+ // name: z.optional(z.string()),
114
+ // uuid: z.optional(z.string()),
115
+ // })
116
+ // ),
117
+ thumbnailS3Key: z
118
+ .optional(z.string())
119
+ .describe("The S3 key of the thumbnail of the face event."),
120
+ // topPersonMatches: z.optional(
121
+ // z.array(
122
+ // z.object({
123
+ // confidence: z.number(),
124
+ // faceId: z.optional(z.string()),
125
+ // name: z.optional(z.string()),
126
+ // uuid: z.optional(z.string()),
127
+ // })
128
+ // )
129
+ // ).describe("The top person matches found for this face event, in order of confidence."),
130
+ uuid: z.optional(z.string()),
131
+ })))
132
+ .describe("A list of all people seen over the given time period."),
133
+ getSavedFacesResponse: z
134
+ .optional(z.array(z.object({
135
+ createdOn: z.optional(z.number()),
136
+ name: z.optional(z.string()),
137
+ orgUuid: z.optional(z.string()),
138
+ updatedOn: z.optional(z.number()),
139
+ uuid: z.optional(z.string()),
140
+ })))
141
+ .describe("A list of all people (registered faces) currently known to the Rhombus system for your organization."),
142
+ error: z.optional(z.string()),
143
+ });
@@ -0,0 +1,25 @@
1
+ import { z } from "zod";
2
+ import { createUuidSchema } from "../types.js";
3
+ import DeviceType from "./deviceType.js";
4
+ import { TempUnit } from "../utils/temp.js";
5
+ export const TOOL_ARGS = {
6
+ entityTypes: z
7
+ .array(z.nativeEnum(DeviceType).describe("The entity type to retreive"))
8
+ .describe("What type of entities to retrieve."),
9
+ filterBy: z
10
+ .object({
11
+ locationUuids: z
12
+ .array(createUuidSchema())
13
+ .nullable()
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."),
17
+ timeZone: z
18
+ .string()
19
+ .describe("The timezone for formatting timestamps. This is necessary for the tool to produce accurate formatted timestamps."),
20
+ tempUnit: z
21
+ .nativeEnum(TempUnit)
22
+ .nullable()
23
+ .describe("The unit of temperature to return, if applicable. Default is Celsius."),
24
+ };
25
+ const TOOL_ARGS_SCHEMA = z.object(TOOL_ARGS);
@@ -0,0 +1,3 @@
1
+ import { z } from "zod";
2
+ export const TOOL_ARGS = {};
3
+ const TOOL_ARGS_SCHEMA = z.object(TOOL_ARGS);
@@ -0,0 +1,11 @@
1
+ import { z } from "zod";
2
+ export const TOOL_ARGS = {
3
+ action: z.enum(["get", "update"]),
4
+ locationUpdate: z
5
+ .object({
6
+ uuid: z.string(),
7
+ name: z.string(),
8
+ })
9
+ .nullable(),
10
+ };
11
+ const TOOL_ARGS_SCHEMA = z.object(TOOL_ARGS);
@@ -0,0 +1,97 @@
1
+ import { z } from "zod";
2
+ import { createUuidSchema } from "../types.js";
3
+ import { ISOTimestampFormatDescription } from "../utils/timestampInput.js";
4
+ export var LprToolRequestType;
5
+ (function (LprToolRequestType) {
6
+ LprToolRequestType["GET_VEHICLE_EVENTS"] = "get-vehicle-events";
7
+ LprToolRequestType["GET_SAVED_VEHICLES"] = "get-saved-vehicles";
8
+ LprToolRequestType["GET_VEHICLE_LABELS"] = "get-vehicle-labels";
9
+ })(LprToolRequestType || (LprToolRequestType = {}));
10
+ export const VehicleEventsArgs = z.object({
11
+ deviceUuidFilter: z
12
+ .array(createUuidSchema())
13
+ .nullable()
14
+ .describe("Filter license plate events by device UUIDs. An empty array will be the same as omitting the filter."),
15
+ locationUuidFilter: z
16
+ .array(createUuidSchema())
17
+ .nullable()
18
+ .describe("Filter license plate events by location UUIDs. An empty array will be the same as omitting the filter."),
19
+ vehicleLabelQuery: z
20
+ .array(z.string())
21
+ .nullable()
22
+ .describe("Filter license plates by vehicle labels. This will do a substring search on vehicle events with these labels."),
23
+ licensePlateFuzzyQuery: z
24
+ .string()
25
+ .nullable()
26
+ .describe("Filter license plates by fuzzy search. This will do a fuzzy search on vehicle events with this license plate. You'll likely want to use this more often than vehicleLabelQuery."),
27
+ // startTime and endTime are required because this endpoint could potentially return a lot of data
28
+ startTime: z
29
+ .string()
30
+ .datetime({
31
+ message: "Invalid datetime string. Expected ISO 8601 format.",
32
+ offset: true,
33
+ })
34
+ .describe("The end of the time range (inclusive) for filtering license plate events." +
35
+ ISOTimestampFormatDescription),
36
+ endTime: z
37
+ .string()
38
+ .datetime({
39
+ message: "Invalid datetime string. Expected ISO 8601 format.",
40
+ offset: true,
41
+ })
42
+ .describe("The start of the time range (inclusive) for filtering license plate events." +
43
+ ISOTimestampFormatDescription),
44
+ });
45
+ export const TOOL_ARGS = {
46
+ requestType: z.nativeEnum(LprToolRequestType).describe("The type of request to make."),
47
+ vehicleEventsArgs: VehicleEventsArgs.nullable().describe("Only necessary for requestType 'get-vehicle-events'"),
48
+ timeZone: z
49
+ .string()
50
+ .describe("The timezone for formatting timestamps which should come from the location of the device for the LPR event, or the user's timezone. This is necessary for the tool to produce accurate formatted timestamps."),
51
+ };
52
+ const TOOL_ARGS_SCHEMA = z.object(TOOL_ARGS);
53
+ // cherry-picked fields from /getVehicleEvents
54
+ const VehicleEvent = z.object({
55
+ uuid: createUuidSchema().describe("The UUID of the license plate event."),
56
+ deviceUuid: z
57
+ .string()
58
+ .optional()
59
+ .describe("The UUID of the device that emitted the license plate event."),
60
+ eventTimestamp: z.string().optional().describe("The timestamp of the license plate event."),
61
+ imageS3Key: z
62
+ .string()
63
+ .optional()
64
+ .describe("The S3 key of the image of the license plate event. Do not modify this."),
65
+ thumbnailS3Key: z
66
+ .string()
67
+ .optional()
68
+ .describe("The S3 key of the thumbnail of the license plate event. Do not modify this."),
69
+ locationUuid: z
70
+ .string()
71
+ .optional()
72
+ .describe("The UUID of the location that emitted the license plate event."),
73
+ vehicleLicensePlate: z
74
+ .string()
75
+ .optional()
76
+ .describe("The license plate of the vehicle that was detected."),
77
+ });
78
+ const VehicleLabels = z.record(z.string(), z.array(z.string()));
79
+ const SavedVehicle = z.object({
80
+ createdTimestamp: z.string().describe("The timestamp of the saved vehicle."),
81
+ name: z.string().describe("The name of the saved vehicle."),
82
+ description: z.string().describe("The description of the saved vehicle."),
83
+ licensePlate: z.string().describe("The license plate of the saved vehicle."),
84
+ orgUuid: createUuidSchema().describe("The UUID of the organization that the saved vehicle belongs to."),
85
+ });
86
+ export const OUTPUT_SCHEMA = z.object({
87
+ vehicleEvents: z
88
+ .array(VehicleEvent)
89
+ .optional()
90
+ .describe(`A list of license plate events, as requested by the request type${LprToolRequestType.GET_VEHICLE_EVENTS}`),
91
+ vehicleLabels: VehicleLabels.optional().describe(`A list of vehicle labels, as requested by the request type${LprToolRequestType.GET_VEHICLE_LABELS}`),
92
+ savedVehicles: z
93
+ .array(SavedVehicle)
94
+ .optional()
95
+ .describe(`A list of saved vehicles, as requested by the request type${LprToolRequestType.GET_SAVED_VEHICLES}`),
96
+ error: z.string().optional().describe("An error message if the request failed."),
97
+ });