@lvce-editor/chat-view 1.9.0 → 1.11.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.
@@ -1196,8 +1196,8 @@ const settings = i18nString('Settings');
1196
1196
  const closeChat = i18nString('Close Chat');
1197
1197
  const clickToOpenNewChat = i18nString('Click the + button to open a new chat.');
1198
1198
  const startConversation = i18nString('Start a conversation by typing below.');
1199
- const you = i18nString('You');
1200
- const assistant = i18nString('Assistant');
1199
+ i18nString('You');
1200
+ i18nString('Assistant');
1201
1201
  const composePlaceholder = i18nString('Type your message. Enter to send, Shift+Enter for newline.');
1202
1202
  const sendMessage = i18nString('Send message');
1203
1203
  const send = i18nString('Send');
@@ -1245,7 +1245,10 @@ const createDefaultState = () => {
1245
1245
  messages: [],
1246
1246
  title: defaultSessionTitle
1247
1247
  }],
1248
+ tokensMax: 0,
1249
+ tokensUsed: 0,
1248
1250
  uid: 0,
1251
+ usageOverviewEnabled: false,
1249
1252
  viewMode: 'list',
1250
1253
  warningCount: 0,
1251
1254
  width: 0,
@@ -1289,7 +1292,7 @@ const diffFocus = (oldState, newState) => {
1289
1292
  };
1290
1293
 
1291
1294
  const isEqual = (oldState, newState) => {
1292
- return oldState.composerValue === newState.composerValue && oldState.initial === newState.initial && oldState.renamingSessionId === newState.renamingSessionId && oldState.selectedModelId === newState.selectedModelId && oldState.selectedSessionId === newState.selectedSessionId && oldState.sessions === newState.sessions && oldState.viewMode === newState.viewMode;
1295
+ return oldState.composerValue === newState.composerValue && oldState.initial === newState.initial && oldState.renamingSessionId === newState.renamingSessionId && oldState.selectedModelId === newState.selectedModelId && oldState.selectedSessionId === newState.selectedSessionId && oldState.sessions === newState.sessions && oldState.tokensMax === newState.tokensMax && oldState.tokensUsed === newState.tokensUsed && oldState.usageOverviewEnabled === newState.usageOverviewEnabled && oldState.viewMode === newState.viewMode;
1293
1296
  };
1294
1297
 
1295
1298
  const RenderItems = 4;
@@ -1306,8 +1309,8 @@ const diffValue = (oldState, newState) => {
1306
1309
  return newState.inputSource !== 'script';
1307
1310
  };
1308
1311
 
1309
- const modules = [isEqual, diffValue, diffFocus, isEqual$1];
1310
- const numbers = [RenderIncremental, RenderValue, RenderFocus, RenderCss];
1312
+ const modules = [isEqual, diffValue, diffFocus, isEqual$1, diffFocus];
1313
+ const numbers = [RenderIncremental, RenderValue, RenderFocus, RenderCss, RenderFocusContext];
1311
1314
 
