@hexabot-ai/api 3.2.2-alpha.16 → 3.2.2-alpha.18
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/dist/mcp/guards/hexabot-mcp-token.guard.js +2 -2
- package/dist/mcp/guards/hexabot-mcp-token.guard.js.map +1 -1
- package/dist/mcp/tools/credential-mcp.tools.d.ts +2 -2
- package/dist/mcp/tools/hexabot-mcp.utils.d.ts +2 -1
- package/dist/mcp/tools/hexabot-mcp.utils.js +13 -1
- package/dist/mcp/tools/hexabot-mcp.utils.js.map +1 -1
- package/dist/mcp/tools/workflow-mcp.helper.d.ts +18 -3
- package/dist/mcp/tools/workflow-mcp.helper.js +22 -2
- package/dist/mcp/tools/workflow-mcp.helper.js.map +1 -1
- package/dist/mcp/tools/workflow-mcp.tools.d.ts +340 -18
- package/dist/mcp/tools/workflow-mcp.tools.js +12 -7
- package/dist/mcp/tools/workflow-mcp.tools.js.map +1 -1
- package/dist/mcp/tools/workflow-run-mcp.tools.d.ts +2 -0
- package/dist/mcp/tools/workflow-run-mcp.tools.js +19 -6
- package/dist/mcp/tools/workflow-run-mcp.tools.js.map +1 -1
- package/dist/mcp/tools/workflow-version-mcp.tools.d.ts +84 -76
- package/dist/mcp/tools/workflow-version-mcp.tools.js +165 -8
- package/dist/mcp/tools/workflow-version-mcp.tools.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +4 -4
- package/src/mcp/README.md +67 -55
- package/src/mcp/guards/hexabot-mcp-token.guard.ts +2 -2
- package/src/mcp/tools/hexabot-mcp.utils.ts +18 -2
- package/src/mcp/tools/workflow-mcp.helper.ts +62 -9
- package/src/mcp/tools/workflow-mcp.tools.ts +25 -8
- package/src/mcp/tools/workflow-run-mcp.tools.ts +25 -7
- package/src/mcp/tools/workflow-version-mcp.tools.ts +245 -12
|
@@ -5,8 +5,16 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import { validateWorkflow } from '@hexabot-ai/agentic';
|
|
8
|
-
import {
|
|
9
|
-
|
|
8
|
+
import {
|
|
9
|
+
Action,
|
|
10
|
+
type WorkflowVersion,
|
|
11
|
+
type WorkflowVersionFull,
|
|
12
|
+
} from '@hexabot-ai/types';
|
|
13
|
+
import {
|
|
14
|
+
BadRequestException,
|
|
15
|
+
Injectable,
|
|
16
|
+
NotFoundException,
|
|
17
|
+
} from '@nestjs/common';
|
|
10
18
|
import { Tool, ToolGuards } from '@rekog/mcp-nest';
|
|
11
19
|
import { z } from 'zod';
|
|
12
20
|
|
|
@@ -67,11 +75,14 @@ export class HexabotWorkflowVersionMcpTools extends HexabotMcpToolBase {
|
|
|
67
75
|
request?: HexabotMcpRequest,
|
|
68
76
|
) {
|
|
69
77
|
const actorId = this.getActorId(request);
|
|
70
|
-
|
|
71
|
-
return await this.workflowHelper.commitWorkflowDefinition({
|
|
78
|
+
const version = await this.workflowHelper.commitWorkflowDefinition({
|
|
72
79
|
...args,
|
|
73
80
|
createdBy: actorId,
|
|
74
81
|
});
|
|
82
|
+
|
|
83
|
+
return this.workflowHelper.summarizeWorkflowVersion(version, {
|
|
84
|
+
includeDefinitionYmlByteLength: true,
|
|
85
|
+
});
|
|
75
86
|
}
|
|
76
87
|
|
|
77
88
|
@McpPermission('workflow', Action.READ)
|
|
@@ -108,7 +119,8 @@ export class HexabotWorkflowVersionMcpTools extends HexabotMcpToolBase {
|
|
|
108
119
|
@ToolGuards([McpPermissionGuard])
|
|
109
120
|
@Tool({
|
|
110
121
|
name: 'hexabot_workflow_version_search',
|
|
111
|
-
description:
|
|
122
|
+
description:
|
|
123
|
+
'List compact workflow definition version metadata for a workflow, excluding YAML bodies.',
|
|
112
124
|
parameters: z.object({
|
|
113
125
|
workflowId: uuidSchema,
|
|
114
126
|
...paginationSchema,
|
|
@@ -118,18 +130,28 @@ export class HexabotWorkflowVersionMcpTools extends HexabotMcpToolBase {
|
|
|
118
130
|
})
|
|
119
131
|
async searchWorkflowVersions(args: { workflowId: string } & PaginationArgs) {
|
|
120
132
|
const where = { workflow: { id: args.workflowId } } as any;
|
|
121
|
-
|
|
122
|
-
return await this.listWithCount(
|
|
133
|
+
const result = await this.listWithCount(
|
|
123
134
|
this.workflowVersionService,
|
|
124
135
|
this.findOptions<WorkflowVersionOrmEntity>(args, where),
|
|
125
136
|
);
|
|
137
|
+
|
|
138
|
+
return {
|
|
139
|
+
...result,
|
|
140
|
+
items: result.items.map((version) =>
|
|
141
|
+
this.workflowHelper.summarizeWorkflowVersion(
|
|
142
|
+
version as WorkflowVersion,
|
|
143
|
+
{ includeDefinitionYmlByteLength: true },
|
|
144
|
+
),
|
|
145
|
+
),
|
|
146
|
+
};
|
|
126
147
|
}
|
|
127
148
|
|
|
128
149
|
@McpPermission('workflowversion', Action.READ)
|
|
129
150
|
@ToolGuards([McpPermissionGuard])
|
|
130
151
|
@Tool({
|
|
131
152
|
name: 'hexabot_workflow_version_get',
|
|
132
|
-
description:
|
|
153
|
+
description:
|
|
154
|
+
'Read compact workflow definition version metadata, excluding the YAML body.',
|
|
133
155
|
parameters: z.object({
|
|
134
156
|
id: uuidSchema,
|
|
135
157
|
workflowId: uuidSchema.optional(),
|
|
@@ -147,7 +169,57 @@ export class HexabotWorkflowVersionMcpTools extends HexabotMcpToolBase {
|
|
|
147
169
|
throw new NotFoundException(`Workflow version ${args.id} not found`);
|
|
148
170
|
}
|
|
149
171
|
|
|
150
|
-
return version
|
|
172
|
+
return this.workflowHelper.summarizeWorkflowVersion(version, {
|
|
173
|
+
includeDefinitionYmlByteLength: true,
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
@McpPermission('workflowversion', Action.READ)
|
|
178
|
+
@ToolGuards([McpPermissionGuard])
|
|
179
|
+
@Tool({
|
|
180
|
+
name: 'hexabot_workflow_yaml_get',
|
|
181
|
+
description:
|
|
182
|
+
'Read workflow definition YAML by workflowId/current version or versionId, with checksum, byte length, and UTF-8 byte offset/limit chunking.',
|
|
183
|
+
parameters: z.object({
|
|
184
|
+
workflowId: uuidSchema.optional(),
|
|
185
|
+
versionId: uuidSchema.optional(),
|
|
186
|
+
offset: z.number().int().min(0).default(0),
|
|
187
|
+
limit: z.number().int().min(1).max(64000).default(16000),
|
|
188
|
+
}),
|
|
189
|
+
})
|
|
190
|
+
async getWorkflowYaml(args: {
|
|
191
|
+
workflowId?: string;
|
|
192
|
+
versionId?: string;
|
|
193
|
+
offset?: number;
|
|
194
|
+
limit?: number;
|
|
195
|
+
}) {
|
|
196
|
+
const version = await this.requireWorkflowVersionForYaml(args);
|
|
197
|
+
const definitionYml = version.definitionYml;
|
|
198
|
+
const offset = args.offset ?? 0;
|
|
199
|
+
const limit = args.limit ?? 16000;
|
|
200
|
+
const { chunk, chunkByteLength, endOffset, totalByteLength } =
|
|
201
|
+
this.sliceUtf8Chunk(definitionYml, offset, limit);
|
|
202
|
+
const workflowId = this.resolveRelationId(version.workflow);
|
|
203
|
+
|
|
204
|
+
return {
|
|
205
|
+
workflowId,
|
|
206
|
+
versionId: version.id,
|
|
207
|
+
version: version.version,
|
|
208
|
+
checksum: version.checksum,
|
|
209
|
+
definitionYmlByteLength: totalByteLength,
|
|
210
|
+
definitionYmlLength: definitionYml.length,
|
|
211
|
+
chunk: {
|
|
212
|
+
offset,
|
|
213
|
+
limit,
|
|
214
|
+
unit: 'utf8Bytes',
|
|
215
|
+
endOffset,
|
|
216
|
+
length: chunk.length,
|
|
217
|
+
byteLength: chunkByteLength,
|
|
218
|
+
hasMore: endOffset < totalByteLength,
|
|
219
|
+
nextOffset: endOffset < totalByteLength ? endOffset : null,
|
|
220
|
+
},
|
|
221
|
+
definitionYml: chunk,
|
|
222
|
+
};
|
|
151
223
|
}
|
|
152
224
|
|
|
153
225
|
@McpPermission('workflowversion', Action.UPDATE)
|
|
@@ -162,9 +234,13 @@ export class HexabotWorkflowVersionMcpTools extends HexabotMcpToolBase {
|
|
|
162
234
|
}),
|
|
163
235
|
})
|
|
164
236
|
async updateWorkflowVersion(args: { id: string; message?: string | null }) {
|
|
165
|
-
|
|
237
|
+
const version = await this.workflowVersionService.updateOne(args.id, {
|
|
166
238
|
message: args.message ?? undefined,
|
|
167
239
|
});
|
|
240
|
+
|
|
241
|
+
return this.workflowHelper.summarizeWorkflowVersion(version, {
|
|
242
|
+
includeDefinitionYmlByteLength: true,
|
|
243
|
+
});
|
|
168
244
|
}
|
|
169
245
|
|
|
170
246
|
@McpPermission('workflowversion', Action.CREATE)
|
|
@@ -184,10 +260,14 @@ export class HexabotWorkflowVersionMcpTools extends HexabotMcpToolBase {
|
|
|
184
260
|
_context: unknown,
|
|
185
261
|
request?: HexabotMcpRequest,
|
|
186
262
|
) {
|
|
187
|
-
|
|
263
|
+
const version = await this.workflowHelper.restoreWorkflowVersionSnapshot(
|
|
188
264
|
args,
|
|
189
265
|
this.getActorId(request),
|
|
190
266
|
);
|
|
267
|
+
|
|
268
|
+
return this.workflowHelper.summarizeWorkflowVersion(version, {
|
|
269
|
+
includeDefinitionYmlByteLength: true,
|
|
270
|
+
});
|
|
191
271
|
}
|
|
192
272
|
|
|
193
273
|
@McpPermission('workflowversion', Action.CREATE)
|
|
@@ -207,10 +287,14 @@ export class HexabotWorkflowVersionMcpTools extends HexabotMcpToolBase {
|
|
|
207
287
|
_context: unknown,
|
|
208
288
|
request?: HexabotMcpRequest,
|
|
209
289
|
) {
|
|
210
|
-
|
|
290
|
+
const version = await this.workflowHelper.restoreWorkflowVersionSnapshot(
|
|
211
291
|
args,
|
|
212
292
|
this.getActorId(request),
|
|
213
293
|
);
|
|
294
|
+
|
|
295
|
+
return this.workflowHelper.summarizeWorkflowVersion(version, {
|
|
296
|
+
includeDefinitionYmlByteLength: true,
|
|
297
|
+
});
|
|
214
298
|
}
|
|
215
299
|
|
|
216
300
|
private getWorkflowValidationActions() {
|
|
@@ -223,4 +307,153 @@ export class HexabotWorkflowVersionMcpTools extends HexabotMcpToolBase {
|
|
|
223
307
|
),
|
|
224
308
|
);
|
|
225
309
|
}
|
|
310
|
+
|
|
311
|
+
private async requireWorkflowVersionForYaml(args: {
|
|
312
|
+
workflowId?: string;
|
|
313
|
+
versionId?: string;
|
|
314
|
+
}): Promise<WorkflowVersion | WorkflowVersionFull> {
|
|
315
|
+
if (!args.workflowId && !args.versionId) {
|
|
316
|
+
throw new BadRequestException(
|
|
317
|
+
'workflowId or versionId is required to read workflow YAML',
|
|
318
|
+
);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
if (args.versionId) {
|
|
322
|
+
const version = await this.workflowVersionService.findOneAndPopulate({
|
|
323
|
+
where: {
|
|
324
|
+
id: args.versionId,
|
|
325
|
+
...(args.workflowId ? { workflow: { id: args.workflowId } } : {}),
|
|
326
|
+
} as any,
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
if (!version) {
|
|
330
|
+
throw new NotFoundException(
|
|
331
|
+
`Workflow version ${args.versionId} not found`,
|
|
332
|
+
);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
return version;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
const workflowId = args.workflowId;
|
|
339
|
+
if (!workflowId) {
|
|
340
|
+
throw new BadRequestException(
|
|
341
|
+
'workflowId is required when versionId is not provided',
|
|
342
|
+
);
|
|
343
|
+
}
|
|
344
|
+
const workflow = await this.workflowHelper.requireWorkflow(workflowId);
|
|
345
|
+
const currentVersionId = this.resolveRelationId(workflow.currentVersion);
|
|
346
|
+
if (!currentVersionId) {
|
|
347
|
+
throw new NotFoundException(
|
|
348
|
+
`Workflow ${workflowId} has no current version`,
|
|
349
|
+
);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
const version = await this.workflowVersionService.findOneAndPopulate({
|
|
353
|
+
where: {
|
|
354
|
+
id: currentVersionId,
|
|
355
|
+
workflow: { id: workflowId },
|
|
356
|
+
} as any,
|
|
357
|
+
});
|
|
358
|
+
|
|
359
|
+
if (!version) {
|
|
360
|
+
throw new NotFoundException(
|
|
361
|
+
`Workflow version ${currentVersionId} not found`,
|
|
362
|
+
);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
return version;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
private sliceUtf8Chunk(
|
|
369
|
+
value: string,
|
|
370
|
+
offset: number,
|
|
371
|
+
limit: number,
|
|
372
|
+
): {
|
|
373
|
+
chunk: string;
|
|
374
|
+
chunkByteLength: number;
|
|
375
|
+
endOffset: number;
|
|
376
|
+
totalByteLength: number;
|
|
377
|
+
} {
|
|
378
|
+
const totalByteLength = Buffer.byteLength(value, 'utf8');
|
|
379
|
+
if (offset > totalByteLength) {
|
|
380
|
+
throw new BadRequestException(
|
|
381
|
+
`Offset ${offset} exceeds workflow YAML byte length ${totalByteLength}`,
|
|
382
|
+
);
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
const startIndex = this.findUtf8IndexForOffset(value, offset);
|
|
386
|
+
let endIndex = value.length;
|
|
387
|
+
let byteOffset = offset;
|
|
388
|
+
|
|
389
|
+
for (let index = startIndex; index < value.length; ) {
|
|
390
|
+
const char = this.readCodePoint(value, index);
|
|
391
|
+
const nextByteOffset = byteOffset + Buffer.byteLength(char, 'utf8');
|
|
392
|
+
|
|
393
|
+
if (nextByteOffset > offset + limit) {
|
|
394
|
+
if (index === startIndex) {
|
|
395
|
+
throw new BadRequestException(
|
|
396
|
+
`Limit ${limit} is too small to include the next UTF-8 character at offset ${offset}`,
|
|
397
|
+
);
|
|
398
|
+
}
|
|
399
|
+
endIndex = index;
|
|
400
|
+
break;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
byteOffset = nextByteOffset;
|
|
404
|
+
index += char.length;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
const chunk = value.slice(startIndex, endIndex);
|
|
408
|
+
const chunkByteLength = Buffer.byteLength(chunk, 'utf8');
|
|
409
|
+
|
|
410
|
+
return {
|
|
411
|
+
chunk,
|
|
412
|
+
chunkByteLength,
|
|
413
|
+
endOffset: offset + chunkByteLength,
|
|
414
|
+
totalByteLength,
|
|
415
|
+
};
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
private findUtf8IndexForOffset(value: string, offset: number): number {
|
|
419
|
+
if (offset === 0) {
|
|
420
|
+
return 0;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
let byteOffset = 0;
|
|
424
|
+
for (let index = 0; index < value.length; ) {
|
|
425
|
+
const char = this.readCodePoint(value, index);
|
|
426
|
+
const nextByteOffset = byteOffset + Buffer.byteLength(char, 'utf8');
|
|
427
|
+
|
|
428
|
+
if (offset === nextByteOffset) {
|
|
429
|
+
return index + char.length;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
if (offset < nextByteOffset) {
|
|
433
|
+
throw new BadRequestException(
|
|
434
|
+
`Offset ${offset} is not aligned to a UTF-8 character boundary`,
|
|
435
|
+
);
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
byteOffset = nextByteOffset;
|
|
439
|
+
index += char.length;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
if (offset === byteOffset) {
|
|
443
|
+
return value.length;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
throw new BadRequestException(
|
|
447
|
+
`Offset ${offset} exceeds workflow YAML byte length ${byteOffset}`,
|
|
448
|
+
);
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
private readCodePoint(value: string, index: number): string {
|
|
452
|
+
const codePoint = value.codePointAt(index);
|
|
453
|
+
if (codePoint === undefined) {
|
|
454
|
+
return '';
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
return String.fromCodePoint(codePoint);
|
|
458
|
+
}
|
|
226
459
|
}
|