@adminforth/agent 1.43.29 → 1.44.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/agentEvents.ts +61 -0
- package/agentResponseEvents.ts +1 -206
- package/build.log +1 -1
- package/dist/agent/checkpointer.d.ts +29 -0
- package/dist/agent/languageDetect.d.ts +10 -0
- package/dist/agent/middleware/apiBasedTools.d.ts +3 -0
- package/dist/agent/middleware/openAiResponsesContinuation.d.ts +1 -0
- package/dist/agent/middleware/sequenceDebug.d.ts +46 -0
- package/dist/agent/simpleAgent.d.ts +61 -0
- package/dist/agent/skills/registry.d.ts +13 -0
- package/dist/agent/systemPrompt.d.ts +11 -0
- package/dist/agent/toolCallEvents.d.ts +27 -0
- package/dist/agent/tools/apiTool.d.ts +6 -0
- package/dist/agent/tools/fetchSkill.d.ts +8 -0
- package/dist/agent/tools/fetchToolSchema.d.ts +9 -0
- package/dist/agent/tools/getUserLocation.d.ts +8 -0
- package/dist/agent/tools/index.d.ts +4 -0
- package/dist/agentEvents.d.ts +52 -0
- package/dist/agentEvents.js +1 -0
- package/dist/agentResponseEvents.d.ts +1 -0
- package/dist/agentResponseEvents.js +1 -144
- package/dist/apiBasedTools.d.ts +29 -0
- package/dist/index.d.ts +58 -0
- package/dist/index.js +222 -43
- package/dist/sanitizeSpeechText.d.ts +1 -0
- package/dist/surfaces/web-sse/createSseEventEmitter.d.ts +14 -0
- package/dist/surfaces/web-sse/createSseEventEmitter.js +196 -0
- package/dist/types.d.ts +94 -0
- package/index.ts +250 -46
- package/package.json +2 -2
- package/surfaces/web-sse/createSseEventEmitter.ts +261 -0
- package/tsconfig.json +1 -0
- package/types.ts +6 -0
package/index.ts
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
AdminUser,
|
|
3
|
+
AdminForthResource,
|
|
4
|
+
ChatSurfaceAdapter,
|
|
5
|
+
ChatSurfaceEventSink,
|
|
6
|
+
ChatSurfaceIncomingMessage,
|
|
7
|
+
IAdminForth,
|
|
8
|
+
IHttpServer,
|
|
9
|
+
} from "adminforth";
|
|
2
10
|
|
|
3
11
|
import { AdminForthPlugin, logger, Filters, Sorts } from "adminforth";
|
|
4
12
|
|
|
@@ -12,12 +20,14 @@ import { AdminForthCheckpointSaver } from "./agent/checkpointer.js";
|
|
|
12
20
|
import { createSequenceDebugCollector } from "./agent/middleware/sequenceDebug.js";
|
|
13
21
|
import { detectUserLanguage, type PreviousUserMessage } from "./agent/languageDetect.js";
|
|
14
22
|
import { prepareApiBasedTools as buildApiBasedTools } from './apiBasedTools.js';
|
|
15
|
-
import {
|
|
23
|
+
import type { AgentEventEmitter } from "./agentEvents.js";
|
|
24
|
+
import { createSseEventEmitter } from "./surfaces/web-sse/createSseEventEmitter.js";
|
|
16
25
|
import { appendCustomSystemPrompt, buildAgentSystemPrompt, buildAgentTurnSystemPrompt, DEFAULT_AGENT_SYSTEM_PROMPT} from "./agent/systemPrompt.js";
|
|
17
|
-
import type { ToolCallEvent } from "./agent/toolCallEvents.js";
|
|
18
26
|
import type { CurrentPageContext } from "./agent/tools/getUserLocation.js";
|
|
19
27
|
import { sanitizeSpeechText } from "./sanitizeSpeechText.js";
|
|
20
28
|
|
|
29
|
+
export type { AgentEvent, AgentEventEmitter } from "./agentEvents.js";
|
|
30
|
+
|
|
21
31
|
type MulterFile = {
|
|
22
32
|
buffer: Buffer;
|
|
23
33
|
originalname: string;
|
|
@@ -37,18 +47,21 @@ type AgentTurnRunInput = {
|
|
|
37
47
|
abortSignal?: AbortSignal;
|
|
38
48
|
adminUser: AdminUser;
|
|
39
49
|
sequenceDebugCollector: ReturnType<typeof createSequenceDebugCollector>;
|
|
40
|
-
|
|
41
|
-
emitTextDelta?: (delta: string) => void;
|
|
42
|
-
emitToolCallEvent?: (event: ToolCallEvent) => void;
|
|
50
|
+
emit?: AgentEventEmitter;
|
|
43
51
|
};
|
|
44
52
|
|
|
45
53
|
type RunAndPersistAgentResponseInput =
|
|
46
54
|
Omit<AgentTurnRunInput, "turnId" | "sequenceDebugCollector" | "previousUserMessages"> & {
|
|
47
|
-
emitErrorResponse?: (response: string) => void;
|
|
48
55
|
failureLogMessage: string;
|
|
49
56
|
abortLogMessage: string;
|
|
50
57
|
};
|
|
51
58
|
|
|
59
|
+
type HandleTurnInput = Omit<RunAndPersistAgentResponseInput, "failureLogMessage" | "abortLogMessage"> & {
|
|
60
|
+
emit: AgentEventEmitter;
|
|
61
|
+
failureLogMessage?: string;
|
|
62
|
+
abortLogMessage?: string;
|
|
63
|
+
};
|
|
64
|
+
|
|
52
65
|
const agentResponseBodySchema = z.object({
|
|
53
66
|
message: z.string(),
|
|
54
67
|
sessionId: z.string(),
|
|
@@ -154,6 +167,33 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
154
167
|
}));
|
|
155
168
|
}
|
|
156
169
|
|
|
170
|
+
private getChatSurfaceSessionId(incoming: ChatSurfaceIncomingMessage) {
|
|
171
|
+
return `${incoming.surface}:${incoming.externalConversationId}`;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
private async getOrCreateChatSurfaceSession(
|
|
175
|
+
incoming: ChatSurfaceIncomingMessage,
|
|
176
|
+
adminUser: AdminUser,
|
|
177
|
+
) {
|
|
178
|
+
const sessionId = this.getChatSurfaceSessionId(incoming);
|
|
179
|
+
const sessionResource = this.adminforth.resource(this.options.sessionResource.resourceId);
|
|
180
|
+
const session = await sessionResource.get(
|
|
181
|
+
[Filters.EQ(this.options.sessionResource.idField, sessionId)]
|
|
182
|
+
);
|
|
183
|
+
|
|
184
|
+
if (session) {
|
|
185
|
+
return sessionId;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
await sessionResource.create({
|
|
189
|
+
[this.options.sessionResource.idField]: sessionId,
|
|
190
|
+
[this.options.sessionResource.titleField]: incoming.prompt.slice(0, 40) || "New Session",
|
|
191
|
+
[this.options.sessionResource.askerIdField]: adminUser.pk,
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
return sessionId;
|
|
195
|
+
}
|
|
196
|
+
|
|
157
197
|
private getCheckpointer() {
|
|
158
198
|
if (this.checkpointer) return this.checkpointer;
|
|
159
199
|
|
|
@@ -223,6 +263,9 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
223
263
|
|
|
224
264
|
validateConfigAfterDiscover(adminforth: IAdminForth, resourceConfig: AdminForthResource) {
|
|
225
265
|
this.options.audioAdapter?.validate();
|
|
266
|
+
for (const chatSurfaceAdapter of this.options.chatSurfaceAdapters ?? []) {
|
|
267
|
+
chatSurfaceAdapter.validate();
|
|
268
|
+
}
|
|
226
269
|
this.agentSystemPromptPromise = buildAgentSystemPrompt(
|
|
227
270
|
adminforth,
|
|
228
271
|
this.getInternalAgentResourceIds(),
|
|
@@ -295,7 +338,10 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
295
338
|
abortSignal: input.abortSignal,
|
|
296
339
|
emitToolCallEvent: (event) => {
|
|
297
340
|
input.sequenceDebugCollector.handleToolCallEvent(event);
|
|
298
|
-
input.
|
|
341
|
+
void input.emit?.({
|
|
342
|
+
type: "tool-call",
|
|
343
|
+
data: event,
|
|
344
|
+
});
|
|
299
345
|
},
|
|
300
346
|
sequenceDebugSink: input.sequenceDebugCollector,
|
|
301
347
|
});
|
|
@@ -332,12 +378,18 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
332
378
|
.join("");
|
|
333
379
|
|
|
334
380
|
if (reasoningDelta) {
|
|
335
|
-
input.
|
|
381
|
+
await input.emit?.({
|
|
382
|
+
type: "reasoning-delta",
|
|
383
|
+
delta: reasoningDelta,
|
|
384
|
+
});
|
|
336
385
|
}
|
|
337
386
|
|
|
338
387
|
if (textDelta) {
|
|
339
388
|
fullResponse += textDelta;
|
|
340
|
-
input.
|
|
389
|
+
await input.emit?.({
|
|
390
|
+
type: "text-delta",
|
|
391
|
+
delta: textDelta,
|
|
392
|
+
});
|
|
341
393
|
}
|
|
342
394
|
}
|
|
343
395
|
|
|
@@ -369,9 +421,7 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
369
421
|
abortSignal: input.abortSignal,
|
|
370
422
|
adminUser: input.adminUser,
|
|
371
423
|
sequenceDebugCollector,
|
|
372
|
-
|
|
373
|
-
emitReasoningDelta: input.emitReasoningDelta,
|
|
374
|
-
emitTextDelta: input.emitTextDelta,
|
|
424
|
+
emit: input.emit,
|
|
375
425
|
});
|
|
376
426
|
fullResponse = agentResponse.text;
|
|
377
427
|
} catch (error) {
|
|
@@ -382,7 +432,6 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
382
432
|
failed = true;
|
|
383
433
|
fullResponse = getErrorMessage(error);
|
|
384
434
|
logger.error(`${input.failureLogMessage}:\n${fullResponse}`);
|
|
385
|
-
input.emitErrorResponse?.(fullResponse);
|
|
386
435
|
}
|
|
387
436
|
}
|
|
388
437
|
|
|
@@ -405,7 +454,134 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
405
454
|
};
|
|
406
455
|
}
|
|
407
456
|
|
|
457
|
+
async handleTurn(input: HandleTurnInput) {
|
|
458
|
+
await input.emit({
|
|
459
|
+
type: "turn-started",
|
|
460
|
+
messageId: randomUUID(),
|
|
461
|
+
});
|
|
462
|
+
|
|
463
|
+
const agentResponse = await this.runAndPersistAgentResponse({
|
|
464
|
+
prompt: input.prompt,
|
|
465
|
+
sessionId: input.sessionId,
|
|
466
|
+
modeName: input.modeName,
|
|
467
|
+
userTimeZone: input.userTimeZone,
|
|
468
|
+
currentPage: input.currentPage,
|
|
469
|
+
abortSignal: input.abortSignal,
|
|
470
|
+
adminUser: input.adminUser,
|
|
471
|
+
emit: input.emit,
|
|
472
|
+
failureLogMessage: input.failureLogMessage ?? "Agent response failed",
|
|
473
|
+
abortLogMessage: input.abortLogMessage ?? "Agent response aborted",
|
|
474
|
+
});
|
|
475
|
+
|
|
476
|
+
if (agentResponse.failed) {
|
|
477
|
+
await input.emit({
|
|
478
|
+
type: "error",
|
|
479
|
+
error: agentResponse.text,
|
|
480
|
+
});
|
|
481
|
+
} else if (!agentResponse.aborted) {
|
|
482
|
+
await input.emit({
|
|
483
|
+
type: "response",
|
|
484
|
+
text: agentResponse.text,
|
|
485
|
+
sessionId: input.sessionId,
|
|
486
|
+
turnId: agentResponse.turnId,
|
|
487
|
+
});
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
await input.emit({
|
|
491
|
+
type: "finish",
|
|
492
|
+
});
|
|
493
|
+
|
|
494
|
+
return agentResponse;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
private createChatSurfaceEventEmitter(sink: ChatSurfaceEventSink): AgentEventEmitter {
|
|
498
|
+
return async (event) => {
|
|
499
|
+
if (event.type === "text-delta") {
|
|
500
|
+
await sink.emit({
|
|
501
|
+
type: "text_delta",
|
|
502
|
+
delta: event.delta,
|
|
503
|
+
});
|
|
504
|
+
return;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
if (event.type === "response") {
|
|
508
|
+
await sink.emit({
|
|
509
|
+
type: "done",
|
|
510
|
+
text: event.text,
|
|
511
|
+
});
|
|
512
|
+
return;
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
if (event.type === "error") {
|
|
516
|
+
await sink.emit({
|
|
517
|
+
type: "error",
|
|
518
|
+
message: event.error,
|
|
519
|
+
});
|
|
520
|
+
}
|
|
521
|
+
};
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
private async handleChatSurfaceMessage(
|
|
525
|
+
adapter: ChatSurfaceAdapter,
|
|
526
|
+
incoming: ChatSurfaceIncomingMessage,
|
|
527
|
+
sink: ChatSurfaceEventSink,
|
|
528
|
+
) {
|
|
529
|
+
const adminUser = await adapter.resolveAdminUser({
|
|
530
|
+
adminforth: this.adminforth,
|
|
531
|
+
incoming,
|
|
532
|
+
});
|
|
533
|
+
|
|
534
|
+
if (!adminUser) {
|
|
535
|
+
await sink.emit({
|
|
536
|
+
type: "error",
|
|
537
|
+
message: "This chat account is not authorized to use AdminForth Agent.",
|
|
538
|
+
});
|
|
539
|
+
return;
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
await this.handleTurn({
|
|
543
|
+
prompt: incoming.prompt,
|
|
544
|
+
sessionId: await this.getOrCreateChatSurfaceSession(incoming, adminUser),
|
|
545
|
+
modeName: incoming.modeName,
|
|
546
|
+
userTimeZone: incoming.userTimeZone ?? "UTC",
|
|
547
|
+
adminUser,
|
|
548
|
+
emit: this.createChatSurfaceEventEmitter(sink),
|
|
549
|
+
failureLogMessage: `Agent ${incoming.surface} surface response failed`,
|
|
550
|
+
abortLogMessage: `Agent ${incoming.surface} surface response aborted`,
|
|
551
|
+
});
|
|
552
|
+
}
|
|
553
|
+
|
|
408
554
|
setupEndpoints(server: IHttpServer) {
|
|
555
|
+
for (const adapter of this.options.chatSurfaceAdapters ?? []) {
|
|
556
|
+
server.endpoint({
|
|
557
|
+
method: "POST",
|
|
558
|
+
noAuth: true,
|
|
559
|
+
path: `/agent/surface/${adapter.name}/webhook`,
|
|
560
|
+
handler: async (ctx) => {
|
|
561
|
+
const surfaceContext = {
|
|
562
|
+
body: ctx.body,
|
|
563
|
+
headers: ctx.headers,
|
|
564
|
+
abortSignal: ctx.abortSignal,
|
|
565
|
+
rawRequest: ctx._raw_express_req,
|
|
566
|
+
rawResponse: ctx._raw_express_res,
|
|
567
|
+
};
|
|
568
|
+
const incoming = await adapter.parseIncomingMessage(surfaceContext);
|
|
569
|
+
|
|
570
|
+
if (!incoming) return { ok: true };
|
|
571
|
+
|
|
572
|
+
const sink = await adapter.createEventSink(surfaceContext, incoming);
|
|
573
|
+
|
|
574
|
+
try {
|
|
575
|
+
await this.handleChatSurfaceMessage(adapter, incoming, sink);
|
|
576
|
+
} finally {
|
|
577
|
+
await sink.close?.();
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
return { ok: true };
|
|
581
|
+
},
|
|
582
|
+
});
|
|
583
|
+
}
|
|
584
|
+
|
|
409
585
|
server.endpoint({
|
|
410
586
|
method: 'POST',
|
|
411
587
|
path: `/agent/get-placeholder-messages`,
|
|
@@ -435,11 +611,12 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
435
611
|
const currentAdminUser = requireAdminUser(adminUser);
|
|
436
612
|
const data = this.parseBody(agentResponseBodySchema, body, response);
|
|
437
613
|
if (!data) return;
|
|
438
|
-
const
|
|
439
|
-
|
|
614
|
+
const emit = createSseEventEmitter(_raw_express_res, {
|
|
615
|
+
vercelAiUiMessageStream: true,
|
|
616
|
+
closeActiveBlockOnToolStart: true,
|
|
617
|
+
});
|
|
440
618
|
|
|
441
|
-
|
|
442
|
-
await this.runAndPersistAgentResponse({
|
|
619
|
+
await this.handleTurn({
|
|
443
620
|
prompt: data.message,
|
|
444
621
|
sessionId: data.sessionId,
|
|
445
622
|
modeName: data.mode,
|
|
@@ -447,14 +624,10 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
447
624
|
currentPage: data.currentPage,
|
|
448
625
|
abortSignal,
|
|
449
626
|
adminUser: currentAdminUser,
|
|
450
|
-
|
|
451
|
-
emitReasoningDelta: stream.reasoningDelta,
|
|
452
|
-
emitTextDelta: stream.textDelta,
|
|
453
|
-
emitErrorResponse: stream.textDelta,
|
|
627
|
+
emit,
|
|
454
628
|
failureLogMessage: "Agent response streaming failed",
|
|
455
629
|
abortLogMessage: "Agent response streaming aborted by the client",
|
|
456
630
|
});
|
|
457
|
-
stream.end();
|
|
458
631
|
return null;
|
|
459
632
|
}
|
|
460
633
|
});
|
|
@@ -476,7 +649,7 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
476
649
|
response.setStatus(400, "Audio file is required");
|
|
477
650
|
return { error: "Audio file is required" };
|
|
478
651
|
}
|
|
479
|
-
const
|
|
652
|
+
const emit = createSseEventEmitter(_raw_express_res);
|
|
480
653
|
|
|
481
654
|
let transcription;
|
|
482
655
|
|
|
@@ -491,28 +664,38 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
491
664
|
} catch (error) {
|
|
492
665
|
if (abortSignal.aborted || isAbortError(error)) {
|
|
493
666
|
logger.info("Agent speech transcription aborted by the client");
|
|
494
|
-
|
|
667
|
+
await emit({ type: "finish" });
|
|
495
668
|
return null;
|
|
496
669
|
}
|
|
497
670
|
|
|
498
671
|
logger.error(`Agent speech transcription failed:\n${getErrorMessage(error)}`);
|
|
499
|
-
|
|
500
|
-
|
|
672
|
+
await emit({
|
|
673
|
+
type: "error",
|
|
674
|
+
error: "Speech transcription failed. Check server logs for details.",
|
|
675
|
+
});
|
|
676
|
+
await emit({ type: "finish" });
|
|
501
677
|
return null;
|
|
502
678
|
}
|
|
503
679
|
|
|
504
680
|
if (abortSignal.aborted) {
|
|
505
|
-
|
|
681
|
+
await emit({ type: "finish" });
|
|
506
682
|
return null;
|
|
507
683
|
}
|
|
508
684
|
|
|
509
685
|
const prompt = transcription.text;
|
|
510
686
|
if (!prompt) {
|
|
511
|
-
|
|
512
|
-
|
|
687
|
+
await emit({
|
|
688
|
+
type: "error",
|
|
689
|
+
error: "Speech transcription is empty",
|
|
690
|
+
});
|
|
691
|
+
await emit({ type: "finish" });
|
|
513
692
|
return null;
|
|
514
693
|
}
|
|
515
|
-
|
|
694
|
+
await emit({
|
|
695
|
+
type: "transcript",
|
|
696
|
+
text: transcription.text,
|
|
697
|
+
language: transcription.language,
|
|
698
|
+
});
|
|
516
699
|
|
|
517
700
|
const sessionId = data.sessionId as string;
|
|
518
701
|
const currentPage = data.currentPage;
|
|
@@ -524,34 +707,42 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
524
707
|
currentPage,
|
|
525
708
|
abortSignal,
|
|
526
709
|
adminUser: currentAdminUser,
|
|
527
|
-
|
|
710
|
+
emit: async (event) => {
|
|
711
|
+
if (event.type === "tool-call") {
|
|
712
|
+
await emit(event);
|
|
713
|
+
}
|
|
714
|
+
},
|
|
528
715
|
failureLogMessage: "Agent speech response failed",
|
|
529
716
|
abortLogMessage: "Agent speech response aborted by the client",
|
|
530
717
|
});
|
|
531
718
|
|
|
532
719
|
if (agentResponse.aborted) {
|
|
533
|
-
|
|
720
|
+
await emit({ type: "finish" });
|
|
534
721
|
return null;
|
|
535
722
|
}
|
|
536
723
|
|
|
537
724
|
if (agentResponse.failed) {
|
|
538
|
-
|
|
539
|
-
|
|
725
|
+
await emit({
|
|
726
|
+
type: "error",
|
|
727
|
+
error: agentResponse.text,
|
|
728
|
+
});
|
|
729
|
+
await emit({ type: "finish" });
|
|
540
730
|
return null;
|
|
541
731
|
}
|
|
542
732
|
|
|
543
733
|
try {
|
|
544
|
-
|
|
545
|
-
|
|
734
|
+
await emit({
|
|
735
|
+
type: "speech-response",
|
|
736
|
+
transcript: {
|
|
546
737
|
text: transcription.text,
|
|
547
738
|
language: transcription.language,
|
|
548
739
|
},
|
|
549
|
-
{
|
|
740
|
+
response: {
|
|
550
741
|
text: agentResponse.text,
|
|
551
742
|
},
|
|
552
743
|
sessionId,
|
|
553
|
-
agentResponse.turnId,
|
|
554
|
-
);
|
|
744
|
+
turnId: agentResponse.turnId,
|
|
745
|
+
});
|
|
555
746
|
const speech = await audioAdapter.synthesize({
|
|
556
747
|
text: sanitizeSpeechText(agentResponse.text),
|
|
557
748
|
stream: true,
|
|
@@ -560,7 +751,14 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
560
751
|
abortSignal,
|
|
561
752
|
});
|
|
562
753
|
|
|
563
|
-
|
|
754
|
+
await emit({
|
|
755
|
+
type: "audio-start",
|
|
756
|
+
mimeType: speech.mimeType,
|
|
757
|
+
format: speech.format,
|
|
758
|
+
sampleRate: 24000,
|
|
759
|
+
channelCount: 1,
|
|
760
|
+
bitsPerSample: 16,
|
|
761
|
+
});
|
|
564
762
|
|
|
565
763
|
const reader = speech.audioStream.getReader();
|
|
566
764
|
const cancelAudioStream = () => {
|
|
@@ -586,24 +784,30 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
586
784
|
break;
|
|
587
785
|
}
|
|
588
786
|
|
|
589
|
-
|
|
787
|
+
await emit({
|
|
788
|
+
type: "audio-delta",
|
|
789
|
+
value,
|
|
790
|
+
});
|
|
590
791
|
}
|
|
591
792
|
} finally {
|
|
592
793
|
abortSignal.removeEventListener("abort", cancelAudioStream);
|
|
593
794
|
reader.releaseLock();
|
|
594
795
|
}
|
|
595
796
|
|
|
596
|
-
|
|
597
|
-
|
|
797
|
+
await emit({ type: "audio-done" });
|
|
798
|
+
await emit({ type: "finish" });
|
|
598
799
|
return null;
|
|
599
800
|
} catch (error) {
|
|
600
801
|
if (abortSignal.aborted || isAbortError(error)) {
|
|
601
802
|
logger.info("Agent speech audio streaming aborted by the client");
|
|
602
803
|
} else {
|
|
603
804
|
logger.error(`Agent speech audio streaming failed:\n${error}`);
|
|
604
|
-
|
|
805
|
+
await emit({
|
|
806
|
+
type: "error",
|
|
807
|
+
error: getErrorMessage(error),
|
|
808
|
+
});
|
|
605
809
|
}
|
|
606
|
-
|
|
810
|
+
await emit({ type: "finish" });
|
|
607
811
|
return null;
|
|
608
812
|
}
|
|
609
813
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adminforth/agent",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.44.0",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"type": "module",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"@langchain/core": "^1.1.40",
|
|
34
34
|
"@langchain/langgraph": "^1.2.8",
|
|
35
35
|
"@langchain/langgraph-checkpoint": "^1.0.1",
|
|
36
|
-
"adminforth": "
|
|
36
|
+
"adminforth": ">=2.54.0",
|
|
37
37
|
"dayjs": "^1.11.20",
|
|
38
38
|
"langchain": "^1.3.3",
|
|
39
39
|
"multer": "^2.1.1",
|