rhombus-node-mcp 0.1.22 → 0.1.23

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 (82) hide show
  1. package/README.md +8 -0
  2. package/dist/api/access-control-tool-api.js +256 -0
  3. package/dist/api/alarm-monitoring-tool-api.js +65 -0
  4. package/dist/api/camera-tool-api.js +35 -15
  5. package/dist/api/camera-uptime-tool-api.js +112 -0
  6. package/dist/api/clips-tool-api.js +110 -21
  7. package/dist/api/create-tool-api.js +143 -16
  8. package/dist/api/door-tool-api.js +66 -0
  9. package/dist/api/events-tool-api.js +151 -28
  10. package/dist/api/faces-tool-api.js +118 -90
  11. package/dist/api/get-entity-tool-api.js +2 -0
  12. package/dist/api/guest-management-tool-api.js +75 -0
  13. package/dist/api/location-tool-api.js +48 -1
  14. package/dist/api/lpr-tool-api.js +26 -0
  15. package/dist/api/policy-alerts-tool-api.js +54 -0
  16. package/dist/api/report-tool-api.js +345 -23
  17. package/dist/api/rules-tool-api.js +78 -0
  18. package/dist/api/search-tool-api.js +93 -0
  19. package/dist/api/time-tool-api.js +3 -1
  20. package/dist/api/update-tool-api.js +204 -0
  21. package/dist/api/user-access-trail-tool-api.js +45 -0
  22. package/dist/api/user-audit-tool-api.js +47 -0
  23. package/dist/api/user-tool-api.js +77 -0
  24. package/dist/createServer.js +3 -1
  25. package/dist/filtering-utils.js +298 -0
  26. package/dist/index.js +0 -9
  27. package/dist/logger.js +6 -5
  28. package/dist/network.js +18 -4
  29. package/dist/tools/access-control-tool.js +97 -0
  30. package/dist/tools/alarm-monitoring-tool.js +50 -0
  31. package/dist/tools/analytics-tool.js +383 -0
  32. package/dist/tools/camera-tool.js +27 -9
  33. package/dist/tools/camera-uptime-tool.js +50 -0
  34. package/dist/tools/clips-tool.js +46 -16
  35. package/dist/tools/door-tool.js +66 -0
  36. package/dist/tools/events-tool.js +103 -81
  37. package/dist/tools/faces-tool.js +175 -32
  38. package/dist/tools/get-entity-tool.js +6 -1
  39. package/dist/tools/guest-management-tool.js +50 -0
  40. package/dist/tools/location-tool.js +23 -4
  41. package/dist/tools/lpr-tool.js +26 -20
  42. package/dist/tools/policy-alerts-tool.js +34 -4
  43. package/dist/tools/report-tool.js +181 -45
  44. package/dist/tools/rules-tool.js +76 -0
  45. package/dist/tools/search-tool.js +69 -0
  46. package/dist/tools/update-tool.js +63 -2
  47. package/dist/tools/user-access-trail-tool.js +64 -0
  48. package/dist/tools/user-audit-tool.js +53 -0
  49. package/dist/tools/user-tool.js +55 -0
  50. package/dist/tools/video-walls-tool.js +41 -0
  51. package/dist/transports/streamable-http.js +25 -15
  52. package/dist/types/access-control-tool-types.js +120 -0
  53. package/dist/types/alarm-monitoring-tool-types.js +60 -0
  54. package/dist/types/analytics-tool-types.js +190 -0
  55. package/dist/types/camera-tool-types.js +3 -2
  56. package/dist/types/camera-uptime-tool-types.js +52 -0
  57. package/dist/types/clips-tool-types.js +60 -11
  58. package/dist/types/door-tool-types.js +64 -0
  59. package/dist/types/events-tools-types.js +71 -3
  60. package/dist/types/faces-tools-types.js +36 -0
  61. package/dist/types/guest-management-tool-types.js +57 -0
  62. package/dist/types/location-tool-types.js +10 -1
  63. package/dist/types/lpr-tool-types.js +14 -0
  64. package/dist/types/policy-alerts-tool-types.js +38 -3
  65. package/dist/types/report-tool-types.js +284 -42
  66. package/dist/types/rules-tool-types.js +58 -0
  67. package/dist/types/schema.js +3123 -1
  68. package/dist/types/search-tool-types.js +82 -0
  69. package/dist/types/update-tool-types.js +4 -1
  70. package/dist/types/user-access-trail-tool-types.js +54 -0
  71. package/dist/types/user-audit-tool-types.js +48 -0
  72. package/dist/types/user-tool-types.js +61 -0
  73. package/dist/types/video-walls-tool-types.js +59 -0
  74. package/dist/types/zod-schemas.js +3237 -986
  75. package/dist/types.js +0 -21
  76. package/dist/util.js +34 -57
  77. package/package.json +7 -5
  78. package/dist/disabled-tools/semantic-search-tool.js +0 -90
  79. package/dist/tools/create-tool.js +0 -30
  80. package/dist/types/create-tool-types.js +0 -8
  81. package/dist/types/schema-components.js +0 -7211
  82. package/dist/types/semantic-search-tool-types.js +0 -5
