rhombus-node-mcp 0.1.22 → 0.1.24

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
@@ -0,0 +1,190 @@
1
+ import { z } from "zod";
2
+ export var AnalyticsRequestType;
3
+ (function (AnalyticsRequestType) {
4
+ AnalyticsRequestType["SPACE_UTILIZATION"] = "space-utilization";
5
+ AnalyticsRequestType["TRAFFIC_FLOW"] = "traffic-flow";
6
+ AnalyticsRequestType["PEAK_VS_AVERAGE"] = "peak-vs-average";
7
+ AnalyticsRequestType["SCENE_INTELLIGENCE"] = "scene-intelligence";
8
+ AnalyticsRequestType["LOCATION_SUMMARY"] = "location-summary";
9
+ })(AnalyticsRequestType || (AnalyticsRequestType = {}));
10
+ export const TOOL_ARGS = {
11
+ requestType: z
12
+ .nativeEnum(AnalyticsRequestType)
13
+ .describe("The type of analytics report to generate."),
14
+ spaceUtilizationRequest: z
15
+ .object({
16
+ locationUuid: z.string().describe("The location UUID to analyze."),
17
+ startTimeMs: z.number().describe("Start time in milliseconds since epoch."),
18
+ endTimeMs: z.number().describe("End time in milliseconds since epoch."),
19
+ interval: z
20
+ .enum(["HOURLY", "DAILY", "WEEKLY", "MONTHLY"])
21
+ .describe("Time interval for the report."),
22
+ })
23
+ .nullable()
24
+ .describe("Request for space utilization report. Compares per-camera people counts against running averages. Required for 'space-utilization'."),
25
+ trafficFlowRequest: z
26
+ .object({
27
+ locationUuid: z.string().describe("The location UUID to analyze."),
28
+ startTimeMs: z.number().describe("Start time in milliseconds since epoch."),
29
+ endTimeMs: z.number().describe("End time in milliseconds since epoch."),
30
+ bucketSize: z
31
+ .enum(["QUARTER_HOUR", "HOUR", "DAY", "WEEK"])
32
+ .describe("Time bucket size for aggregation."),
33
+ crossingObject: z
34
+ .enum(["HUMAN", "VEHICLE", "UNKNOWN"])
35
+ .describe("Type of object to track."),
36
+ })
37
+ .nullable()
38
+ .describe("Request for multi-camera traffic flow report. Compares ingress/egress across all line-crossing cameras at a location. Required for 'traffic-flow'."),
39
+ peakVsAverageRequest: z
40
+ .object({
41
+ uuid: z
42
+ .string()
43
+ .nullable()
44
+ .describe("Device or location UUID depending on scope."),
45
+ scope: z
46
+ .enum(["DEVICE", "LOCATION", "ORG"])
47
+ .describe("Level of granularity."),
48
+ startTimeMs: z.number().describe("Start time in milliseconds since epoch."),
49
+ endTimeMs: z.number().describe("End time in milliseconds since epoch."),
50
+ timeZone: z
51
+ .string()
52
+ .nullable()
53
+ .describe("Timezone string for bucketing (e.g. 'America/New_York')."),
54
+ })
55
+ .nullable()
56
+ .describe("Request for peak-vs-average analysis. Shows hourly actual counts vs historical running averages. Required for 'peak-vs-average'."),
57
+ sceneIntelligenceRequest: z
58
+ .object({
59
+ deviceFacetUuid: z
60
+ .string()
61
+ .describe("Camera device UUID (with optional facet suffix) to query."),
62
+ prompt: z
63
+ .string()
64
+ .describe("The question to ask the camera (e.g. 'How many treadmills are in use?')."),
65
+ promptType: z
66
+ .enum(["COUNT", "PERCENT", "BOOLEAN"])
67
+ .describe("Type of answer expected: COUNT for numbers, PERCENT for percentages, BOOLEAN for yes/no."),
68
+ timestampMs: z
69
+ .number()
70
+ .nullable()
71
+ .describe("Optional timestamp to query a historical moment. Omit for real-time."),
72
+ })
73
+ .nullable()
74
+ .describe("Request for real-time scene intelligence. Asks a camera an arbitrary question using AI. Required for 'scene-intelligence'."),
75
+ locationSummaryRequest: z
76
+ .object({
77
+ locationUuid: z.string().describe("The location UUID to summarize."),
78
+ startTimeMs: z.number().describe("Start time in milliseconds since epoch."),
79
+ endTimeMs: z.number().describe("End time in milliseconds since epoch."),
80
+ })
81
+ .nullable()
82
+ .describe("Request for a comprehensive location analytics summary covering people counts, traffic flow, occupancy, and comparison to averages. Required for 'location-summary'."),
83
+ };
84
+ const TOOL_ARGS_SCHEMA = z.object(TOOL_ARGS);
85
+ const PerCameraUtilization = z.object({
86
+ cameraUuid: z.string().optional(),
87
+ cameraName: z.string().optional(),
88
+ totalCount: z.number().optional(),
89
+ averageCount: z.number().optional(),
90
+ deltaPercent: z.number().optional().describe("Percentage above/below average. Positive = busier than normal."),
91
+ });
92
+ const TrafficFlowEntry = z.object({
93
+ cameraUuid: z.string().optional(),
94
+ cameraName: z.string().optional(),
95
+ totalIngress: z.number().optional(),
96
+ totalEgress: z.number().optional(),
97
+ totalTraffic: z.number().optional(),
98
+ peakHour: z.string().optional().describe("Human-readable peak hour label."),
99
+ peakHourTraffic: z.number().optional(),
100
+ });
101
+ const HourlyComparison = z.object({
102
+ hour: z.string().optional().describe("Hour label (e.g. '9 AM', '2 PM')."),
103
+ actualCount: z.number().optional(),
104
+ averageCount: z.number().optional(),
105
+ deltaPercent: z.number().optional(),
106
+ });
107
+ const SceneResult = z.object({
108
+ value: z.string().optional().describe("The AI answer to the question."),
109
+ prompt: z.string().optional(),
110
+ timestampMs: z.number().optional(),
111
+ checkCondition: z.boolean().optional(),
112
+ });
113
+ export const OUTPUT_SCHEMA = z.object({
114
+ spaceUtilization: z
115
+ .object({
116
+ locationUuid: z.string().optional(),
117
+ cameras: z.array(PerCameraUtilization).optional(),
118
+ summary: z
119
+ .object({
120
+ totalPeopleCount: z.number().optional(),
121
+ averagePeopleCount: z.number().optional(),
122
+ overallDeltaPercent: z.number().optional(),
123
+ busiestCamera: z.string().optional(),
124
+ quietestCamera: z.string().optional(),
125
+ })
126
+ .optional(),
127
+ })
128
+ .optional()
129
+ .describe("Space utilization report with per-camera counts vs running averages."),
130
+ trafficFlow: z
131
+ .object({
132
+ locationUuid: z.string().optional(),
133
+ cameras: z.array(TrafficFlowEntry).optional(),
134
+ summary: z
135
+ .object({
136
+ totalIngress: z.number().optional(),
137
+ totalEgress: z.number().optional(),
138
+ totalTraffic: z.number().optional(),
139
+ busiestEntrance: z.string().optional(),
140
+ busiestEntranceTraffic: z.number().optional(),
141
+ })
142
+ .optional(),
143
+ })
144
+ .optional()
145
+ .describe("Multi-camera traffic flow comparison with ingress/egress ranking."),
146
+ peakVsAverage: z
147
+ .object({
148
+ hourlyComparison: z.array(HourlyComparison).optional(),
149
+ summary: z
150
+ .object({
151
+ peakHour: z.string().optional(),
152
+ peakHourCount: z.number().optional(),
153
+ quietestHour: z.string().optional(),
154
+ quietestHourCount: z.number().optional(),
155
+ overallAverageDelta: z.number().optional().describe("Overall delta vs average across all hours."),
156
+ })
157
+ .optional(),
158
+ })
159
+ .optional()
160
+ .describe("Hour-by-hour actual vs. average analysis with peak/quiet hour identification."),
161
+ sceneIntelligence: SceneResult.optional().describe("Real-time AI answer from a camera about what it currently sees."),
162
+ locationSummary: z
163
+ .object({
164
+ locationUuid: z.string().optional(),
165
+ peopleCounts: z
166
+ .object({
167
+ totalPeople: z.number().optional(),
168
+ averagePerHour: z.number().optional(),
169
+ peakHour: z.string().optional(),
170
+ peakCount: z.number().optional(),
171
+ })
172
+ .optional(),
173
+ trafficFlow: z
174
+ .object({
175
+ totalIngress: z.number().optional(),
176
+ totalEgress: z.number().optional(),
177
+ busiestEntrance: z.string().optional(),
178
+ })
179
+ .optional(),
180
+ comparison: z
181
+ .object({
182
+ overallDeltaPercent: z.number().optional(),
183
+ trend: z.string().optional().describe("'busier' or 'quieter' compared to average."),
184
+ })
185
+ .optional(),
186
+ })
187
+ .optional()
188
+ .describe("Comprehensive multi-metric location analytics summary."),
189
+ error: z.string().optional().describe("An error message if the request failed."),
190
+ });
@@ -1,5 +1,6 @@
1
1
  import { z } from "zod";