1312
1315
  const diff = (oldState, newState) => {
1313
1316
  const diffResult = [];
@@ -2517,8 +2520,7 @@ const renderFocus = (oldState, newState) => {
2517
2520
  };
2518
2521
 
2519
2522
  const renderFocusContext = (oldState, newState) => {
2520
- const when = 2344;
2521
- return [SetFocusContext, newState.uid, when];
2523
+ return [SetFocusContext, newState.uid, FocusChatInput];
2522
2524
  };
2523
2525
 
2524
2526
  const ChatActions = 'ChatActions';
@@ -2533,21 +2535,26 @@ const ButtonDisabled = 'ButtonDisabled';
2533
2535
  const ButtonPrimary = 'ButtonPrimary';
2534
2536
  const IconButton = 'IconButton';
2535
2537
  const Label = 'Label';
2538
+ const LabelDetail = 'LabelDetail';
2536
2539
  const ChatList = 'ChatList';
2537
2540
  const ChatListEmpty = 'ChatListEmpty';
2538
2541
  const ChatListItem = 'ChatListItem';
2539
2542
  const ChatListItemLabel = 'ChatListItemLabel';
2540
2543
  const Markdown = 'Markdown';
2541
2544
  const Message = 'Message';
2545
+ const ChatMessageContent = 'ChatMessageContent';
2542
2546
  const MessageUser = 'MessageUser';
2543
2547
  const MessageAssistant = 'MessageAssistant';
2544
2548
  const MultilineInputBox = 'MultilineInputBox';
2545
2549
  const Option = 'Option';
2550
+ const TokenUsageOverview = 'TokenUsageOverview';
2551
+ const TokenUsageRing = 'TokenUsageRing';
2552
+ const TokenUsageRingInner = 'TokenUsageRingInner';
2546
2553
  const Select = 'Select';
2547
2554
  const Viewlet = 'Viewlet';
2548
2555
  const ChatWelcomeMessage = 'ChatWelcomeMessage';
2549
2556
 
2550
- const HandleContextMenu = 2;
2557
+ const HandleListContextMenu = 2;
2551
2558
  const HandleFocus = 3;
2552
2559
  const HandleInput = 4;
2553
2560
  const HandleClick = 11;
@@ -2561,18 +2568,71 @@ const HandleClickDelete = 18;
2561
2568
  const HandleSubmit = 19;
2562
2569
  const HandleModelChange = 20;
2563
2570
 
2564
- const getChatSendAreaDom = (composerValue, models, selectedModelId) => {
2571
+ const getModelOptionDOm = (model, selectedModelId) => {
2572
+ return [{
2573
+ childCount: 1,
2574
+ className: Option,
2575
+ selected: model.id === selectedModelId,
2576
+ type: Option$1,
2577
+ value: model.id
2578
+ }, text(model.name)];
2579
+ };
2580
+
2581
+ const getSendButtonClassName = isSendDisabled => {
2582
+ return isSendDisabled ? `${Button} ${ButtonPrimary} ${ButtonDisabled}` : `${Button} ${ButtonPrimary}`;
2583
+ };
2584
+ const getSendButtonDom = isSendDisabled => {
2585
+ const sendButtonClassName = getSendButtonClassName(isSendDisabled);
2586
+ return [{
2587
+ childCount: 1,
2588
+ className: sendButtonClassName,
2589
+ disabled: isSendDisabled,
2590
+ name: 'send',
2591
+ onClick: HandleSubmit,
2592
+ role: Button$2,
2593
+ title: sendMessage,
2594
+ type: Button$1
2595
+ }, text(send)];
2596
+ };
2597
+
2598
+ const clampToPercentage = (tokensUsed, tokensMax) => {
2599
+ if (tokensMax <= 0) {
2600
+ return 0;
2601
+ }
2602
+ const percentage = tokensUsed / tokensMax * 100;
2603
+ return Math.max(0, Math.min(100, percentage));
2604
+ };
2605
+
2606
+ const getUsageOverviewDom = (tokensUsed, tokensMax) => {
2607
+ const usagePercent = clampToPercentage(tokensUsed, tokensMax);
2608
+ const usageLabel = `${tokensUsed} / ${tokensMax}`;
2609
+ const usageTitle = `${tokensUsed} of ${tokensMax} tokens used (${Math.round(usagePercent)}%)`;
2610
+ return [{
2611
+ childCount: 3,
2612
+ className: TokenUsageOverview,
2613
+ type: Div
2614
+ }, {
2615
+ childCount: 1,
2616
+ className: TokenUsageRing,
2617
+ style: `background: conic-gradient(var(--vscode-button-background) ${usagePercent}%, var(--vscode-editorWidget-border) 0);`,
2618
+ title: usageTitle,
2619
+ type: Div
2620
+ }, {
2621
+ childCount: 0,
2622
+ className: TokenUsageRingInner,
2623
+ style: 'background: var(--vscode-editor-background);',
2624
+ type: Div
2625
+ }, {
2626
+ childCount: 1,
2627
+ className: LabelDetail,
2628
+ title: usageTitle,
2629
+ type: Span
2630
+ }, text(usageLabel)];
2631
+ };
2632
+
2633
+ const getChatSendAreaDom = (composerValue, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax) => {
2565
2634
  const isSendDisabled = composerValue.trim() === '';
2566
- const sendButtonClassName = isSendDisabled ? `${Button} ${ButtonPrimary} ${ButtonDisabled}` : `${Button} ${ButtonPrimary}`;
2567
- const modelOptions = models.flatMap(model => {
2568
- return [{
2569
- childCount: 1,
2570
- className: Option,
2571
- selected: model.id === selectedModelId,
2572
- type: Option$1,
2573
- value: model.id
2574
- }, text(model.name)];
2575
- });
2635
+ const modelOptions = models.flatMap(model => getModelOptionDOm(model, selectedModelId));
2576
2636
  return [{
2577
2637
  childCount: 1,
2578
2638
  className: ChatSendArea,
@@ -2591,7 +2651,7 @@ const getChatSendAreaDom = (composerValue, models, selectedModelId) => {
2591
2651
  type: TextArea,
2592
2652
  value: composerValue
2593
2653
  }, {
2594
- childCount: 2,
2654
+ childCount: usageOverviewEnabled ? 3 : 2,
2595
2655
  className: ChatSendAreaBottom,
2596
2656
  type: Div
2597
2657
  }, {
@@ -2601,16 +2661,23 @@ const getChatSendAreaDom = (composerValue, models, selectedModelId) => {
2601
2661
  onInput: HandleModelChange,
2602
2662
  type: Select$1,
2603
2663
  value: selectedModelId
2604
- }, ...modelOptions, {
2664
+ }, ...modelOptions, ...(usageOverviewEnabled ? getUsageOverviewDom(tokensUsed, tokensMax) : []), ...getSendButtonDom(isSendDisabled)];
2665
+ };
2666
+
2667
+ const getBackButtonVirtualDom = () => {
2668
+ return [{
2605
2669
  childCount: 1,
2606
- className: sendButtonClassName,
2607
- disabled: isSendDisabled,
2608
- name: 'send',
2609
- onClick: HandleSubmit,
2670
+ className: IconButton,
2671
+ name: 'back',
2672
+ onClick: HandleClickBack,
2610
2673
  role: Button$2,
2611
- title: sendMessage,
2674
+ title: backToChats,
2612
2675
  type: Button$1
2613
- }, text(send)];
2676
+ }, {
2677
+ childCount: 0,
2678
+ className: 'MaskIcon MaskIconArrowLeft',
2679
+ type: Div
2680
+ }];
2614
2681
  };
2615
2682
 
2616
2683
  const getHeaderActionVirtualDom = item => {
@@ -2622,22 +2689,26 @@ const getHeaderActionVirtualDom = item => {
2622
2689
  role: Button$2,
2623
2690
  title: item.title,
2624
2691
  type: Button$1
2625
- }, text(item.icon)];
2692
+ }, {
2693
+ childCount: 0,
2694
+ className: item.icon,
2695
+ type: Div
2696
+ }];
2626
2697
  };