@@ -1,11 +1,20 @@
1
1
  import { z } from "zod";
2
2
  export const TOOL_ARGS = {
3
- action: z.enum(["get", "update"]),
3
+ action: z.enum(["get", "update", "create", "get-labels"]),
4
4
  locationUpdate: z
5
5
  .object({
6
6
  uuid: z.string(),
7
7
  name: z.string(),
8
8
  })
9
9
  .nullable(),
10
+ locationName: z.string().nullable().describe("Name for the new location. Required for 'create'."),
11
+ locationAddress: z.string().nullable().describe("Address for the location. Optional for 'create' and 'update'."),
12
+ locationUuid: z.string().nullable().describe("UUID of the location. Required for 'update'."),
10
13
  };
11
14
  const TOOL_ARGS_SCHEMA = z.object(TOOL_ARGS);
15
+ export const OUTPUT_SCHEMA = z.object({
16
+ createdLocation: z.object({ uuid: z.string().optional(), success: z.boolean().optional() }).optional(),
17
+ updatedLocation: z.object({ success: z.boolean().optional() }).optional(),
18
+ locationLabels: z.array(z.object({ uuid: z.string().optional(), name: z.string().optional() })).optional(),
19
+ error: z.string().optional(),
20
+ });
@@ -6,6 +6,8 @@ export var LprToolRequestType;
6
6
  LprToolRequestType["GET_VEHICLE_EVENTS"] = "get-vehicle-events";
7
7
  LprToolRequestType["GET_SAVED_VEHICLES"] = "get-saved-vehicles";
8
8
  LprToolRequestType["GET_VEHICLE_LABELS"] = "get-vehicle-labels";
9
+ LprToolRequestType["SEARCH_LICENSE_PLATES"] = "search-license-plates";
10
+ LprToolRequestType["SAVE_VEHICLE"] = "save-vehicle";
9
11
  })(LprToolRequestType || (LprToolRequestType = {}));
