@wilnertech/halopsa-mcp-server 1.2.0 → 1.3.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/README.md +43 -2
- package/dist/cache/memory-cache.d.ts +3 -0
- package/dist/cache/memory-cache.d.ts.map +1 -1
- package/dist/cache/memory-cache.js +4 -0
- package/dist/cache/memory-cache.js.map +1 -1
- package/dist/tools/batch-operations.d.ts +47 -0
- package/dist/tools/batch-operations.d.ts.map +1 -1
- package/dist/tools/batch-operations.js +144 -1
- package/dist/tools/batch-operations.js.map +1 -1
- package/dist/tools/budgets.d.ts +130 -0
- package/dist/tools/budgets.d.ts.map +1 -0
- package/dist/tools/budgets.js +277 -0
- package/dist/tools/budgets.js.map +1 -0
- package/dist/tools/milestones.d.ts +90 -0
- package/dist/tools/milestones.d.ts.map +1 -0
- package/dist/tools/milestones.js +170 -0
- package/dist/tools/milestones.js.map +1 -0
- package/dist/tools/registrations.d.ts +6 -2
- package/dist/tools/registrations.d.ts.map +1 -1
- package/dist/tools/registrations.js +38 -5
- package/dist/tools/registrations.js.map +1 -1
- package/dist/tools/ticket-links.d.ts +41 -0
- package/dist/tools/ticket-links.d.ts.map +1 -0
- package/dist/tools/ticket-links.js +84 -0
- package/dist/tools/ticket-links.js.map +1 -0
- package/dist/tools/tickets.d.ts +2 -0
- package/dist/tools/tickets.d.ts.map +1 -1
- package/dist/tools/tickets.js +15 -0
- package/dist/tools/tickets.js.map +1 -1
- package/dist/tools/workflows.d.ts +125 -0
- package/dist/tools/workflows.d.ts.map +1 -0
- package/dist/tools/workflows.js +355 -0
- package/dist/tools/workflows.js.map +1 -0
- package/dist/types/budgets.d.ts +45 -0
- package/dist/types/budgets.d.ts.map +1 -0
- package/dist/types/budgets.js +12 -0
- package/dist/types/budgets.js.map +1 -0
- package/dist/types/milestones.d.ts +37 -0
- package/dist/types/milestones.d.ts.map +1 -0
- package/dist/types/milestones.js +14 -0
- package/dist/types/milestones.js.map +1 -0
- package/dist/types/tickets.d.ts +1 -0
- package/dist/types/tickets.d.ts.map +1 -1
- package/dist/types/workflows.d.ts +77 -0
- package/dist/types/workflows.d.ts.map +1 -0
- package/dist/types/workflows.js +11 -0
- package/dist/types/workflows.js.map +1 -0
- package/dist/utils/formatter.d.ts +1 -1
- package/dist/utils/formatter.d.ts.map +1 -1
- package/dist/utils/formatter.js +21 -1
- package/dist/utils/formatter.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HaloPSA Budget Management tools.
|
|
3
|
+
*
|
|
4
|
+
* Covers two domains:
|
|
5
|
+
* 1. BudgetType — top-level reference CRUD (/BudgetType).
|
|
6
|
+
* 2. Per-ticket budgets — nested ticket.budgets[] array, managed via
|
|
7
|
+
* read-before-write POST /Tickets (Halo REPLACE, not PATCH semantics).
|
|
8
|
+
*
|
|
9
|
+
* Safety:
|
|
10
|
+
* - delete_halopsa_budget_type applies a two-factor OVERRIDE gate (same
|
|
11
|
+
* pattern as delete_halopsa_ticket): reason >= 5 chars required;
|
|
12
|
+
* confirm_destructive + "OVERRIDE" substring to bypass a soft refusal.
|
|
13
|
+
* - set_halopsa_ticket_budget REPLACES all budgets on the ticket; callers
|
|
14
|
+
* should fetch current budgets first if they need a partial update.
|
|
15
|
+
*/
|
|
16
|
+
import { z } from 'zod';
|
|
17
|
+
import { formatResponse, stripWriteResponse } from '../utils/formatter.js';
|
|
18
|
+
import { TTL } from '../cache/memory-cache.js';
|
|
19
|
+
import { FormatOptionsSchema } from '../schemas/common.js';
|
|
20
|
+
// =============================================================================
|
|
21
|
+
// Schemas
|
|
22
|
+
// =============================================================================
|
|
23
|
+
export const ListBudgetTypesArgsSchema = z.object({
|
|
24
|
+
format_options: FormatOptionsSchema,
|
|
25
|
+
});
|
|
26
|
+
export const CreateBudgetTypeArgsSchema = z.object({
|
|
27
|
+
name: z.string().min(1)
|
|
28
|
+
.describe('Budget type name (required)'),
|
|
29
|
+
defaultrate: z.number().optional()
|
|
30
|
+
.describe('Default hourly rate for this budget type'),
|
|
31
|
+
chargerate: z.number().optional()
|
|
32
|
+
.describe('Charge rate override for this budget type'),
|
|
33
|
+
format_options: FormatOptionsSchema,
|
|
34
|
+
});
|
|
35
|
+
export const DeleteBudgetTypeArgsSchema = z.object({
|
|
36
|
+
budget_type_id: z.number().int()
|
|
37
|
+
.describe('HaloPSA BudgetType ID to delete'),
|
|
38
|
+
reason: z.string().min(5).describe('REQUIRED audit-trail reason (min 5 chars). To bypass the soft safety refusal, ' +
|
|
39
|
+
'the reason MUST include the substring "OVERRIDE" (case-sensitive) AND ' +
|
|
40
|
+
'confirm_destructive must be true.'),
|
|
41
|
+
confirm_destructive: z.boolean().optional().default(false).describe('Set true AND include "OVERRIDE" in reason to bypass the soft safety refusal. Default false.'),
|
|
42
|
+
format_options: FormatOptionsSchema,
|
|
43
|
+
});
|
|
44
|
+
export const GetTicketBudgetArgsSchema = z.object({
|
|
45
|
+
ticket_id: z.number().int()
|
|
46
|
+
.describe('HaloPSA ticket ID'),
|
|
47
|
+
format_options: FormatOptionsSchema,
|
|
48
|
+
});
|
|
49
|
+
/** Input shape for a single budget entry in set_halopsa_ticket_budget. */
|
|
50
|
+
const BudgetEntryInputSchema = z.object({
|
|
51
|
+
budgettype_id: z.number().int()
|
|
52
|
+
.describe('Budget type ID — see list_halopsa_budget_types'),
|
|
53
|
+
hours: z.number().optional()
|
|
54
|
+
.describe('Budgeted hours for this type'),
|
|
55
|
+
days: z.number().optional()
|
|
56
|
+
.describe('Budgeted days for this type'),
|
|
57
|
+
rate: z.number().optional()
|
|
58
|
+
.describe('Rate override for this budget entry'),
|
|
59
|
+
});
|
|
60
|
+
export const SetTicketBudgetArgsSchema = z.object({
|
|
61
|
+
ticket_id: z.number().int()
|
|
62
|
+
.describe('HaloPSA ticket ID'),
|
|
63
|
+
budgets: z.array(BudgetEntryInputSchema).min(1)
|
|
64
|
+
.describe('Full replacement budget array. REPLACES all existing budgets on the ticket. ' +
|
|
65
|
+
'Each entry requires budgettype_id; hours/days/rate are optional.'),
|
|
66
|
+
format_options: FormatOptionsSchema,
|
|
67
|
+
});
|
|
68
|
+
// =============================================================================
|
|
69
|
+
// Helpers
|
|
70
|
+
// =============================================================================
|
|
71
|
+
/** Compact fields for budget type list responses. */
|
|
72
|
+
const BUDGET_TYPE_COMPACT_FIELDS = ['id', 'name', 'defaultrate'];
|
|
73
|
+
function resolveBudgetTypeListFormat(input) {
|
|
74
|
+
const opts = { ...(input || {}) };
|
|
75
|
+
if (!opts.format) {
|
|
76
|
+
opts.format = 'standard';
|
|
77
|
+
opts.fields = opts.fields ?? BUDGET_TYPE_COMPACT_FIELDS;
|
|
78
|
+
}
|
|
79
|
+
return opts;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Unwrap a BudgetType write response — Halo POST returns either a single
|
|
83
|
+
* object or a single-element array depending on tenant config.
|
|
84
|
+
*/
|
|
85
|
+
function unwrapBudgetTypeWrite(response) {
|
|
86
|
+
return Array.isArray(response) ? response[0] : response;
|
|
87
|
+
}
|
|
88
|
+
// =============================================================================
|
|
89
|
+
// Implementations
|
|
90
|
+
// =============================================================================
|
|
91
|
+
/**
|
|
92
|
+
* List all budget types (reference data).
|
|
93
|
+
* Cached 1 hour. Compact response returns {id, name, defaultrate}.
|
|
94
|
+
*/
|
|
95
|
+
export async function listBudgetTypes(client, args) {
|
|
96
|
+
const formatOpts = resolveBudgetTypeListFormat(args.format_options);
|
|
97
|
+
const response = await client.getCached('/BudgetType', { count: 100 }, {
|
|
98
|
+
enabled: true,
|
|
99
|
+
ttl: TTL.BUDGET_TYPES,
|
|
100
|
+
keyPrefix: 'budget-types:all',
|
|
101
|
+
});
|
|
102
|
+
let budgetTypes;
|
|
103
|
+
let recordCount;
|
|
104
|
+
if (Array.isArray(response)) {
|
|
105
|
+
budgetTypes = response;
|
|
106
|
+
recordCount = response.length;
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
budgetTypes = response.budget_types ?? [];
|
|
110
|
+
recordCount = response.record_count ?? budgetTypes.length;
|
|
111
|
+
}
|
|
112
|
+
return formatResponse(budgetTypes, formatOpts, { record_count: recordCount });
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Create a new budget type.
|
|
116
|
+
* POST /BudgetType with array-wrapped body (Halo convention).
|
|
117
|
+
* Invalidates budget-types cache.
|
|
118
|
+
*/
|
|
119
|
+
export async function createBudgetType(client, args) {
|
|
120
|
+
const payload = {
|
|
121
|
+
name: args.name,
|
|
122
|
+
};
|
|
123
|
+
if (args.defaultrate !== undefined)
|
|
124
|
+
payload.defaultrate = args.defaultrate;
|
|
125
|
+
if (args.chargerate !== undefined)
|
|
126
|
+
payload.chargerate = args.chargerate;
|
|
127
|
+
const created = unwrapBudgetTypeWrite(await client.post('/BudgetType', [payload]));
|
|
128
|
+
client.invalidateCache('budget-types:*');
|
|
129
|
+
const format = args.format_options?.format ?? 'compact';
|
|
130
|
+
// Budget types have no heavy nested objects — passthrough (no entity-specific strip needed).
|
|
131
|
+
return formatResponse(created, { format });
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Delete a budget type by ID.
|
|
135
|
+
*
|
|
136
|
+
* Safety gate (adapted from deleteTicket):
|
|
137
|
+
* - Reason is always required (min 5 chars; validated by Zod).
|
|
138
|
+
* - A soft refusal is issued by default with a warning that dependent tickets
|
|
139
|
+
* cannot be automatically checked (Halo does not support budgettype_id
|
|
140
|
+
* filtering on /Tickets). The caller is instructed to verify manually.
|
|
141
|
+
* - To bypass: confirm_destructive: true AND reason includes "OVERRIDE".
|
|
142
|
+
* - 404 on GET is idempotent (already_absent: true).
|
|
143
|
+
*/
|
|
144
|
+
export async function deleteBudgetType(client, args) {
|
|
145
|
+
// Step 1: Verify existence. 404 is idempotent.
|
|
146
|
+
let existing;
|
|
147
|
+
try {
|
|
148
|
+
existing = await client.get(`/BudgetType/${args.budget_type_id}`);
|
|
149
|
+
}
|
|
150
|
+
catch (error) {
|
|
151
|
+
const status = error?.response?.status;
|
|
152
|
+
if (status === 404) {
|
|
153
|
+
return JSON.stringify({ already_absent: true, deleted_id: args.budget_type_id }, null, 2);
|
|
154
|
+
}
|
|
155
|
+
throw error;
|
|
156
|
+
}
|
|
157
|
+
// Step 2: Accumulate violations. Halo does not expose a query filter for
|
|
158
|
+
// budgettype_id on /Tickets, so we cannot automatically probe for open-ticket
|
|
159
|
+
// references. Issue a standing warning instead.
|
|
160
|
+
const violations = [];
|
|
161
|
+
violations.push('dependency-check-unavailable: Halo /Tickets does not support budgettype_id filtering. ' +
|
|
162
|
+
`Caller must verify that no open tickets reference budgettype_id=${args.budget_type_id} ` +
|
|
163
|
+
`(name: "${existing.name}") before deletion.`);
|
|
164
|
+
// Step 3: Decision matrix.
|
|
165
|
+
const overrideProvided = args.confirm_destructive === true && args.reason.includes('OVERRIDE');
|
|
166
|
+
if (!overrideProvided) {
|
|
167
|
+
return JSON.stringify({
|
|
168
|
+
deleted: false,
|
|
169
|
+
refused: true,
|
|
170
|
+
budget_type_id: args.budget_type_id,
|
|
171
|
+
budget_type_name: existing.name,
|
|
172
|
+
violations,
|
|
173
|
+
remediation: "Pass confirm_destructive: true AND include 'OVERRIDE' (case-sensitive) in the reason to proceed. " +
|
|
174
|
+
'Manually confirm no open tickets reference this budget type before overriding.',
|
|
175
|
+
}, null, 2);
|
|
176
|
+
}
|
|
177
|
+
// Step 4: Execute DELETE.
|
|
178
|
+
await client.delete(`/BudgetType/${args.budget_type_id}?reason=${encodeURIComponent(args.reason)}`);
|
|
179
|
+
// Step 5: Cache invalidation.
|
|
180
|
+
client.invalidateCache('budget-types:*');
|
|
181
|
+
// Step 6: Structured success.
|
|
182
|
+
return JSON.stringify({
|
|
183
|
+
deleted: true,
|
|
184
|
+
budget_type_id: args.budget_type_id,
|
|
185
|
+
budget_type_name: existing.name,
|
|
186
|
+
reason: args.reason,
|
|
187
|
+
override_used: true,
|
|
188
|
+
safety_violations_bypassed: violations,
|
|
189
|
+
}, null, 2);
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Get all budget entries for a specific ticket.
|
|
193
|
+
* Fetches GET /Tickets/{id}?includedetails=true and returns ticket.budgets[].
|
|
194
|
+
* Cache key 'ticket-budgets:{id}' TTL 1 min.
|
|
195
|
+
*/
|
|
196
|
+
export async function getTicketBudget(client, args) {
|
|
197
|
+
const formatOpts = args.format_options || { format: 'detailed' };
|
|
198
|
+
const ticket = await client.getCached(`/Tickets/${args.ticket_id}`, { includedetails: true }, {
|
|
199
|
+
enabled: true,
|
|
200
|
+
ttl: TTL.TICKET_LIST,
|
|
201
|
+
keyPrefix: `ticket-budgets:${args.ticket_id}`,
|
|
202
|
+
});
|
|
203
|
+
const budgets = ticket.budgets ?? [];
|
|
204
|
+
return formatResponse(budgets, formatOpts, { record_count: budgets.length, ticket_id: args.ticket_id });
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Replace the budget array on a ticket.
|
|
208
|
+
*
|
|
209
|
+
* Read-before-write merge: fetches the existing ticket, spreads it into the
|
|
210
|
+
* POST body, and replaces the budgets[] array entirely (Halo REPLACE semantics).
|
|
211
|
+
* Returns the updated ticket's budgets[] after strip.
|
|
212
|
+
*/
|
|
213
|
+
export async function setTicketBudget(client, args) {
|
|
214
|
+
// Read the baseline ticket (no cache — must be current).
|
|
215
|
+
const existing = await client.get(`/Tickets/${args.ticket_id}`, { includedetails: true });
|
|
216
|
+
const newBudgets = args.budgets.map((b) => {
|
|
217
|
+
const entry = { budgettype_id: b.budgettype_id };
|
|
218
|
+
if (b.hours !== undefined)
|
|
219
|
+
entry.hours = b.hours;
|
|
220
|
+
if (b.days !== undefined)
|
|
221
|
+
entry.days = b.days;
|
|
222
|
+
if (b.rate !== undefined)
|
|
223
|
+
entry.rate = b.rate;
|
|
224
|
+
return entry;
|
|
225
|
+
});
|
|
226
|
+
const mergedPayload = { ...existing, budgets: newBudgets, id: args.ticket_id };
|
|
227
|
+
// POST /Tickets with array wrapper (Halo convention).
|
|
228
|
+
const rawResponse = await client.post('/Tickets', [mergedPayload]);
|
|
229
|
+
const updated = Array.isArray(rawResponse) ? rawResponse[0] : rawResponse;
|
|
230
|
+
// Cache invalidation.
|
|
231
|
+
client.invalidateCache('tickets:*');
|
|
232
|
+
client.invalidateCache(`ticket:${args.ticket_id}*`);
|
|
233
|
+
client.invalidateCache(`ticket-budgets:${args.ticket_id}*`);
|
|
234
|
+
const format = args.format_options?.format ?? 'compact';
|
|
235
|
+
const stripped = stripWriteResponse(updated, format, 'ticket');
|
|
236
|
+
// Return only the budgets sub-array from the updated ticket for clarity.
|
|
237
|
+
const returnedBudgets = stripped['budgets'] ?? updated.budgets ?? [];
|
|
238
|
+
return formatResponse(returnedBudgets, { format }, { ticket_id: args.ticket_id });
|
|
239
|
+
}
|
|
240
|
+
// =============================================================================
|
|
241
|
+
// Tool Definitions
|
|
242
|
+
// =============================================================================
|
|
243
|
+
export const listBudgetTypesTool = {
|
|
244
|
+
name: 'list_halopsa_budget_types',
|
|
245
|
+
description: 'List all HaloPSA budget types (reference data). Compact response returns {id, name, defaultrate}. Cached 1 hour.',
|
|
246
|
+
schema: ListBudgetTypesArgsSchema,
|
|
247
|
+
handler: listBudgetTypes,
|
|
248
|
+
};
|
|
249
|
+
export const createBudgetTypeTool = {
|
|
250
|
+
name: 'create_halopsa_budget_type',
|
|
251
|
+
description: 'Create a new HaloPSA budget type. POST /BudgetType with array-wrapped body (Halo convention). Invalidates budget-types cache.',
|
|
252
|
+
schema: CreateBudgetTypeArgsSchema,
|
|
253
|
+
handler: createBudgetType,
|
|
254
|
+
};
|
|
255
|
+
export const deleteBudgetTypeTool = {
|
|
256
|
+
name: 'delete_halopsa_budget_type',
|
|
257
|
+
description: 'Delete a HaloPSA budget type by ID. Issues a soft safety refusal by default because Halo does not support ' +
|
|
258
|
+
'automatic dependency checking via /Tickets?budgettype_id=X. Pass confirm_destructive: true AND include ' +
|
|
259
|
+
'"OVERRIDE" (case-sensitive) in reason to proceed after manual verification. 404 returns already_absent: true (idempotent).',
|
|
260
|
+
schema: DeleteBudgetTypeArgsSchema,
|
|
261
|
+
handler: deleteBudgetType,
|
|
262
|
+
};
|
|
263
|
+
export const getTicketBudgetTool = {
|
|
264
|
+
name: 'get_halopsa_ticket_budget',
|
|
265
|
+
description: 'Get the budget entries for a HaloPSA ticket. Returns ticket.budgets[] (or [] if none set). Cached 1 min.',
|
|
266
|
+
schema: GetTicketBudgetArgsSchema,
|
|
267
|
+
handler: getTicketBudget,
|
|
268
|
+
};
|
|
269
|
+
export const setTicketBudgetTool = {
|
|
270
|
+
name: 'set_halopsa_ticket_budget',
|
|
271
|
+
description: 'Replace the budget array on a HaloPSA ticket. Performs read-before-write merge (Halo POST is REPLACE not PATCH). ' +
|
|
272
|
+
'The supplied budgets[] array FULLY REPLACES any existing budgets. Each entry requires budgettype_id; ' +
|
|
273
|
+
'hours/days/rate are optional. Returns the updated ticket budgets field.',
|
|
274
|
+
schema: SetTicketBudgetArgsSchema,
|
|
275
|
+
handler: setTicketBudget,
|
|
276
|
+
};
|
|
277
|
+
//# sourceMappingURL=budgets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"budgets.js","sourceRoot":"","sources":["../../src/tools/budgets.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HaloPSA milestone management tools.
|
|
3
|
+
*
|
|
4
|
+
* Milestones are stored as a nested `milestones[]` array on the ticket
|
|
5
|
+
* itself — there is no top-level /Milestone endpoint (GET /Milestone
|
|
6
|
+
* returns 404). All reads use GET /Tickets/{id}?includedetails=true
|
|
7
|
+
* and all writes use POST /Tickets with a read-before-write merge,
|
|
8
|
+
* replacing the milestones array in its entirety (same pattern as
|
|
9
|
+
* customfields).
|
|
10
|
+
*
|
|
11
|
+
* Discovery note (2026-05-11): confirmed `milestones: []` (empty array)
|
|
12
|
+
* on ticket 22541; Swagger declares `MileStone` schema with 24 props.
|
|
13
|
+
*/
|
|
14
|
+
import { z } from 'zod';
|
|
15
|
+
import type { HaloPSAAPIClient } from '../api/client.js';
|
|
16
|
+
import type { ZodToolDefinition } from './registry.js';
|
|
17
|
+
export declare const ListTicketMilestonesArgsSchema: z.ZodObject<{
|
|
18
|
+
ticket_id: z.ZodNumber;
|
|
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
|
+
export declare const SetTicketMilestonesArgsSchema: z.ZodObject<{
|
|
30
|
+
ticket_id: z.ZodNumber;
|
|
31
|
+
milestones: z.ZodArray<z.ZodObject<{
|
|
32
|
+
name: z.ZodString;
|
|
33
|
+
target_date: z.ZodString;
|
|
34
|
+
start_date: z.ZodOptional<z.ZodString>;
|
|
35
|
+
sequence: z.ZodOptional<z.ZodNumber>;
|
|
36
|
+
billing_amount: z.ZodOptional<z.ZodNumber>;
|
|
37
|
+
status_id: z.ZodOptional<z.ZodNumber>;
|
|
38
|
+
}, z.core.$strip>>;
|
|
39
|
+
format_options: z.ZodOptional<z.ZodObject<{
|
|
40
|
+
format: z.ZodOptional<z.ZodEnum<{
|
|
41
|
+
compact: "compact";
|
|
42
|
+
standard: "standard";
|
|
43
|
+
detailed: "detailed";
|
|
44
|
+
}>>;
|
|
45
|
+
fields: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
46
|
+
omit_empty: z.ZodOptional<z.ZodBoolean>;
|
|
47
|
+
}, z.core.$strip>>;
|
|
48
|
+
}, z.core.$strip>;
|
|
49
|
+
export declare const AddTicketMilestoneArgsSchema: z.ZodObject<{
|
|
50
|
+
ticket_id: z.ZodNumber;
|
|
51
|
+
milestone: z.ZodObject<{
|
|
52
|
+
name: z.ZodString;
|
|
53
|
+
target_date: z.ZodString;
|
|
54
|
+
start_date: z.ZodOptional<z.ZodString>;
|
|
55
|
+
sequence: z.ZodOptional<z.ZodNumber>;
|
|
56
|
+
billing_amount: z.ZodOptional<z.ZodNumber>;
|
|
57
|
+
status_id: z.ZodOptional<z.ZodNumber>;
|
|
58
|
+
}, z.core.$strip>;
|
|
59
|
+
format_options: z.ZodOptional<z.ZodObject<{
|
|
60
|
+
format: z.ZodOptional<z.ZodEnum<{
|
|
61
|
+
compact: "compact";
|
|
62
|
+
standard: "standard";
|
|
63
|
+
detailed: "detailed";
|
|
64
|
+
}>>;
|
|
65
|
+
fields: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
66
|
+
omit_empty: z.ZodOptional<z.ZodBoolean>;
|
|
67
|
+
}, z.core.$strip>>;
|
|
68
|
+
}, z.core.$strip>;
|
|
69
|
+
export declare const RemoveTicketMilestoneArgsSchema: z.ZodObject<{
|
|
70
|
+
ticket_id: z.ZodNumber;
|
|
71
|
+
milestone_id: z.ZodNumber;
|
|
72
|
+
format_options: z.ZodOptional<z.ZodObject<{
|
|
73
|
+
format: z.ZodOptional<z.ZodEnum<{
|
|
74
|
+
compact: "compact";
|
|
75
|
+
standard: "standard";
|
|
76
|
+
detailed: "detailed";
|
|
77
|
+
}>>;
|
|
78
|
+
fields: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
79
|
+
omit_empty: z.ZodOptional<z.ZodBoolean>;
|
|
80
|
+
}, z.core.$strip>>;
|
|
81
|
+
}, z.core.$strip>;
|
|
82
|
+
export declare function listTicketMilestones(client: HaloPSAAPIClient, args: z.infer<typeof ListTicketMilestonesArgsSchema>): Promise<string>;
|
|
83
|
+
export declare function setTicketMilestones(client: HaloPSAAPIClient, args: z.infer<typeof SetTicketMilestonesArgsSchema>): Promise<string>;
|
|
84
|
+
export declare function addTicketMilestone(client: HaloPSAAPIClient, args: z.infer<typeof AddTicketMilestoneArgsSchema>): Promise<string>;
|
|
85
|
+
export declare function removeTicketMilestone(client: HaloPSAAPIClient, args: z.infer<typeof RemoveTicketMilestoneArgsSchema>): Promise<string>;
|
|
86
|
+
export declare const listTicketMilestonesTool: ZodToolDefinition;
|
|
87
|
+
export declare const setTicketMilestonesTool: ZodToolDefinition;
|
|
88
|
+
export declare const addTicketMilestoneTool: ZodToolDefinition;
|
|
89
|
+
export declare const removeTicketMilestoneTool: ZodToolDefinition;
|
|
90
|
+
//# sourceMappingURL=milestones.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"milestones.d.ts","sourceRoot":"","sources":["../../src/tools/milestones.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;AA6BvD,eAAO,MAAM,8BAA8B;;;;;;;;;;;iBAIzC,CAAC;AAEH,eAAO,MAAM,6BAA6B;;;;;;;;;;;;;;;;;;;iBAMxC,CAAC;AAEH,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;;;;;iBAMvC,CAAC;AAEH,eAAO,MAAM,+BAA+B;;;;;;;;;;;;iBAM1C,CAAC;AAmEH,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,gBAAgB,EACxB,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,8BAA8B,CAAC,GACnD,OAAO,CAAC,MAAM,CAAC,CAkBjB;AAED,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,gBAAgB,EACxB,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,6BAA6B,CAAC,GAClD,OAAO,CAAC,MAAM,CAAC,CAKjB;AAED,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,gBAAgB,EACxB,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,4BAA4B,CAAC,GACjD,OAAO,CAAC,MAAM,CAAC,CAQjB;AAED,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,gBAAgB,EACxB,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,+BAA+B,CAAC,GACpD,OAAO,CAAC,MAAM,CAAC,CAiBjB;AAMD,eAAO,MAAM,wBAAwB,EAAE,iBAKtC,CAAC;AAEF,eAAO,MAAM,uBAAuB,EAAE,iBAKrC,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,iBAKpC,CAAC;AAEF,eAAO,MAAM,yBAAyB,EAAE,iBAKvC,CAAC"}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HaloPSA milestone management tools.
|
|
3
|
+
*
|
|
4
|
+
* Milestones are stored as a nested `milestones[]` array on the ticket
|
|
5
|
+
* itself — there is no top-level /Milestone endpoint (GET /Milestone
|
|
6
|
+
* returns 404). All reads use GET /Tickets/{id}?includedetails=true
|
|
7
|
+
* and all writes use POST /Tickets with a read-before-write merge,
|
|
8
|
+
* replacing the milestones array in its entirety (same pattern as
|
|
9
|
+
* customfields).
|
|
10
|
+
*
|
|
11
|
+
* Discovery note (2026-05-11): confirmed `milestones: []` (empty array)
|
|
12
|
+
* on ticket 22541; Swagger declares `MileStone` schema with 24 props.
|
|
13
|
+
*/
|
|
14
|
+
import { z } from 'zod';
|
|
15
|
+
import { formatResponse, stripWriteResponse } from '../utils/formatter.js';
|
|
16
|
+
import { TTL } from '../cache/memory-cache.js';
|
|
17
|
+
import { FormatOptionsSchema } from '../schemas/common.js';
|
|
18
|
+
// =============================================================================
|
|
19
|
+
// Schemas
|
|
20
|
+
// =============================================================================
|
|
21
|
+
/**
|
|
22
|
+
* Single milestone input — reused by set (array element) and add (single).
|
|
23
|
+
*/
|
|
24
|
+
const MilestoneInputSchema = z.object({
|
|
25
|
+
name: z.string().min(1)
|
|
26
|
+
.describe('Milestone name (required)'),
|
|
27
|
+
target_date: z.string()
|
|
28
|
+
.describe('Target completion date — ISO 8601 (required)'),
|
|
29
|
+
start_date: z.string().optional()
|
|
30
|
+
.describe('Start date — ISO 8601'),
|
|
31
|
+
sequence: z.number().int().optional()
|
|
32
|
+
.describe('Ordering sequence number'),
|
|
33
|
+
billing_amount: z.number().optional()
|
|
34
|
+
.describe('Billing amount associated with this milestone'),
|
|
35
|
+
status_id: z.number().int().optional()
|
|
36
|
+
.describe('Milestone status ID'),
|
|
37
|
+
});
|
|
38
|
+
export const ListTicketMilestonesArgsSchema = z.object({
|
|
39
|
+
ticket_id: z.number().int()
|
|
40
|
+
.describe('HaloPSA project ticket ID to read milestones from'),
|
|
41
|
+
format_options: FormatOptionsSchema,
|
|
42
|
+
});
|
|
43
|
+
export const SetTicketMilestonesArgsSchema = z.object({
|
|
44
|
+
ticket_id: z.number().int()
|
|
45
|
+
.describe('HaloPSA project ticket ID'),
|
|
46
|
+
milestones: z.array(MilestoneInputSchema).min(1)
|
|
47
|
+
.describe('Full replacement array of milestones. This REPLACES all existing milestones on the ticket.'),
|
|
48
|
+
format_options: FormatOptionsSchema,
|
|
49
|
+
});
|
|
50
|
+
export const AddTicketMilestoneArgsSchema = z.object({
|
|
51
|
+
ticket_id: z.number().int()
|
|
52
|
+
.describe('HaloPSA project ticket ID'),
|
|
53
|
+
milestone: MilestoneInputSchema
|
|
54
|
+
.describe('Milestone to append to the existing list'),
|
|
55
|
+
format_options: FormatOptionsSchema,
|
|
56
|
+
});
|
|
57
|
+
export const RemoveTicketMilestoneArgsSchema = z.object({
|
|
58
|
+
ticket_id: z.number().int()
|
|
59
|
+
.describe('HaloPSA project ticket ID'),
|
|
60
|
+
milestone_id: z.number().int()
|
|
61
|
+
.describe('ID of the milestone to remove'),
|
|
62
|
+
format_options: FormatOptionsSchema,
|
|
63
|
+
});
|
|
64
|
+
// =============================================================================
|
|
65
|
+
// Helpers
|
|
66
|
+
// =============================================================================
|
|
67
|
+
/**
|
|
68
|
+
* Halo write endpoints sometimes return `[{...}]` and sometimes `{...}`.
|
|
69
|
+
* Normalize to a single object so handlers don't have to branch.
|
|
70
|
+
*/
|
|
71
|
+
function unwrapWriteResponse(response) {
|
|
72
|
+
return Array.isArray(response) ? response[0] : response;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Fetch ticket with includedetails=true, bypassing cache so we always
|
|
76
|
+
* have a fresh baseline before a write.
|
|
77
|
+
*/
|
|
78
|
+
async function fetchTicketFresh(client, ticketId) {
|
|
79
|
+
return client.get(`/Tickets/${ticketId}`, { includedetails: true });
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* POST the merged ticket payload to Halo and return the stripped, formatted
|
|
83
|
+
* milestones array from the response.
|
|
84
|
+
*/
|
|
85
|
+
async function writeMilestones(client, ticketId, existing, newMilestones, format) {
|
|
86
|
+
const payload = { ...existing, id: ticketId, milestones: newMilestones };
|
|
87
|
+
const response = unwrapWriteResponse(await client.post('/Tickets', [payload]));
|
|
88
|
+
client.invalidateCache(`ticket-milestones:${ticketId}*`);
|
|
89
|
+
client.invalidateCache(`ticket:${ticketId}*`);
|
|
90
|
+
client.invalidateCache('tickets:*');
|
|
91
|
+
// Return the milestones array from the written ticket.
|
|
92
|
+
const strippedTicket = stripWriteResponse(response, format, 'ticket');
|
|
93
|
+
const milestones = strippedTicket['milestones'] ?? [];
|
|
94
|
+
const resolvedFormat = format ?? 'compact';
|
|
95
|
+
return formatResponse(milestones, { format: resolvedFormat }, {
|
|
96
|
+
ticket_id: ticketId,
|
|
97
|
+
milestone_count: milestones.length,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
// =============================================================================
|
|
101
|
+
// Implementations
|
|
102
|
+
// =============================================================================
|
|
103
|
+
export async function listTicketMilestones(client, args) {
|
|
104
|
+
const response = await client.getCached(`/Tickets/${args.ticket_id}`, { includedetails: true }, {
|
|
105
|
+
enabled: true,
|
|
106
|
+
ttl: TTL.TICKET_LIST,
|
|
107
|
+
keyPrefix: `ticket-milestones:${args.ticket_id}`,
|
|
108
|
+
});
|
|
109
|
+
const milestones = response.milestones ?? [];
|
|
110
|
+
const formatOpts = args.format_options ?? { format: 'standard' };
|
|
111
|
+
return formatResponse(milestones, formatOpts, {
|
|
112
|
+
ticket_id: args.ticket_id,
|
|
113
|
+
milestone_count: milestones.length,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
export async function setTicketMilestones(client, args) {
|
|
117
|
+
const existing = await fetchTicketFresh(client, args.ticket_id);
|
|
118
|
+
const format = args.format_options?.format;
|
|
119
|
+
return writeMilestones(client, args.ticket_id, existing, args.milestones, format);
|
|
120
|
+
}
|
|
121
|
+
export async function addTicketMilestone(client, args) {
|
|
122
|
+
const existing = await fetchTicketFresh(client, args.ticket_id);
|
|
123
|
+
const format = args.format_options?.format;
|
|
124
|
+
const currentMilestones = existing.milestones ?? [];
|
|
125
|
+
const merged = [...currentMilestones, args.milestone];
|
|
126
|
+
return writeMilestones(client, args.ticket_id, existing, merged, format);
|
|
127
|
+
}
|
|
128
|
+
export async function removeTicketMilestone(client, args) {
|
|
129
|
+
const existing = await fetchTicketFresh(client, args.ticket_id);
|
|
130
|
+
const format = args.format_options?.format;
|
|
131
|
+
const currentMilestones = existing.milestones ?? [];
|
|
132
|
+
const filtered = currentMilestones.filter((m) => m.id !== args.milestone_id);
|
|
133
|
+
if (filtered.length === currentMilestones.length) {
|
|
134
|
+
return JSON.stringify({
|
|
135
|
+
removed: false,
|
|
136
|
+
ticket_id: args.ticket_id,
|
|
137
|
+
milestone_id: args.milestone_id,
|
|
138
|
+
message: `Milestone id=${args.milestone_id} not found on ticket ${args.ticket_id}.`,
|
|
139
|
+
}, null, 2);
|
|
140
|
+
}
|
|
141
|
+
return writeMilestones(client, args.ticket_id, existing, filtered, format);
|
|
142
|
+
}
|
|
143
|
+
// =============================================================================
|
|
144
|
+
// Tool Definitions
|
|
145
|
+
// =============================================================================
|
|
146
|
+
export const listTicketMilestonesTool = {
|
|
147
|
+
name: 'list_halopsa_ticket_milestones',
|
|
148
|
+
description: 'Read the milestones[] array from a HaloPSA project ticket. Milestones are nested on the ticket — GET /Ticket/{id}?includedetails=true. Returns [] if none defined. Cached 1 min.',
|
|
149
|
+
schema: ListTicketMilestonesArgsSchema,
|
|
150
|
+
handler: listTicketMilestones,
|
|
151
|
+
};
|
|
152
|
+
export const setTicketMilestonesTool = {
|
|
153
|
+
name: 'set_halopsa_ticket_milestones',
|
|
154
|
+
description: 'Replace ALL milestones on a HaloPSA project ticket with the provided array. Uses read-before-write merge via POST /Tickets (REPLACE semantics). Returns updated milestones[].',
|
|
155
|
+
schema: SetTicketMilestonesArgsSchema,
|
|
156
|
+
handler: setTicketMilestones,
|
|
157
|
+
};
|
|
158
|
+
export const addTicketMilestoneTool = {
|
|
159
|
+
name: 'add_halopsa_ticket_milestone',
|
|
160
|
+
description: 'Append a single milestone to a HaloPSA project ticket. Reads existing milestones, appends the new one, then writes the full array via POST /Tickets. Returns updated milestones[].',
|
|
161
|
+
schema: AddTicketMilestoneArgsSchema,
|
|
162
|
+
handler: addTicketMilestone,
|
|
163
|
+
};
|
|
164
|
+
export const removeTicketMilestoneTool = {
|
|
165
|
+
name: 'remove_halopsa_ticket_milestone',
|
|
166
|
+
description: 'Remove a single milestone (by ID) from a HaloPSA project ticket. Reads existing milestones, filters out the target, then writes the remaining array via POST /Tickets. Returns updated milestones[] or a not-found message.',
|
|
167
|
+
schema: RemoveTicketMilestoneArgsSchema,
|
|
168
|
+
handler: removeTicketMilestone,
|
|
169
|
+
};
|
|
170
|
+
//# sourceMappingURL=milestones.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"milestones.js","sourceRoot":"","sources":["../../src/tools/milestones.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,11 +2,15 @@
|
|
|
2
2
|
* Central tool registration — imports all ZodToolDefinition exports
|
|
3
3
|
* and registers them with a ToolRegistry instance.
|
|
4
4
|
*
|
|
5
|
-
* Tool inventory (
|
|
5
|
+
* Tool inventory (66 total):
|
|
6
6
|
* Assets (11), Users (7), Sites (4), Clients (3),
|
|
7
7
|
* Reference data (4), Ticket reference data (5),
|
|
8
8
|
* Tickets (7), Ticket actions (2), Ticket custom fields (2),
|
|
9
|
-
* Batch operations (
|
|
9
|
+
* Batch operations (5 — assets, users, sites, tickets, bulk-update),
|
|
10
|
+
* Ticket links (1 — read-side only),
|
|
11
|
+
* Workflows (6 — list/get/list-steps/create/update/delete),
|
|
12
|
+
* Ticket milestones (4 — list/set/add/remove on parent ticket),
|
|
13
|
+
* Budgets (5 — list/create/delete BudgetType, get/set per-ticket)
|
|
10
14
|
*/
|
|
11
15
|
import type { ToolRegistry } from './registry.js';
|
|
12
16
|
export declare function registerAllTools(registry: ToolRegistry): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registrations.d.ts","sourceRoot":"","sources":["../../src/tools/registrations.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"registrations.d.ts","sourceRoot":"","sources":["../../src/tools/registrations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AA+MlD,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI,CAI7D"}
|