@adminforth/agent 1.43.29 → 1.44.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.
Files changed (39) hide show
  1. package/agentEvents.ts +66 -0
  2. package/agentResponseEvents.ts +1 -206
  3. package/build.log +2 -2
  4. package/custom/conversation_area/ProcessingTimeline.vue +23 -2
  5. package/custom/incremark_code_renderers/IncremarkShikiCodeBlock.vue +2 -2
  6. package/custom/types.ts +5 -4
  7. package/dist/agent/checkpointer.d.ts +29 -0
  8. package/dist/agent/languageDetect.d.ts +10 -0
  9. package/dist/agent/middleware/apiBasedTools.d.ts +3 -0
  10. package/dist/agent/middleware/openAiResponsesContinuation.d.ts +1 -0
  11. package/dist/agent/middleware/sequenceDebug.d.ts +46 -0
  12. package/dist/agent/simpleAgent.d.ts +61 -0
  13. package/dist/agent/skills/registry.d.ts +13 -0
  14. package/dist/agent/systemPrompt.d.ts +11 -0
  15. package/dist/agent/toolCallEvents.d.ts +27 -0
  16. package/dist/agent/tools/apiTool.d.ts +6 -0
  17. package/dist/agent/tools/fetchSkill.d.ts +8 -0
  18. package/dist/agent/tools/fetchToolSchema.d.ts +9 -0
  19. package/dist/agent/tools/getUserLocation.d.ts +8 -0
  20. package/dist/agent/tools/index.d.ts +4 -0
  21. package/dist/agentEvents.d.ts +56 -0
  22. package/dist/agentEvents.js +1 -0
  23. package/dist/agentResponseEvents.d.ts +1 -0
  24. package/dist/agentResponseEvents.js +1 -144
  25. package/dist/apiBasedTools.d.ts +29 -0
  26. package/dist/custom/conversation_area/ProcessingTimeline.vue +23 -2
  27. package/dist/custom/incremark_code_renderers/IncremarkShikiCodeBlock.vue +2 -2
  28. package/dist/custom/types.ts +5 -4
  29. package/dist/index.d.ts +58 -0
  30. package/dist/index.js +280 -48
  31. package/dist/sanitizeSpeechText.d.ts +1 -0
  32. package/dist/surfaces/web-sse/createSseEventEmitter.d.ts +14 -0
  33. package/dist/surfaces/web-sse/createSseEventEmitter.js +211 -0
  34. package/dist/types.d.ts +94 -0
  35. package/index.ts +315 -46
  36. package/package.json +2 -2
  37. package/surfaces/web-sse/createSseEventEmitter.ts +278 -0
  38. package/tsconfig.json +1 -0
  39. package/types.ts +6 -0
package/index.ts CHANGED
@@ -1,4 +1,12 @@
1
- import type { AdminUser, AdminForthResource, IAdminForth, IHttpServer } from "adminforth";
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 { createAgentEventStream } from "./agentResponseEvents.js";
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
- emitReasoningDelta?: (delta: string) => void;
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(),
@@ -76,6 +89,9 @@ const createSessionBodySchema = z.object({
76
89
  triggerMessage: z.string().optional(),
77
90
  }).strict();
78
91
 
92
+ const VEGA_LITE_FENCE_START = "```vega-lite";
93
+ const COMPLETE_VEGA_LITE_BLOCK_RE = /```vega-lite[\s\S]*?```/;
94
+
79
95
  function isAbortError(error: unknown): boolean {
80
96
  return (
81
97
  error instanceof DOMException && error.name === "AbortError"
@@ -154,6 +170,33 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
154
170
  }));
155
171
  }
156
172
 