10
12
  export const VehicleEventsArgs = z.object({
11
13
  deviceUuidFilter: z
@@ -48,6 +50,10 @@ export const TOOL_ARGS = {
48
50
  timeZone: z
49
51
  .string()
50
52
  .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."),
53
+ licensePlateQuery: z.string().nullable().describe("License plate number to search. Required for 'search-license-plates'."),
54
+ vehicleName: z.string().nullable().describe("Name for the vehicle. Required for 'save-vehicle'."),
55
+ vehicleLicensePlate: z.string().nullable().describe("License plate for the vehicle. Required for 'save-vehicle'."),
56
+ vehicleDescription: z.string().nullable().describe("Description for the vehicle. Optional for 'save-vehicle'."),
51
57
  };
52
58
  const TOOL_ARGS_SCHEMA = z.object(TOOL_ARGS);
53
59
  // cherry-picked fields from /getVehicleEvents
@@ -93,5 +99,13 @@ export const OUTPUT_SCHEMA = z.object({
93
99
  .array(SavedVehicle)
94
100
  .optional()
95
101
  .describe(`A list of saved vehicles, as requested by the request type${LprToolRequestType.GET_SAVED_VEHICLES}`),
102
+ licensePlateSearchResults: z.array(z.object({
103
+ licensePlate: z.string().optional(),
104
+ deviceUuid: z.string().optional(),
105
+ timestampMs: z.number().optional(),
106
+ })).optional().describe("License plate search results"),
107
+ saveVehicleResult: z.object({
108
+ success: z.boolean().optional(),
109
+ }).optional().describe("Result of saving a vehicle"),
96
110
  error: z.string().optional().describe("An error message if the request failed."),
97
111
  });
@@ -3,7 +3,7 @@ import { schemas } from "./zod-schemas.js";
3
3
  import { createEpochSchema, ISOTimestampFormatDescription } from "../utils/timestampInput.js";
4
4
  export const TOOL_ARGS = {
5
5
  queryType: z
6
- .enum(["existing", "expiringSoon"])
6
+ .enum(["existing", "expiringSoon", "details", "dismiss", "unhealthy-devices", "alert-groups"])
7
7
  .describe('The type of policy alerts to retrieve. Use "existing" to get current policy alerts, and "expiringSoon" to get policy alerts that are nearing their expiration date.'),
8
8
  afterTimestampISO: z
9
9
  .string()
@@ -28,20 +28,40 @@ export const TOOL_ARGS = {
28
28
  maxResults: z
29
29
  .number()
30
30
  .nullable()
31
- .describe("The maximum number of policy alerts to return. The system may default to a reasonable number (e.g., 20) if not specified, but there is a hard cap (e.g., 100) on the maximum results the API will return."),
31
+ .describe("The maximum number of policy alerts to return. A good default is 100, but you may increase or decrease this number as needed. A reasonable hard maximum is 1000 alerts."),
32
+ lastEvaluatedKey: z
33
+ .string()
34
+ .nullable()
35
+ .describe("Opaque pagination cursor from a previous response. When the response includes lastEvaluatedKey, pass it here on the next call to retrieve the next page. Used by queryType 'expiringSoon'."),
36
+ lastTimestampISO: z
37
+ .string()
38
+ .datetime({ message: "Invalid ISO 8601 date format.", offset: true })
39
+ .nullable()
40
+ .describe("Pagination cursor (ISO 8601 timestamp). When the response includes lastTimestampISO, pass it here with lastUuid on the next call for the next page. Used by queryTypes 'existing' and 'alert-groups'." +
41
+ ISOTimestampFormatDescription),
42
+ lastUuid: z
43
+ .string()
44
+ .nullable()
45
+ .describe("Pagination cursor (UUID of last item). Pass together with lastTimestampISO from the previous response to fetch the next page. Used by queryTypes 'existing' and 'alert-groups'."),
32
46
  timeZone: z
33
47
  .string()
34
48
  .describe("The timezone from the location of the camera of the policy alert, for formatting timestamps. This is necessary for the tool to produce accurate formatted timestamps."),
49
+ alertUuid: z
50
+ .string()
51
+ .nullable()
52
+ .describe("The UUID of a specific policy alert. Required for 'details' and 'dismiss'."),
35
53
  };
36
54
  const TOOL_ARGS_SCHEMA = z.object(TOOL_ARGS);
37
55
  export const ApiPayloadSchema = TOOL_ARGS_SCHEMA.transform(args => {
38
- const { queryType, afterTimestampISO, beforeTimestampISO, timeZone, ...rest } = args;
56
+ const { queryType, afterTimestampISO, beforeTimestampISO, timeZone, lastTimestampISO, ...rest } = args;
39
57
  const afterTimestampMs = createEpochSchema().parse(afterTimestampISO);
40
58
  const beforeTimestampMs = createEpochSchema().parse(beforeTimestampISO);
59
+ const lastTimestampMs = lastTimestampISO != null ? createEpochSchema().parse(lastTimestampISO) : null;
41
60
  return {
42
61
  ...rest,
43
62
  afterTimestampMs,
44
63
  beforeTimestampMs,
64
+ lastTimestampMs,
45
65
  timeZone,
46
66
  };
47
67
  });
@@ -70,5 +90,20 @@ export const OUTPUT_SCHEMA = z
70
90
  error: z.boolean().optional(),
71
91
  errorMsg: z.string().optional(),
72
92
  policyAlerts: z.array(ExtendedPolicyAlertType).optional().default([]),
93
+ lastEvaluatedKey: z
94
+ .string()
95
+ .nullable()
96
+ .optional()
97
+ .describe("If present, more results are available. Pass this value as lastEvaluatedKey on the next call to get the next page (queryType 'expiringSoon')."),
98
+ lastTimestampISO: z
99
+ .string()
100
+ .nullable()
101
+ .optional()
102
+ .describe("If present with lastUuid, more results are available. Pass both as lastTimestampISO and lastUuid on the next call for the next page ('existing' or 'alert-groups'). ISO 8601 format."),
103
+ lastUuid: z
104
+ .string()
105
+ .nullable()
106
+ .optional()
107
+ .describe("If present with lastTimestampISO, more results are available. Pass both on the next call for the next page ('existing' or 'alert-groups')."),
73
108
  })
74
109
  .passthrough();
@@ -9,6 +9,11 @@ export var RequestType;
9
9
  RequestType["GET_THRESHOLD_CROSSING_COUNT_REPORT"] = "get-threshold-crossing-count-report";
10
10
  RequestType["FIND_PROMPT_CONFIGURATIONS"] = "find-prompt-configurations";
11
11
  RequestType["GET_CUSTOM_LLM_REPORT"] = "get-custom-llm-report";
12
+ RequestType["GET_AUDIT_FEED"] = "get-audit-feed";
13
+ RequestType["GET_DIAGNOSTIC_FEED"] = "get-diagnostic-feed";
14
+ RequestType["GET_THRESHOLD_CROSSING_EVENTS"] = "get-threshold-crossing-events";
15
+ RequestType["GET_CUSTOM_EVENTS_REPORT"] = "get-custom-events-report";
16
+ RequestType["GET_PEOPLE_COUNT_EVENTS"] = "get-people-count-events";
12
17
  })(RequestType || (RequestType = {}));
