@hef2024/llmasaservice-ui 0.24.4 → 0.24.6

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/index.ts CHANGED
@@ -23,7 +23,14 @@ export type {
23
23
  // Import and export AIChatPanel (shadcn-style chat interface)
24
24
  import AIChatPanel from './src/AIChatPanel';
25
25
  export { AIChatPanel };
26
- export type { AIChatPanelProps } from './src/AIChatPanel';
26
+ export type {
27
+ AIChatPanelProps,
28
+ AIChatHistoryEntry,
29
+ ArtifactBlockType,
30
+ PlanningStep,
31
+ PlanningStepStatus,
32
+ ResponseArtifactBlock,
33
+ } from './src/AIChatPanel';
27
34
 
28
35
  // Export hooks
29
36
  export { useAgentRegistry } from './src/hooks/useAgentRegistry';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hef2024/llmasaservice-ui",
3
- "version": "0.24.4",
3
+ "version": "0.24.6",
4
4
  "description": "Prebuilt UI components for LLMAsAService.io",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -2,6 +2,7 @@ import { LLMAsAServiceCustomer } from 'llmasaservice-client';
2
2
  import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
3
3
  import './AIAgentPanel.css';
4
4
  import AIChatPanel, {
5
+ AIChatHistoryEntry,
5
6
  AgentOption,
6
7
  BeforeSendPayload,
7
8
  LocalToolExecutor,
@@ -63,7 +64,7 @@ export interface ActiveConversation {
63
64
  conversationId: string;
64
65
  stableKey: string; // Stable key for React component - never changes
65
66
  agentId: string;
66
- history: Record<string, { content: string; callId: string }>;
67
+ history: Record<string, AIChatHistoryEntry>;
67
68
  transcriptLoaded: boolean; // Prevent re-fetch loops for conversations with empty history
68
69
  isLoading: boolean;
69
70
  title: string;
@@ -134,7 +135,7 @@ export interface AIAgentPanelProps {
134
135
  onAgentSwitch?: (fromAgent: string, toAgent: string) => void;
135
136
  onConversationChange?: (conversationId: string) => void;
136
137
  onBeforeSend?: (payload: BeforeSendPayload) => Promise<void> | void;
137
- historyChangedCallback?: (history: Record<string, { content: string; callId: string }>) => void;
138
+ historyChangedCallback?: (history: Record<string, AIChatHistoryEntry>) => void;
138
139
  responseCompleteCallback?: (callId: string, prompt: string, response: string) => void;
139
140
  thumbsUpClick?: (callId: string) => void;
140
141
  thumbsDownClick?: (callId: string) => void;
@@ -708,8 +709,8 @@ const buildTranscriptTurnsFromCalls = (calls: Record<string, unknown>[]): Transc
708
709
 
709
710
  const buildHistoryFromTranscriptTurns = (
710
711
  turns: TranscriptTurn[],
711
- ): Record<string, { content: string; callId: string }> => {
712
- const history: Record<string, { content: string; callId: string }> = {};
712
+ ): Record<string, AIChatHistoryEntry> => {
713
+ const history: Record<string, AIChatHistoryEntry> = {};
713
714
  const keyUsageByPrompt = new Map<string, number>();
714
715
 
715
716
  turns.forEach((turn, index) => {
@@ -740,9 +741,86 @@ const truncatePromptForTitle = (prompt: string): string => {
740
741
  return prompt;
741
742
  };
742
743
 
744
+ const stripHistoryPromptTimestamp = (prompt: string): string => {
745
+ const isoMatch = prompt.match(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z:(.+)/);
746
+ if (isoMatch && isoMatch[1]) {
747
+ return isoMatch[1];
748
+ }
749
+
750
+ return prompt.replace(/^\d+:/, '');
751
+ };
752
+
753
+ const upsertConversationSummary = (
754
+ conversations: APIConversationSummary[],
755
+ summary: APIConversationSummary,
756
+ ): APIConversationSummary[] => {
757
+ const normalizedSummary = normalizeConversationListPayload([summary])[0];
758
+ if (!normalizedSummary) {
759
+ return conversations;
760
+ }
761
+
762
+ const dedupedById = new Map<string, APIConversationSummary>();
763
+ for (const conv of conversations) {
764
+ dedupedById.set(conv.conversationId, conv);
765
+ }
766
+
767
+ const existing = dedupedById.get(normalizedSummary.conversationId);
768
+ const existingUpdatedAt = existing ? new Date(existing.updatedAt).getTime() : 0;
769
+ const incomingUpdatedAt = new Date(normalizedSummary.updatedAt).getTime();
770
+ const preferIncoming = !existing || incomingUpdatedAt >= existingUpdatedAt;
771
+ const latest = preferIncoming ? normalizedSummary : existing;
772
+ const fallback = preferIncoming ? existing : normalizedSummary;
773
+
774
+ dedupedById.set(normalizedSummary.conversationId, {
775
+ ...(fallback || {}),
776
+ ...(latest || {}),
777
+ createdAt: existing?.createdAt || normalizedSummary.createdAt,
778
+ updatedAt: latest?.updatedAt || fallback?.updatedAt || normalizedSummary.updatedAt,
779
+ title: latest?.title || fallback?.title || '',
780
+ summary: latest?.summary || fallback?.summary,
781
+ agentId: latest?.agentId || fallback?.agentId,
782
+ messageCount:
783
+ typeof latest?.messageCount === 'number'
784
+ ? latest.messageCount
785
+ : fallback?.messageCount,
786
+ });
787
+
788
+ return Array.from(dedupedById.values()).sort(
789
+ (a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime()
790
+ );
791
+ };
792
+
793
+ const buildOptimisticConversationSummary = (
794
+ conversation: ActiveConversation,
795
+ ): APIConversationSummary | null => {
796
+ const conversationId =
797
+ typeof conversation.conversationId === 'string' ? conversation.conversationId.trim() : '';
798
+ if (!conversationId || conversationId.startsWith('new-')) {
799
+ return null;
800
+ }
801
+
802
+ const historyKeys = Object.keys(conversation.history || {});
803
+ if (historyKeys.length === 0 && conversation.title === 'New conversation') {
804
+ return null;
805
+ }
806
+
807
+ const firstPrompt = historyKeys[0] ? stripHistoryPromptTimestamp(historyKeys[0]) : '';
808
+ const title = truncatePromptForTitle(firstPrompt || conversation.title || 'New conversation');
809
+ const now = new Date().toISOString();
810
+
811
+ return {
812
+ conversationId,
813
+ title,
814
+ createdAt: now,
815
+ updatedAt: now,
816
+ agentId: conversation.agentId,
817
+ messageCount: historyKeys.length > 0 ? historyKeys.length * 2 : undefined,
818
+ };
819
+ };
820
+
743
821
  // Empty arrays/objects to prevent recreating on every render
744
822
  const EMPTY_ARRAY: never[] = [];
745
- const EMPTY_HISTORY: Record<string, { content: string; callId: string }> = {};
823
+ const EMPTY_HISTORY: Record<string, AIChatHistoryEntry> = {};
746
824
 
747
825
  /**
748
826
  * Memoized wrapper for AIChatPanel to prevent unnecessary re-renders
@@ -754,7 +832,7 @@ interface ChatPanelWrapperProps {
754
832
  url: string;
755
833
  theme: 'light' | 'dark';
756
834
  chatPanelData: { key: string; data: string }[];
757
- handleHistoryChanged: (history: Record<string, { content: string; callId: string }>, conversationId?: string) => void;
835
+ handleHistoryChanged: (history: Record<string, AIChatHistoryEntry>, conversationId?: string) => void;
758
836
  handleLoadingChange: (isLoading: boolean, conversationId?: string) => void;
759
837
  responseCompleteCallback?: (callId: string, prompt: string, response: string) => void;
760
838
  thumbsUpClick?: (callId: string) => void;
@@ -867,7 +945,7 @@ const ChatPanelWrapper = (({
867
945
 
868
946
  // Memoize callbacks to prevent recreating on every render
869
947
  const historyCallback = useCallback(
870
- (history: Record<string, { content: string; callId: string }>) => {
948
+ (history: Record<string, AIChatHistoryEntry>) => {
871
949
  handleHistoryChanged(history, activeConv.conversationId);
872
950
  },
873
951
  [handleHistoryChanged, activeConv.conversationId]
@@ -1308,12 +1386,15 @@ const AIAgentPanel = React.forwardRef<AIAgentPanelHandle, AIAgentPanelProps>(({
1308
1386
  agentList,
1309
1387
  } = useAgentRegistry(agentIds, { url, localOverrides });
1310
1388
 
1389
+ const getAgentRef = useRef(getAgent);
1390
+ useEffect(() => {
1391
+ getAgentRef.current = getAgent;
1392
+ }, [getAgent]);
1393
+
1311
1394
  // Ref to track if fetch is in progress (prevents duplicate calls)
1312
1395
  const fetchInProgressRef = useRef(false);
1313
1396
  const loadingTranscriptIdsRef = useRef<Set<string>>(new Set());
1314
-
1315
- // Ref to track the last agent we fetched for
1316
- const lastFetchedAgentRef = useRef<string | null>(null);
1397
+ const [conversationListRefreshNonce, setConversationListRefreshNonce] = useState(0);
1317
1398
 
1318
1399
  // Ref to track which conversations we've checked for prompts
1319
1400
  const checkedPromptsRef = useRef<Set<string>>(new Set());
@@ -1332,6 +1413,43 @@ const AIAgentPanel = React.forwardRef<AIAgentPanelHandle, AIAgentPanelProps>(({
1332
1413
  const currentConversationIdRef = useRef<string | null>(currentConversationId);
1333
1414
  currentConversationIdRef.current = currentConversationId;
1334
1415
 
1416
+ const controlledConversationIdRef = useRef<string | null>(controlledConversationId);
1417
+ controlledConversationIdRef.current = controlledConversationId;
1418
+
1419
+ const requestConversationListRefresh = useCallback(() => {
1420
+ setConversationListRefreshNonce(prev => prev + 1);
1421
+ }, []);
1422
+
1423
+ const upsertApiConversationFromHistory = useCallback(
1424
+ (
1425
+ conversationId: string,
1426
+ history: Record<string, AIChatHistoryEntry>,
1427
+ fallbackTitle?: string,
1428
+ ) => {
1429
+ const firstPromptKey = Object.keys(history)[0];
1430
+ const firstPrompt = firstPromptKey ? stripHistoryPromptTimestamp(firstPromptKey) : '';
1431
+ const title = truncatePromptForTitle(firstPrompt || fallbackTitle || 'New conversation');
1432
+ const messageCount = Object.keys(history).length * 2;
1433
+ const timestamp = new Date().toISOString();
1434
+
1435
+ setApiConversations(prev =>
1436
+ upsertConversationSummary(prev, {
1437
+ conversationId,
1438
+ title,
1439
+ createdAt:
1440
+ prev.find((conversation) => conversation.conversationId === conversationId)?.createdAt ||
1441
+ timestamp,
1442
+ updatedAt: timestamp,
1443
+ agentId:
1444
+ prev.find((conversation) => conversation.conversationId === conversationId)?.agentId ||
1445
+ currentAgentId,
1446
+ messageCount,
1447
+ }),
1448
+ );
1449
+ },
1450
+ [currentAgentId]
1451
+ );
1452
+
1335
1453
  // Centralized conversation selection flow.
1336
1454
  // In controlled mode, we only update local selection for prop-driven updates (notify=false).
1337
1455
  const commitConversationSelection = useCallback(
@@ -1433,7 +1551,7 @@ const AIAgentPanel = React.forwardRef<AIAgentPanelHandle, AIAgentPanelProps>(({
1433
1551
 
1434
1552
  // Use the conversation's agentId if available, otherwise fall back to currentAgentId
1435
1553
  const agentIdToUse = agentIdForConversation || currentAgentId;
1436
- const agentProfile = getAgent(agentIdToUse);
1554
+ const agentProfile = getAgentRef.current(agentIdToUse);
1437
1555
  const projectId = agentProfile?.metadata?.projectId;
1438
1556
 
1439
1557
  if (!apiKey || !projectId) {
@@ -1522,14 +1640,14 @@ const AIAgentPanel = React.forwardRef<AIAgentPanelHandle, AIAgentPanelProps>(({
1522
1640
  return next;
1523
1641
  });
1524
1642
  }
1525
- }, [apiKey, currentAgentId, getAgent]);
1643
+ }, [apiKey, currentAgentId]);
1526
1644
 
1527
1645
  // Fetch conversations from API
1528
- const fetchConversations = useCallback(async (agentId: string, signal?: AbortSignal) => {
1529
- // Get the agent profile to access projectId
1530
- const agentProfile = getAgent(agentId);
1531
- const projectId = agentProfile?.metadata?.projectId;
1532
-
1646
+ const fetchConversations = useCallback(async (
1647
+ agentId: string,
1648
+ projectId: string,
1649
+ signal?: AbortSignal,
1650
+ ) => {
1533
1651
  if (!agentId || !apiKey || !projectId) {
1534
1652
  setApiConversations([]);
1535
1653
  return;
@@ -1563,7 +1681,44 @@ const AIAgentPanel = React.forwardRef<AIAgentPanelHandle, AIAgentPanelProps>(({
1563
1681
  const normalized = normalizeConversationListPayload(payload);
1564
1682
 
1565
1683
  if (!signal?.aborted) {
1566
- setApiConversations(normalized);
1684
+ setApiConversations(prev => {
1685
+ const next = [...normalized];
1686
+ const optimisticIds = new Set<string>();
1687
+
1688
+ const trackedConversationId = controlledConversationIdRef.current;
1689
+ if (trackedConversationId) {
1690
+ optimisticIds.add(trackedConversationId);
1691
+ }
1692
+
1693
+ activeConversationsRef.current.forEach((conversation) => {
1694
+ const optimisticSummary = buildOptimisticConversationSummary(conversation);
1695
+ if (!optimisticSummary) {
1696
+ return;
1697
+ }
1698
+
1699
+ optimisticIds.add(optimisticSummary.conversationId);
1700
+ const existing = prev.find(
1701
+ (candidate) => candidate.conversationId === optimisticSummary.conversationId
1702
+ );
1703
+ next.push({
1704
+ ...optimisticSummary,
1705
+ createdAt: existing?.createdAt || optimisticSummary.createdAt,
1706
+ updatedAt: optimisticSummary.updatedAt,
1707
+ });
1708
+ });
1709
+
1710
+ let merged = normalizeConversationListPayload(next);
1711
+ if (optimisticIds.size > 0) {
1712
+ prev.forEach((conversation) => {
1713
+ if (!optimisticIds.has(conversation.conversationId)) {
1714
+ return;
1715
+ }
1716
+ merged = upsertConversationSummary(merged, conversation);
1717
+ });
1718
+ }
1719
+
1720
+ return merged;
1721
+ });
1567
1722
 
1568
1723
  // Fetch first prompts for Today and Yesterday conversations
1569
1724
  const now = new Date();
@@ -1588,7 +1743,7 @@ const AIAgentPanel = React.forwardRef<AIAgentPanelHandle, AIAgentPanelProps>(({
1588
1743
  setConversationsLoading(false);
1589
1744
  }
1590
1745
  }
1591
- }, [apiKey, customerId, getAgent, fetchFirstPrompt]);
1746
+ }, [apiKey, customerId, fetchFirstPrompt]);
1592
1747
 
1593
1748
  // Helper to strip context/template data from a prompt - keeps only the user's actual message
1594
1749
  // Load a specific conversation's transcript (or switch to it if already active)
@@ -1616,7 +1771,7 @@ const AIAgentPanel = React.forwardRef<AIAgentPanelHandle, AIAgentPanelProps>(({
1616
1771
 
1617
1772
  // Use the conversation's agentId if available, otherwise fall back to currentAgentId
1618
1773
  const agentIdToUse = agentIdForConversation || currentAgentId;
1619
- const agentProfile = getAgent(agentIdToUse);
1774
+ const agentProfile = getAgentRef.current(agentIdToUse);
1620
1775
  const projectId = agentProfile?.metadata?.projectId;
1621
1776
 
1622
1777
  if (!apiKey || !projectId) {
@@ -1711,7 +1866,7 @@ const AIAgentPanel = React.forwardRef<AIAgentPanelHandle, AIAgentPanelProps>(({
1711
1866
  loadingTranscriptIdsRef.current.delete(conversationId);
1712
1867
  setLoadingConversationId(prev => (prev === conversationId ? null : prev));
1713
1868
  }
1714
- }, [apiKey, commitConversationSelection, conversationFirstPrompts, currentAgentId, getAgent]);
1869
+ }, [apiKey, commitConversationSelection, conversationFirstPrompts, currentAgentId]);
1715
1870
 
1716
1871
  // Controlled conversation mode: keep panel selection in sync with external conversation prop.
1717
1872
  useEffect(() => {
@@ -1798,10 +1953,15 @@ const AIAgentPanel = React.forwardRef<AIAgentPanelHandle, AIAgentPanelProps>(({
1798
1953
  ]);
1799
1954
 
1800
1955
 
1956
+ const currentAgentProjectId = useMemo(() => {
1957
+ const agentProfile = getAgent(currentAgentId);
1958
+ return agentProfile?.metadata?.projectId || '';
1959
+ }, [currentAgentId, getAgent]);
1960
+
1801
1961
  // Refresh conversations callback
1802
1962
  const handleRefreshConversations = useCallback(() => {
1803
- fetchConversations(currentAgentId);
1804
- }, [currentAgentId, fetchConversations]);
1963
+ requestConversationListRefresh();
1964
+ }, [requestConversationListRefresh]);
1805
1965
 
1806
1966
  // Fetch conversations on mount and when agent changes
1807
1967
  useEffect(() => {
@@ -1810,17 +1970,21 @@ const AIAgentPanel = React.forwardRef<AIAgentPanelHandle, AIAgentPanelProps>(({
1810
1970
 
1811
1971
  // Only fetch if agents are loaded and we have necessary data
1812
1972
  if (!agentsLoading && currentAgentId && apiKey) {
1813
- // Check if agent is ready (has projectId)
1814
- const agentProfile = getAgent(currentAgentId);
1815
- const projectId = agentProfile?.metadata?.projectId;
1816
-
1817
- // Only fetch once per agent, and only if agent is ready
1818
- if (projectId && lastFetchedAgentRef.current !== currentAgentId) {
1819
- lastFetchedAgentRef.current = currentAgentId;
1820
- fetchConversations(currentAgentId);
1973
+ if (currentAgentProjectId) {
1974
+ const controller = new AbortController();
1975
+ fetchConversations(currentAgentId, currentAgentProjectId, controller.signal);
1976
+ return () => controller.abort();
1821
1977
  }
1822
1978
  }
1823
- }, [agentsLoading, currentAgentId, apiKey, fetchConversations, getAgent, showConversationHistory]);
1979
+ }, [
1980
+ agentsLoading,
1981
+ apiKey,
1982
+ conversationListRefreshNonce,
1983
+ currentAgentId,
1984
+ currentAgentProjectId,
1985
+ fetchConversations,
1986
+ showConversationHistory,
1987
+ ]);
1824
1988
 
1825
1989
  // Start new conversation
1826
1990
  const handleNewConversation = useCallback(() => {
@@ -2273,7 +2437,7 @@ const AIAgentPanel = React.forwardRef<AIAgentPanelHandle, AIAgentPanelProps>(({
2273
2437
 
2274
2438
  // Handle history changes from ChatPanel
2275
2439
  const handleHistoryChanged = useCallback(
2276
- (history: Record<string, { content: string; callId: string }>, conversationId?: string) => {
2440
+ (history: Record<string, AIChatHistoryEntry>, conversationId?: string) => {
2277
2441
  const targetConversationId = conversationId || currentConversationIdRef.current;
2278
2442
 
2279
2443
  // Update active conversation history
@@ -2287,12 +2451,7 @@ const AIAgentPanel = React.forwardRef<AIAgentPanelHandle, AIAgentPanelProps>(({
2287
2451
  if (title === 'New conversation' && Object.keys(history).length > 0) {
2288
2452
  const firstPrompt = Object.keys(history)[0];
2289
2453
  if (firstPrompt) {
2290
- // Strip timestamp prefix
2291
- let cleanPrompt = firstPrompt;
2292
- const isoMatch = cleanPrompt.match(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z:(.+)/);
2293
- if (isoMatch && isoMatch[1]) {
2294
- cleanPrompt = isoMatch[1];
2295
- }
2454
+ const cleanPrompt = stripHistoryPromptTimestamp(firstPrompt);
2296
2455
  title = cleanPrompt.length > 60 ? cleanPrompt.slice(0, 57) + '...' : cleanPrompt;
2297
2456
  }
2298
2457
  }
@@ -2306,6 +2465,13 @@ const AIAgentPanel = React.forwardRef<AIAgentPanelHandle, AIAgentPanelProps>(({
2306
2465
  }
2307
2466
  return prev;
2308
2467
  });
2468
+
2469
+ const existingActiveConversation = activeConversationsRef.current.get(targetConversationId);
2470
+ upsertApiConversationFromHistory(
2471
+ targetConversationId,
2472
+ history,
2473
+ existingActiveConversation?.title,
2474
+ );
2309
2475
  }
2310
2476
 
2311
2477
  // Check for agent handoff suggestion
@@ -2328,9 +2494,11 @@ const AIAgentPanel = React.forwardRef<AIAgentPanelHandle, AIAgentPanelProps>(({
2328
2494
  }
2329
2495
  },
2330
2496
  [
2497
+ activeConversationsRef,
2331
2498
  currentAgentId,
2332
2499
  historyChangedCallback,
2333
2500
  agents,
2501
+ upsertApiConversationFromHistory,
2334
2502
  ]
2335
2503
  );
2336
2504
 
@@ -2342,6 +2510,9 @@ const AIAgentPanel = React.forwardRef<AIAgentPanelHandle, AIAgentPanelProps>(({
2342
2510
  setActiveConversations(prev => {
2343
2511
  const existing = prev.get(targetConversationId);
2344
2512
  if (existing && existing.isLoading !== isLoading) {
2513
+ if (existing.isLoading && !isLoading) {
2514
+ requestConversationListRefresh();
2515
+ }
2345
2516
  const next = new Map(prev);
2346
2517
  next.set(targetConversationId, {
2347
2518
  ...existing,
@@ -2352,7 +2523,7 @@ const AIAgentPanel = React.forwardRef<AIAgentPanelHandle, AIAgentPanelProps>(({
2352
2523
  return prev;
2353
2524
  });
2354
2525
  }
2355
- }, []);
2526
+ }, [requestConversationListRefresh]);
2356
2527
 
2357
2528
  // Handle handoff confirmation
2358
2529
  const handleHandoffConfirm = useCallback(() => {
@@ -2413,7 +2584,8 @@ const AIAgentPanel = React.forwardRef<AIAgentPanelHandle, AIAgentPanelProps>(({
2413
2584
  if (currentConversationIdRef.current === tempId) {
2414
2585
  commitConversationSelection(realId, true);
2415
2586
  }
2416
- }, [commitConversationSelection]);
2587
+ requestConversationListRefresh();
2588
+ }, [commitConversationSelection, requestConversationListRefresh]);
2417
2589
 
2418
2590
  // Toggle collapse - only if collapsible is enabled
2419
2591
  const toggleCollapse = useCallback(() => {
@@ -2700,6 +2700,14 @@
2700
2700
  border-color: var(--thinking-block-accent);
2701
2701
  }
2702
2702
 
2703
+ .thinking-block--planning {
2704
+ --thinking-block-accent: #f59e0b;
2705
+ --thinking-block-bg: #fffbeb;
2706
+ --thinking-block-text: #b45309;
2707
+ background-color: var(--thinking-block-bg);
2708
+ border-color: var(--thinking-block-accent);
2709
+ }
2710
+
2703
2711
  /* Dark theme type-specific */
2704
2712
  .dark-theme .thinking-block--thinking {
2705
2713
  --thinking-block-bg: #1e1b2e;
@@ -2719,6 +2727,12 @@
2719
2727
  --thinking-block-text: #86efac;
2720
2728
  }
2721
2729
 
2730
+ .dark-theme .thinking-block--planning {
2731
+ --thinking-block-bg: #2b2111;
2732
+ --thinking-block-accent: #fbbf24;
2733
+ --thinking-block-text: #fcd34d;
2734
+ }
2735
+
2722
2736
  /* Header (clickable toggle) */
2723
2737
  .thinking-block__header {
2724
2738
  display: flex;