Andrew commited on
Commit
a2bcf5b
·
1 Parent(s): f41db77

(fix) Stabilize persona card thinking display

Browse files
src/lib/components/chat/PersonaResponseCards.svelte CHANGED
@@ -1,12 +1,13 @@
1
  <script lang="ts">
2
  import type { PersonaResponse } from "$lib/types/Message";
3
- import MarkdownRenderer from "./MarkdownRenderer.svelte";
4
- import OpenReasoningResults from "./OpenReasoningResults.svelte";
5
- import CopyToClipBoardBtn from "../CopyToClipBoardBtn.svelte";
6
- import CarbonRotate360 from "~icons/carbon/rotate-360";
7
- import CarbonChevronDown from "~icons/carbon/chevron-down";
8
- import CarbonChevronUp from "~icons/carbon/chevron-up";
9
- import { THINK_BLOCK_REGEX } from "$lib/constants/thinkBlockRegex";
 
10
  import { goto } from "$app/navigation";
11
  import { base } from "$app/paths";
12
 
@@ -31,7 +32,7 @@
31
 
32
  // Check if content has <think> blocks
33
  function hasClientThink(content: string | undefined): boolean {
34
- return content ? THINK_BLOCK_REGEX.test(content) : false;
35
  }
36
 
37
  // Check if content has overflow
@@ -91,28 +92,28 @@
91
  class="mt-2"
92
  style={isExpanded ? '' : `max-height: ${MAX_COLLAPSED_HEIGHT}px; overflow: hidden;`}
93
  >
94
- {#if hasClientThink(response.content)}
95
- {#each response.content.split(THINK_BLOCK_REGEX) as part, _i}
96
- {#if part && part.startsWith("<think>")}
97
- {@const isClosed = part.endsWith("</think>")}
98
- {@const thinkContent = part.slice(7, isClosed ? -8 : undefined)}
99
- {@const summary = isClosed
100
- ? thinkContent.trim().split(/\n+/)[0] || "Reasoning"
101
- : "Thinking..."}
102
-
103
- <OpenReasoningResults
104
- {summary}
105
- content={thinkContent}
106
- loading={loading && !isClosed}
107
- />
108
- {:else if part && part.trim().length > 0}
109
- <div
110
- class="prose max-w-none dark:prose-invert max-sm:prose-sm prose-headings:font-semibold prose-h1:text-lg prose-h2:text-base prose-h3:text-base prose-pre:bg-gray-800 dark:prose-pre:bg-gray-900"
111
- >
112
- <MarkdownRenderer content={part} {loading} />
113
- </div>
114
  {/if}
115
- {/each}
 
 
 
 
 
 
 
116
  {:else}
117
  <div
118
  class="prose max-w-none dark:prose-invert max-sm:prose-sm prose-headings:font-semibold prose-h1:text-lg prose-h2:text-base prose-h3:text-base prose-pre:bg-gray-800 dark:prose-pre:bg-gray-900"
 
1
  <script lang="ts">
2
  import type { PersonaResponse } from "$lib/types/Message";
3
+ import MarkdownRenderer from "./MarkdownRenderer.svelte";
4
+ import OpenReasoningResults from "./OpenReasoningResults.svelte";
5
+ import CopyToClipBoardBtn from "../CopyToClipBoardBtn.svelte";
6
+ import CarbonRotate360 from "~icons/carbon/rotate-360";
7
+ import CarbonChevronDown from "~icons/carbon/chevron-down";
8
+ import CarbonChevronUp from "~icons/carbon/chevron-up";
9
+ import ThinkingPlaceholder from "./ThinkingPlaceholder.svelte";
10
+ import { hasThinkSegments, splitThinkSegments } from "$lib/utils/stripThinkBlocks";
11
  import { goto } from "$app/navigation";
12
  import { base } from "$app/paths";
13
 
 
32
 
33
  // Check if content has <think> blocks
34
  function hasClientThink(content: string | undefined): boolean {
35
+ return content ? hasThinkSegments(content) : false;
36
  }
37
 
38
  // Check if content has overflow
 
92
  class="mt-2"
93
  style={isExpanded ? '' : `max-height: ${MAX_COLLAPSED_HEIGHT}px; overflow: hidden;`}
94
  >
95
+ {#if hasClientThink(response.content)}
96
+ {@const segments = splitThinkSegments(response.content ?? "")}
97
+ {#each segments as part, _i}
98
+ {#if part && part.startsWith("<think>")}
99
+ {@const trimmed = part.trimEnd()}
100
+ {@const isClosed = trimmed.endsWith("</think>")}
101
+
102
+ {#if isClosed}
103
+ {@const thinkContent = trimmed.slice(7, -8)}
104
+ {@const summary = thinkContent.trim().split(/\n+/)[0] || "Reasoning"}
105
+ <OpenReasoningResults {summary} content={thinkContent} loading={false} />
106
+ {:else}
107
+ <ThinkingPlaceholder />
 
 
 
 
 
 
 
108
  {/if}
109
+ {:else if part && part.trim().length > 0}
110
+ <div
111
+ class="prose max-w-none dark:prose-invert max-sm:prose-sm prose-headings:font-semibold prose-h1:text-lg prose-h2:text-base prose-h3:text-base prose-pre:bg-gray-800 dark:prose-pre:bg-gray-900"
112
+ >
113
+ <MarkdownRenderer content={part} {loading} />
114
+ </div>
115
+ {/if}
116
+ {/each}
117
  {:else}
118
  <div
119
  class="prose max-w-none dark:prose-invert max-sm:prose-sm prose-headings:font-semibold prose-h1:text-lg prose-h2:text-base prose-h3:text-base prose-pre:bg-gray-800 dark:prose-pre:bg-gray-900"