173
+ private getChatSurfaceSessionId(incoming: ChatSurfaceIncomingMessage) {
174
+ return `${incoming.surface}:${incoming.externalConversationId}`;
175
+ }
176
+
177
+ private async getOrCreateChatSurfaceSession(
178
+ incoming: ChatSurfaceIncomingMessage,
179
+ adminUser: AdminUser,
180
+ ) {
181
+ const sessionId = this.getChatSurfaceSessionId(incoming);
182
+ const sessionResource = this.adminforth.resource(this.options.sessionResource.resourceId);
183
+ const session = await sessionResource.get(
184
+ [Filters.EQ(this.options.sessionResource.idField, sessionId)]
185
+ );
186
+
187
+ if (session) {
188
+ return sessionId;
189
+ }
190
+
191
+ await sessionResource.create({
192
+ [this.options.sessionResource.idField]: sessionId,
193
+ [this.options.sessionResource.titleField]: incoming.prompt.slice(0, 40) || "New Session",
194
+ [this.options.sessionResource.askerIdField]: adminUser.pk,
195
+ });
196
+
197
+ return sessionId;
198
+ }
199
+
157
200
  private getCheckpointer() {
158
201
  if (this.checkpointer) return this.checkpointer;
159
202
 
@@ -223,6 +266,9 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
223
266
 
224
267
  validateConfigAfterDiscover(adminforth: IAdminForth, resourceConfig: AdminForthResource) {
225
268
  this.options.audioAdapter?.validate();
269
+ for (const chatSurfaceAdapter of this.options.chatSurfaceAdapters ?? []) {
270
+ chatSurfaceAdapter.validate();
271
+ }
226
272
  this.agentSystemPromptPromise = buildAgentSystemPrompt(
227
273
  adminforth,
228
274
  this.getInternalAgentResourceIds(),
@@ -236,6 +282,8 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
236
282
 
237
283
  private async runAgentTurn(input: AgentTurnRunInput) {
238
284
  let fullResponse = "";
285
+ let bufferedTextDelta = "";
286
+ let isRenderingVegaLite = false;
239
287
  const maxTokens = this.options.maxTokens ?? 1000;
240
288
  const selectedMode = this.options.modes.find((mode) => mode.name === input.modeName) ?? this.options.modes[0];
241
289
  const [primaryModelSpec, summaryModelSpec] = await Promise.all([
@@ -295,7 +343,10 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
295
343
  abortSignal: input.abortSignal,
296
344
  emitToolCallEvent: (event) => {
297
345
  input.sequenceDebugCollector.handleToolCallEvent(event);
298
- input.emitToolCallEvent?.(event);
346
+ void input.emit?.({
347
+ type: "tool-call",
348
+ data: event,
349
+ });
299
350
  },
300
351
  sequenceDebugSink: input.sequenceDebugCollector,
301
352
  });
@@ -332,15 +383,71 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
332
383
  .join("");
333
384
 
334
385
  if (reasoningDelta) {
335
- input.emitReasoningDelta?.(reasoningDelta);
386
+ await input.emit?.({
387
+ type: "reasoning-delta",
388
+ delta: reasoningDelta,
389
+ });
336
390
  }
337
391
 
338
392
  if (textDelta) {
339
393
  fullResponse += textDelta;
340
- input.emitTextDelta?.(textDelta);
394
+ bufferedTextDelta += textDelta;
395
+
396
+ if (
397
+ bufferedTextDelta.includes(VEGA_LITE_FENCE_START) &&
398
+ !COMPLETE_VEGA_LITE_BLOCK_RE.test(bufferedTextDelta)
399
+ ) {
400
+ if (!isRenderingVegaLite) {
401
+ isRenderingVegaLite = true;
402
+ await input.emit?.({
403
+ type: "rendering",
404
+ phase: "start",
405
+ label: "Rendering...",
406
+ });
407
+ }
408
+ continue;
409
+ }
410
+
411
+ if (isRenderingVegaLite) {
412
+ isRenderingVegaLite = false;
413
+ await input.emit?.({
414
+ type: "rendering",
415
+ phase: "end",
416
+ label: "Rendering...",
417
+ });
418
+ }
419
+
420
+ const streamableLength = bufferedTextDelta.includes(VEGA_LITE_FENCE_START)
421
+ ? bufferedTextDelta.length
422
+ : bufferedTextDelta.length - getPartialVegaLiteFenceStartLength(bufferedTextDelta);
423
+
424
+ if (!streamableLength) {
425
+ continue;
426
+ }
427
+
428
+ await input.emit?.({
429
+ type: "text-delta",
430
+ delta: bufferedTextDelta.slice(0, streamableLength),
431
+ });
432
+ bufferedTextDelta = bufferedTextDelta.slice(streamableLength);
341
433
  }
342
434
  }
343
435
 
436
+ if (isRenderingVegaLite) {
437
+ await input.emit?.({
438
+ type: "rendering",
439
+ phase: "end",
440
+ label: "Rendering...",
441
+ });
442
+ }
443
+
444
+ if (bufferedTextDelta) {
445
+ await input.emit?.({
446
+ type: "text-delta",
447
+ delta: bufferedTextDelta,
448
+ });
449
+ }
450
+
344
451
  return {
345
452
  text: fullResponse,
346
453
  };
@@ -369,9 +476,7 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
369
476
  abortSignal: input.abortSignal,
370
477
  adminUser: input.adminUser,
371
478
  sequenceDebugCollector,
372
- emitToolCallEvent: input.emitToolCallEvent,
373
- emitReasoningDelta: input.emitReasoningDelta,
374
- emitTextDelta: input.emitTextDelta,
479
+ emit: input.emit,
375
480
  });
376
481
  fullResponse = agentResponse.text;
377
482
  } catch (error) {
@@ -382,7 +487,6 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
382
487
  failed = true;
383
488
  fullResponse = getErrorMessage(error);
384
489
  logger.error(`${input.failureLogMessage}:\n${fullResponse}`);
385
- input.emitErrorResponse?.(fullResponse);
386
490
  }