13
18
  export const TOOL_ARGS = z.object({
14
19
  requestType: z.enum([
@@ -19,26 +24,43 @@ export const TOOL_ARGS = z.object({
19
24
  RequestType.GET_THRESHOLD_CROSSING_COUNT_REPORT,
20
25
  RequestType.FIND_PROMPT_CONFIGURATIONS,
21
26
  RequestType.GET_CUSTOM_LLM_REPORT,
27
+ RequestType.GET_AUDIT_FEED,
28
+ RequestType.GET_DIAGNOSTIC_FEED,
29
+ RequestType.GET_THRESHOLD_CROSSING_EVENTS,
30
+ RequestType.GET_CUSTOM_EVENTS_REPORT,
31
+ RequestType.GET_PEOPLE_COUNT_EVENTS,
22
32
  ]),
23
- occupancyCountRequest: z.object({
24
- deviceUuid: z.string().describe("The uuid of the device to get occupancy count for"),
33
+ occupancyCountRequest: z
34
+ .object({
35
+ deviceUuid: z
36
+ .string()
37
+ .describe("The uuid of the device to get occupancy count for"),
25
38
  rangeStart: z
26
39
  .string()
27
- .datetime({ message: "Invalid datetime string. Expected ISO 8601 format.", offset: true })
40
+ .datetime({
41
+ message: "Invalid datetime string. Expected ISO 8601 format.",
42
+ offset: true,
43
+ })
28
44
  .describe("The start of the time range (inclusive) for the report period." +
29
45
  ISOTimestampFormatDescription),
30
46
  rangeEnd: z
31
47
  .string()
32
- .datetime({ message: "Invalid datetime string. Expected ISO 8601 format.", offset: true })
48
+ .datetime({
49
+ message: "Invalid datetime string. Expected ISO 8601 format.",
50
+ offset: true,
51
+ })
33
52
  .describe("The end of the time range (inclusive) for the report period." +
34
53
  ISOTimestampFormatDescription),
35
54
  interval: z
36
55
  .enum(["MINUTELY", "HOURLY", "DAILY", "WEEKLY", "MONTHLY", "YEARLY"])
37
56
  .describe("The time interval for the report aggregation"),
38
- }),
39
- summaryCountRequest: z.object({
57
+ })
58
+ .nullable()
59
+ .describe("Required for requestType === 'get-occupancy-count-report', null for other request types."),
60
+ summaryCountRequest: z
61
+ .object({
40
62
  interval: z
41
- .enum(["MINUTELY", "HOURLY", "DAILY", "WEEKLY", "MONTHLY", "YEARLY"])
63
+ .enum(["MINUTELY", "QUARTERHOURLY", "HOURLY", "DAILY", "WEEKLY", "MONTHLY", "YEARLY"])
42
64
  .describe("The time interval for the report aggregation"),
43
65
  uuid: z
44
66
  .nullable(z.string())
@@ -51,9 +73,7 @@ export const TOOL_ARGS = z.object({
51
73
  "CROWD",
52
74
  "PEOPLE",
53
75
  "FACES",
54
- "MOTION",
55
76
  "BANDWIDTH",
56
- "VEHICLES",
57
77
  "LICENSEPLATES",
58
78
  "ALERTS",
59
79
  "AM_VERIFICATION",
@@ -62,36 +82,58 @@ export const TOOL_ARGS = z.object({
62
82
  .describe("The types of data to include in the summary count report"),
63
83
  rangeStart: z
64
84
  .string()
65
- .datetime({ message: "Invalid datetime string. Expected ISO 8601 format.", offset: true })
85
+ .datetime({
86
+ message: "Invalid datetime string. Expected ISO 8601 format.",
87
+ offset: true,
88
+ })
66
89
  .describe("The start of the time range (inclusive) for the report period." +
67
90
  ISOTimestampFormatDescription),
68
91
  rangeEnd: z
69
92
  .string()
70
- .datetime({ message: "Invalid datetime string. Expected ISO 8601 format.", offset: true })
93
+ .datetime({
94
+ message: "Invalid datetime string. Expected ISO 8601 format.",
95
+ offset: true,
96
+ })
71
97
  .describe("The end of the time range (inclusive) for the report period." +
72
98
  ISOTimestampFormatDescription),
73
- timeZone: z.string()
99
+ timeZone: z
100
+ .string()
74
101
  .describe(`The timezone of the requested locations or devices. This is necessary for the tool to produce
75
102
  accurate UTC dates for the returned data.`),
76
- }),
103
+ })
104
+ .nullable()
105
+ .describe("Required for requestType === 'get-summary-count-report', null for other request types."),
77
106
  occupancyEnabledCamerasRequest: z
78
107
  .object({})
79
- .describe("Request to get list of occupancy enabled cameras"),
80
- lineCrossingEnabledCamerasRequest: z.object({
108
+ .nullable()
109
+ .describe("Required for requestType === 'get-occupancy-enabled-cameras', null for other request types."),
110
+ lineCrossingEnabledCamerasRequest: z
111
+ .object({
81
112
  locationUuid: z
82
113
  .string()
83
114
  .describe("The uuid of the location to get line crossing enabled cameras for"),
84
- }),
85
- thresholdCrossingCountRequest: z.object({
86
- deviceUuid: z.string().describe("The uuid of the device to get threshold crossing count for"),
115
+ })
116
+ .nullable()
117
+ .describe("Required for requestType === 'get-line-crossing-enabled-cameras', null for other request types."),
118
+ thresholdCrossingCountRequest: z
119
+ .object({
120
+ deviceUuid: z
121
+ .string()
122
+ .describe("The uuid of the device to get threshold crossing count for"),
87
123
  rangeStart: z
88
124
  .string()
89
- .datetime({ message: "Invalid datetime string. Expected ISO 8601 format.", offset: true })
125
+ .datetime({
126
+ message: "Invalid datetime string. Expected ISO 8601 format.",
127
+ offset: true,
128
+ })
90
129
  .describe("The start of the time range (inclusive) for the report period." +
91
130
  ISOTimestampFormatDescription),
92
131
  rangeEnd: z
93
132
  .string()
94
- .datetime({ message: "Invalid datetime string. Expected ISO 8601 format.", offset: true })
133
+ .datetime({
134
+ message: "Invalid datetime string. Expected ISO 8601 format.",
135
+ offset: true,
136
+ })
95
137
  .describe("The end of the time range (inclusive) for the report period." +
96
138
  ISOTimestampFormatDescription),
97
139
  bucketSize: z
@@ -101,29 +143,120 @@ export const TOOL_ARGS = z.object({
101
143
  .enum(["HUMAN", "VEHICLE", "UNKNOWN"])
102
144
  .describe("The type of object crossing to report on"),
103
145
  dedupe: z.boolean().describe("Whether to deduplicate crossing events"),
104
- }),
146
+ })
147
+ .nullable()
148
+ .describe("Required for requestType === 'get-threshold-crossing-count-report', null for other request types."),
105
149
  findPromptConfigurationsRequest: z
106
150
  .object({})
107
- .describe("Request to find all custom event prompt configurations"),
108
- customLLMReportRequest: z.object({
109
- promptUuid: z.string().describe("The uuid of the prompt configuration to get counts for"),
151
+ .nullable()
152
+ .describe("Required for requestType === 'find-prompt-configurations', null for other request types."),
153
+ customLLMReportRequest: z
154
+ .object({
155
+ promptUuid: z
156
+ .string()
157
+ .describe("The uuid of the prompt configuration to get counts for"),
110
158
  promptType: z
111
159
  .enum(["COUNT", "PERCENT", "BOOLEAN"])
112
160
  .describe("The type of prompt configuration - determines which API endpoint to use"),
113
161
  rangeStart: z
114
162
  .string()
115
- .datetime({ message: "Invalid datetime string. Expected ISO 8601 format.", offset: true })
116
- .describe("The start of the time range (inclusive) for the report period." +
117
- ISOTimestampFormatDescription),
163
+ .datetime({
164
+ message: "Invalid datetime string. Expected ISO 8601 format.",
165
+ offset: true,
166
+ })
167
+ .describe(`The start of the time range (inclusive) for the report period. ${ISOTimestampFormatDescription}`),
118
168
  rangeEnd: z
119
169
  .string()
120
- .datetime({ message: "Invalid datetime string. Expected ISO 8601 format.", offset: true })
121
- .describe("The end of the time range (inclusive) for the report period." +
122
- ISOTimestampFormatDescription),
170
+ .datetime({
171
+ message: "Invalid datetime string. Expected ISO 8601 format.",
172
+ offset: true,
173
+ })
174
+ .describe(`The end of the time range (inclusive) for the report period. ${ISOTimestampFormatDescription}`),
123
175
  interval: z
124
- .enum(["MINUTELY", "QUARTERHOURLY", "HOURLY", "DAILY", "WEEKLY", "MONTHLY"])
176
+ .enum([
177
+ "MINUTELY",
178
+ "QUARTERHOURLY",
179
+ "HOURLY",
180
+ "DAILY",
181
+ "WEEKLY",
182
+ "MONTHLY",
183
+ ])
125
184
  .describe("The time interval for the report aggregation"),
126
- }),
185
+ })
186
+ .nullable()
187
+ .describe("Required for requestType === 'get-custom-llm-report', null for other request types."),
188
+ auditFeedRequest: z
189
+ .object({
190
+ startTime: z
191
+ .string()
192
+ .datetime({ message: "Invalid datetime string.", offset: true })
193
+ .describe(`Start of time range. ${ISOTimestampFormatDescription}`),
194
+ endTime: z
195
+ .string()
196
+ .datetime({ message: "Invalid datetime string.", offset: true })
197
+ .describe(`End of time range. ${ISOTimestampFormatDescription}`),
198
+ })
199
+ .nullable()
200
+ .describe("Required for requestType === 'get-audit-feed', null for other request types."),
201
+ diagnosticFeedRequest: z
202
+ .object({
203
+ startTime: z
204
+ .string()
205
+ .datetime({ message: "Invalid datetime string.", offset: true })
206
+ .describe(`Start of time range. ${ISOTimestampFormatDescription}`),
207
+ endTime: z
208
+ .string()
209
+ .datetime({ message: "Invalid datetime string.", offset: true })
210
+ .describe(`End of time range. ${ISOTimestampFormatDescription}`),
211
+ })
212
+ .nullable()
213
+ .describe("Required for requestType === 'get-diagnostic-feed', null for other request types."),
214
+ thresholdCrossingEventsRequest: z
215
+ .object({
216
+ deviceUuid: z.string().describe("The uuid of the device"),
217
+ startTime: z
218
+ .string()
219
+ .datetime({ message: "Invalid datetime string.", offset: true })
220
+ .describe(`Start of time range. ${ISOTimestampFormatDescription}`),
221
+ endTime: z
222
+ .string()
223
+ .datetime({ message: "Invalid datetime string.", offset: true })
224
+ .describe(`End of time range. ${ISOTimestampFormatDescription}`),
225
+ })
226
+ .nullable()
227
+ .describe("Required for requestType === 'get-threshold-crossing-events', null for other request types."),
228
+ customEventsReportRequest: z
229
+ .object({
230
+ promptUuid: z.string().describe("The uuid of the prompt configuration"),
231
+ startTime: z
232
+ .string()
233
+ .datetime({ message: "Invalid datetime string.", offset: true })
234
+ .describe(`Start of time range. ${ISOTimestampFormatDescription}`),
235
+ endTime: z
236
+ .string()
237
+ .datetime({ message: "Invalid datetime string.", offset: true })
238
+ .describe(`End of time range. ${ISOTimestampFormatDescription}`),
239
+ interval: z
240
+ .enum([
241
+ "MINUTELY",
242
+ "QUARTERHOURLY",
243
+ "HOURLY",
244
+ "DAILY",
245
+ "WEEKLY",
246
+ "MONTHLY",
247
+ ])
248
+ .describe("The time interval for aggregation"),
249
+ })
250
+ .nullable()
251
+ .describe("Required for requestType === 'get-custom-events-report', null for other request types."),
252
+ peopleCountEventsRequest: z
253
+ .object({
254
+ deviceUuids: z
255
+ .array(z.string())
256
+ .describe("Array of device UUIDs to get people count for"),
257
+ })
258
+ .nullable()
259
+ .describe("Required for requestType === 'get-people-count-events', null for other request types."),
127
260
  });
128
261
  const TOOL_ARGS_SCHEMA = TOOL_ARGS;
129
262
  export const SanitizedTimeSeriesDataPoint = z.object({
@@ -132,6 +265,15 @@ export const SanitizedTimeSeriesDataPoint = z.object({
132
265
  .describe("The UTC date of the data point in ISO 8601 format"),
133
266
  eventCountMap: z.optional(z.record(z.any())),
134
267
  });
268
+ const FaceCountEnrichment = z.object({
269
+ uniqueFaceCount: z.number().describe("Number of unique people identified by face recognition in the same time range"),
270
+ totalFaceEvents: z.number().describe("Total face detection events in the same time range"),
271
+ });
272
+ const OccupancyEnabledCamera = z.object({
273
+ uuid: z.optional(z.string()),
274
+ name: z.optional(z.string()),
275
+ locationUuid: z.optional(z.string()),
276
+ });
135
277
  export const OUTPUT_SCHEMA = z.object({
136
278
  error: z.optional(z.boolean()),
137
279
  errorMsg: z.optional(z.string()),
@@ -140,6 +282,15 @@ export const OUTPUT_SCHEMA = z.object({
140
282
  error: z.optional(z.boolean()),
141
283
  errorMsg: z.optional(z.string()),
142
284
  timeSeriesDataPoints: z.optional(z.array(SanitizedTimeSeriesDataPoint)),
285
+ faceCountEnrichment: z
286
+ .optional(FaceCountEnrichment)
287
+ .describe("Unique face count data for the same device and time range, auto-included when PEOPLE type is queried at DEVICE scope"),
288
+ hint: z
289
+ .optional(z.string())
290
+ .describe("Guidance when primary data source returned empty results"),
291
+ occupancyEnabledCameras: z
292
+ .optional(z.array(OccupancyEnabledCamera))
293
+ .describe("Cameras that support occupancy counting, included when the queried device returned zero people counts"),
143
294
  })
144
295
  .nullable()
145
296
  .describe("Report data for various high level organization metrics like people counts, bandwidth counts, face counts, etc.")),
@@ -156,6 +307,15 @@ export const OUTPUT_SCHEMA = z.object({
156
307
  eventCountMap: z.optional(z.record(z.unknown())),
157
308
  timestampMs: z.optional(z.number()),
158
309
  }))),
310
+ faceCountEnrichment: z
311
+ .optional(FaceCountEnrichment)
312
+ .describe("Unique face count data for the same device and time range, always included for occupancy reports"),
313
+ hint: z
314
+ .optional(z.string())
315
+ .describe("Guidance when the queried device does not support occupancy counting"),
316
+ occupancyEnabledCameras: z
317
+ .optional(z.array(OccupancyEnabledCamera))
318
+ .describe("Cameras that support occupancy counting, included when the queried device does not"),
159
319
  }))
160
320
  .nullable(),
161
321
  occupancyEnabledCamerasReport: z
@@ -198,11 +358,17 @@ export const OUTPUT_SCHEMA = z.object({
198
358
  averageEntriesPerHour: z
199
359
  .number()
200
360
  .describe("Average number of entries (ingress) per hour"),
201
- averageExitsPerHour: z.number().describe("Average number of exits (egress) per hour"),
361
+ averageExitsPerHour: z
362
+ .number()
363
+ .describe("Average number of exits (egress) per hour"),
202
364
  mostEntriesInHour: z
203
365
  .object({
204
- count: z.number().describe("Maximum number of entries in a single hour"),
205
- timestamp: z.string().describe("ISO timestamp of the hour with most entries"),
366
+ count: z
367
+ .number()
368
+ .describe("Maximum number of entries in a single hour"),
369
+ timestamp: z
370
+ .string()
371
+ .describe("ISO timestamp of the hour with most entries"),
206
372
  hourLabel: z
207
373
  .string()
208
374
  .describe("Human-readable hour label (e.g., '2:00 PM - 3:00 PM')"),
@@ -210,8 +376,12 @@ export const OUTPUT_SCHEMA = z.object({
210
376
  .describe("Hour with the most entries"),
211
377
  mostExitsInHour: z
212
378
  .object({
213
- count: z.number().describe("Maximum number of exits in a single hour"),
214
- timestamp: z.string().describe("ISO timestamp of the hour with most exits"),
379
+ count: z
380
+ .number()
381
+ .describe("Maximum number of exits in a single hour"),
382
+ timestamp: z
383
+ .string()
384
+ .describe("ISO timestamp of the hour with most exits"),
215
385
  hourLabel: z
216
386
  .string()
217
387
  .describe("Human-readable hour label (e.g., '2:00 PM - 3:00 PM')"),
@@ -219,13 +389,21 @@ export const OUTPUT_SCHEMA = z.object({
219
389
  .describe("Hour with the most exits"),
220
390
  busiestHour: z
221
391
  .object({
222
- totalCount: z.number().describe("Total entries + exits in the busiest hour"),
223
- timestamp: z.string().describe("ISO timestamp of the busiest hour"),
392
+ totalCount: z
393
+ .number()
394
+ .describe("Total entries + exits in the busiest hour"),
395
+ timestamp: z
396
+ .string()
397
+ .describe("ISO timestamp of the busiest hour"),
224
398
  hourLabel: z
225
399
  .string()
226
400
  .describe("Human-readable hour label (e.g., '2:00 PM - 3:00 PM')"),
227
- entries: z.number().describe("Number of entries in the busiest hour"),
228
- exits: z.number().describe("Number of exits in the busiest hour"),
401
+ entries: z
402
+ .number()
403
+ .describe("Number of entries in the busiest hour"),
404
+ exits: z
405
+ .number()
406
+ .describe("Number of exits in the busiest hour"),
229
407
  })
230
408
  .describe("Hour with the most total activity (entries + exits)"),
231
409
  }))
@@ -245,7 +423,7 @@ export const OUTPUT_SCHEMA = z.object({
245
423
  name: z.optional(z.string()),
246
424
  orgUuid: z.optional(z.string()),
247
425
  prompt: z.optional(z.string()),
248
- promptType: z.optional(z.enum(["COUNT", "PERCENT", "BOOLEAN"])),
426
+ promptType: z.optional(z.enum(["COUNT", "PERCENT", "BOOLEAN", "TEXT"])),
249
427
  scheduleUuid: z.optional(z.string()),
250
428
  shortName: z.optional(z.string()),
251
429
  uuid: z.optional(z.string()),
@@ -265,4 +443,68 @@ export const OUTPUT_SCHEMA = z.object({
265
443
  }))
266
444
  .nullable()
267
445
  .describe("Custom LLM report showing event data over time - supports COUNT, PERCENT, and BOOLEAN prompt types"),
446
+ auditFeedReport: z
447
+ .optional(z.object({
448
+ error: z.optional(z.boolean()),
449
+ errorMsg: z.optional(z.string()),
450
+ auditEvents: z.optional(z.array(z.object({
451
+ timestamp: z.optional(z.string()),
452
+ timestampMs: z.optional(z.number()),
453
+ action: z.optional(z.string()),
454
+ displayText: z.optional(z.string()),
455
+ principalName: z.optional(z.string()),
456
+ principalUuid: z.optional(z.string()),
457
+ principalType: z.optional(z.string()),
458
+ targetName: z.optional(z.string()),
459
+ targetUuid: z.optional(z.string()),
460
+ targetType: z.optional(z.string()),
461
+ description: z.optional(z.string()),
462
+ }))),
463
+ }))
464
+ .describe("Audit feed showing user actions"),
465
+ diagnosticFeedReport: z
466
+ .optional(z.object({
467
+ error: z.optional(z.boolean()),
468
+ errorMsg: z.optional(z.string()),
469
+ diagnosticEvents: z.optional(z.array(z.object({
470
+ timestampMs: z.optional(z.number()),
471
+ deviceUuid: z.optional(z.string()),
472
+ eventType: z.optional(z.string()),
473
+ description: z.optional(z.string()),
474
+ }))),
475
+ }))
476
+ .describe("Diagnostic feed showing device events"),
477
+ thresholdCrossingEventsReport: z
478
+ .optional(z.object({
479
+ error: z.optional(z.boolean()),
480
+ errorMsg: z.optional(z.string()),
481
+ events: z.optional(z.array(z.object({
482
+ timestampMs: z.optional(z.number()),
483
+ direction: z.optional(z.string()),
484
+ objectType: z.optional(z.string()),
485
+ }))),
486
+ }))
487
+ .describe("Individual threshold crossing events"),
488
+ customEventsReport: z
489
+ .optional(z.object({
490
+ error: z.optional(z.boolean()),
491
+ errorMsg: z.optional(z.string()),
492
+ timeSeriesDataPoints: z.optional(z.array(z.object({
493
+ dateLocal: z.optional(z.string()),
494
+ dateUtc: z.optional(z.string()),
495
+ eventCountMap: z.optional(z.record(z.any())),
496
+ }))),
497
+ }))
498
+ .describe("Custom events report time series"),
499
+ peopleCountEventsReport: z
500
+ .optional(z.object({
501
+ error: z.optional(z.boolean()),
502
+ errorMsg: z.optional(z.string()),
503
+ events: z.optional(z.array(z.object({
504
+ deviceUuid: z.optional(z.string()),
505
+ timestampMs: z.optional(z.number()),
506
+ count: z.optional(z.number()),
507
+ }))),
508
+ }))
509
+ .describe("Most recent people count events"),
268
510
  });
@@ -0,0 +1,58 @@
1
+ import { z } from "zod";
2
+ export var RulesToolRequestType;
3
+ (function (RulesToolRequestType) {
4
+ RulesToolRequestType["LIST"] = "list";
5
+ RulesToolRequestType["CREATE"] = "create";
6
+ RulesToolRequestType["UPDATE"] = "update";
7
+ RulesToolRequestType["DELETE"] = "delete";
8
+ RulesToolRequestType["GET_RECORDS"] = "get-records";
9
+ })(RulesToolRequestType || (RulesToolRequestType = {}));
10
+ export const TOOL_ARGS = {
11
+ requestType: z.nativeEnum(RulesToolRequestType).describe("The type of rules operation to perform."),
12
+ ruleUuid: z
13
+ .string()
14
+ .nullable()
15
+ .describe("The UUID of the rule. Required for 'update', 'delete', and 'get-records'."),
16
+ ruleName: z
17
+ .string()
18
+ .nullable()
19
+ .describe("The name of the rule. Required for 'create'."),
20
+ ruleConfig: z
21
+ .string()
22
+ .nullable()
23
+ .describe("JSON string of the rule configuration. Required for 'create' and 'update'. Contains the rule definition."),
24
+ };
25
+ const TOOL_ARGS_SCHEMA = z.object(TOOL_ARGS);
26
+ export const OUTPUT_SCHEMA = z.object({
27
+ rules: z
28
+ .array(z.object({
29
+ uuid: z.string().optional(),
30
+ name: z.string().optional(),
31
+ enabled: z.boolean().optional(),
32
+ orgUuid: z.string().optional(),
33
+ ruleType: z.string().optional(),
34
+ createdAtMs: z.number().optional(),
35
+ updatedAtMs: z.number().optional(),
36
+ }))
37
+ .optional()
38
+ .describe("List of rules"),
39
+ rule: z
40
+ .object({
41
+ uuid: z.string().optional(),
42
+ name: z.string().optional(),
43
+ success: z.boolean().optional(),
44
+ })
45
+ .optional()
46
+ .describe("Result of create/update/delete operation"),
47
+ ruleRecords: z
48
+ .array(z.object({
49
+ uuid: z.string().optional(),
50
+ ruleUuid: z.string().optional(),
51
+ triggeredAtMs: z.number().optional(),
52
+ deviceUuid: z.string().optional(),
53
+ locationUuid: z.string().optional(),
54
+ }))
55
+ .optional()
56
+ .describe("Rule trigger event records"),
57
+ error: z.string().optional().describe("An error message if the request failed."),
58
+ });