@adminforth/agent 1.52.6 → 1.53.1
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/apiBasedTools.ts +58 -15
- package/build.log +1 -1
- package/dist/apiBasedTools.js +44 -5
- package/package.json +3 -3
package/apiBasedTools.ts
CHANGED
|
@@ -480,6 +480,15 @@ function normalizeDateTimeInputsToUtc(
|
|
|
480
480
|
}
|
|
481
481
|
|
|
482
482
|
const METHODS_WITHOUT_REQUEST_BODY = new Set<string>(['GET', 'HEAD']);
|
|
483
|
+
const TOOL_HANDLER_TIMEOUT_MS = 15_000;
|
|
484
|
+
const EMPTY_HANDLER_RESPONSE_ERROR = {
|
|
485
|
+
error: 'EMPTY_HANDLER_RESPONSE',
|
|
486
|
+
message: 'Tool handler completed without returning a response.',
|
|
487
|
+
};
|
|
488
|
+
const TOOL_HANDLER_TIMEOUT_ERROR = {
|
|
489
|
+
error: 'TOOL_HANDLER_TIMEOUT',
|
|
490
|
+
message: `Tool handler timed out after ${TOOL_HANDLER_TIMEOUT_MS / 1000} seconds.`,
|
|
491
|
+
};
|
|
483
492
|
|
|
484
493
|
function createDirectToolResponse(): IAdminForthHttpResponse & {
|
|
485
494
|
headers: Array<[string, string]>;
|
|
@@ -514,6 +523,30 @@ function validationErrorResponse(
|
|
|
514
523
|
};
|
|
515
524
|
}
|
|
516
525
|
|
|
526
|
+
async function withToolHandlerTimeout<T>(callback: (abortSignal: AbortSignal) => T | Promise<T>, abortSignal?: AbortSignal) {
|
|
527
|
+
const controller = new AbortController();
|
|
528
|
+
const abortHandler = () => controller.abort();
|
|
529
|
+
let timeout: ReturnType<typeof setTimeout>;
|
|
530
|
+
const timeoutPromise = new Promise<typeof TOOL_HANDLER_TIMEOUT_ERROR>((resolve) => {
|
|
531
|
+
timeout = setTimeout(() => {
|
|
532
|
+
controller.abort();
|
|
533
|
+
resolve(TOOL_HANDLER_TIMEOUT_ERROR);
|
|
534
|
+
}, TOOL_HANDLER_TIMEOUT_MS);
|
|
535
|
+
});
|
|
536
|
+
|
|
537
|
+
abortSignal?.addEventListener('abort', abortHandler, { once: true });
|
|
538
|
+
|
|
539
|
+
try {
|
|
540
|
+
return await Promise.race([
|
|
541
|
+
callback(controller.signal),
|
|
542
|
+
timeoutPromise,
|
|
543
|
+
]);
|
|
544
|
+
} finally {
|
|
545
|
+
clearTimeout(timeout!);
|
|
546
|
+
abortSignal?.removeEventListener('abort', abortHandler);
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
|
|
517
550
|
async function callOpenApiSchema(params: {
|
|
518
551
|
adminforth: IAdminForth;
|
|
519
552
|
adminUser?: AdminUser;
|
|
@@ -549,19 +582,21 @@ async function callOpenApiSchema(params: {
|
|
|
549
582
|
trParams: unknown,
|
|
550
583
|
pluralizationNumber?: number,
|
|
551
584
|
) => adminforth.tr(msg, category, lang, trParams, pluralizationNumber);
|
|
552
|
-
const output = await schema.handler({
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
585
|
+
const output = await withToolHandlerTimeout((handlerAbortSignal) => schema.handler({
|
|
586
|
+
body,
|
|
587
|
+
query,
|
|
588
|
+
headers: {},
|
|
589
|
+
cookies: [],
|
|
590
|
+
adminUser,
|
|
591
|
+
response,
|
|
592
|
+
requestUrl: schema.path,
|
|
593
|
+
abortSignal: handlerAbortSignal,
|
|
594
|
+
_raw_express_req: undefined as never,
|
|
595
|
+
_raw_express_res: undefined as never,
|
|
596
|
+
tr,
|
|
597
|
+
}),
|
|
598
|
+
abortSignal,
|
|
599
|
+
);
|
|
565
600
|
|
|
566
601
|
if (response.message) {
|
|
567
602
|
return response.status >= 400
|
|
@@ -573,6 +608,10 @@ async function callOpenApiSchema(params: {
|
|
|
573
608
|
: response.message;
|
|
574
609
|
}
|
|
575
610
|
|
|
611
|
+
if (output === undefined) {
|
|
612
|
+
return EMPTY_HANDLER_RESPONSE_ERROR;
|
|
613
|
+
}
|
|
614
|
+
|
|
576
615
|
if (output === null) {
|
|
577
616
|
return { status: response.status };
|
|
578
617
|
}
|
|
@@ -592,6 +631,10 @@ async function callOpenApiSchema(params: {
|
|
|
592
631
|
: output;
|
|
593
632
|
}
|
|
594
633
|
|
|
634
|
+
function stringifyToolOutput(output: unknown): string {
|
|
635
|
+
return YAML.stringify(output === undefined ? EMPTY_HANDLER_RESPONSE_ERROR : output);
|
|
636
|
+
}
|
|
637
|
+
|
|
595
638
|
export function prepareApiBasedTools(
|
|
596
639
|
adminforth: IAdminForth,
|
|
597
640
|
hiddenResourceIds: Iterable<string> = [],
|
|
@@ -624,7 +667,7 @@ export function prepareApiBasedTools(
|
|
|
624
667
|
agent: schema.agent,
|
|
625
668
|
call: async ({ adminUser, adminuser, abortSignal, inputs, userTimeZone, acceptLanguage } = {}) => {
|
|
626
669
|
if (isHiddenResourceCall(hiddenResourceIdSet, inputs)) {
|
|
627
|
-
return
|
|
670
|
+
return stringifyToolOutput({
|
|
628
671
|
error: 'RESOURCE_NOT_AVAILABLE',
|
|
629
672
|
message: 'This resource is not available to the agent.',
|
|
630
673
|
});
|
|
@@ -650,7 +693,7 @@ export function prepareApiBasedTools(
|
|
|
650
693
|
userTimeZone,
|
|
651
694
|
});
|
|
652
695
|
|
|
653
|
-
return
|
|
696
|
+
return stringifyToolOutput(processedOutput);
|
|
654
697
|
},
|
|
655
698
|
};
|
|
656
699
|
}
|
package/build.log
CHANGED
|
@@ -63,5 +63,5 @@ custom/speech_recognition_frontend/voiceActivityDetection.ts
|
|
|
63
63
|
custom/speech_recognition_frontend/types/
|
|
64
64
|
custom/speech_recognition_frontend/types/voice-activity-detection.d.ts
|
|
65
65
|
|
|
66
|
-
sent 1,683,
|
|
66
|
+
sent 1,683,270 bytes received 940 bytes 3,368,420.00 bytes/sec
|
|
67
67
|
total size is 1,679,042 speedup is 1.00
|
package/dist/apiBasedTools.js
CHANGED
|
@@ -316,6 +316,15 @@ function normalizeDateTimeInputsToUtc(body, adminforth, userTimeZone) {
|
|
|
316
316
|
return normalizeValue(body);
|
|
317
317
|
}
|
|
318
318
|
const METHODS_WITHOUT_REQUEST_BODY = new Set(['GET', 'HEAD']);
|
|
319
|
+
const TOOL_HANDLER_TIMEOUT_MS = 15000;
|
|
320
|
+
const EMPTY_HANDLER_RESPONSE_ERROR = {
|
|
321
|
+
error: 'EMPTY_HANDLER_RESPONSE',
|
|
322
|
+
message: 'Tool handler completed without returning a response.',
|
|
323
|
+
};
|
|
324
|
+
const TOOL_HANDLER_TIMEOUT_ERROR = {
|
|
325
|
+
error: 'TOOL_HANDLER_TIMEOUT',
|
|
326
|
+
message: `Tool handler timed out after ${TOOL_HANDLER_TIMEOUT_MS / 1000} seconds.`,
|
|
327
|
+
};
|
|
319
328
|
function createDirectToolResponse() {
|
|
320
329
|
const headers = [];
|
|
321
330
|
return {
|
|
@@ -339,6 +348,30 @@ function validationErrorResponse(error, details) {
|
|
|
339
348
|
details,
|
|
340
349
|
};
|
|
341
350
|
}
|
|
351
|
+
function withToolHandlerTimeout(callback, abortSignal) {
|
|
352
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
353
|
+
const controller = new AbortController();
|
|
354
|
+
const abortHandler = () => controller.abort();
|
|
355
|
+
let timeout;
|
|
356
|
+
const timeoutPromise = new Promise((resolve) => {
|
|
357
|
+
timeout = setTimeout(() => {
|
|
358
|
+
controller.abort();
|
|
359
|
+
resolve(TOOL_HANDLER_TIMEOUT_ERROR);
|
|
360
|
+
}, TOOL_HANDLER_TIMEOUT_MS);
|
|
361
|
+
});
|
|
362
|
+
abortSignal === null || abortSignal === void 0 ? void 0 : abortSignal.addEventListener('abort', abortHandler, { once: true });
|
|
363
|
+
try {
|
|
364
|
+
return yield Promise.race([
|
|
365
|
+
callback(controller.signal),
|
|
366
|
+
timeoutPromise,
|
|
367
|
+
]);
|
|
368
|
+
}
|
|
369
|
+
finally {
|
|
370
|
+
clearTimeout(timeout);
|
|
371
|
+
abortSignal === null || abortSignal === void 0 ? void 0 : abortSignal.removeEventListener('abort', abortHandler);
|
|
372
|
+
}
|
|
373
|
+
});
|
|
374
|
+
}
|
|
342
375
|
function callOpenApiSchema(params) {
|
|
343
376
|
return __awaiter(this, void 0, void 0, function* () {
|
|
344
377
|
const { adminforth, adminUser, abortSignal, inputs, schema, toolName, userTimeZone, acceptLanguage } = params;
|
|
@@ -355,7 +388,7 @@ function callOpenApiSchema(params) {
|
|
|
355
388
|
logger.info(`Calling OpenAPI tool "${toolName}" with direct handler`);
|
|
356
389
|
const lang = acceptLanguage !== null && acceptLanguage !== void 0 ? acceptLanguage : "en";
|
|
357
390
|
const tr = (msg, category, trParams, pluralizationNumber) => adminforth.tr(msg, category, lang, trParams, pluralizationNumber);
|
|
358
|
-
const output = yield schema.handler({
|
|
391
|
+
const output = yield withToolHandlerTimeout((handlerAbortSignal) => schema.handler({
|
|
359
392
|
body,
|
|
360
393
|
query,
|
|
361
394
|
headers: {},
|
|
@@ -363,11 +396,11 @@ function callOpenApiSchema(params) {
|
|
|
363
396
|
adminUser,
|
|
364
397
|
response,
|
|
365
398
|
requestUrl: schema.path,
|
|
366
|
-
abortSignal:
|
|
399
|
+
abortSignal: handlerAbortSignal,
|
|
367
400
|
_raw_express_req: undefined,
|
|
368
401
|
_raw_express_res: undefined,
|
|
369
402
|
tr,
|
|
370
|
-
});
|
|
403
|
+
}), abortSignal);
|
|
371
404
|
if (response.message) {
|
|
372
405
|
return response.status >= 400
|
|
373
406
|
? {
|
|
@@ -377,6 +410,9 @@ function callOpenApiSchema(params) {
|
|
|
377
410
|
}
|
|
378
411
|
: response.message;
|
|
379
412
|
}
|
|
413
|
+
if (output === undefined) {
|
|
414
|
+
return EMPTY_HANDLER_RESPONSE_ERROR;
|
|
415
|
+
}
|
|
380
416
|
if (output === null) {
|
|
381
417
|
return { status: response.status };
|
|
382
418
|
}
|
|
@@ -393,6 +429,9 @@ function callOpenApiSchema(params) {
|
|
|
393
429
|
: output;
|
|
394
430
|
});
|
|
395
431
|
}
|
|
432
|
+
function stringifyToolOutput(output) {
|
|
433
|
+
return YAML.stringify(output === undefined ? EMPTY_HANDLER_RESPONSE_ERROR : output);
|
|
434
|
+
}
|
|
396
435
|
export function prepareApiBasedTools(adminforth, hiddenResourceIds = []) {
|
|
397
436
|
const apiBasedTools = {};
|
|
398
437
|
const openApiSchemas = adminforth.openApi.registeredSchemas;
|
|
@@ -413,7 +452,7 @@ export function prepareApiBasedTools(adminforth, hiddenResourceIds = []) {
|
|
|
413
452
|
agent: schema.agent,
|
|
414
453
|
call: (...args_1) => __awaiter(this, [...args_1], void 0, function* ({ adminUser, adminuser, abortSignal, inputs, userTimeZone, acceptLanguage } = {}) {
|
|
415
454
|
if (isHiddenResourceCall(hiddenResourceIdSet, inputs)) {
|
|
416
|
-
return
|
|
455
|
+
return stringifyToolOutput({
|
|
417
456
|
error: 'RESOURCE_NOT_AVAILABLE',
|
|
418
457
|
message: 'This resource is not available to the agent.',
|
|
419
458
|
});
|
|
@@ -436,7 +475,7 @@ export function prepareApiBasedTools(adminforth, hiddenResourceIds = []) {
|
|
|
436
475
|
toolName,
|
|
437
476
|
userTimeZone,
|
|
438
477
|
});
|
|
439
|
-
return
|
|
478
|
+
return stringifyToolOutput(processedOutput);
|
|
440
479
|
}),
|
|
441
480
|
};
|
|
442
481
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adminforth/agent",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.53.1",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"type": "module",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"description": "AI agent plugin for AdminForth with tool-based workflows and persistent chat sessions",
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@types/node": "latest",
|
|
28
|
-
"adminforth": "3.
|
|
28
|
+
"adminforth": "3.1.1",
|
|
29
29
|
"semantic-release": "^24.2.1",
|
|
30
30
|
"semantic-release-slack-bot": "^4.0.2",
|
|
31
31
|
"typescript": "^5.7.3"
|
|
@@ -67,6 +67,6 @@
|
|
|
67
67
|
}
|
|
68
68
|
],
|
|
69
69
|
"peerDependencies": {
|
|
70
|
-
"adminforth": "3.
|
|
70
|
+
"adminforth": "3.1.1"
|
|
71
71
|
}
|
|
72
72
|
}
|