2
2
  import { ISOTimestampFormatDescription } from "../utils/timestampInput.js";
3
+ import { createUuidSchema } from "../types.js";
3
4
  export const TimeWindowSecondsSchema = z.object({
4
5
  startSeconds: z.number(),
5
6
  durationSeconds: z.number(),
@@ -211,7 +212,7 @@ export const ExternalUpdateableFacetedUserConfigSchema = z.object({
211
212
  .describe("For each of the object keys: v0, v1, v2, v3, they correspond to a specific facet of the camera, since a camera may have multiple facets, up to 4. Hence, why they are zero-indexed."),
212
213
  });
213
214
  export const BASE_TOOL_ARGS = {
214
- cameraUuid: z.string().nullable().describe("the camera uuid requested"),
215
+ cameraUuid: createUuidSchema().describe("the camera uuid requested"),
215
216
  timestampISO: z
216
217
  .string()
217
218
  .datetime({ message: "Invalid ISO 8601 date format.", offset: true })
@@ -219,6 +220,6 @@ export const BASE_TOOL_ARGS = {
219
220
  .describe(`
220
221
  the timestamp for the image. This will default to 5 minutes before the current time. You can also call time-tool to parse the user's time description.
221
222
  ` + ISOTimestampFormatDescription),
222
- requestType: z.enum(["image", "get-settings"]),
223
+ requestType: z.enum(["image", "get-settings", "get-media-uris", "get-ai-thresholds"]),
223
224
  };
224
225
  const BASE_TOOL_ARGS_SCHEMA = z.object(BASE_TOOL_ARGS);
@@ -0,0 +1,52 @@
1
+ import { z } from "zod";
2
+ import { INCLUDE_FIELDS_ARG, FILTER_BY_ARG } from "../util.js";
3
+ export var CameraUptimeRequestType;
4
+ (function (CameraUptimeRequestType) {
5
+ CameraUptimeRequestType["GET_CAMERA_UPTIME"] = "get-camera-uptime";
6
+ CameraUptimeRequestType["GET_FLEET_UPTIME"] = "get-fleet-uptime";
7
+ })(CameraUptimeRequestType || (CameraUptimeRequestType = {}));
8
+ export const TOOL_ARGS = {
9
+ requestType: z
10
+ .nativeEnum(CameraUptimeRequestType)
11
+ .describe("The type of uptime request to make."),
12
+ cameraUuid: z
13
+ .string()
14
+ .nullable()
15
+ .describe("Camera UUID. Required for 'get-camera-uptime'."),
16
+ startTimeSec: z
17
+ .number()
18
+ .describe("Start time as UNIX timestamp in seconds. Required for all requests."),
19
+ endTimeSec: z
20
+ .number()
21
+ .describe("End time as UNIX timestamp in seconds. Required for all requests."),
22
+ includeFields: INCLUDE_FIELDS_ARG,
23
+ filterBy: FILTER_BY_ARG,
24
+ };
25
+ const TOOL_ARGS_SCHEMA = z.object(TOOL_ARGS);
26
+ const CameraUptimeSchema = z.object({
27
+ cameraUuid: z.string().optional(),
28
+ cameraName: z.string().optional(),
29
+ locationUuid: z.string().optional(),
30
+ totalUptimeSeconds: z.number().optional(),
31
+ totalPeriodSeconds: z.number().optional(),
32
+ uptimePercentage: z.number().optional(),
33
+ outageCount: z.number().optional(),
34
+ longestOutageSeconds: z.number().optional(),
35
+ });
36
+ export const OUTPUT_SCHEMA = z.object({
37
+ cameraUptime: CameraUptimeSchema.optional().describe("Uptime stats for a single camera"),
38
+ fleetUptime: z
39
+ .array(CameraUptimeSchema)
40
+ .optional()
41
+ .describe("Uptime stats for all cameras in the fleet, sorted by worst uptime first"),
42
+ fleetSummary: z
43
+ .object({
44
+ totalCameras: z.number().optional(),
45
+ averageUptimePercentage: z.number().optional(),
46
+ worstCamera: z.string().optional(),
47
+ worstUptimePercentage: z.number().optional(),
48
+ })
49
+ .optional()
50
+ .describe("Fleet-wide uptime summary"),
51
+ error: z.string().optional().describe("An error message if the request failed."),
52
+ });
@@ -1,10 +1,10 @@
1
1
  import { z } from "zod";
2
- import { createEpochSchema, ISOTimestampFormatDescription } from "../utils/timestampInput.js";
3
2
  import { createUuidSchema } from "../types.js";
3
+ import { createEpochSchema, ISOTimestampFormatDescription, } from "../utils/timestampInput.js";
4
4
  export const TOOL_ARGS = {
5
- queryType: z
6
- .enum(["saved", "expiringSoon"])
7
- .describe('The type of clips to retrieve. Use "saved" to get regular saved clips, and "expiringSoon" to get clips that are nearing their expiration date.'),
5
+ requestType: z
6
+ .enum(["saved", "expiringSoon", "sharedLiveStreams", "timelapseClips", "clipGroups", "sharedClips", "createClip", "deleteClip"])
7
+ .describe('The type of data to retrieve. Use "saved" for regular saved clips, "expiringSoon" for clips nearing expiration, "sharedLiveStreams" for all shared live video streams, or "timelapseClips" for all timelapse clips.'),
8
8
  deviceUuidFilters: z
9
9
  .array(createUuidSchema())
10
10
  .nullable()
@@ -19,18 +19,43 @@ export const TOOL_ARGS = {
19
19
  .describe("A simple string to search for within the names of the clips."),
20
20
  timestampISOAfter: z
21
21
  .string()
22
- .datetime({ message: "Invalid datetime string. Expected ISO 8601 format.", offset: true })
23
- .describe("The start of the time range for which to retrieve clips. Only clips that occurred AFTER this timestamp will be returned."
24
- + ISOTimestampFormatDescription),
22
+ .datetime({
23
+ message: "Invalid datetime string. Expected ISO 8601 format.",
24
+ offset: true,
25
+ })
26
+ .nullable()
27
+ .describe("The start of the time range for which to retrieve clips. Only clips that occurred AFTER this timestamp will be returned. Required when requestType is saved or expiringSoon." +
28
+ ISOTimestampFormatDescription),
25
29
  timestampISOBefore: z
26
30
  .string()
27
- .datetime({ message: "Invalid datetime string. Expected ISO 8601 format.", offset: true })
28
- .describe("The end of the time range for which to retrieve clips. Only clips that occurred BEFORE this timestamp will be returned."
29
- + ISOTimestampFormatDescription),
31
+ .datetime({
32
+ message: "Invalid datetime string. Expected ISO 8601 format.",
33
+ offset: true,
34
+ })
35
+ .nullable()
36
+ .describe("The end of the time range for which to retrieve clips. Only clips that occurred BEFORE this timestamp will be returned. Required when requestType is saved or expiringSoon." +
37
+ ISOTimestampFormatDescription),
38
+ clipUuid: z.string().nullable().describe("UUID of a clip. Required for 'deleteClip'."),
39
+ spliceRequest: z.object({
40
+ cameraUuid: z.string().describe("Camera UUID to create clip from"),
41
+ startTimeMs: z.number().describe("Start time in milliseconds"),
42
+ endTimeMs: z.number().describe("End time in milliseconds"),
43
+ }).nullable().describe("Required for 'createClip'. Specifies the camera and time range for the new clip."),
30
44
  };
31
45
  const TOOL_ARGS_SCHEMA = z.object(TOOL_ARGS);
32
46
  export const ApiPayloadSchema = TOOL_ARGS_SCHEMA.transform((args) => {
33
- const { queryType, timestampISOAfter, timestampISOBefore, ...rest } = args;
47
+ if (args.requestType === "sharedLiveStreams" ||
48
+ args.requestType === "timelapseClips" ||
49
+ args.requestType === "clipGroups" ||
50
+ args.requestType === "sharedClips" ||
51
+ args.requestType === "createClip" ||
52
+ args.requestType === "deleteClip") {
53
+ return {};
54
+ }
55
+ const { timestampISOAfter, timestampISOBefore, ...rest } = args;
56
+ if (timestampISOAfter == null || timestampISOBefore == null) {
57
+ throw new Error("timestampISOAfter and timestampISOBefore are required when requestType is saved or expiringSoon");
58
+ }
34
59
  const timestampMsAfter = createEpochSchema().parse(timestampISOAfter);
35
60
  const timestampMsBefore = createEpochSchema().parse(timestampISOBefore);
36
61
  return {
@@ -39,3 +64,27 @@ export const ApiPayloadSchema = TOOL_ARGS_SCHEMA.transform((args) => {
39
64
  timestampMsBefore,
40
65
  };
41
66
  });
67
+ export const OUTPUT_SCHEMA = z.object({
68
+ error: z.optional(z.string()),
69
+ // set these as z.any() to prevent us from over-loading the context with tool
70
+ savedClips: z.array(z.any()).optional(),
71
+ expiringClips: z.array(z.any()).optional(),
72
+ sharedLiveVideoStreams: z.array(z.any()).optional(),
73
+ timelapseClips: z.array(z.any()).optional(),
74
+ clipGroups: z.array(z.object({
75
+ uuid: z.string().optional(),
76
+ name: z.string().optional(),
77
+ clipCount: z.number().optional(),
78
+ })).optional().describe("List of clip groups/folders"),
79
+ sharedClipGroups: z.array(z.object({
80
+ uuid: z.string().optional(),
81
+ name: z.string().optional(),
82
+ })).optional().describe("List of shared clip groups"),
83
+ spliceResult: z.object({
84
+ success: z.boolean().optional(),
85
+ clipUuid: z.string().optional(),
86
+ }).optional().describe("Result of creating a new clip"),
87
+ deleteResult: z.object({
88
+ success: z.boolean().optional(),
89
+ }).optional().describe("Result of deleting a clip"),
90
+ });
@@ -0,0 +1,64 @@
1
+ import { z } from "zod";
2
+ export var DoorToolRequestType;
3
+ (function (DoorToolRequestType) {
4
+ DoorToolRequestType["GET_DOOR_CONTROLLER_RULES"] = "get-door-controller-rules";
5
+ DoorToolRequestType["CREATE_DOOR_CONTROLLER_RULE"] = "create-door-controller-rule";
6
+ DoorToolRequestType["GET_DOOR_POLICIES"] = "get-door-policies";
7
+ DoorToolRequestType["CREATE_DOOR_POLICY"] = "create-door-policy";
8
+ })(DoorToolRequestType || (DoorToolRequestType = {}));
9
+ export const TOOL_ARGS = {
10
+ requestType: z.nativeEnum(DoorToolRequestType).describe("The type of door operation to perform."),
11
+ doorControllerUuid: z
12
+ .string()
13
+ .nullable()
14
+ .describe("The UUID of the door controller device. Required for 'get-door-controller-rules' and 'create-door-controller-rule'."),
15
+ ruleConfig: z
16
+ .string()
17
+ .nullable()
18
+ .describe("JSON string of the door controller rule configuration. Required for 'create-door-controller-rule'."),
19
+ policyName: z
20
+ .string()
21
+ .nullable()
22
+ .describe("The name for the new door policy. Required for 'create-door-policy'."),
23
+ policyConfig: z
24
+ .string()
25
+ .nullable()
26
+ .describe("JSON string of door policy configuration. Required for 'create-door-policy'."),
27
+ };
28
+ const TOOL_ARGS_SCHEMA = z.object(TOOL_ARGS);
29
+ export const OUTPUT_SCHEMA = z.object({
30
+ doorControllerRules: z
31
+ .array(z.object({
32
+ uuid: z.string().optional(),
33
+ name: z.string().optional(),
34
+ deviceUuid: z.string().optional(),
35
+ enabled: z.boolean().optional(),
36
+ ruleType: z.string().optional(),
37
+ }))
38
+ .optional()
39
+ .describe("List of door controller rules"),
40
+ createdRule: z
41
+ .object({
42
+ uuid: z.string().optional(),
43
+ success: z.boolean().optional(),
44
+ })
45
+ .optional()
46
+ .describe("Result of creating a door controller rule"),
47
+ doorPolicies: z
48
+ .array(z.object({
49
+ uuid: z.string().optional(),
50
+ name: z.string().optional(),
51
+ orgUuid: z.string().optional(),
52
+ enabled: z.boolean().optional(),
53
+ }))
54
+ .optional()
55
+ .describe("List of door policies"),
56
+ createdPolicy: z
57
+ .object({
58
+ uuid: z.string().optional(),
59
+ success: z.boolean().optional(),
60
+ })
61
+ .optional()
62
+ .describe("Result of creating a door policy"),
63
+ error: z.string().optional().describe("An error message if the request failed."),
64
+ });
@@ -1,6 +1,6 @@
1
1
  import { z } from "zod";
2
2
  import { ISOTimestampFormatDescription } from "../utils/timestampInput.js";
3
- import { ComponentEventEnumType } from "./schema-components.js";
3
+ import { ComponentEventEnumType } from "./schema.js";
4
4
  import { HumanEvent } from "../api/events-tool-api.js";
5
5
  import { TempUnit } from "../utils/temp.js";
6
6
  export var EventsToolRequestType;
@@ -10,6 +10,10 @@ export var EventsToolRequestType;
10
10
  EventsToolRequestType["CLIMATE_SENSOR"] = "climate-sensor";
11
11
  EventsToolRequestType["COMPONENT_EVENTS"] = "component-events";
12
12
  EventsToolRequestType["CAMERA"] = "camera";
13
+ EventsToolRequestType["BUTTON_PRESS"] = "button-press";
14
+ EventsToolRequestType["OCCUPANCY"] = "occupancy";
15
+ EventsToolRequestType["PROXIMITY"] = "proximity";
16
+ EventsToolRequestType["DOORBELL"] = "doorbell";
13
17
  })(EventsToolRequestType || (EventsToolRequestType = {}));
14
18
  export const TOOL_ARGS = {
15
19
  eventType: z
@@ -19,7 +23,11 @@ export const TOOL_ARGS = {
19
23
  "environmental-gateway: Environmental gateway events with sensor readings and derived values. " +
20
24
  "climate-sensor: Climate sensor events with temperature, humidity, air quality readings. " +
21
25
  "component-events: All types of component events for a location (most flexible option). " +
22
- "camera: Human motion events detected by cameras."),
26
+ "camera: Human motion events detected by cameras. " +
27
+ "button-press: Button press events from button sensors. " +
28
+ "occupancy: Occupancy sensor events with people count. " +
29
+ "proximity: Proximity tag events with RSSI readings. " +
30
+ "doorbell: Doorbell camera events."),
23
31
  startTime: z
24
32
  .string()
25
33
  .datetime({ message: "Invalid datetime string. Expected ISO 8601 format.", offset: true })
@@ -77,6 +85,22 @@ export const TOOL_ARGS = {
77
85
  .positive()
78
86
  .nullable()
79
87
  .describe("Duration in seconds to search for human motion events. Required when eventType is 'camera'. Default is 3600 (1 hour)."),
88
+ buttonSensorUuid: z
89
+ .string()
90
+ .nullable()
91
+ .describe("The UUID of the button sensor. Required when eventType is 'button-press'."),
92
+ occupancySensorUuid: z
93
+ .string()
94
+ .nullable()
95
+ .describe("The UUID of the occupancy sensor. Required when eventType is 'occupancy'."),
96
+ proximityTagUuids: z
97
+ .array(z.string())
98
+ .nullable()
99
+ .describe("Array of proximity tag UUIDs. Required when eventType is 'proximity'."),
100
+ doorbellCameraUuid: z
101
+ .string()
102
+ .nullable()
103
+ .describe("The UUID of the doorbell camera. Required when eventType is 'doorbell'."),
80
104
  tempUnit: z
81
105
  .nativeEnum(TempUnit)
82
106
  .nullable()
@@ -123,6 +147,10 @@ export const OUTPUT_SCHEMA = z.object({
123
147
  "climate-sensor",
124
148
  "component-events",
125
149
  "camera",
150
+ "button-press",
151
+ "occupancy",
152
+ "proximity",
153
+ "doorbell",
126
154
  ])
127
155
  .optional(),
128
156
  accessControlEvents: z.optional(z
@@ -154,10 +182,14 @@ export const OUTPUT_SCHEMA = z.object({
154
182
  "BLE_WAVE is a user badging in by physically waving their hand over the reader. " +
155
183
  "NFC is a user badging in by tapping their badge or their phone on the reader. " +
156
184
  "REMOTE is unlocking the door remotely through the Rhombus app."),
185
+ timestampMs: z
186
+ .number()
187
+ .optional()
188
+ .describe("Timestamp in milliseconds when the event occurred"),
157
189
  datetime: z.string().optional().describe("Datetime string of when the event occurred"),
158
190
  }))
159
191
  .nullable()
160
- .describe("Access control events data including badge ins, credentials, arrivals, etc.")),
192
+ .describe("Access control events data including badge ins, credentials, arrivals, etc., sorted by timestamp (newest first).")),
161
193
  environmentalGatewayEvents: z.optional(z
162
194
  .object({
163
195
  events: z
@@ -252,6 +284,42 @@ export const OUTPUT_SCHEMA = z.object({
252
284
  .array(HumanEvent)
253
285
  .optional()
254
286
  .describe(`Camera events data, as requested with requestType ${EventsToolRequestType.CAMERA}`),
287
+ buttonPressEvents: z
288
+ .array(z.object({
289
+ timestampMs: z.number().optional(),
290
+ datetime: z.string().optional(),
291
+ sensorUuid: z.string().optional(),
292
+ buttonState: z.string().optional(),
293
+ }))
294
+ .optional()
295
+ .describe("Button press events"),
296
+ occupancyEvents: z
297
+ .array(z.object({
298
+ timestampMs: z.number().optional(),
299
+ datetime: z.string().optional(),
300
+ sensorUuid: z.string().optional(),
301
+ count: z.number().optional(),
302
+ }))
303
+ .optional()
304
+ .describe("Occupancy sensor events"),
305
+ proximityEvents: z
306
+ .array(z.object({
307
+ timestampMs: z.number().optional(),
308
+ datetime: z.string().optional(),
309
+ tagUuid: z.string().optional(),
310
+ rssi: z.number().optional(),
311
+ }))
312
+ .optional()
313
+ .describe("Proximity tag events"),
314
+ doorbellEvents: z
315
+ .array(z.object({
316
+ timestampMs: z.number().optional(),
317
+ datetime: z.string().optional(),
318
+ doorbellCameraUuid: z.string().optional(),
319
+ eventType: z.string().optional(),
320
+ }))
321
+ .optional()
322
+ .describe("Doorbell camera events"),
255
323
  needUserInput: z.boolean().optional(),
256
324
  commandForUser: z.string().optional(),
257
325
  });
@@ -1,10 +1,15 @@
1
1
  import { z } from "zod";
2
2
  import { ISOTimestampFormatDescription } from "../utils/timestampInput.js";
3
3
  import { createUuidSchema } from "../types.js";
4
+ import { INCLUDE_FIELDS_ARG, FILTER_BY_ARG } from "../util.js";
4
5
  export var RequestType;
5
6
  (function (RequestType) {
6
7
  RequestType["GET_FACE_EVENTS"] = "get-face-events";
7
8
  RequestType["GET_REGISTERED_FACES"] = "get-registered-faces";
9
+ RequestType["GET_PERSON_LABELS"] = "get-person-labels";
10
+ RequestType["SEARCH_SIMILAR_FACES"] = "search-similar-faces";
11
+ RequestType["GET_FACE_MATCHMAKERS"] = "get-face-matchmakers";
12
+ RequestType["GET_FACE_EVENTS_BY_PERSON"] = "get-face-events-by-person";
8
13
  })(RequestType || (RequestType = {}));
9
14
  export const GetRegisteredFacesArgsSchema = z.object({
10
15
  requestType: z.literal(RequestType.GET_REGISTERED_FACES),
@@ -88,6 +93,10 @@ export const TOOL_ARGS = {
88
93
  timeZone: z
89
94
  .string()
90
95
  .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."),
96
+ faceEventUuid: z.string().nullable().describe("UUID of a face event to search similar faces from. Required for 'search-similar-faces'."),
97
+ personUuid: z.string().nullable().describe("UUID of a person to get face events for. Required for 'get-face-events-by-person'."),
98
+ includeFields: INCLUDE_FIELDS_ARG,
99
+ filterBy: FILTER_BY_ARG,
91
100
  };
92
101
  const TOOL_ARGS_SCHEMA = z.object(TOOL_ARGS);
93
102
  export const OUTPUT_SCHEMA = z.object({
@@ -137,7 +146,34 @@ export const OUTPUT_SCHEMA = z.object({
137
146
  orgUuid: z.optional(z.string()),
138
147
  updatedOn: z.optional(z.number()),
139
148
  uuid: z.optional(z.string()),
149
+ labels: z.optional(z.array(z.string())).describe("Labels assigned to this person, useful for grouping (e.g., 'Engineering', 'Visitors')."),
140
150
  })))
141
151
  .describe("A list of all people (registered faces) currently known to the Rhombus system for your organization."),
152
+ getPersonLabelsResponse: z
153
+ .optional(z.record(z.string(), z.array(z.string())))
154
+ .describe("A map of person UUIDs to their assigned label arrays. Use this to discover what label groups exist and which people belong to them."),
155
+ resolvedNames: z
156
+ .optional(z.record(z.string(), z.string().nullable()))
157
+ .describe("When faceNames are provided in a get-face-events request, this shows how each queried name was automatically resolved to a registered face. " +
158
+ "Key is the queried name (e.g., 'Brandon'), value is the matched registered name (e.g., 'Brandon Salzberg') or null if no match was found. " +
159
+ "Use these resolved names when reporting results to the user."),
160
+ similarFaceEvents: z.array(z.object({
161
+ uuid: z.string().optional(),
162
+ personUuid: z.string().optional(),
163
+ similarity: z.number().optional(),
164
+ eventTimestamp: z.string().optional(),
165
+ })).optional().describe("Similar face event results"),
166
+ faceMatchmakers: z.array(z.object({
167
+ uuid: z.string().optional(),
168
+ personUuid: z.string().optional(),
169
+ name: z.string().optional(),
170
+ })).optional().describe("Face matchmaker records"),
171
+ personFaceEvents: z.array(z.object({
172
+ uuid: z.string().optional(),
173
+ personUuid: z.string().optional(),
174
+ eventTimestamp: z.string().optional(),
175
+ deviceUuid: z.string().optional(),
176
+ })).optional().describe("Face events for a specific person"),
177
+ lastEvaluatedKey: z.string().optional().describe("For paginated requests, this is the returned last evaluated key that can be passed back in on the next request to get the next page of results"),
142
178
  error: z.optional(z.string()),
143
179
  });
@@ -0,0 +1,57 @@
1
+ import { z } from "zod";
2
+ import { INCLUDE_FIELDS_ARG, FILTER_BY_ARG } from "../util.js";
3
+ export var GuestManagementRequestType;
4
+ (function (GuestManagementRequestType) {
5
+ GuestManagementRequestType["GET_ALL_GUESTS"] = "get-all-guests";
6
+ GuestManagementRequestType["GET_ACTIVITY_LOGS"] = "get-activity-logs";
7
+ GuestManagementRequestType["GET_ACTIVITIES_FOR_LOCATION"] = "get-activities-for-location";
8
+ })(GuestManagementRequestType || (GuestManagementRequestType = {}));
9
+ export const TOOL_ARGS = {
10
+ requestType: z
11
+ .nativeEnum(GuestManagementRequestType)
12
+ .describe("The type of guest management request to make."),
13
+ locationUuid: z
14
+ .string()
15
+ .nullable()
16
+ .describe("Location UUID. Required for 'get-activities-for-location'."),
17
+ startTimeMs: z
18
+ .number()
19
+ .nullable()
20
+ .describe("Start time filter in milliseconds since epoch. Optional for activity queries."),
21
+ endTimeMs: z
22
+ .number()
23
+ .nullable()
24
+ .describe("End time filter in milliseconds since epoch. Optional for activity queries."),
25
+ includeFields: INCLUDE_FIELDS_ARG,
26
+ filterBy: FILTER_BY_ARG,
27
+ };
28
+ const TOOL_ARGS_SCHEMA = z.object(TOOL_ARGS);
29
+ const GuestSchema = z.object({
30
+ firstName: z.string().optional(),
31
+ lastName: z.string().optional(),
32
+ email: z.string().optional(),
33
+ companyName: z.string().optional(),
34
+ locationUuid: z.string().optional(),
35
+ hostUserUuid: z.string().optional(),
36
+ guestType: z.string().optional(),
37
+ checkedInStatus: z.string().optional(),
38
+ lastCheckedInMs: z.number().optional(),
39
+ lastCheckedOutMs: z.number().optional(),
40
+ phoneNumber: z.string().optional(),
41
+ });
42
+ const GuestActivitySchema = z.object({
43
+ activity: z.string().optional(),
44
+ email: z.string().optional(),
45
+ guestType: z.string().optional(),
46
+ locationUuid: z.string().optional(),
47
+ hostUserUuid: z.string().optional(),
48
+ timestampMs: z.number().optional(),
49
+ });
50
+ export const OUTPUT_SCHEMA = z.object({
51
+ guests: z.array(GuestSchema).optional().describe("List of guests in the organization"),
52
+ activities: z
53
+ .array(GuestActivitySchema)
54
+ .optional()
55
+ .describe("List of guest activity log entries"),
56
+ error: z.string().optional().describe("An error message if the request failed."),
57
+ });