387
491
  }
388
492
 
@@ -405,7 +509,134 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
405
509
  };
406
510
  }
407
511
 
512
+ async handleTurn(input: HandleTurnInput) {
513
+ await input.emit({
514
+ type: "turn-started",
515
+ messageId: randomUUID(),
516
+ });
517
+
518
+ const agentResponse = await this.runAndPersistAgentResponse({
519
+ prompt: input.prompt,
520
+ sessionId: input.sessionId,
521
+ modeName: input.modeName,
522
+ userTimeZone: input.userTimeZone,
523
+ currentPage: input.currentPage,
524
+ abortSignal: input.abortSignal,
525
+ adminUser: input.adminUser,
526
+ emit: input.emit,
527
+ failureLogMessage: input.failureLogMessage ?? "Agent response failed",
528
+ abortLogMessage: input.abortLogMessage ?? "Agent response aborted",
529
+ });
530
+
531
+ if (agentResponse.failed) {
532
+ await input.emit({
533
+ type: "error",
534
+ error: agentResponse.text,
535
+ });
536
+ } else if (!agentResponse.aborted) {
537
+ await input.emit({
538
+ type: "response",
539
+ text: agentResponse.text,
540
+ sessionId: input.sessionId,
541
+ turnId: agentResponse.turnId,
542
+ });
543
+ }
544
+
545
+ await input.emit({
546
+ type: "finish",
547
+ });
548
+
549
+ return agentResponse;
550
+ }
551
+
552
+ private createChatSurfaceEventEmitter(sink: ChatSurfaceEventSink): AgentEventEmitter {
553
+ return async (event) => {
554
+ if (event.type === "text-delta") {
555
+ await sink.emit({
556
+ type: "text_delta",
557
+ delta: event.delta,
558
+ });
559
+ return;
560
+ }
561
+
562
+ if (event.type === "response") {
563
+ await sink.emit({
564
+ type: "done",
565
+ text: event.text,
566
+ });
567
+ return;
568
+ }
569
+
570
+ if (event.type === "error") {
571
+ await sink.emit({
572
+ type: "error",
573
+ message: event.error,
574
+ });
575
+ }
576
+ };
577
+ }
578
+
579
+ private async handleChatSurfaceMessage(
580
+ adapter: ChatSurfaceAdapter,
581
+ incoming: ChatSurfaceIncomingMessage,
582
+ sink: ChatSurfaceEventSink,
583
+ ) {
584
+ const adminUser = await adapter.resolveAdminUser({
585
+ adminforth: this.adminforth,
586
+ incoming,
587
+ });
588
+
589
+ if (!adminUser) {
590
+ await sink.emit({
591
+ type: "error",
592
+ message: "This chat account is not authorized to use AdminForth Agent.",
593
+ });
594
+ return;
595
+ }
596
+
597
+ await this.handleTurn({
598
+ prompt: incoming.prompt,
599
+ sessionId: await this.getOrCreateChatSurfaceSession(incoming, adminUser),
600
+ modeName: incoming.modeName,
601
+ userTimeZone: incoming.userTimeZone ?? "UTC",
602
+ adminUser,
603
+ emit: this.createChatSurfaceEventEmitter(sink),
604
+ failureLogMessage: `Agent ${incoming.surface} surface response failed`,
605
+ abortLogMessage: `Agent ${incoming.surface} surface response aborted`,
606
+ });
607
+ }
608
+
408
609
  setupEndpoints(server: IHttpServer) {
610
+ for (const adapter of this.options.chatSurfaceAdapters ?? []) {
611
+ server.endpoint({
612
+ method: "POST",
613
+ noAuth: true,
614
+ path: `/agent/surface/${adapter.name}/webhook`,
615
+ handler: async (ctx) => {
616
+ const surfaceContext = {
617
+ body: ctx.body,
618
+ headers: ctx.headers,
619
+ abortSignal: ctx.abortSignal,
620
+ rawRequest: ctx._raw_express_req,
621
+ rawResponse: ctx._raw_express_res,
622
+ };
623
+ const incoming = await adapter.parseIncomingMessage(surfaceContext);
624
+
625
+ if (!incoming) return { ok: true };
626
+
627
+ const sink = await adapter.createEventSink(surfaceContext, incoming);
628
+
629
+ try {
630
+ await this.handleChatSurfaceMessage(adapter, incoming, sink);
631
+ } finally {
632
+ await sink.close?.();
633
+ }
634
+
635
+ return { ok: true };
636
+ },
637
+ });
638
+ }
639
+
409
640
  server.endpoint({
410
641
  method: 'POST',
411
642
  path: `/agent/get-placeholder-messages`,
@@ -435,11 +666,12 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
435
666
  const currentAdminUser = requireAdminUser(adminUser);
436
667
  const data = this.parseBody(agentResponseBodySchema, body, response);
437
668
  if (!data) return;
438
- const stream = createAgentEventStream(_raw_express_res, {vercelAiUiMessageStream: true, closeActiveBlockOnToolStart: true});
439
- const messageId = randomUUID();
669
+ const emit = createSseEventEmitter(_raw_express_res, {
670
+ vercelAiUiMessageStream: true,
671
+ closeActiveBlockOnToolStart: true,
672
+ });
440
673
 
441
- stream.start(messageId);
442
- await this.runAndPersistAgentResponse({
674
+ await this.handleTurn({
443
675
  prompt: data.message,
444
676
  sessionId: data.sessionId,
445
677
  modeName: data.mode,
@@ -447,14 +679,10 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
447
679
  currentPage: data.currentPage,
448
680
  abortSignal,
449
681
  adminUser: currentAdminUser,
450
- emitToolCallEvent: stream.toolCall,
451
- emitReasoningDelta: stream.reasoningDelta,
452
- emitTextDelta: stream.textDelta,
453
- emitErrorResponse: stream.textDelta,
682
+ emit,
454
683
  failureLogMessage: "Agent response streaming failed",
455
684
  abortLogMessage: "Agent response streaming aborted by the client",
456
685
  });
457
- stream.end();
458
686
  return null;
459
687
  }
460
688
  });
@@ -476,7 +704,7 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
476
704
  response.setStatus(400, "Audio file is required");
477
705
  return { error: "Audio file is required" };
478
706
  }
479
- const stream = createAgentEventStream(_raw_express_res);
707
+ const emit = createSseEventEmitter(_raw_express_res);
480
708
 
481
709
  let transcription;
482
710
 
@@ -491,28 +719,38 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
491
719
  } catch (error) {
492
720
  if (abortSignal.aborted || isAbortError(error)) {
493
721
  logger.info("Agent speech transcription aborted by the client");
494
- stream.end();
722
+ await emit({ type: "finish" });
495
723
  return null;
496
724
  }
497
725
 
498
726
  logger.error(`Agent speech transcription failed:\n${getErrorMessage(error)}`);
499
- stream.error("Speech transcription failed. Check server logs for details.");
500
- stream.end();
727
+ await emit({
728
+ type: "error",
729
+ error: "Speech transcription failed. Check server logs for details.",
730
+ });
731
+ await emit({ type: "finish" });
501
732
  return null;
502
733
  }
