@hef2024/llmasaservice-ui 0.25.0 → 0.25.2

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.
@@ -516,7 +516,69 @@ const parseCallMessages = (rawMessages: unknown): TranscriptMessage[] => {
516
516
  };
517
517
 
518
518
  const shouldSkipTranscriptMessage = (message: TranscriptMessage): boolean => {
519
- return message.role === 'system' || (message.role === 'user' && message.content.startsWith('__system__:'));
519
+ const normalizedContent = message.content.trim().toLowerCase();
520
+ const isInternalContinuationPrompt =
521
+ message.role === 'user' &&
522
+ normalizedContent.startsWith('original request:') &&
523
+ normalizedContent.includes('tool execution summary for the previous request:');
524
+ return (
525
+ message.role === 'system' ||
526
+ (message.role === 'user' && message.content.startsWith('__system__:')) ||
527
+ isInternalContinuationPrompt
528
+ );
529
+ };
530
+
531
+ const looksLikeToolStubResponse = (value: string): boolean => {
532
+ const text = value.trim();
533
+ if (!text) return false;
534
+ return (
535
+ text.includes('"type":"tool_use"') ||
536
+ text.includes('"type": "tool_use"') ||
537
+ text.includes('"type":"function"') ||
538
+ text.includes('"type": "function"')
539
+ );
540
+ };
541
+
542
+ const pickMoreCompleteResponse = (primaryResponse: string, fallbackResponse: string): string => {
543
+ const primary = primaryResponse.trim();
544
+ const fallback = fallbackResponse.trim();
545
+ if (!fallback) return primary;
546
+ if (!primary) return fallback;
547
+ if (primary === fallback) return primary;
548
+
549
+ if (looksLikeToolStubResponse(primary) && !looksLikeToolStubResponse(fallback)) {
550
+ return fallback;
551
+ }
552
+
553
+ if (fallback.startsWith(primary) || fallback.length > primary.length + 40) {
554
+ return fallback;
555
+ }
556
+
557
+ return primary;
558
+ };
559
+
560
+ const mergeContinuationResponse = (baseResponse: string, continuationResponse: string): string => {
561
+ const base = baseResponse.trim();
562
+ const continuation = continuationResponse.trim();
563
+ if (!base) return continuation;
564
+ if (!continuation) return base;
565
+
566
+ if (looksLikeToolStubResponse(base) && !looksLikeToolStubResponse(continuation)) {
567
+ return continuation;
568
+ }
569
+
570
+ if (base.includes(continuation)) {
571
+ return base;
572
+ }
573
+
574
+ const maxOverlap = Math.min(base.length, continuation.length);
575
+ for (let overlap = maxOverlap; overlap > 0; overlap -= 1) {
576
+ if (base.slice(-overlap) === continuation.slice(0, overlap)) {
577
+ return `${base}${continuation.slice(overlap)}`;
578
+ }
579
+ }
580
+
581
+ return `${base}\n\n${continuation}`;
520
582
  };
521
583
 
522
584
  const parseTimestampMs = (value: unknown): number | null => {
@@ -626,14 +688,21 @@ const buildTurnsFromMessages = (
626
688
  if (!prompt) continue;
627
689
 
628
690
  let response = '';
691
+ let lastAssistantIndex = -1;
629
692
  let reachedNextUser = false;
630
693
  for (let lookAhead = index + 1; lookAhead < messages.length; lookAhead += 1) {
631
694
  const nextMessage = messages[lookAhead];
632
695
  if (!nextMessage) continue;
633
696
  if (nextMessage.role === 'assistant') {
634
- response = nextMessage.content.trim();
635
- index = lookAhead;
636
- break;
697
+ const assistantResponse = nextMessage.content.trim();
698
+ if (assistantResponse) {
699
+ // Keep scanning until the next user turn so transcript replay stores
700
+ // the final assistant output for this user prompt (post-tool result),
701
+ // not just the first assistant placeholder/tool-call message.
702
+ response = assistantResponse;
703
+ lastAssistantIndex = lookAhead;
704
+ }
705
+ continue;
637
706
  }
638
707
  if (nextMessage.role === 'user') {
639
708
  reachedNextUser = true;
@@ -641,9 +710,14 @@ const buildTurnsFromMessages = (
641
710
  }
642
711
  }
643
712
 
644
- // Only pair fallback response with the final unresolved user message for this call.
645
- if (!response && !reachedNextUser) {
646
- response = fallbackResponse;
713
+ if (lastAssistantIndex >= 0) {
714
+ index = lastAssistantIndex;
715
+ }
716
+
717
+ // For the final user turn in a call, prefer the call-level fallback response
718
+ // when it is clearly more complete than the in-message assistant stub.
719
+ if (!reachedNextUser) {
720
+ response = pickMoreCompleteResponse(response, fallbackResponse);
647
721
  }
648
722
 
649
723
  if (!response) continue;
@@ -700,6 +774,18 @@ const buildTranscriptTurnsFromCalls = (calls: Record<string, unknown>[]): Transc
700
774
  timestampMs,
701
775
  },
702
776
  ];
777
+ } else if (fallbackResponse && mergedTurns.length > 0) {
778
+ const previousTurn = mergedTurns[mergedTurns.length - 1]!;
779
+ mergedTurns = [
780
+ ...mergedTurns.slice(0, -1),
781
+ {
782
+ ...previousTurn,
783
+ response: mergeContinuationResponse(previousTurn.response, fallbackResponse),
784
+ callId: callId || previousTurn.callId,
785
+ timestampMs: Math.max(previousTurn.timestampMs, timestampMs),
786
+ },
787
+ ];
788
+ continue;
703
789
  }
704
790
  }
705
791