bingocode 1.1.116 → 1.1.118

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.116",
3
+ "version": "1.1.118",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "claude": "bin/claude-win.cjs",
@@ -51,7 +51,6 @@
51
51
  "auto-bind": "^5.0.1",
52
52
  "axios": "^1.14.0",
53
53
  "bidi-js": "^1.0.3",
54
- "bingocode": "^1.1.112",
55
54
  "chalk": "^5.6.2",
56
55
  "chokidar": "^5.0.0",
57
56
  "cli-boxes": "^4.0.1",
@@ -995,7 +995,7 @@ export const CliMenuManager: React.FC = () => {
995
995
  return <StateDisplay type="empty" message={i18nMap[lang].emptyHistory} />;
996
996
  }
997
997
 
998
- const ACTIONS_H = 6;
998
+ const ACTIONS_H = 7; // Actions title(1) + 4 items + hint(1) + padding(1)
999
999
  const LIST_H = Math.max(2, MID_H - ACTIONS_H - 1);
1000
1000
 
1001
1001
  if (historyMenuStage === 'window' && selectedHistory) {
@@ -1042,7 +1042,7 @@ export const CliMenuManager: React.FC = () => {
1042
1042
  )}
1043
1043
  </Box>
1044
1044
 
1045
- <Box height={1} marginBottom={0}><Text dimColor>{'─'.repeat(VIEW_W - 2)}</Text></Box>
1045
+ <Box height={1} marginBottom={0}><Text dimColor>{'─'.repeat(VIEW_W - 4)}</Text></Box>
1046
1046
 
1047
1047
  {/* Lower Pane: Actions */}
1048
1048
  <Box height={ACTIONS_H} paddingX={1} flexDirection="column" overflow="hidden">
@@ -1060,42 +1060,47 @@ export const CliMenuManager: React.FC = () => {
1060
1060
  }
1061
1061
 
1062
1062
  // History List View (Default)
1063
+ // MID_H - 1 (hint bar at top) - 1 (scrollbar safety) = MID_H - 2 visible items
1063
1064
  const HIST_VISIBLE = MID_H - 2;
1064
1065
  const start = Math.min(listOffset, Math.max(0, groupedHistoryItems.length - HIST_VISIBLE));
1065
1066
  const slicedItems = groupedHistoryItems.slice(start, start + HIST_VISIBLE);
1066
1067
 
1067
1068
  return (
1068
- <Box width={VIEW_W} height={MID_H} flexDirection="row" position="relative">
1069
- <Box flexDirection="column" flexGrow={1} paddingX={1}>
1070
- <SelectInput
1071
- key={`${historyCursor ?? 'first'}:${slicedItems.length}:${start}`}
1072
- items={slicedItems}
1073
- onSelect={item => {
1074
- if (String(item.value).startsWith('__group_')) return;
1075
- const session = historyList.find(h => h.id === item.value);
1076
- if (session) {
1077
- setSelectedHistory(session);
1078
- setHistoryMenuStage('window');
1079
- }
1080
- }}
1081
- itemComponent={({ isSelected, label }) => {
1082
- const it = groupedHistoryItems.find(i => i.label === label);
1083
- const isGroup = it?.isGroup;
1084
- const color = it?.color;
1085
- return (
1086
- <Box height={1} overflow="hidden">
1087
- <Text wrap="truncate" color={isGroup ? 'gray' : (color ? color : (isSelected ? 'cyan' : undefined))}>
1088
- {isSelected ? '> ' : ' '}{label}
1089
- </Text>
1090
- </Box>
1091
- )
1092
- }}
1093
- />
1094
- </Box>
1095
- <ScrollBar total={groupedHistoryItems.length} offset={start} height={MID_H - 2} />
1096
- <Box position="absolute" bottom={0} left={1} width={VIEW_W - 4}>
1069
+ <Box width={VIEW_W} height={MID_H} flexDirection="column">
1070
+ {/* Hint bar — fixed 1 row at top, never overlaps list */}
1071
+ <Box height={1} paddingX={1}>
1097
1072
  <Hint>{i18nMap[lang].historyHint}</Hint>
1098
1073
  </Box>
1074
+ {/* List area — takes the rest of the height */}
1075
+ <Box flexDirection="row" flexGrow={1} position="relative">
1076
+ <Box flexDirection="column" flexGrow={1} paddingX={1}>
1077
+ <SelectInput
1078
+ key={`${historyCursor ?? 'first'}:${slicedItems.length}:${start}`}
1079
+ items={slicedItems}
1080
+ onSelect={item => {
1081
+ if (String(item.value).startsWith('__group_')) return;
1082
+ const session = historyList.find(h => h.id === item.value);
1083
+ if (session) {
1084
+ setSelectedHistory(session);
1085
+ setHistoryMenuStage('window');
1086
+ }
1087
+ }}
1088
+ itemComponent={({ isSelected, label }) => {
1089
+ const it = groupedHistoryItems.find(i => i.label === label);
1090
+ const isGroup = it?.isGroup;
1091
+ const color = it?.color;
1092
+ return (
1093
+ <Box height={1} overflow="hidden">
1094
+ <Text wrap="truncate" color={isGroup ? 'gray' : (color ? color : (isSelected ? 'cyan' : undefined))}>
1095
+ {isSelected ? '> ' : ' '}{label}
1096
+ </Text>
1097
+ </Box>
1098
+ )
1099
+ }}
1100
+ />
1101
+ </Box>
1102
+ <ScrollBar total={groupedHistoryItems.length} offset={start} height={MID_H - 3} />
1103
+ </Box>
1099
1104
  </Box>
1100
1105
  );
1101
1106
  }
@@ -746,7 +746,7 @@ export function normalizeMessages(messages: Message[]): NormalizedMessage[] {
746
746
  // This flag is set to true once we encounter a message with multiple content blocks,
747
747
  // and remains true for all subsequent messages in the normalization process.
748
748
  let isNewChain = false
749
- return messages.flatMap(message => {
749
+ const raw = messages.flatMap(message => {
750
750
  switch (message.type) {
751
751
  case 'assistant': {
752
752
  isNewChain = isNewChain || message.message.content.length > 1
@@ -820,6 +820,14 @@ export function normalizeMessages(messages: Message[]): NormalizedMessage[] {
820
820
  }
821
821
  }
822
822
  })
823
+ // Dedup: keep only the last occurrence of each uuid.
824
+ // Prevents repeated assistant text blocks when the same normalized message
825
+ // is pushed multiple times during a tool-use loop.
826
+ const seen = new Map<string, number>()
827
+ for (let i = 0; i < raw.length; i++) {
828
+ seen.set(raw[i]!.uuid, i)
829
+ }
830
+ return raw.filter((_, i) => seen.get(raw[i]!.uuid) === i)
823
831
  }
824
832
 
825
833
  type ToolUseRequestMessage = NormalizedAssistantMessage & {
@@ -1,7 +0,0 @@
1
- {
2
- "permissions": {
3
- "allow": [
4
- "WebFetch(domain:github.com)"
5
- ]
6
- }
7
- }