rhombus-node-mcp 0.1.21 → 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.
- package/README.md +8 -0
- package/dist/api/access-control-tool-api.js +256 -0
- package/dist/api/alarm-monitoring-tool-api.js +65 -0
- package/dist/api/camera-tool-api.js +35 -15
- package/dist/api/camera-uptime-tool-api.js +112 -0
- package/dist/api/clips-tool-api.js +110 -21
- package/dist/api/create-tool-api.js +143 -16
- package/dist/api/door-tool-api.js +66 -0
- package/dist/api/events-tool-api.js +151 -28
- package/dist/api/faces-tool-api.js +118 -91
- package/dist/api/get-entity-tool-api.js +2 -0
- package/dist/api/guest-management-tool-api.js +75 -0
- package/dist/api/location-tool-api.js +48 -1
- package/dist/api/lpr-tool-api.js +26 -0
- package/dist/api/policy-alerts-tool-api.js +54 -0
- package/dist/api/report-tool-api.js +345 -23
- package/dist/api/rules-tool-api.js +78 -0
- package/dist/api/search-tool-api.js +93 -0
- package/dist/api/time-tool-api.js +3 -1
- package/dist/api/update-tool-api.js +204 -0
- package/dist/api/user-access-trail-tool-api.js +45 -0
- package/dist/api/user-audit-tool-api.js +47 -0
- package/dist/api/user-tool-api.js +77 -0
- package/dist/createServer.js +3 -1
- package/dist/filtering-utils.js +298 -0
- package/dist/index.js +0 -9
- package/dist/logger.js +6 -5
- package/dist/network.js +18 -4
- package/dist/tools/access-control-tool.js +97 -0
- package/dist/tools/alarm-monitoring-tool.js +50 -0
- package/dist/tools/analytics-tool.js +383 -0
- package/dist/tools/camera-tool.js +27 -9
- package/dist/tools/camera-uptime-tool.js +50 -0
- package/dist/tools/clips-tool.js +46 -16
- package/dist/tools/door-tool.js +66 -0
- package/dist/tools/events-tool.js +103 -81
- package/dist/tools/faces-tool.js +175 -32
- package/dist/tools/get-entity-tool.js +6 -1
- package/dist/tools/guest-management-tool.js +50 -0
- package/dist/tools/location-tool.js +23 -4
- package/dist/tools/lpr-tool.js +26 -20
- package/dist/tools/policy-alerts-tool.js +34 -4
- package/dist/tools/report-tool.js +183 -46
- package/dist/tools/rules-tool.js +76 -0
- package/dist/tools/search-tool.js +69 -0
- package/dist/tools/update-tool.js +63 -2
- package/dist/tools/user-access-trail-tool.js +64 -0
- package/dist/tools/user-audit-tool.js +53 -0
- package/dist/tools/user-tool.js +55 -0
- package/dist/tools/video-walls-tool.js +41 -0
- package/dist/transports/streamable-http.js +25 -15
- package/dist/types/access-control-tool-types.js +120 -0
- package/dist/types/alarm-monitoring-tool-types.js +60 -0
- package/dist/types/analytics-tool-types.js +190 -0
- package/dist/types/camera-tool-types.js +3 -2
- package/dist/types/camera-uptime-tool-types.js +52 -0
- package/dist/types/clips-tool-types.js +60 -11
- package/dist/types/door-tool-types.js +64 -0
- package/dist/types/events-tools-types.js +71 -3
- package/dist/types/faces-tools-types.js +36 -0
- package/dist/types/guest-management-tool-types.js +57 -0
- package/dist/types/location-tool-types.js +10 -1
- package/dist/types/lpr-tool-types.js +14 -0
- package/dist/types/policy-alerts-tool-types.js +38 -3
- package/dist/types/report-tool-types.js +284 -42
- package/dist/types/rules-tool-types.js +58 -0
- package/dist/types/schema.js +3123 -1
- package/dist/types/search-tool-types.js +82 -0
- package/dist/types/update-tool-types.js +4 -1
- package/dist/types/user-access-trail-tool-types.js +54 -0
- package/dist/types/user-audit-tool-types.js +48 -0
- package/dist/types/user-tool-types.js +61 -0
- package/dist/types/video-walls-tool-types.js +59 -0
- package/dist/types/zod-schemas.js +3237 -986
- package/dist/types.js +0 -21
- package/dist/util.js +34 -57
- package/package.json +7 -5
- package/dist/disabled-tools/semantic-search-tool.js +0 -90
- package/dist/tools/create-tool.js +0 -30
- package/dist/types/create-tool-types.js +0 -8
- package/dist/types/schema-components.js +0 -7211
- 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.
|
|
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
|
|
24
|
-
|
|
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({
|
|
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({
|
|
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
|
-
|
|
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({
|
|
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({
|
|
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
|
|
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
|
-
.
|
|
80
|
-
|
|
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
|
-
|
|
86
|
-
|
|
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({
|
|
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({
|
|
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
|
-
.
|
|
108
|
-
|
|
109
|
-
|
|
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({
|
|
116
|
-
|
|
117
|
-
|
|
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({
|
|
121
|
-
|
|
122
|
-
|
|
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([
|
|
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
|
|
361
|
+
averageExitsPerHour: z
|
|
362
|
+
.number()
|
|
363
|
+
.describe("Average number of exits (egress) per hour"),
|
|
202
364
|
mostEntriesInHour: z
|
|
203
365
|
.object({
|
|
204
|
-
count: z
|
|
205
|
-
|
|
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
|
|
214
|
-
|
|
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
|
|
223
|
-
|
|
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
|
|
228
|
-
|
|
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
|
+
});
|