2627
2698
 
2628
2699
  const getChatHeaderActionsDom = () => {
2629
2700
  const items = [{
2630
- icon: '+',
2701
+ icon: 'MaskIcon MaskIconAdd',
2631
2702
  name: 'create-session',
2632
2703
  onClick: HandleClickNew,
2633
2704
  title: newChat
2634
2705
  }, {
2635
- icon: '',
2706
+ icon: 'MaskIcon MaskIconSettingsGear',
2636
2707
  name: 'settings',
2637
2708
  onClick: HandleClickSettings,
2638
2709
  title: settings
2639
2710
  }, {
2640
- icon: '×',
2711
+ icon: 'MaskIcon MaskIconClose',
2641
2712
  name: 'close-chat',
2642
2713
  onClick: HandleClickClose,
2643
2714
  title: closeChat
@@ -2649,18 +2720,6 @@ const getChatHeaderActionsDom = () => {
2649
2720
  }, ...items.flatMap(getHeaderActionVirtualDom)];
2650
2721
  };
2651
2722
 
2652
- const getChatHeaderBackButtonVirtualDom = () => {
2653
- return [{
2654
- childCount: 1,
2655
- className: IconButton,
2656
- name: 'back',
2657
- onClick: HandleClickBack,
2658
- role: Button$2,
2659
- title: backToChats,
2660
- type: Button$1
2661
- }, text('←')];
2662
- };
2663
-
2664
2723
  const getChatHeaderDomDetailMode = selectedSessionTitle => {
2665
2724
  return [{
2666
2725
  childCount: 2,
@@ -2670,7 +2729,7 @@ const getChatHeaderDomDetailMode = selectedSessionTitle => {
2670
2729
  childCount: 2,
2671
2730
  className: ChatName,
2672
2731
  type: Div
2673
- }, ...getChatHeaderBackButtonVirtualDom(), {
2732
+ }, ...getBackButtonVirtualDom(), {
2674
2733
  childCount: 1,
2675
2734
  className: Label,
2676
2735
  type: Span
@@ -2680,14 +2739,14 @@ const getChatHeaderDomDetailMode = selectedSessionTitle => {
2680
2739
  const getChatMessageDom = message => {
2681
2740
  const roleClassName = message.role === 'user' ? MessageUser : MessageAssistant;
2682
2741
  return [{
2683
- childCount: 2,
2742
+ childCount: 1,
2684
2743
  className: mergeClassNames(Message, roleClassName),
2685
2744
  type: Div
2686
2745
  }, {
2687
2746
  childCount: 1,
2688
- className: Label,
2747
+ className: ChatMessageContent,
2689
2748
  type: Div
2690
- }, text(`${message.role === 'user' ? you : assistant} · ${message.time}`), {
2749
+ }, {
2691
2750
  childCount: 1,
2692
2751
  className: Markdown,
2693
2752
  type: P
@@ -2709,7 +2768,7 @@ const getMessagesDom = messages => {
2709
2768
  }, ...messages.flatMap(getChatMessageDom)];
2710
2769
  };
2711
2770
 
2712
- const getChatModeDetailVirtualDom = (sessions, selectedSessionId, composerValue, models, selectedModelId) => {
2771
+ const getChatModeDetailVirtualDom = (sessions, selectedSessionId, composerValue, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax) => {
2713
2772
  const selectedSession = sessions.find(session => session.id === selectedSessionId);
2714
2773
  const selectedSessionTitle = selectedSession?.title || chatTitle;
2715
2774
  const messages = selectedSession ? selectedSession.messages : [];
@@ -2717,7 +2776,7 @@ const getChatModeDetailVirtualDom = (sessions, selectedSessionId, composerValue,
2717
2776
  childCount: 3,
2718
2777
  className: mergeClassNames(Viewlet, Chat),
2719
2778
  type: Div
2720
- }, ...getChatHeaderDomDetailMode(selectedSessionTitle), ...getMessagesDom(messages), ...getChatSendAreaDom(composerValue, models, selectedModelId)];
2779
+ }, ...getChatHeaderDomDetailMode(selectedSessionTitle), ...getMessagesDom(messages), ...getChatSendAreaDom(composerValue, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax)];
2721
2780
  };
2722
2781
 
2723
2782
  const getChatHeaderListModeDom = () => {
@@ -2754,7 +2813,7 @@ const getSessionDom = session => {
2754
2813
  childCount: 1,
2755
2814
  className: ChatListItemLabel,
2756
2815
  name: `session:${session.id}`,
2757
- onContextMenu: HandleContextMenu,
2816
+ onContextMenu: HandleListContextMenu,
2758
2817
  tabIndex: 0,
2759
2818
  type: Div
2760
2819
  }, text(session.title), {
@@ -2786,12 +2845,12 @@ const getChatListDom = (sessions, selectedSessionId) => {
2786
2845
  }, ...sessions.flatMap(getSessionDom)];
2787
2846
  };
2788
2847
 
2789
- const getChatModeListVirtualDom = (sessions, selectedSessionId, composerValue, models, selectedModelId) => {
2848
+ const getChatModeListVirtualDom = (sessions, selectedSessionId, composerValue, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax) => {
2790
2849
  return [{
2791
2850
  childCount: 3,
2792
2851
  className: mergeClassNames(Viewlet, Chat),
2793
2852
  type: Div
2794
- }, ...getChatHeaderListModeDom(), ...getChatListDom(sessions), ...getChatSendAreaDom(composerValue, models, selectedModelId)];
2853
+ }, ...getChatHeaderListModeDom(), ...getChatListDom(sessions), ...getChatSendAreaDom(composerValue, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax)];
2795
2854
  };
2796
2855
 
2797
2856
  const getChatModeUnsupportedVirtualDom = () => {
@@ -2801,12 +2860,12 @@ const getChatModeUnsupportedVirtualDom = () => {
2801
2860
  }, text('Unknown view mode')];
2802
2861
  };
2803
2862
 
2804
- const getChatVirtualDom = (sessions, selectedSessionId, composerValue, viewMode, models, selectedModelId) => {
2863
+ const getChatVirtualDom = (sessions, selectedSessionId, composerValue, viewMode, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax) => {
2805
2864
  switch (viewMode) {
2806
2865
  case 'detail':
2807
- return getChatModeDetailVirtualDom(sessions, selectedSessionId, composerValue, models, selectedModelId);
2866
+ return getChatModeDetailVirtualDom(sessions, selectedSessionId, composerValue, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax);
2808
2867
  case 'list':
2809
- return getChatModeListVirtualDom(sessions, selectedSessionId, composerValue, models, selectedModelId);
2868
+ return getChatModeListVirtualDom(sessions, selectedSessionId, composerValue, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax);
2810
2869
  default:
2811
2870
  return getChatModeUnsupportedVirtualDom();
2812
2871
  }
@@ -2820,13 +2879,16 @@ const renderItems = (oldState, newState) => {
2820
2879
  selectedModelId,
2821
2880
  selectedSessionId,
2822
2881
  sessions,
2882
+ tokensMax,
2883
+ tokensUsed,
2823
2884
  uid,
2885
+ usageOverviewEnabled,
2824
2886
  viewMode
2825
2887
  } = newState;
2826
2888
  if (initial) {
2827
2889
  return [SetDom2, uid, []];
2828
2890
  }
2829
- const dom = getChatVirtualDom(sessions, selectedSessionId, composerValue, viewMode, models, selectedModelId);
2891
+ const dom = getChatVirtualDom(sessions, selectedSessionId, composerValue, viewMode, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax);
2830
2892
  return [SetDom2, uid, dom];
2831
2893
  };
2832
2894
 
@@ -2887,8 +2949,8 @@ const render2 = (uid, diffResult) => {
2887
2949
 
2888
2950
  const renderEventListeners = () => {
2889
2951
  return [{
2890
- name: HandleContextMenu,
2891
- params: ['handleChatListContextMenu', TargetName, ClientX, ClientY],
2952
+ name: HandleListContextMenu,
2953
+ params: ['handleChatListContextMenu', ClientX, ClientY],
2892
2954
  preventDefault: true
2893
2955
  }, {
2894
2956
  name: HandleClick,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/chat-view",
3
- "version": "1.9.0",
3
+ "version": "1.11.0",
4
4
  "description": "Chat View Worker",
5
5
  "repository": {
6
6
  "type": "git",