bingocode 1.1.73 → 1.1.75

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bingocode",
3
- "version": "1.1.73",
3
+ "version": "1.1.75",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "claude": "bin/claude-win.cjs",
@@ -91,6 +91,8 @@ const i18nMap = {
91
91
  about: 'Bingo CLI - Version Info & About',
92
92
  aboutContent: [
93
93
  'Bingo is an AI assistant terminal client.',
94
+ 'Author: leanchy (Email: leanchy07@outlook.com)',
95
+ 'Github: github.com/leanchy/bingo-claude-code-offline-installer',
94
96
  '1. API Config: Press "P" or select "API Config" to set up your keys.',
95
97
  '2. Model Slots: Configure specific models in the Provider panel.',
96
98
  '3. Background Service: Bingo runs a local server to manage sessions.',
@@ -117,6 +119,8 @@ const i18nMap = {
117
119
  about: 'Bingo CLI Terminal - Version Info & About',
118
120
  aboutContent: [
119
121
  'Bingo is an AI assistant terminal client.',
122
+ 'Author: leanchy (Email: leanchy07@outlook.com)',
123
+ 'Github: github.com/leanchy/bingo-claude-code-offline-installer',
120
124
  '1. API Config: Press "P" or select "API Config" to set up your keys.',
121
125
  '2. Model Slots: Configure specific models in the Provider panel.',
122
126
  '3. Background Service: Bingo runs a local server to manage sessions.',
@@ -739,47 +743,54 @@ export const CliMenuManager: React.FC = () => {
739
743
  }
740
744
 
741
745
 
742
- // 历史分组展示
743
- const groupedHistoryItems = useMemo(() => {
744
- if (!historyList || !Array.isArray(historyList)) return [];
745
- const now = new Date();
746
- const today: any[] = [];
747
- const week: any[] = [];
748
- const earlier: any[] = [];
749
- for (const item of historyList) {
750
- const dt = new Date(item.createdAt);
751
- const isToday =
752
- dt.getFullYear() === now.getFullYear() &&
753
- dt.getMonth() === now.getMonth() &&
754
- dt.getDate() === now.getDate();
755
- const weekStart = new Date(now);
756
- weekStart.setDate(now.getDate() - ((now.getDay() + 6) % 7));
757
- weekStart.setHours(0, 0, 0, 0);
758
- if (isToday) today.push(item);
759
- else if (dt >= weekStart) week.push(item);
760
- else earlier.push(item);
761
- }
762
- function groupToItems(group: any[], groupTitle: string) {
763
- if (group.length === 0) return [];
764
- return [
765
- { label: groupTitle, value: `__group_${groupTitle}`, isGroup: true },
766
- ...group.map(item => {
767
- const isMarked = markedSessionIds.has(item.id);
768
- return {
769
- label: makeHistoryLabel(item, Math.max(20, VIEW_W - 8), isMarked),
770
- value: item.id,
771
- color: isMarked ? 'yellow' : undefined,
772
- };
773
- })
774
- ];
775
- }
776
- const items = [
777
- ...groupToItems(today, '—— Today ——'),
778
- ...groupToItems(week, '—— This Week ——'),
779
- ...groupToItems(earlier, '—— Earlier ——'),
780
- ];
781
- return items;
782
- }, [historyList, markedSessionIds]);
746
+ // 历史分组展示
747
+ const groupedHistoryItems = useMemo(() => {
748
+ if (!historyList || !Array.isArray(historyList)) return [];
749
+ const now = new Date();
750
+ const today: any[] = [];
751
+ const week: any[] = [];
752
+ const earlier: any[] = [];
753
+ const marked: any[] = [];
754
+
755
+ for (const item of historyList) {
756
+ if (markedSessionIds.has(item.id)) {
757
+ marked.push(item);
758
+ continue;
759
+ }
760
+ const dt = new Date(item.createdAt);
761
+ const isToday =
762
+ dt.getFullYear() === now.getFullYear() &&
763
+ dt.getMonth() === now.getMonth() &&
764
+ dt.getDate() === now.getDate();
765
+ const weekStart = new Date(now);
766
+ weekStart.setDate(now.getDate() - ((now.getDay() + 6) % 7));
767
+ weekStart.setHours(0, 0, 0, 0);
768
+ if (isToday) today.push(item);
769
+ else if (dt >= weekStart) week.push(item);
770
+ else earlier.push(item);
771
+ }
772
+ function groupToItems(group: any[], groupTitle: string) {
773
+ if (group.length === 0) return [];
774
+ return [
775
+ { label: groupTitle, value: `__group_${groupTitle}`, isGroup: true },
776
+ ...group.map(item => {
777
+ const isMarked = markedSessionIds.has(item.id);
778
+ return {
779
+ label: makeHistoryLabel(item, Math.max(20, VIEW_W - 8), isMarked),
780
+ value: item.id,
781
+ color: isMarked ? 'yellow' : undefined,
782
+ };
783
+ })
784
+ ];
785
+ }
786
+ const items = [
787
+ ...groupToItems(marked, '—— Marked ——'),
788
+ ...groupToItems(today, '—— Today ——'),
789
+ ...groupToItems(week, '—— This Week ——'),
790
+ ...groupToItems(earlier, '—— Earlier ——'),
791
+ ];
792
+ return items;
793
+ }, [historyList, markedSessionIds]);
783
794
 
784
795
  // Toggle Mark
785
796
  const toggleMarkSession = (sessionId: string) => {
@@ -1003,15 +1014,15 @@ export const CliMenuManager: React.FC = () => {
1003
1014
  return (
1004
1015
  <Box width={VIEW_W} height={MID_H} flexDirection="column">
1005
1016
  {/* Upper Pane: Preview */}
1006
- <Box height={LIST_H} flexDirection="column" paddingX={1}>
1007
- <Box justifyContent="space-between" marginBottom={1}>
1017
+ <Box height={LIST_H} flexDirection="column" paddingX={1} overflow="hidden">
1018
+ <Box justifyContent="space-between" marginBottom={0}>
1008
1019
  <Text color={isMarked ? 'yellow' : 'cyan'} bold>
1009
- {isMarked ? '★ ' : ''}{selectedHistory.title || 'Untitled'}
1020
+ {isMarked ? '★ ' : ''}{truncate(selectedHistory.title || 'Untitled', VIEW_W - 24)}
1010
1021
  </Text>
1011
1022
  <Text dimColor>{selectedHistory.createdAt?.slice(0,16).replace('T',' ')}</Text>
1012
1023
  </Box>
1013
1024
 
1014
- <Box flexDirection="column" flexGrow={1}>
1025
+ <Box flexDirection="column" flexGrow={1} overflow="hidden">
1015
1026
  {loadingMsgs && <StateDisplay type="loading" message="Loading messages..." />}
1016
1027
  {msgsErr && <StateDisplay type="error" message={msgsErr} />}
1017
1028
  {!loadingMsgs && pageMsgs.length === 0 && <StateDisplay type="empty" message="No messages" />}
@@ -1020,28 +1031,25 @@ export const CliMenuManager: React.FC = () => {
1020
1031
  const roleLabel = msg.type === 'user' ? 'You' : 'Bot';
1021
1032
  const roleColor = msg.type === 'user' ? 'green' : 'cyan';
1022
1033
  return (
1023
- <Box key={msg.id} marginBottom={1} flexDirection="column">
1024
- <Text color={roleColor} bold>{roleLabel}:</Text>
1025
- <Box paddingLeft={2}>
1026
- <Text>{clampTextLines(text, VIEW_W - 6, 3)}</Text>
1027
- </Box>
1034
+ <Box key={msg.id} marginBottom={0} flexDirection="column" height={1} overflow="hidden">
1035
+ <Text color={roleColor} bold>{roleLabel}: <Text color="white" bold={false}>{clampTextLines(text, VIEW_W - 10, 1)}</Text></Text>
1028
1036
  </Box>
1029
1037
  );
1030
1038
  })}
1031
1039
  </Box>
1032
1040
  {totalPages > 1 && (
1033
- <Box justifyContent="center" marginTop={1}>
1041
+ <Box justifyContent="center" height={1}>
1034
1042
  <Hint>Page {safePage + 1}/{totalPages} (↑↓ to scroll)</Hint>
1035
1043
  </Box>
1036
1044
  )}
1037
1045
  </Box>
1038
1046
 
1039
- <Box height={1}><Text dimColor>{'─'.repeat(VIEW_W - 2)}</Text></Box>
1047
+ <Box height={1} marginBottom={0}><Text dimColor>{'─'.repeat(VIEW_W - 2)}</Text></Box>
1040
1048
 
1041
1049
  {/* Lower Pane: Actions */}
1042
- <Box height={ACTIONS_H} paddingX={1} flexDirection="column">
1050
+ <Box height={ACTIONS_H} paddingX={1} flexDirection="column" overflow="hidden">
1043
1051
  <Text color="magenta" bold>Actions</Text>
1044
- <Box marginTop={0}>
1052
+ <Box marginTop={0} height={ACTIONS_H - 2} overflow="hidden">
1045
1053
  <SelectInput
1046
1054
  items={secondaryMenu?.items || []}
1047
1055
  onSelect={secondaryMenu?.onSelect}
@@ -1077,9 +1085,11 @@ export const CliMenuManager: React.FC = () => {
1077
1085
  const isGroup = it?.isGroup;
1078
1086
  const color = it?.color;
1079
1087
  return (
1080
- <Text color={isGroup ? 'gray' : (color ? color : (isSelected ? 'cyan' : undefined))}>
1081
- {isSelected ? '> ' : ' '}{label}
1082
- </Text>
1088
+ <Box height={1} overflow="hidden">
1089
+ <Text wrap="truncate" color={isGroup ? 'gray' : (color ? color : (isSelected ? 'cyan' : undefined))}>
1090
+ {isSelected ? '> ' : ' '}{label}
1091
+ </Text>
1092
+ </Box>
1083
1093
  )
1084
1094
  }}
1085
1095
  />
@@ -1087,7 +1097,7 @@ export const CliMenuManager: React.FC = () => {
1087
1097
  <Hint>{i18nMap[lang].historyHint}</Hint>
1088
1098
  </Box>
1089
1099
  </Box>
1090
- <ScrollBar total={groupedHistoryItems.length} offset={start} height={MID_H - 2} />
1100
+ <ScrollBar total={groupedHistoryItems.length} offset={start} height={MID_H - 1} />
1091
1101
  </Box>
1092
1102
  );
1093
1103
  }
@@ -7,7 +7,7 @@ const repeatChar = (ch: string, n: number) => ch.repeat(Math.max(0, n));
7
7
  // Truncate by terminal display width
8
8
  const charDisplayWidth = (c: string) => c.charCodeAt(0) > 127 ? 2 : 1;
9
9
  const displayWidth = (s: string) => [...s].reduce((acc, c) => acc + charDisplayWidth(c), 0);
10
- const truncate = (s: string, maxCols: number) => {
10
+ export const truncate = (s: string, maxCols: number) => {
11
11
  let cols = 0;
12
12
  let out = '';
13
13
  for (const c of s) {
@@ -295,5 +295,5 @@ export const InfoPair: React.FC<{ label: string; value: string; labelColor?: str
295
295
  });
296
296
 
297
297
  export default {
298
- Kbd, Hint, Title, Divider, Panel, FallbackTop, TopBar, BottomBar, Chip, ChipRow, InfoPair
298
+ Kbd, Hint, Title, Divider, Panel, FallbackTop, TopBar, BottomBar, Chip, ChipRow, InfoPair, safePadEnd, truncate
299
299
  };