@adminforth/agent 1.43.27 → 1.43.29
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/LICENSE +21 -0
- package/agent/checkpointer.ts +2 -1
- package/agent/systemPrompt.ts +2 -1
- package/apiBasedTools.ts +7 -3
- package/build.log +1 -1
- package/dist/agent/systemPrompt.js +3 -1
- package/dist/apiBasedTools.js +5 -3
- package/dist/index.js +32 -19
- package/index.ts +30 -14
- package/package.json +2 -2
- package/tsconfig.json +1 -1
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Devforth.io
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/agent/checkpointer.ts
CHANGED
|
@@ -12,6 +12,7 @@ import type { PluginOptions } from "../types.js";
|
|
|
12
12
|
import { Filters } from "adminforth";
|
|
13
13
|
|
|
14
14
|
const ROOT_CHECKPOINT_NAMESPACE = "__root__";
|
|
15
|
+
type CheckpointRow = Record<string, unknown>;
|
|
15
16
|
|
|
16
17
|
export class AdminForthCheckpointSaver extends BaseCheckpointSaver {
|
|
17
18
|
constructor(
|
|
@@ -227,7 +228,7 @@ export class AdminForthCheckpointSaver extends BaseCheckpointSaver {
|
|
|
227
228
|
[{ field: r.sequenceField, direction: "asc" }],
|
|
228
229
|
);
|
|
229
230
|
|
|
230
|
-
const pendingWrites: CheckpointPendingWrite[] = writesRows.flatMap((row) => {
|
|
231
|
+
const pendingWrites: CheckpointPendingWrite[] = writesRows.flatMap((row: CheckpointRow) => {
|
|
231
232
|
const taskId = String(row[r.taskIdField] ?? "");
|
|
232
233
|
const write = this.deserialize<PendingWrite>(row[r.writesPayloadField]);
|
|
233
234
|
if (!write) {
|
package/agent/systemPrompt.ts
CHANGED
|
@@ -95,8 +95,9 @@ export async function buildAgentSystemPrompt(
|
|
|
95
95
|
adminforth: IAdminForth,
|
|
96
96
|
hiddenResourceIds: Iterable<string> = [],
|
|
97
97
|
) {
|
|
98
|
+
const customComponentsDir = adminforth.config.customization.customComponentsDir ?? "custom";
|
|
98
99
|
const [primarySkills, defaultSkills] = await Promise.all([
|
|
99
|
-
listProjectSkillManifests(
|
|
100
|
+
listProjectSkillManifests(customComponentsDir),
|
|
100
101
|
listBundledSkillManifests(),
|
|
101
102
|
]);
|
|
102
103
|
const adminBasePath = adminforth.config.baseUrlSlashed;
|
package/apiBasedTools.ts
CHANGED
|
@@ -169,6 +169,7 @@ export type ApiBasedToolCallParams = {
|
|
|
169
169
|
abortSignal?: AbortSignal;
|
|
170
170
|
inputs?: Record<string, unknown>;
|
|
171
171
|
userTimeZone?: string;
|
|
172
|
+
acceptLanguage?: string;
|
|
172
173
|
};
|
|
173
174
|
|
|
174
175
|
export type ApiBasedTool = {
|
|
@@ -516,8 +517,9 @@ async function callOpenApiSchema(params: {
|
|
|
516
517
|
schema: RegisteredApiToolSchema;
|
|
517
518
|
toolName: string;
|
|
518
519
|
userTimeZone?: string;
|
|
520
|
+
acceptLanguage?: string;
|
|
519
521
|
}) {
|
|
520
|
-
const { adminforth, adminUser, abortSignal, inputs, schema, toolName, userTimeZone } = params;
|
|
522
|
+
const { adminforth, adminUser, abortSignal, inputs, schema, toolName, userTimeZone, acceptLanguage } = params;
|
|
521
523
|
const method = schema.method.toUpperCase();
|
|
522
524
|
const normalizedInputs = normalizeDateTimeInputsToUtc(
|
|
523
525
|
(inputs ?? {}) as Record<string, unknown>,
|
|
@@ -535,12 +537,13 @@ async function callOpenApiSchema(params: {
|
|
|
535
537
|
|
|
536
538
|
const response = createDirectToolResponse();
|
|
537
539
|
logger.info(`Calling OpenAPI tool "${toolName}" with direct handler`);
|
|
540
|
+
const lang = acceptLanguage ?? "en";
|
|
538
541
|
const tr = (
|
|
539
542
|
msg: string,
|
|
540
543
|
category: string,
|
|
541
544
|
trParams: unknown,
|
|
542
545
|
pluralizationNumber?: number,
|
|
543
|
-
) => adminforth.tr(msg, category,
|
|
546
|
+
) => adminforth.tr(msg, category, lang, trParams, pluralizationNumber);
|
|
544
547
|
const output = await schema.handler({
|
|
545
548
|
body,
|
|
546
549
|
query,
|
|
@@ -614,7 +617,7 @@ export function prepareApiBasedTools(
|
|
|
614
617
|
description: schema.description,
|
|
615
618
|
input_schema: schema.request_schema,
|
|
616
619
|
output_schema: schema.response_schema,
|
|
617
|
-
call: async ({ adminUser, adminuser, abortSignal, inputs, userTimeZone } = {}) => {
|
|
620
|
+
call: async ({ adminUser, adminuser, abortSignal, inputs, userTimeZone, acceptLanguage } = {}) => {
|
|
618
621
|
if (isHiddenResourceCall(hiddenResourceIdSet, inputs)) {
|
|
619
622
|
return YAML.stringify({
|
|
620
623
|
error: 'RESOURCE_NOT_AVAILABLE',
|
|
@@ -630,6 +633,7 @@ export function prepareApiBasedTools(
|
|
|
630
633
|
toolName,
|
|
631
634
|
inputs,
|
|
632
635
|
userTimeZone,
|
|
636
|
+
acceptLanguage,
|
|
633
637
|
});
|
|
634
638
|
|
|
635
639
|
const processedOutput = await applyToolOverride({
|
package/build.log
CHANGED
|
@@ -62,5 +62,5 @@ custom/speech_recognition_frontend/voiceActivityDetection.ts
|
|
|
62
62
|
custom/speech_recognition_frontend/types/
|
|
63
63
|
custom/speech_recognition_frontend/types/voice-activity-detection.d.ts
|
|
64
64
|
|
|
65
|
-
sent 1,666,
|
|
65
|
+
sent 1,666,103 bytes received 921 bytes 3,334,048.00 bytes/sec
|
|
66
66
|
total size is 1,662,008 speedup is 1.00
|
|
@@ -73,8 +73,10 @@ function formatSkills(skills, label) {
|
|
|
73
73
|
}
|
|
74
74
|
export function buildAgentSystemPrompt(adminforth_1) {
|
|
75
75
|
return __awaiter(this, arguments, void 0, function* (adminforth, hiddenResourceIds = []) {
|
|
76
|
+
var _a;
|
|
77
|
+
const customComponentsDir = (_a = adminforth.config.customization.customComponentsDir) !== null && _a !== void 0 ? _a : "custom";
|
|
76
78
|
const [primarySkills, defaultSkills] = yield Promise.all([
|
|
77
|
-
listProjectSkillManifests(
|
|
79
|
+
listProjectSkillManifests(customComponentsDir),
|
|
78
80
|
listBundledSkillManifests(),
|
|
79
81
|
]);
|
|
80
82
|
const adminBasePath = adminforth.config.baseUrlSlashed;
|
package/dist/apiBasedTools.js
CHANGED
|
@@ -341,7 +341,7 @@ function validationErrorResponse(error, details) {
|
|
|
341
341
|
}
|
|
342
342
|
function callOpenApiSchema(params) {
|
|
343
343
|
return __awaiter(this, void 0, void 0, function* () {
|
|
344
|
-
const { adminforth, adminUser, abortSignal, inputs, schema, toolName, userTimeZone } = params;
|
|
344
|
+
const { adminforth, adminUser, abortSignal, inputs, schema, toolName, userTimeZone, acceptLanguage } = params;
|
|
345
345
|
const method = schema.method.toUpperCase();
|
|
346
346
|
const normalizedInputs = normalizeDateTimeInputsToUtc((inputs !== null && inputs !== void 0 ? inputs : {}), adminforth, userTimeZone);
|
|
347
347
|
const hasRequestBody = !METHODS_WITHOUT_REQUEST_BODY.has(method);
|
|
@@ -353,7 +353,8 @@ function callOpenApiSchema(params) {
|
|
|
353
353
|
}
|
|
354
354
|
const response = createDirectToolResponse();
|
|
355
355
|
logger.info(`Calling OpenAPI tool "${toolName}" with direct handler`);
|
|
356
|
-
const
|
|
356
|
+
const lang = acceptLanguage !== null && acceptLanguage !== void 0 ? acceptLanguage : "en";
|
|
357
|
+
const tr = (msg, category, trParams, pluralizationNumber) => adminforth.tr(msg, category, lang, trParams, pluralizationNumber);
|
|
357
358
|
const output = yield schema.handler({
|
|
358
359
|
body,
|
|
359
360
|
query,
|
|
@@ -410,7 +411,7 @@ export function prepareApiBasedTools(adminforth, hiddenResourceIds = []) {
|
|
|
410
411
|
description: schema.description,
|
|
411
412
|
input_schema: schema.request_schema,
|
|
412
413
|
output_schema: schema.response_schema,
|
|
413
|
-
call: (...args_1) => __awaiter(this, [...args_1], void 0, function* ({ adminUser, adminuser, abortSignal, inputs, userTimeZone } = {}) {
|
|
414
|
+
call: (...args_1) => __awaiter(this, [...args_1], void 0, function* ({ adminUser, adminuser, abortSignal, inputs, userTimeZone, acceptLanguage } = {}) {
|
|
414
415
|
if (isHiddenResourceCall(hiddenResourceIdSet, inputs)) {
|
|
415
416
|
return YAML.stringify({
|
|
416
417
|
error: 'RESOURCE_NOT_AVAILABLE',
|
|
@@ -425,6 +426,7 @@ export function prepareApiBasedTools(adminforth, hiddenResourceIds = []) {
|
|
|
425
426
|
toolName,
|
|
426
427
|
inputs,
|
|
427
428
|
userTimeZone,
|
|
429
|
+
acceptLanguage,
|
|
428
430
|
});
|
|
429
431
|
const processedOutput = yield applyToolOverride({
|
|
430
432
|
adminforth,
|
package/dist/index.js
CHANGED
|
@@ -57,6 +57,12 @@ function isAbortError(error) {
|
|
|
57
57
|
function getErrorMessage(error) {
|
|
58
58
|
return error instanceof Error ? error.message : String(error);
|
|
59
59
|
}
|
|
60
|
+
function requireAdminUser(adminUser) {
|
|
61
|
+
if (!adminUser) {
|
|
62
|
+
throw new Error("AdminForth Agent endpoint requires an authenticated admin user");
|
|
63
|
+
}
|
|
64
|
+
return adminUser;
|
|
65
|
+
}
|
|
60
66
|
export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
61
67
|
parseBody(schema, body, response) {
|
|
62
68
|
const parsed = schema.safeParse(body !== null && body !== void 0 ? body : {});
|
|
@@ -175,7 +181,7 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
175
181
|
runAgentTurn(input) {
|
|
176
182
|
return __awaiter(this, void 0, void 0, function* () {
|
|
177
183
|
var _a, e_1, _b, _c;
|
|
178
|
-
var _d, _e, _f, _g, _h;
|
|
184
|
+
var _d, _e, _f, _g, _h, _j;
|
|
179
185
|
let fullResponse = "";
|
|
180
186
|
const maxTokens = (_d = this.options.maxTokens) !== null && _d !== void 0 ? _d : 1000;
|
|
181
187
|
const selectedMode = (_e = this.options.modes.find((mode) => mode.name === input.modeName)) !== null && _e !== void 0 ? _e : this.options.modes[0];
|
|
@@ -223,7 +229,7 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
223
229
|
adminUser: input.adminUser,
|
|
224
230
|
adminforth: this.adminforth,
|
|
225
231
|
apiBasedTools,
|
|
226
|
-
customComponentsDir: this.adminforth.config.customization.customComponentsDir,
|
|
232
|
+
customComponentsDir: (_f = this.adminforth.config.customization.customComponentsDir) !== null && _f !== void 0 ? _f : "custom",
|
|
227
233
|
sessionId: input.sessionId,
|
|
228
234
|
turnId: input.turnId,
|
|
229
235
|
currentPage: input.currentPage,
|
|
@@ -237,11 +243,11 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
237
243
|
sequenceDebugSink: input.sequenceDebugCollector,
|
|
238
244
|
});
|
|
239
245
|
try {
|
|
240
|
-
for (var
|
|
241
|
-
_c =
|
|
242
|
-
|
|
246
|
+
for (var _k = true, _l = __asyncValues(stream), _m; _m = yield _l.next(), _a = _m.done, !_a; _k = true) {
|
|
247
|
+
_c = _m.value;
|
|
248
|
+
_k = false;
|
|
243
249
|
const rawChunk = _c;
|
|
244
|
-
if ((
|
|
250
|
+
if ((_g = input.abortSignal) === null || _g === void 0 ? void 0 : _g.aborted) {
|
|
245
251
|
throw new DOMException("This operation was aborted", "AbortError");
|
|
246
252
|
}
|
|
247
253
|
const [token, metadata] = rawChunk;
|
|
@@ -265,18 +271,18 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
265
271
|
.map((b) => { var _a; return String((_a = b.text) !== null && _a !== void 0 ? _a : ""); })
|
|
266
272
|
.join("");
|
|
267
273
|
if (reasoningDelta) {
|
|
268
|
-
(
|
|
274
|
+
(_h = input.emitReasoningDelta) === null || _h === void 0 ? void 0 : _h.call(input, reasoningDelta);
|
|
269
275
|
}
|
|
270
276
|
if (textDelta) {
|
|
271
277
|
fullResponse += textDelta;
|
|
272
|
-
(
|
|
278
|
+
(_j = input.emitTextDelta) === null || _j === void 0 ? void 0 : _j.call(input, textDelta);
|
|
273
279
|
}
|
|
274
280
|
}
|
|
275
281
|
}
|
|
276
282
|
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
277
283
|
finally {
|
|
278
284
|
try {
|
|
279
|
-
if (!
|
|
285
|
+
if (!_k && !_a && (_b = _l.return)) yield _b.call(_l);
|
|
280
286
|
}
|
|
281
287
|
finally { if (e_1) throw e_1.error; }
|
|
282
288
|
}
|
|
@@ -348,13 +354,14 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
348
354
|
method: 'POST',
|
|
349
355
|
path: `/agent/get-placeholder-messages`,
|
|
350
356
|
handler: (_a) => __awaiter(this, [_a], void 0, function* ({ headers, adminUser }) {
|
|
357
|
+
const currentAdminUser = requireAdminUser(adminUser);
|
|
351
358
|
if (!this.options.placeholderMessages) {
|
|
352
359
|
return {
|
|
353
360
|
messages: [],
|
|
354
361
|
};
|
|
355
362
|
}
|
|
356
363
|
const messages = yield this.options.placeholderMessages({
|
|
357
|
-
adminUser,
|
|
364
|
+
adminUser: currentAdminUser,
|
|
358
365
|
headers,
|
|
359
366
|
});
|
|
360
367
|
return {
|
|
@@ -367,6 +374,7 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
367
374
|
path: `/agent/response`,
|
|
368
375
|
handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, response, _raw_express_res, abortSignal }) {
|
|
369
376
|
var _b;
|
|
377
|
+
const currentAdminUser = requireAdminUser(adminUser);
|
|
370
378
|
const data = this.parseBody(agentResponseBodySchema, body, response);
|
|
371
379
|
if (!data)
|
|
372
380
|
return;
|
|
@@ -380,7 +388,7 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
380
388
|
userTimeZone: (_b = data.timeZone) !== null && _b !== void 0 ? _b : 'UTC',
|
|
381
389
|
currentPage: data.currentPage,
|
|
382
390
|
abortSignal,
|
|
383
|
-
adminUser,
|
|
391
|
+
adminUser: currentAdminUser,
|
|
384
392
|
emitToolCallEvent: stream.toolCall,
|
|
385
393
|
emitReasoningDelta: stream.reasoningDelta,
|
|
386
394
|
emitTextDelta: stream.textDelta,
|
|
@@ -398,17 +406,18 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
398
406
|
target: 'upload',
|
|
399
407
|
handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, response, _raw_express_req, _raw_express_res, abortSignal }) {
|
|
400
408
|
var _b;
|
|
409
|
+
const currentAdminUser = requireAdminUser(adminUser);
|
|
401
410
|
const req = _raw_express_req;
|
|
402
411
|
const audioAdapter = this.options.audioAdapter;
|
|
403
412
|
if (!audioAdapter) {
|
|
404
|
-
response.setStatus(400,
|
|
413
|
+
response.setStatus(400, "Audio adapter is not configured for AdminForth Agent");
|
|
405
414
|
return { error: "Audio adapter is not configured for AdminForth Agent" };
|
|
406
415
|
}
|
|
407
416
|
const data = this.parseBody(agentSpeechResponseBodySchema, body, response);
|
|
408
417
|
if (!data)
|
|
409
418
|
return;
|
|
410
419
|
if (!req.file) {
|
|
411
|
-
response.setStatus(400,
|
|
420
|
+
response.setStatus(400, "Audio file is required");
|
|
412
421
|
return { error: "Audio file is required" };
|
|
413
422
|
}
|
|
414
423
|
const stream = createAgentEventStream(_raw_express_res);
|
|
@@ -453,7 +462,7 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
453
462
|
userTimeZone: (_b = data.timeZone) !== null && _b !== void 0 ? _b : 'UTC',
|
|
454
463
|
currentPage,
|
|
455
464
|
abortSignal,
|
|
456
|
-
adminUser,
|
|
465
|
+
adminUser: currentAdminUser,
|
|
457
466
|
emitToolCallEvent: stream.toolCall,
|
|
458
467
|
failureLogMessage: "Agent speech response failed",
|
|
459
468
|
abortLogMessage: "Agent speech response aborted by the client",
|
|
@@ -517,7 +526,7 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
517
526
|
}
|
|
518
527
|
else {
|
|
519
528
|
logger.error(`Agent speech audio streaming failed:\n${error}`);
|
|
520
|
-
stream.error(error);
|
|
529
|
+
stream.error(getErrorMessage(error));
|
|
521
530
|
}
|
|
522
531
|
stream.end();
|
|
523
532
|
return null;
|
|
@@ -529,10 +538,11 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
529
538
|
path: `/agent/get-sessions`,
|
|
530
539
|
handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, response }) {
|
|
531
540
|
var _b;
|
|
541
|
+
const currentAdminUser = requireAdminUser(adminUser);
|
|
532
542
|
const data = this.parseBody(getSessionsBodySchema, body, response);
|
|
533
543
|
if (!data)
|
|
534
544
|
return;
|
|
535
|
-
const userId =
|
|
545
|
+
const userId = currentAdminUser.pk;
|
|
536
546
|
const limit = (_b = data.limit) !== null && _b !== void 0 ? _b : 20;
|
|
537
547
|
const sessions = yield this.adminforth.resource(this.options.sessionResource.resourceId).list([Filters.EQ(this.options.sessionResource.askerIdField, userId)], limit, undefined, [Sorts.DESC(this.options.sessionResource.createdAtField)]);
|
|
538
548
|
return {
|
|
@@ -548,12 +558,13 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
548
558
|
method: 'POST',
|
|
549
559
|
path: `/agent/get-session-info`,
|
|
550
560
|
handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, response }) {
|
|
561
|
+
const currentAdminUser = requireAdminUser(adminUser);
|
|
551
562
|
const parsedBody = sessionIdBodySchema.safeParse(body);
|
|
552
563
|
if (!parsedBody.success) {
|
|
553
564
|
response.setStatus(422, parsedBody.error.message);
|
|
554
565
|
return;
|
|
555
566
|
}
|
|
556
|
-
const userId =
|
|
567
|
+
const userId = currentAdminUser.pk;
|
|
557
568
|
const sessionId = parsedBody.data.sessionId;
|
|
558
569
|
const session = yield this.adminforth.resource(this.options.sessionResource.resourceId).get([Filters.EQ(this.options.sessionResource.idField, sessionId)]);
|
|
559
570
|
if (!session) {
|
|
@@ -596,11 +607,12 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
596
607
|
method: 'POST',
|
|
597
608
|
path: `/agent/create-session`,
|
|
598
609
|
handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, response }) {
|
|
610
|
+
const currentAdminUser = requireAdminUser(adminUser);
|
|
599
611
|
const data = this.parseBody(createSessionBodySchema, body, response);
|
|
600
612
|
if (!data)
|
|
601
613
|
return;
|
|
602
614
|
const triggerMessage = data.triggerMessage;
|
|
603
|
-
const userId =
|
|
615
|
+
const userId = currentAdminUser.pk;
|
|
604
616
|
const title = (triggerMessage === null || triggerMessage === void 0 ? void 0 : triggerMessage.slice(0, 40)) || "New Session";
|
|
605
617
|
const newSession = {
|
|
606
618
|
[this.options.sessionResource.idField]: randomUUID(),
|
|
@@ -620,11 +632,12 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
620
632
|
method: 'POST',
|
|
621
633
|
path: `/agent/delete-session`,
|
|
622
634
|
handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, response }) {
|
|
635
|
+
const currentAdminUser = requireAdminUser(adminUser);
|
|
623
636
|
const data = this.parseBody(sessionIdBodySchema, body, response);
|
|
624
637
|
if (!data)
|
|
625
638
|
return;
|
|
626
639
|
const sessionId = data.sessionId;
|
|
627
|
-
const userId =
|
|
640
|
+
const userId = currentAdminUser.pk;
|
|
628
641
|
const session = yield this.adminforth.resource(this.options.sessionResource.resourceId).get([Filters.EQ(this.options.sessionResource.idField, sessionId)]);
|
|
629
642
|
if (!session) {
|
|
630
643
|
return {
|
package/index.ts
CHANGED
|
@@ -91,6 +91,14 @@ function getErrorMessage(error: unknown): string {
|
|
|
91
91
|
return error instanceof Error ? error.message : String(error);
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
+
function requireAdminUser(adminUser: AdminUser | undefined): AdminUser {
|
|
95
|
+
if (!adminUser) {
|
|
96
|
+
throw new Error("AdminForth Agent endpoint requires an authenticated admin user");
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return adminUser;
|
|
100
|
+
}
|
|
101
|
+
|
|
94
102
|
export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
95
103
|
options: PluginOptions;
|
|
96
104
|
agentSystemPromptPromise: Promise<string>;
|
|
@@ -98,7 +106,7 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
98
106
|
private parseBody<T>(
|
|
99
107
|
schema: z.ZodType<T>,
|
|
100
108
|
body: unknown,
|
|
101
|
-
response: { setStatus: (code: number, message
|
|
109
|
+
response: { setStatus: (code: number, message: string) => void },
|
|
102
110
|
): T | null {
|
|
103
111
|
const parsed = schema.safeParse(body ?? {});
|
|
104
112
|
if (!parsed.success) {
|
|
@@ -258,7 +266,7 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
258
266
|
const systemPrompt = buildAgentTurnSystemPrompt({
|
|
259
267
|
agentSystemPrompt: await this.agentSystemPromptPromise,
|
|
260
268
|
adminUser: input.adminUser,
|
|
261
|
-
usernameField: this.adminforth.config.auth
|
|
269
|
+
usernameField: this.adminforth.config.auth!.usernameField,
|
|
262
270
|
userLanguage,
|
|
263
271
|
});
|
|
264
272
|
const apiBasedTools = buildApiBasedTools(
|
|
@@ -279,7 +287,7 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
279
287
|
adminUser: input.adminUser,
|
|
280
288
|
adminforth: this.adminforth,
|
|
281
289
|
apiBasedTools,
|
|
282
|
-
|
|
290
|
+
customComponentsDir: this.adminforth.config.customization.customComponentsDir ?? "custom",
|
|
283
291
|
sessionId: input.sessionId,
|
|
284
292
|
turnId: input.turnId,
|
|
285
293
|
currentPage: input.currentPage,
|
|
@@ -402,6 +410,8 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
402
410
|
method: 'POST',
|
|
403
411
|
path: `/agent/get-placeholder-messages`,
|
|
404
412
|
handler: async ({ headers, adminUser }) => {
|
|
413
|
+
const currentAdminUser = requireAdminUser(adminUser);
|
|
414
|
+
|
|
405
415
|
if (!this.options.placeholderMessages) {
|
|
406
416
|
return {
|
|
407
417
|
messages: [],
|
|
@@ -409,7 +419,7 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
409
419
|
}
|
|
410
420
|
|
|
411
421
|
const messages = await this.options.placeholderMessages({
|
|
412
|
-
adminUser,
|
|
422
|
+
adminUser: currentAdminUser,
|
|
413
423
|
headers,
|
|
414
424
|
});
|
|
415
425
|
|
|
@@ -422,6 +432,7 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
422
432
|
method: 'POST',
|
|
423
433
|
path: `/agent/response`,
|
|
424
434
|
handler: async ({ body, adminUser, response, _raw_express_res, abortSignal }) => {
|
|
435
|
+
const currentAdminUser = requireAdminUser(adminUser);
|
|
425
436
|
const data = this.parseBody(agentResponseBodySchema, body, response);
|
|
426
437
|
if (!data) return;
|
|
427
438
|
const stream = createAgentEventStream(_raw_express_res, {vercelAiUiMessageStream: true, closeActiveBlockOnToolStart: true});
|
|
@@ -435,7 +446,7 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
435
446
|
userTimeZone: data.timeZone ?? 'UTC',
|
|
436
447
|
currentPage: data.currentPage,
|
|
437
448
|
abortSignal,
|
|
438
|
-
adminUser,
|
|
449
|
+
adminUser: currentAdminUser,
|
|
439
450
|
emitToolCallEvent: stream.toolCall,
|
|
440
451
|
emitReasoningDelta: stream.reasoningDelta,
|
|
441
452
|
emitTextDelta: stream.textDelta,
|
|
@@ -452,16 +463,17 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
452
463
|
path: `/agent/speech-response`,
|
|
453
464
|
target: 'upload',
|
|
454
465
|
handler: async ({ body, adminUser, response, _raw_express_req, _raw_express_res, abortSignal }) => {
|
|
466
|
+
const currentAdminUser = requireAdminUser(adminUser);
|
|
455
467
|
const req = _raw_express_req as ExpressMulterRequest;
|
|
456
468
|
const audioAdapter = this.options.audioAdapter;
|
|
457
469
|
if (!audioAdapter) {
|
|
458
|
-
response.setStatus(400,
|
|
470
|
+
response.setStatus(400, "Audio adapter is not configured for AdminForth Agent");
|
|
459
471
|
return { error: "Audio adapter is not configured for AdminForth Agent" };
|
|
460
472
|
}
|
|
461
473
|
const data = this.parseBody(agentSpeechResponseBodySchema, body, response);
|
|
462
474
|
if (!data) return;
|
|
463
475
|
if (!req.file) {
|
|
464
|
-
response.setStatus(400,
|
|
476
|
+
response.setStatus(400, "Audio file is required");
|
|
465
477
|
return { error: "Audio file is required" };
|
|
466
478
|
}
|
|
467
479
|
const stream = createAgentEventStream(_raw_express_res);
|
|
@@ -511,7 +523,7 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
511
523
|
userTimeZone: data.timeZone ?? 'UTC',
|
|
512
524
|
currentPage,
|
|
513
525
|
abortSignal,
|
|
514
|
-
adminUser,
|
|
526
|
+
adminUser: currentAdminUser,
|
|
515
527
|
emitToolCallEvent: stream.toolCall,
|
|
516
528
|
failureLogMessage: "Agent speech response failed",
|
|
517
529
|
abortLogMessage: "Agent speech response aborted by the client",
|
|
@@ -589,7 +601,7 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
589
601
|
logger.info("Agent speech audio streaming aborted by the client");
|
|
590
602
|
} else {
|
|
591
603
|
logger.error(`Agent speech audio streaming failed:\n${error}`);
|
|
592
|
-
stream.error(error);
|
|
604
|
+
stream.error(getErrorMessage(error));
|
|
593
605
|
}
|
|
594
606
|
stream.end();
|
|
595
607
|
return null;
|
|
@@ -600,9 +612,10 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
600
612
|
method: 'POST',
|
|
601
613
|
path: `/agent/get-sessions`,
|
|
602
614
|
handler: async ({body, adminUser, response }) => {
|
|
615
|
+
const currentAdminUser = requireAdminUser(adminUser);
|
|
603
616
|
const data = this.parseBody(getSessionsBodySchema, body, response);
|
|
604
617
|
if (!data) return;
|
|
605
|
-
const userId =
|
|
618
|
+
const userId = currentAdminUser.pk;
|
|
606
619
|
const limit = data.limit ?? 20;
|
|
607
620
|
const sessions = await this.adminforth.resource(this.options.sessionResource.resourceId).list(
|
|
608
621
|
[Filters.EQ(this.options.sessionResource.askerIdField, userId)], limit, undefined, [Sorts.DESC(this.options.sessionResource.createdAtField)]
|
|
@@ -620,12 +633,13 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
620
633
|
method: 'POST',
|
|
621
634
|
path: `/agent/get-session-info`,
|
|
622
635
|
handler: async ({body, adminUser, response }) => {
|
|
636
|
+
const currentAdminUser = requireAdminUser(adminUser);
|
|
623
637
|
const parsedBody = sessionIdBodySchema.safeParse(body);
|
|
624
638
|
if (!parsedBody.success) {
|
|
625
639
|
response.setStatus(422, parsedBody.error.message);
|
|
626
640
|
return;
|
|
627
641
|
}
|
|
628
|
-
const userId =
|
|
642
|
+
const userId = currentAdminUser.pk;
|
|
629
643
|
const sessionId = parsedBody.data.sessionId;
|
|
630
644
|
const session = await this.adminforth.resource(this.options.sessionResource.resourceId).get(
|
|
631
645
|
[Filters.EQ(this.options.sessionResource.idField, sessionId)]
|
|
@@ -647,7 +661,7 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
647
661
|
title: session[this.options.sessionResource.titleField],
|
|
648
662
|
timestamp: session[this.options.sessionResource.createdAtField],
|
|
649
663
|
messages: turns.flatMap(turn => {
|
|
650
|
-
const messages = [];
|
|
664
|
+
const messages: Array<{ text: string; role: 'user' | 'assistant' }> = [];
|
|
651
665
|
if (turn.prompt) {
|
|
652
666
|
messages.push({
|
|
653
667
|
text: turn.prompt,
|
|
@@ -670,10 +684,11 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
670
684
|
method: 'POST',
|
|
671
685
|
path: `/agent/create-session`,
|
|
672
686
|
handler: async ({body, adminUser, response }) => {
|
|
687
|
+
const currentAdminUser = requireAdminUser(adminUser);
|
|
673
688
|
const data = this.parseBody(createSessionBodySchema, body, response);
|
|
674
689
|
if (!data) return;
|
|
675
690
|
const triggerMessage = data.triggerMessage;
|
|
676
|
-
const userId =
|
|
691
|
+
const userId = currentAdminUser.pk;
|
|
677
692
|
const title = triggerMessage?.slice(0, 40) || "New Session";
|
|
678
693
|
const newSession = {
|
|
679
694
|
[this.options.sessionResource.idField]: randomUUID(),
|
|
@@ -693,10 +708,11 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
693
708
|
method: 'POST',
|
|
694
709
|
path: `/agent/delete-session`,
|
|
695
710
|
handler: async ({body, adminUser, response }) => {
|
|
711
|
+
const currentAdminUser = requireAdminUser(adminUser);
|
|
696
712
|
const data = this.parseBody(sessionIdBodySchema, body, response);
|
|
697
713
|
if (!data) return;
|
|
698
714
|
const sessionId = data.sessionId;
|
|
699
|
-
const userId =
|
|
715
|
+
const userId = currentAdminUser.pk;
|
|
700
716
|
const session = await this.adminforth.resource(this.options.sessionResource.resourceId).get(
|
|
701
717
|
[Filters.EQ(this.options.sessionResource.idField, sessionId)]
|
|
702
718
|
);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adminforth/agent",
|
|
3
|
-
"version": "1.43.
|
|
3
|
+
"version": "1.43.29",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"type": "module",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"session-memory"
|
|
22
22
|
],
|
|
23
23
|
"author": "DevForth (https://devforth.io)",
|
|
24
|
-
"license": "
|
|
24
|
+
"license": "MIT",
|
|
25
25
|
"description": "AI agent plugin for AdminForth with tool-based workflows and persistent chat sessions",
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@types/node": "latest",
|
package/tsconfig.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"outDir": "./dist", /* Specify an output folder for all emitted files. */
|
|
6
6
|
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. */
|
|
7
7
|
"forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
|
|
8
|
-
"strict":
|
|
8
|
+
"strict": true, /* Enable all strict type-checking options. */
|
|
9
9
|
"skipLibCheck": true, /* Skip type checking all .d.ts files. */
|
|
10
10
|
},
|
|
11
11
|
"exclude": ["node_modules", "dist", "custom"], /* Exclude files from compilation. */
|