503
734
 
504
735
  if (abortSignal.aborted) {
505
- stream.end();
736
+ await emit({ type: "finish" });
506
737
  return null;
507
738
  }
508
739
 
509
740
  const prompt = transcription.text;
510
741
  if (!prompt) {
511
- stream.error("Speech transcription is empty");
512
- stream.end();
742
+ await emit({
743
+ type: "error",
744
+ error: "Speech transcription is empty",
745
+ });
746
+ await emit({ type: "finish" });
513
747
  return null;
514
748
  }
515
- stream.transcript(transcription.text, transcription.language);
749
+ await emit({
750
+ type: "transcript",
751
+ text: transcription.text,
752
+ language: transcription.language,
753
+ });
516
754
 
517
755
  const sessionId = data.sessionId as string;
518
756
  const currentPage = data.currentPage;
@@ -524,34 +762,42 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
524
762
  currentPage,
525
763
  abortSignal,
526
764
  adminUser: currentAdminUser,
527
- emitToolCallEvent: stream.toolCall,
765
+ emit: async (event) => {
766
+ if (event.type === "tool-call") {
767
+ await emit(event);
768
+ }
769
+ },
528
770
  failureLogMessage: "Agent speech response failed",
529
771
  abortLogMessage: "Agent speech response aborted by the client",
