@wilnertech/halopsa-mcp-server 1.0.2 → 1.1.0
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/.env.example +18 -18
- package/LICENSE +21 -21
- package/README.md +252 -205
- package/dist/api/client.d.ts +7 -2
- package/dist/api/client.d.ts.map +1 -1
- package/dist/api/client.js +35 -8
- package/dist/api/client.js.map +1 -1
- package/dist/cache/memory-cache.d.ts +7 -0
- package/dist/cache/memory-cache.d.ts.map +1 -1
- package/dist/cache/memory-cache.js +7 -0
- package/dist/cache/memory-cache.js.map +1 -1
- package/dist/cache/prewarm.d.ts +3 -1
- package/dist/cache/prewarm.d.ts.map +1 -1
- package/dist/cache/prewarm.js +17 -1
- package/dist/cache/prewarm.js.map +1 -1
- package/dist/schemas/common.d.ts +30 -99
- package/dist/schemas/common.d.ts.map +1 -1
- package/dist/schemas/common.js +2 -2
- package/dist/schemas/common.js.map +1 -1
- package/dist/tools/assets.d.ts +69 -297
- package/dist/tools/assets.d.ts.map +1 -1
- package/dist/tools/batch-operations.d.ts +49 -81
- package/dist/tools/batch-operations.d.ts.map +1 -1
- package/dist/tools/batch-operations.js +62 -0
- package/dist/tools/batch-operations.js.map +1 -1
- package/dist/tools/clients.d.ts +24 -92
- package/dist/tools/clients.d.ts.map +1 -1
- package/dist/tools/reference-data.d.ts +44 -72
- package/dist/tools/reference-data.d.ts.map +1 -1
- package/dist/tools/reference-data.js +27 -0
- package/dist/tools/reference-data.js.map +1 -1
- package/dist/tools/registrations.d.ts +7 -1
- package/dist/tools/registrations.d.ts.map +1 -1
- package/dist/tools/registrations.js +43 -7
- package/dist/tools/registrations.js.map +1 -1
- package/dist/tools/registry.d.ts +12 -5
- package/dist/tools/registry.d.ts.map +1 -1
- package/dist/tools/registry.js +26 -2
- package/dist/tools/registry.js.map +1 -1
- package/dist/tools/sites.d.ts +19 -111
- package/dist/tools/sites.d.ts.map +1 -1
- package/dist/tools/ticket-actions.d.ts +41 -0
- package/dist/tools/ticket-actions.d.ts.map +1 -0
- package/dist/tools/ticket-actions.js +222 -0
- package/dist/tools/ticket-actions.js.map +1 -0
- package/dist/tools/ticket-custom-fields.d.ts +33 -0
- package/dist/tools/ticket-custom-fields.d.ts.map +1 -0
- package/dist/tools/ticket-custom-fields.js +155 -0
- package/dist/tools/ticket-custom-fields.js.map +1 -0
- package/dist/tools/ticket-reference-data.d.ts +88 -0
- package/dist/tools/ticket-reference-data.d.ts.map +1 -0
- package/dist/tools/ticket-reference-data.js +185 -0
- package/dist/tools/ticket-reference-data.js.map +1 -0
- package/dist/tools/tickets.d.ts +168 -0
- package/dist/tools/tickets.d.ts.map +1 -0
- package/dist/tools/tickets.js +572 -0
- package/dist/tools/tickets.js.map +1 -0
- package/dist/tools/users.d.ts +37 -193
- package/dist/tools/users.d.ts.map +1 -1
- package/dist/types/tickets.d.ts +193 -0
- package/dist/types/tickets.d.ts.map +1 -0
- package/dist/types/tickets.js +14 -0
- package/dist/types/tickets.js.map +1 -0
- package/dist/utils/formatter.d.ts +15 -1
- package/dist/utils/formatter.d.ts.map +1 -1
- package/dist/utils/formatter.js +52 -6
- package/dist/utils/formatter.js.map +1 -1
- package/package.json +68 -61
- package/dist/utils/zod-to-schema.d.ts +0 -29
- package/dist/utils/zod-to-schema.d.ts.map +0 -1
- package/dist/utils/zod-to-schema.js +0 -182
- package/dist/utils/zod-to-schema.js.map +0 -1
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HaloPSA Ticket Custom Field tools.
|
|
3
|
+
*
|
|
4
|
+
* Two complementary inspection paths:
|
|
5
|
+
* 1. `list_halopsa_ticket_custom_fields` — preferred. Calls
|
|
6
|
+
* GET /api/FieldInfo?type=1&tickettype_id={id}. If the tenant
|
|
7
|
+
* returns a non-empty field list, that's the canonical schema.
|
|
8
|
+
* 2. `get_halopsa_ticket_field_schema` — fallback. Samples N recent
|
|
9
|
+
* tickets of a given type and derives field shape from their
|
|
10
|
+
* `customfields[]` arrays. Mirrors `getAssetFieldSchemaTool`.
|
|
11
|
+
*
|
|
12
|
+
* The dual approach exists because Halo's `/FieldInfo` endpoint behaves
|
|
13
|
+
* inconsistently across tenants — some installs gate it behind admin
|
|
14
|
+
* scope, others return empty arrays for non-admin agents. The sampling
|
|
15
|
+
* path is robust but lossy (only fields that ARE used on existing
|
|
16
|
+
* tickets show up).
|
|
17
|
+
*/
|
|
18
|
+
import { z } from 'zod';
|
|
19
|
+
// =============================================================================
|
|
20
|
+
// Schemas
|
|
21
|
+
// =============================================================================
|
|
22
|
+
// These tools return purpose-built analysis objects (field schema summaries,
|
|
23
|
+
// not raw HaloPSA records) so they intentionally do NOT accept format_options
|
|
24
|
+
// — the response shape is fixed.
|
|
25
|
+
export const ListTicketCustomFieldsArgsSchema = z.object({
|
|
26
|
+
tickettype_id: z.number().int()
|
|
27
|
+
.describe('Ticket type ID — schema is per-tickettype'),
|
|
28
|
+
});
|
|
29
|
+
export const GetTicketFieldSchemaArgsSchema = z.object({
|
|
30
|
+
tickettype_id: z.number().int()
|
|
31
|
+
.describe('Ticket type ID — sampling is scoped to this type'),
|
|
32
|
+
client_id: z.number().int().optional()
|
|
33
|
+
.describe('Optional client filter — narrows the sample further'),
|
|
34
|
+
sample_size: z.number().int().min(1).max(100).optional()
|
|
35
|
+
.describe('Number of tickets to inspect (default 50)'),
|
|
36
|
+
});
|
|
37
|
+
// =============================================================================
|
|
38
|
+
// Helpers
|
|
39
|
+
// =============================================================================
|
|
40
|
+
function getValueType(value) {
|
|
41
|
+
if (value === null || value === undefined)
|
|
42
|
+
return 'null';
|
|
43
|
+
if (typeof value === 'string')
|
|
44
|
+
return 'string';
|
|
45
|
+
if (typeof value === 'number')
|
|
46
|
+
return 'number';
|
|
47
|
+
if (typeof value === 'boolean')
|
|
48
|
+
return 'boolean';
|
|
49
|
+
return 'mixed';
|
|
50
|
+
}
|
|
51
|
+
function unwrapList(response, preferredKey) {
|
|
52
|
+
if (Array.isArray(response))
|
|
53
|
+
return response;
|
|
54
|
+
const wrapped = response;
|
|
55
|
+
return wrapped[preferredKey] ?? [];
|
|
56
|
+
}
|
|
57
|
+
// =============================================================================
|
|
58
|
+
// Implementations
|
|
59
|
+
// =============================================================================
|
|
60
|
+
export async function listTicketCustomFields(client, args) {
|
|
61
|
+
// Halo type=1 means ticket fields per the FieldInfo endpoint convention.
|
|
62
|
+
let fields = [];
|
|
63
|
+
let source = 'empty';
|
|
64
|
+
let warning;
|
|
65
|
+
try {
|
|
66
|
+
const response = await client.get('/FieldInfo', { type: 1, tickettype_id: args.tickettype_id });
|
|
67
|
+
fields = unwrapList(response, 'fields');
|
|
68
|
+
if (fields.length > 0) {
|
|
69
|
+
source = 'fieldinfo';
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
catch (err) {
|
|
73
|
+
warning = `FieldInfo endpoint failed: ${err instanceof Error ? err.message : String(err)}. ` +
|
|
74
|
+
'Use get_halopsa_ticket_field_schema for sampling-based schema discovery.';
|
|
75
|
+
}
|
|
76
|
+
const result = {
|
|
77
|
+
tickettype_id: args.tickettype_id,
|
|
78
|
+
source,
|
|
79
|
+
field_count: fields.length,
|
|
80
|
+
fields: fields.map((f) => ({
|
|
81
|
+
id: f.id ?? f.field_id,
|
|
82
|
+
name: f.name ?? f.label,
|
|
83
|
+
type: f.type,
|
|
84
|
+
required: f.required ?? false,
|
|
85
|
+
display_order: f.display_order,
|
|
86
|
+
})),
|
|
87
|
+
...(warning && { warning }),
|
|
88
|
+
};
|
|
89
|
+
return JSON.stringify(result, null, 2);
|
|
90
|
+
}
|
|
91
|
+
export async function getTicketFieldSchema(client, args) {
|
|
92
|
+
const sampleSize = args.sample_size ?? 50;
|
|
93
|
+
const params = {
|
|
94
|
+
tickettype_id: args.tickettype_id,
|
|
95
|
+
count: sampleSize,
|
|
96
|
+
};
|
|
97
|
+
if (args.client_id !== undefined)
|
|
98
|
+
params.client_id = args.client_id;
|
|
99
|
+
const response = await client.get('/Tickets', params);
|
|
100
|
+
const tickets = Array.isArray(response)
|
|
101
|
+
? response
|
|
102
|
+
: (response.tickets ?? []);
|
|
103
|
+
const fieldMap = new Map();
|
|
104
|
+
for (const ticket of tickets) {
|
|
105
|
+
const customfields = ticket.customfields ?? [];
|
|
106
|
+
for (const field of customfields) {
|
|
107
|
+
const existing = fieldMap.get(field.id);
|
|
108
|
+
const valueType = getValueType(field.value);
|
|
109
|
+
if (existing) {
|
|
110
|
+
if (existing.sample_values.length < 5 &&
|
|
111
|
+
!existing.sample_values.includes(field.value)) {
|
|
112
|
+
existing.sample_values.push(field.value);
|
|
113
|
+
}
|
|
114
|
+
existing.usage_count++;
|
|
115
|
+
if (existing.value_type !== valueType && existing.value_type !== 'mixed') {
|
|
116
|
+
existing.value_type = 'mixed';
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
fieldMap.set(field.id, {
|
|
121
|
+
field_id: field.id,
|
|
122
|
+
name: field.name,
|
|
123
|
+
sample_values: [field.value],
|
|
124
|
+
value_type: valueType,
|
|
125
|
+
usage_count: 1,
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
const fieldSchemas = Array.from(fieldMap.values()).sort((a, b) => a.field_id - b.field_id);
|
|
131
|
+
const result = {
|
|
132
|
+
tickettype_id: args.tickettype_id,
|
|
133
|
+
client_id: args.client_id ?? 'all',
|
|
134
|
+
tickets_analyzed: tickets.length,
|
|
135
|
+
unique_fields: fieldSchemas.length,
|
|
136
|
+
field_schemas: fieldSchemas,
|
|
137
|
+
};
|
|
138
|
+
return JSON.stringify(result, null, 2);
|
|
139
|
+
}
|
|
140
|
+
// =============================================================================
|
|
141
|
+
// Tool Definitions
|
|
142
|
+
// =============================================================================
|
|
143
|
+
export const listTicketCustomFieldsTool = {
|
|
144
|
+
name: 'list_halopsa_ticket_custom_fields',
|
|
145
|
+
description: 'List custom-field definitions for a ticket type via /FieldInfo. Falls back gracefully with a warning if the endpoint is empty/unauthorized — use get_halopsa_ticket_field_schema then.',
|
|
146
|
+
schema: ListTicketCustomFieldsArgsSchema,
|
|
147
|
+
handler: listTicketCustomFields,
|
|
148
|
+
};
|
|
149
|
+
export const getTicketFieldSchemaTool = {
|
|
150
|
+
name: 'get_halopsa_ticket_field_schema',
|
|
151
|
+
description: 'Sample N recent tickets of a given type and derive custom-field schema from their customfields[] arrays. Use when /FieldInfo is unavailable. Returns field_id, name, sample_values, value_type, usage_count per field.',
|
|
152
|
+
schema: GetTicketFieldSchemaArgsSchema,
|
|
153
|
+
handler: getTicketFieldSchema,
|
|
154
|
+
};
|
|
155
|
+
//# sourceMappingURL=ticket-custom-fields.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ticket-custom-fields.js","sourceRoot":"","sources":["../../src/tools/ticket-custom-fields.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HaloPSA Ticket Reference Data tools.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors the existing pattern in `src/tools/reference-data.ts` for asset
|
|
5
|
+
* reference data. All five tools default to compact responses (token
|
|
6
|
+
* optimization) and use 1-hour cache TTLs because reference data on a
|
|
7
|
+
* Halo tenant changes infrequently — most reads should hit cache.
|
|
8
|
+
*
|
|
9
|
+
* The tools deliberately accept BOTH a `full` boolean shortcut AND the
|
|
10
|
+
* standard `format_options` block so callers can choose their style:
|
|
11
|
+
* `{ full: true }` is the path-of-least-surprise for ad-hoc lookups,
|
|
12
|
+
* while `format_options` keeps parity with the rest of the MCP surface.
|
|
13
|
+
*/
|
|
14
|
+
import { z } from 'zod';
|
|
15
|
+
import type { HaloPSAAPIClient } from '../api/client.js';
|
|
16
|
+
import type { ZodToolDefinition } from './registry.js';
|
|
17
|
+
declare const ListTicketTypesArgsSchema: z.ZodObject<{
|
|
18
|
+
full: z.ZodOptional<z.ZodBoolean>;
|
|
19
|
+
format_options: z.ZodOptional<z.ZodObject<{
|
|
20
|
+
format: z.ZodOptional<z.ZodEnum<{
|
|
21
|
+
compact: "compact";
|
|
22
|
+
standard: "standard";
|
|
23
|
+
detailed: "detailed";
|
|
24
|
+
}>>;
|
|
25
|
+
fields: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
26
|
+
omit_empty: z.ZodOptional<z.ZodBoolean>;
|
|
27
|
+
}, z.core.$strip>>;
|
|
28
|
+
}, z.core.$strip>;
|
|
29
|
+
declare const GetTicketTypeArgsSchema: z.ZodObject<{
|
|
30
|
+
tickettype_id: z.ZodNumber;
|
|
31
|
+
format_options: z.ZodOptional<z.ZodObject<{
|
|
32
|
+
format: z.ZodOptional<z.ZodEnum<{
|
|
33
|
+
compact: "compact";
|
|
34
|
+
standard: "standard";
|
|
35
|
+
detailed: "detailed";
|
|
36
|
+
}>>;
|
|
37
|
+
fields: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
38
|
+
omit_empty: z.ZodOptional<z.ZodBoolean>;
|
|
39
|
+
}, z.core.$strip>>;
|
|
40
|
+
}, z.core.$strip>;
|
|
41
|
+
declare const ListTicketStatusesArgsSchema: z.ZodObject<{
|
|
42
|
+
full: z.ZodOptional<z.ZodBoolean>;
|
|
43
|
+
format_options: z.ZodOptional<z.ZodObject<{
|
|
44
|
+
format: z.ZodOptional<z.ZodEnum<{
|
|
45
|
+
compact: "compact";
|
|
46
|
+
standard: "standard";
|
|
47
|
+
detailed: "detailed";
|
|
48
|
+
}>>;
|
|
49
|
+
fields: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
50
|
+
omit_empty: z.ZodOptional<z.ZodBoolean>;
|
|
51
|
+
}, z.core.$strip>>;
|
|
52
|
+
}, z.core.$strip>;
|
|
53
|
+
declare const ListTicketPrioritiesArgsSchema: z.ZodObject<{
|
|
54
|
+
full: z.ZodOptional<z.ZodBoolean>;
|
|
55
|
+
format_options: z.ZodOptional<z.ZodObject<{
|
|
56
|
+
format: z.ZodOptional<z.ZodEnum<{
|
|
57
|
+
compact: "compact";
|
|
58
|
+
standard: "standard";
|
|
59
|
+
detailed: "detailed";
|
|
60
|
+
}>>;
|
|
61
|
+
fields: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
62
|
+
omit_empty: z.ZodOptional<z.ZodBoolean>;
|
|
63
|
+
}, z.core.$strip>>;
|
|
64
|
+
}, z.core.$strip>;
|
|
65
|
+
declare const ListTicketCategoriesArgsSchema: z.ZodObject<{
|
|
66
|
+
full: z.ZodOptional<z.ZodBoolean>;
|
|
67
|
+
format_options: z.ZodOptional<z.ZodObject<{
|
|
68
|
+
format: z.ZodOptional<z.ZodEnum<{
|
|
69
|
+
compact: "compact";
|
|
70
|
+
standard: "standard";
|
|
71
|
+
detailed: "detailed";
|
|
72
|
+
}>>;
|
|
73
|
+
fields: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
74
|
+
omit_empty: z.ZodOptional<z.ZodBoolean>;
|
|
75
|
+
}, z.core.$strip>>;
|
|
76
|
+
}, z.core.$strip>;
|
|
77
|
+
export declare function listTicketTypes(client: HaloPSAAPIClient, args: z.infer<typeof ListTicketTypesArgsSchema>): Promise<string>;
|
|
78
|
+
export declare function getTicketType(client: HaloPSAAPIClient, args: z.infer<typeof GetTicketTypeArgsSchema>): Promise<string>;
|
|
79
|
+
export declare function listTicketStatuses(client: HaloPSAAPIClient, args: z.infer<typeof ListTicketStatusesArgsSchema>): Promise<string>;
|
|
80
|
+
export declare function listTicketPriorities(client: HaloPSAAPIClient, args: z.infer<typeof ListTicketPrioritiesArgsSchema>): Promise<string>;
|
|
81
|
+
export declare function listTicketCategories(client: HaloPSAAPIClient, args: z.infer<typeof ListTicketCategoriesArgsSchema>): Promise<string>;
|
|
82
|
+
export declare const listTicketTypesTool: ZodToolDefinition;
|
|
83
|
+
export declare const getTicketTypeTool: ZodToolDefinition;
|
|
84
|
+
export declare const listTicketStatusesTool: ZodToolDefinition;
|
|
85
|
+
export declare const listTicketPrioritiesTool: ZodToolDefinition;
|
|
86
|
+
export declare const listTicketCategoriesTool: ZodToolDefinition;
|
|
87
|
+
export {};
|
|
88
|
+
//# sourceMappingURL=ticket-reference-data.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ticket-reference-data.d.ts","sourceRoot":"","sources":["../../src/tools/ticket-reference-data.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAoBvD,QAAA,MAAM,yBAAyB;;;;;;;;;;;iBAI7B,CAAC;AAEH,QAAA,MAAM,uBAAuB;;;;;;;;;;;iBAI3B,CAAC;AAEH,QAAA,MAAM,4BAA4B;;;;;;;;;;;iBAIhC,CAAC;AAEH,QAAA,MAAM,8BAA8B;;;;;;;;;;;iBAIlC,CAAC;AAEH,QAAA,MAAM,8BAA8B;;;;;;;;;;;iBAIlC,CAAC;AAqEH,wBAAsB,eAAe,CACnC,MAAM,EAAE,gBAAgB,EACxB,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,GAC9C,OAAO,CAAC,MAAM,CAAC,CAejB;AAED,wBAAsB,aAAa,CACjC,MAAM,EAAE,gBAAgB,EACxB,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,GAC5C,OAAO,CAAC,MAAM,CAAC,CAcjB;AAED,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,gBAAgB,EACxB,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,4BAA4B,CAAC,GACjD,OAAO,CAAC,MAAM,CAAC,CAejB;AAED,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,gBAAgB,EACxB,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,8BAA8B,CAAC,GACnD,OAAO,CAAC,MAAM,CAAC,CAgBjB;AAED,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,gBAAgB,EACxB,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,8BAA8B,CAAC,GACnD,OAAO,CAAC,MAAM,CAAC,CAejB;AAMD,eAAO,MAAM,mBAAmB,EAAE,iBAKjC,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,iBAK/B,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,iBAKpC,CAAC;AAEF,eAAO,MAAM,wBAAwB,EAAE,iBAKtC,CAAC;AAEF,eAAO,MAAM,wBAAwB,EAAE,iBAKtC,CAAC"}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HaloPSA Ticket Reference Data tools.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors the existing pattern in `src/tools/reference-data.ts` for asset
|
|
5
|
+
* reference data. All five tools default to compact responses (token
|
|
6
|
+
* optimization) and use 1-hour cache TTLs because reference data on a
|
|
7
|
+
* Halo tenant changes infrequently — most reads should hit cache.
|
|
8
|
+
*
|
|
9
|
+
* The tools deliberately accept BOTH a `full` boolean shortcut AND the
|
|
10
|
+
* standard `format_options` block so callers can choose their style:
|
|
11
|
+
* `{ full: true }` is the path-of-least-surprise for ad-hoc lookups,
|
|
12
|
+
* while `format_options` keeps parity with the rest of the MCP surface.
|
|
13
|
+
*/
|
|
14
|
+
import { z } from 'zod';
|
|
15
|
+
import { formatResponse } from '../utils/formatter.js';
|
|
16
|
+
import { TTL } from '../cache/memory-cache.js';
|
|
17
|
+
import { FormatOptionsSchema } from '../schemas/common.js';
|
|
18
|
+
// =============================================================================
|
|
19
|
+
// Schemas
|
|
20
|
+
// =============================================================================
|
|
21
|
+
const ListTicketTypesArgsSchema = z.object({
|
|
22
|
+
full: z.boolean().optional()
|
|
23
|
+
.describe('Return full records instead of compact (default false). Equivalent to format_options.format="detailed".'),
|
|
24
|
+
format_options: FormatOptionsSchema,
|
|
25
|
+
});
|
|
26
|
+
const GetTicketTypeArgsSchema = z.object({
|
|
27
|
+
tickettype_id: z.number().int()
|
|
28
|
+
.describe('HaloPSA ticket type ID'),
|
|
29
|
+
format_options: FormatOptionsSchema,
|
|
30
|
+
});
|
|
31
|
+
const ListTicketStatusesArgsSchema = z.object({
|
|
32
|
+
full: z.boolean().optional()
|
|
33
|
+
.describe('Return full records instead of compact (default false).'),
|
|
34
|
+
format_options: FormatOptionsSchema,
|
|
35
|
+
});
|
|
36
|
+
const ListTicketPrioritiesArgsSchema = z.object({
|
|
37
|
+
full: z.boolean().optional()
|
|
38
|
+
.describe('Return full records instead of compact (default false).'),
|
|
39
|
+
format_options: FormatOptionsSchema,
|
|
40
|
+
});
|
|
41
|
+
const ListTicketCategoriesArgsSchema = z.object({
|
|
42
|
+
full: z.boolean().optional()
|
|
43
|
+
.describe('Return full records instead of compact (default false).'),
|
|
44
|
+
format_options: FormatOptionsSchema,
|
|
45
|
+
});
|
|
46
|
+
// =============================================================================
|
|
47
|
+
// Helpers
|
|
48
|
+
// =============================================================================
|
|
49
|
+
/**
|
|
50
|
+
* Resolve the effective FormatOptions from caller input, defaulting to
|
|
51
|
+
* compact unless the user opted in to a fuller view via `full: true` or
|
|
52
|
+
* an explicit `format_options.format`.
|
|
53
|
+
*/
|
|
54
|
+
function resolveFormat(full, formatOptions) {
|
|
55
|
+
const opts = { ...(formatOptions || {}) };
|
|
56
|
+
if (full && !opts.format) {
|
|
57
|
+
opts.format = 'detailed';
|
|
58
|
+
}
|
|
59
|
+
if (!opts.format) {
|
|
60
|
+
opts.format = 'compact';
|
|
61
|
+
}
|
|
62
|
+
return opts;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Normalize a raw /Priority record.
|
|
66
|
+
*
|
|
67
|
+
* The raw API shape has:
|
|
68
|
+
* - `id`: GUID string — uniquely identifies this priority+SLA combo
|
|
69
|
+
* - `priorityid`: integer 1-4 — the value Faults.priority_id expects
|
|
70
|
+
*
|
|
71
|
+
* We promote `priorityid` to `id` and expose the GUID as `sla_priority_id`
|
|
72
|
+
* to prevent callers from accidentally passing the GUID as priority_id.
|
|
73
|
+
*/
|
|
74
|
+
function normalizePriority(p) {
|
|
75
|
+
return {
|
|
76
|
+
id: p.priorityid,
|
|
77
|
+
name: p.name,
|
|
78
|
+
sla_priority_id: p.id,
|
|
79
|
+
slaid: p.slaid,
|
|
80
|
+
fixtime: p.fixtime,
|
|
81
|
+
fixunits: p.fixunits,
|
|
82
|
+
responsetime: p.responsetime,
|
|
83
|
+
responseunits: p.responseunits,
|
|
84
|
+
colour: p.colour,
|
|
85
|
+
firstresponsetime: p.firstresponsetime,
|
|
86
|
+
firstresponseunits: p.firstresponseunits,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
/** Halo list endpoints return either bare arrays or `{ <plural>: [...] }`. */
|
|
90
|
+
function unwrapList(response, preferredKey) {
|
|
91
|
+
if (Array.isArray(response)) {
|
|
92
|
+
return { items: response, record_count: response.length };
|
|
93
|
+
}
|
|
94
|
+
const wrapped = response;
|
|
95
|
+
const items = wrapped[preferredKey] ?? [];
|
|
96
|
+
const record_count = wrapped.record_count ?? items.length;
|
|
97
|
+
return { items, record_count };
|
|
98
|
+
}
|
|
99
|
+
// =============================================================================
|
|
100
|
+
// Implementations
|
|
101
|
+
// =============================================================================
|
|
102
|
+
export async function listTicketTypes(client, args) {
|
|
103
|
+
const formatOpts = resolveFormat(args.full, args.format_options);
|
|
104
|
+
const response = await client.getCached('/TicketType', { count: 500 }, {
|
|
105
|
+
enabled: true,
|
|
106
|
+
ttl: TTL.TICKET_TYPES,
|
|
107
|
+
keyPrefix: 'tickettypes:all',
|
|
108
|
+
});
|
|
109
|
+
const { items, record_count } = unwrapList(response, 'tickettypes');
|
|
110
|
+
return formatResponse(items, formatOpts, { record_count });
|
|
111
|
+
}
|
|
112
|
+
export async function getTicketType(client, args) {
|
|
113
|
+
const formatOpts = args.format_options || { format: 'standard' };
|
|
114
|
+
const response = await client.getCached(`/TicketType/${args.tickettype_id}`, undefined, {
|
|
115
|
+
enabled: true,
|
|
116
|
+
ttl: TTL.TICKET_TYPES,
|
|
117
|
+
keyPrefix: `tickettype:${args.tickettype_id}`,
|
|
118
|
+
});
|
|
119
|
+
return formatResponse(response, formatOpts);
|
|
120
|
+
}
|
|
121
|
+
export async function listTicketStatuses(client, args) {
|
|
122
|
+
const formatOpts = resolveFormat(args.full, args.format_options);
|
|
123
|
+
const response = await client.getCached('/Status', { count: 500 }, {
|
|
124
|
+
enabled: true,
|
|
125
|
+
ttl: TTL.TICKET_STATUSES,
|
|
126
|
+
keyPrefix: 'ticketstatuses:all',
|
|
127
|
+
});
|
|
128
|
+
const { items, record_count } = unwrapList(response, 'statuses');
|
|
129
|
+
return formatResponse(items, formatOpts, { record_count });
|
|
130
|
+
}
|
|
131
|
+
export async function listTicketPriorities(client, args) {
|
|
132
|
+
const formatOpts = resolveFormat(args.full, args.format_options);
|
|
133
|
+
const response = await client.getCached('/Priority', { count: 500 }, {
|
|
134
|
+
enabled: true,
|
|
135
|
+
ttl: TTL.TICKET_PRIORITIES,
|
|
136
|
+
keyPrefix: 'ticketpriorities:all',
|
|
137
|
+
});
|
|
138
|
+
const { items: rawItems, record_count } = unwrapList(response, 'priorities');
|
|
139
|
+
const items = rawItems.map(normalizePriority);
|
|
140
|
+
return formatResponse(items, formatOpts, { record_count });
|
|
141
|
+
}
|
|
142
|
+
export async function listTicketCategories(client, args) {
|
|
143
|
+
const formatOpts = resolveFormat(args.full, args.format_options);
|
|
144
|
+
const response = await client.getCached('/Category', { count: 500 }, {
|
|
145
|
+
enabled: true,
|
|
146
|
+
ttl: TTL.TICKET_CATEGORIES,
|
|
147
|
+
keyPrefix: 'ticketcategories:all',
|
|
148
|
+
});
|
|
149
|
+
const { items, record_count } = unwrapList(response, 'categories');
|
|
150
|
+
return formatResponse(items, formatOpts, { record_count });
|
|
151
|
+
}
|
|
152
|
+
// =============================================================================
|
|
153
|
+
// Tool Definitions
|
|
154
|
+
// =============================================================================
|
|
155
|
+
export const listTicketTypesTool = {
|
|
156
|
+
name: 'list_halopsa_tickettypes',
|
|
157
|
+
description: 'List all HaloPSA ticket types (Incident, Service Request, Change, etc.) with 1h cache. Compact by default; pass full=true for full records.',
|
|
158
|
+
schema: ListTicketTypesArgsSchema,
|
|
159
|
+
handler: listTicketTypes,
|
|
160
|
+
};
|
|
161
|
+
export const getTicketTypeTool = {
|
|
162
|
+
name: 'get_halopsa_tickettype',
|
|
163
|
+
description: 'Get a single HaloPSA ticket type by ID. Cached 1h.',
|
|
164
|
+
schema: GetTicketTypeArgsSchema,
|
|
165
|
+
handler: getTicketType,
|
|
166
|
+
};
|
|
167
|
+
export const listTicketStatusesTool = {
|
|
168
|
+
name: 'list_halopsa_ticket_statuses',
|
|
169
|
+
description: 'List HaloPSA ticket statuses. Each record carries `type` (0=regular ticket statuses, 1=Order, 2=Item, 3=Action Required/Invoiced/With CAB) and `sequence` (UI ordering). NOTE: the API does NOT return `complete` / `is_closed` / `is_active` flags despite some prior documentation. To find the canonical Closed status, match `name === "Closed" && type === 0` (returns id=9 on this tenant). For Order/Item flavours, see id=13 "Closed Order" (type=1) and id=15 "Closed Item" (type=2). Cached 1h.',
|
|
170
|
+
schema: ListTicketStatusesArgsSchema,
|
|
171
|
+
handler: listTicketStatuses,
|
|
172
|
+
};
|
|
173
|
+
export const listTicketPrioritiesTool = {
|
|
174
|
+
name: 'list_halopsa_ticket_priorities',
|
|
175
|
+
description: 'List HaloPSA ticket priorities. The `id` field is the integer priority value (1-4) that maps to `Faults.priority_id` on ticket creates — NOT the underlying GUID, which is per-SLA and exposed as `sla_priority_id`. Pass `id` to create/update_halopsa_ticket. Names duplicate across SLAs (3 Critical, 3 High, 3 Medium, 3 Low — one per SLA). Includes fix/response time hints. Cached 1h.',
|
|
176
|
+
schema: ListTicketPrioritiesArgsSchema,
|
|
177
|
+
handler: listTicketPriorities,
|
|
178
|
+
};
|
|
179
|
+
export const listTicketCategoriesTool = {
|
|
180
|
+
name: 'list_halopsa_ticket_categories',
|
|
181
|
+
description: 'List all HaloPSA ticket categories (used for category_1..category_4 fields on tickets). Cached 1h.',
|
|
182
|
+
schema: ListTicketCategoriesArgsSchema,
|
|
183
|
+
handler: listTicketCategories,
|
|
184
|
+
};
|
|
185
|
+
//# sourceMappingURL=ticket-reference-data.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ticket-reference-data.js","sourceRoot":"","sources":["../../src/tools/ticket-reference-data.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HaloPSA Ticket CRUD tools.
|
|
3
|
+
*
|
|
4
|
+
* Tickets are append-only business events — unlike assets/users/sites,
|
|
5
|
+
* there is no `find_*_match` deduplication step. Update by explicit id
|
|
6
|
+
* always.
|
|
7
|
+
*
|
|
8
|
+
* Update mechanics mirror `updateAsset` in `src/tools/assets.ts`:
|
|
9
|
+
* Halo's POST /api/Tickets is REPLACE-not-PATCH, so we read the current
|
|
10
|
+
* record first and spread it under the partial payload before sending.
|
|
11
|
+
*
|
|
12
|
+
* Compact responses INTENTIONALLY omit `details_html` (HTML body, can be
|
|
13
|
+
* 50KB+) and `customfields[]` to keep MCP responses sub-second and
|
|
14
|
+
* within token budgets. Callers that need them call `get_halopsa_ticket`
|
|
15
|
+
* or pass `format_options.format = 'detailed'` / `full: true`.
|
|
16
|
+
*/
|
|
17
|
+
import { z } from 'zod';
|
|
18
|
+
import type { HaloPSAAPIClient } from '../api/client.js';
|
|
19
|
+
import type { ZodToolDefinition } from './registry.js';
|
|
20
|
+
export declare const ListTicketsArgsSchema: z.ZodObject<{
|
|
21
|
+
client_id: z.ZodOptional<z.ZodNumber>;
|
|
22
|
+
client_ids: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodArray<z.ZodNumber>]>>;
|
|
23
|
+
site_id: z.ZodOptional<z.ZodNumber>;
|
|
24
|
+
user_id: z.ZodOptional<z.ZodNumber>;
|
|
25
|
+
agent_id: z.ZodOptional<z.ZodNumber>;
|
|
26
|
+
agent: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodArray<z.ZodNumber>]>>;
|
|
27
|
+
team_id: z.ZodOptional<z.ZodNumber>;
|
|
28
|
+
tickettype_id: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodArray<z.ZodNumber>]>>;
|
|
29
|
+
status_id: z.ZodOptional<z.ZodNumber>;
|
|
30
|
+
category_1: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodArray<z.ZodNumber>]>>;
|
|
31
|
+
category_2: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodArray<z.ZodNumber>]>>;
|
|
32
|
+
category_3: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodArray<z.ZodNumber>]>>;
|
|
33
|
+
category_4: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodArray<z.ZodNumber>]>>;
|
|
34
|
+
search: z.ZodOptional<z.ZodString>;
|
|
35
|
+
open_only: z.ZodOptional<z.ZodBoolean>;
|
|
36
|
+
date_from: z.ZodOptional<z.ZodString>;
|
|
37
|
+
date_to: z.ZodOptional<z.ZodString>;
|
|
38
|
+
count: z.ZodOptional<z.ZodNumber>;
|
|
39
|
+
page_no: z.ZodOptional<z.ZodNumber>;
|
|
40
|
+
format_options: z.ZodOptional<z.ZodObject<{
|
|
41
|
+
format: z.ZodOptional<z.ZodEnum<{
|
|
42
|
+
compact: "compact";
|
|
43
|
+
standard: "standard";
|
|
44
|
+
detailed: "detailed";
|
|
45
|
+
}>>;
|
|
46
|
+
fields: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
47
|
+
omit_empty: z.ZodOptional<z.ZodBoolean>;
|
|
48
|
+
}, z.core.$strip>>;
|
|
49
|
+
}, z.core.$strip>;
|
|
50
|
+
export declare const GetTicketArgsSchema: z.ZodObject<{
|
|
51
|
+
ticket_id: z.ZodNumber;
|
|
52
|
+
format_options: z.ZodOptional<z.ZodObject<{
|
|
53
|
+
format: z.ZodOptional<z.ZodEnum<{
|
|
54
|
+
compact: "compact";
|
|
55
|
+
standard: "standard";
|
|
56
|
+
detailed: "detailed";
|
|
57
|
+
}>>;
|
|
58
|
+
fields: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
59
|
+
omit_empty: z.ZodOptional<z.ZodBoolean>;
|
|
60
|
+
}, z.core.$strip>>;
|
|
61
|
+
}, z.core.$strip>;
|
|
62
|
+
export declare const SearchTicketsArgsSchema: z.ZodObject<{
|
|
63
|
+
search: z.ZodString;
|
|
64
|
+
client_id: z.ZodOptional<z.ZodNumber>;
|
|
65
|
+
open_only: z.ZodOptional<z.ZodBoolean>;
|
|
66
|
+
count: z.ZodOptional<z.ZodNumber>;
|
|
67
|
+
format_options: z.ZodOptional<z.ZodObject<{
|
|
68
|
+
format: z.ZodOptional<z.ZodEnum<{
|
|
69
|
+
compact: "compact";
|
|
70
|
+
standard: "standard";
|
|
71
|
+
detailed: "detailed";
|
|
72
|
+
}>>;
|
|
73
|
+
fields: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
74
|
+
omit_empty: z.ZodOptional<z.ZodBoolean>;
|
|
75
|
+
}, z.core.$strip>>;
|
|
76
|
+
}, z.core.$strip>;
|
|
77
|
+
export declare const CreateTicketArgsSchema: z.ZodObject<{
|
|
78
|
+
summary: z.ZodString;
|
|
79
|
+
tickettype_id: z.ZodNumber;
|
|
80
|
+
client_id: z.ZodNumber;
|
|
81
|
+
details_html: z.ZodOptional<z.ZodString>;
|
|
82
|
+
category_1: z.ZodOptional<z.ZodString>;
|
|
83
|
+
priority_id: z.ZodOptional<z.ZodNumber>;
|
|
84
|
+
status_id: z.ZodOptional<z.ZodNumber>;
|
|
85
|
+
source: z.ZodOptional<z.ZodNumber>;
|
|
86
|
+
agent_id: z.ZodOptional<z.ZodNumber>;
|
|
87
|
+
team_id: z.ZodOptional<z.ZodNumber>;
|
|
88
|
+
site_id: z.ZodOptional<z.ZodNumber>;
|
|
89
|
+
user_id: z.ZodOptional<z.ZodNumber>;
|
|
90
|
+
parent_id: z.ZodOptional<z.ZodNumber>;
|
|
91
|
+
dateoccurred: z.ZodOptional<z.ZodString>;
|
|
92
|
+
startdate: z.ZodOptional<z.ZodString>;
|
|
93
|
+
customfields: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
94
|
+
id: z.ZodOptional<z.ZodNumber>;
|
|
95
|
+
name: z.ZodOptional<z.ZodString>;
|
|
96
|
+
value: z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodNull]>;
|
|
97
|
+
}, z.core.$strip>>>;
|
|
98
|
+
}, z.core.$strip>;
|
|
99
|
+
export declare const UpdateTicketArgsSchema: z.ZodObject<{
|
|
100
|
+
ticket_id: z.ZodNumber;
|
|
101
|
+
summary: z.ZodOptional<z.ZodString>;
|
|
102
|
+
details_html: z.ZodOptional<z.ZodString>;
|
|
103
|
+
tickettype_id: z.ZodOptional<z.ZodNumber>;
|
|
104
|
+
status_id: z.ZodOptional<z.ZodNumber>;
|
|
105
|
+
priority_id: z.ZodOptional<z.ZodNumber>;
|
|
106
|
+
category_1: z.ZodOptional<z.ZodString>;
|
|
107
|
+
agent_id: z.ZodOptional<z.ZodNumber>;
|
|
108
|
+
team_id: z.ZodOptional<z.ZodNumber>;
|
|
109
|
+
site_id: z.ZodOptional<z.ZodNumber>;
|
|
110
|
+
user_id: z.ZodOptional<z.ZodNumber>;
|
|
111
|
+
parent_id: z.ZodOptional<z.ZodNumber>;
|
|
112
|
+
dateoccurred: z.ZodOptional<z.ZodString>;
|
|
113
|
+
startdate: z.ZodOptional<z.ZodString>;
|
|
114
|
+
source: z.ZodOptional<z.ZodNumber>;
|
|
115
|
+
customfields: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
116
|
+
id: z.ZodOptional<z.ZodNumber>;
|
|
117
|
+
name: z.ZodOptional<z.ZodString>;
|
|
118
|
+
value: z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodNull]>;
|
|
119
|
+
}, z.core.$strip>>>;
|
|
120
|
+
}, z.core.$strip>;
|
|
121
|
+
export declare const CloseTicketArgsSchema: z.ZodObject<{
|
|
122
|
+
ticket_id: z.ZodNumber;
|
|
123
|
+
resolution_note: z.ZodOptional<z.ZodString>;
|
|
124
|
+
}, z.core.$strip>;
|
|
125
|
+
export declare const DeleteTicketArgsSchema: z.ZodObject<{
|
|
126
|
+
ticket_id: z.ZodNumber;
|
|
127
|
+
reason: z.ZodString;
|
|
128
|
+
confirm_destructive: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
129
|
+
}, z.core.$strip>;
|
|
130
|
+
export declare function listTickets(client: HaloPSAAPIClient, args: z.infer<typeof ListTicketsArgsSchema>): Promise<string>;
|
|
131
|
+
export declare function getTicket(client: HaloPSAAPIClient, args: z.infer<typeof GetTicketArgsSchema>): Promise<string>;
|
|
132
|
+
export declare function searchTickets(client: HaloPSAAPIClient, args: z.infer<typeof SearchTicketsArgsSchema>): Promise<string>;
|
|
133
|
+
export declare function createTicket(client: HaloPSAAPIClient, args: z.infer<typeof CreateTicketArgsSchema>): Promise<string>;
|
|
134
|
+
export declare function updateTicket(client: HaloPSAAPIClient, args: z.infer<typeof UpdateTicketArgsSchema>): Promise<string>;
|
|
135
|
+
/**
|
|
136
|
+
* Permanently delete a HaloPSA ticket by ID after running four safety
|
|
137
|
+
* pre-flight checks:
|
|
138
|
+
*
|
|
139
|
+
* 1. Financial — refuses if `timetaken > 0` or `hoursinvoiced > 0` (billable
|
|
140
|
+
* history would be destroyed on delete).
|
|
141
|
+
* 2. Cascade — refuses if `child_count > 0` (children would orphan; Halo
|
|
142
|
+
* cascade behavior is undocumented).
|
|
143
|
+
* 3. Historical — refuses if the ticket is closed or completed. Uses a
|
|
144
|
+
* tenant-portable dual-check: primary `hasbeenclosed === true` (Halo
|
|
145
|
+
* boolean); secondary fetches `/Status` (cached 1h) and matches against
|
|
146
|
+
* known closed-flavour names (Closed, Closed Order, Closed Item, Completed).
|
|
147
|
+
* 4. Authorship — refuses unless `who === 'claude_mcp'` (prevents accidental
|
|
148
|
+
* deletion of human-created tickets).
|
|
149
|
+
*
|
|
150
|
+
* OVERRIDE mechanism: when violations exist, pass `confirm_destructive: true`
|
|
151
|
+
* AND include the substring `"OVERRIDE"` (case-sensitive) in `reason` to
|
|
152
|
+
* bypass all checks and proceed with the DELETE.
|
|
153
|
+
*
|
|
154
|
+
* Return shapes:
|
|
155
|
+
* - `{ already_absent: true, deleted_id }` — 404 on GET (idempotent).
|
|
156
|
+
* - `{ deleted: false, refused: true, violations, remediation }` — safety block.
|
|
157
|
+
* - `{ deleted: true, ticket_id, reason, override_used, safety_violations_bypassed? }` — success.
|
|
158
|
+
*/
|
|
159
|
+
export declare function deleteTicket(client: HaloPSAAPIClient, args: z.infer<typeof DeleteTicketArgsSchema>): Promise<string>;
|
|
160
|
+
export declare function closeTicket(client: HaloPSAAPIClient, args: z.infer<typeof CloseTicketArgsSchema>): Promise<string>;
|
|
161
|
+
export declare const listTicketsTool: ZodToolDefinition;
|
|
162
|
+
export declare const getTicketTool: ZodToolDefinition;
|
|
163
|
+
export declare const searchTicketsTool: ZodToolDefinition;
|
|
164
|
+
export declare const createTicketTool: ZodToolDefinition;
|
|
165
|
+
export declare const updateTicketTool: ZodToolDefinition;
|
|
166
|
+
export declare const closeTicketTool: ZodToolDefinition;
|
|
167
|
+
export declare const deleteTicketTool: ZodToolDefinition;
|
|
168
|
+
//# sourceMappingURL=tickets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tickets.d.ts","sourceRoot":"","sources":["../../src/tools/tickets.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AA+BvD,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAwChC,CAAC;AAEH,eAAO,MAAM,mBAAmB;;;;;;;;;;;iBAI9B,CAAC;AAEH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;iBAUlC,CAAC;AAEH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;iBAiCjC,CAAC;AAEH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;iBAuBjC,CAAC;AAEH,eAAO,MAAM,qBAAqB;;;iBAKhC,CAAC;AAEH,eAAO,MAAM,sBAAsB;;;;iBAQjC,CAAC;AAoGH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,gBAAgB,EACxB,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,GAC1C,OAAO,CAAC,MAAM,CAAC,CAwCjB;AAED,wBAAsB,SAAS,CAC7B,MAAM,EAAE,gBAAgB,EACxB,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,GACxC,OAAO,CAAC,MAAM,CAAC,CAcjB;AAED,wBAAsB,aAAa,CACjC,MAAM,EAAE,gBAAgB,EACxB,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,GAC5C,OAAO,CAAC,MAAM,CAAC,CAQjB;AAED,wBAAsB,YAAY,CAChC,MAAM,EAAE,gBAAgB,EACxB,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,GAC3C,OAAO,CAAC,MAAM,CAAC,CA2BjB;AAED,wBAAsB,YAAY,CAChC,MAAM,EAAE,gBAAgB,EACxB,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,GAC3C,OAAO,CAAC,MAAM,CAAC,CA2CjB;AAgBD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,gBAAgB,EACxB,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,GAC3C,OAAO,CAAC,MAAM,CAAC,CA0HjB;AAED,wBAAsB,WAAW,CAC/B,MAAM,EAAE,gBAAgB,EACxB,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,GAC1C,OAAO,CAAC,MAAM,CAAC,CAiBjB;AAMD,eAAO,MAAM,eAAe,EAAE,iBAK7B,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,iBAK3B,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,iBAK/B,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,iBAK9B,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,iBAK9B,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,iBAK7B,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,iBAK9B,CAAC"}
|