530
772
  });
531
773
 
532
774
  if (agentResponse.aborted) {
533
- stream.end();
775
+ await emit({ type: "finish" });
534
776
  return null;
535
777
  }
536
778
 
537
779
  if (agentResponse.failed) {
538
- stream.error(agentResponse.text);
539
- stream.end();
780
+ await emit({
781
+ type: "error",
782
+ error: agentResponse.text,
783
+ });
784
+ await emit({ type: "finish" });
540
785
  return null;
541
786
  }
542
787
 
543
788
  try {
544
- stream.speechResponse(
545
- {
789
+ await emit({
790
+ type: "speech-response",
791
+ transcript: {
546
792
  text: transcription.text,
547
793
  language: transcription.language,
548
794
  },
549
- {
795
+ response: {
550
796
  text: agentResponse.text,
551
797
  },
552
798
  sessionId,
553
- agentResponse.turnId,
554
- );
799
+ turnId: agentResponse.turnId,
800
+ });
555
801
  const speech = await audioAdapter.synthesize({
556
802
  text: sanitizeSpeechText(agentResponse.text),
557
803
  stream: true,
@@ -560,7 +806,14 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
560
806
  abortSignal,
561
807
  });
562
808
 
563
- stream.audioStart(speech.mimeType, speech.format, 24000, 1, 16);
809
+ await emit({
810
+ type: "audio-start",
811
+ mimeType: speech.mimeType,
812
+ format: speech.format,
813
+ sampleRate: 24000,
814
+ channelCount: 1,
815
+ bitsPerSample: 16,
816
+ });
564
817
 
565
818
  const reader = speech.audioStream.getReader();
566
819
  const cancelAudioStream = () => {
@@ -586,24 +839,30 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
586
839
  break;
587
840
  }
588
841
 
589
- stream.audioDelta(value);
842
+ await emit({
843
+ type: "audio-delta",
844
+ value,
845
+ });
590
846
  }
591
847
  } finally {
592
848
  abortSignal.removeEventListener("abort", cancelAudioStream);
593
849
  reader.releaseLock();
594
850
  }
595
851
 
596
- stream.audioDone();
597
- stream.end();
852
+ await emit({ type: "audio-done" });
853
+ await emit({ type: "finish" });
598
854
  return null;
599
855
  } catch (error) {
600
856
  if (abortSignal.aborted || isAbortError(error)) {
601
857
  logger.info("Agent speech audio streaming aborted by the client");
602
858
  } else {
603
859
  logger.error(`Agent speech audio streaming failed:\n${error}`);
604
- stream.error(getErrorMessage(error));
860
+ await emit({
861
+ type: "error",
862
+ error: getErrorMessage(error),
863
+ });
605
864
  }
606
- stream.end();
865
+ await emit({ type: "finish" });
607
866
  return null;
608
867
  }
609
868
  }
@@ -752,3 +1011,13 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
752
1011
  })
753
1012
  }
754
1013
  }
1014
+
1015
+ function getPartialVegaLiteFenceStartLength(text: string): number {
1016
+ for (let length = Math.min(text.length, VEGA_LITE_FENCE_START.length - 1); length > 0; length -= 1) {
1017
+ if (VEGA_LITE_FENCE_START.startsWith(text.slice(-length))) {
1018
+ return length;
1019
+ }
1020
+ }
1021
+
1022
+ return 0;
1023
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adminforth/agent",
3
- "version": "1.43.29",
3
+ "version": "1.44.1",
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": "^2.53.5",
36
+ "adminforth": ">=2.54.0",
37
37
  "dayjs": "^1.11.20",
38
38
  "langchain": "^1.3.3",
39
39
  "multer": "^2.1.1",