bingocode 1.1.103 → 1.1.105

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.
@@ -283,7 +283,7 @@ export const TopBar: React.FC<{
283
283
  )}
284
284
  {ip ? (
285
285
  <Box marginTop={1}>
286
- <Text color="gray" dimColor>IP: {ip.replace(':','\n ')}</Text>
286
+ <Text dimColor>IP: {ip.replace(':','\n ')}</Text>
287
287
  </Box>
288
288
  ) : null}
289
289
  </Box>
@@ -1,111 +1,128 @@
1
- //@C:M ID=M.UI.TopToolbar;K=M;V=1.2;P=top toolbar;D=CLI;M=cli;S=ui
2
- import React, { memo, useMemo } from 'react';
3
- import { Box } from 'ink';
4
- import { Chip, ChipRow } from './CliMenuUi.tsx';
5
- import { useTheme } from '../components/design-system/ThemeProvider.js';
6
- import { getGlobalConfig, getCurrentProjectConfig, isPathTrusted, checkHasTrustDialogAccepted } from '../utils/config.ts';
7
- import { getCwd } from '../utils/cwd.js';
8
- // Update: Import respectively according to the new interface
9
- import type { ClawdPose } from '../components/LogoV2/Clawd.tsx';
10
- import { Clawd } from '../components/LogoV2/Clawd.tsx';
11
- import { AnimatedClawd } from '../components/LogoV2/AnimatedClawd.tsx';
12
-
13
- type Props = {
14
- ready: boolean;
15
- page: string | null;
16
- animEnabled: boolean;
17
- tipsEnabled: boolean;
18
- };
19
-
20
- function basename(p: string) {
21
- if (!p) return '';
22
- const parts = p.split(/[/\\]/).filter(Boolean);
23
- return parts[parts.length - 1] || p;
24
- }
25
- function ellipsisPath(p: string, keep = 2) {
26
- if (!p) return '';
27
- const parts = p.split(/[/\\]/).filter(Boolean);
28
- if (parts.length <= keep) return p;
29
- return '…/' + parts.slice(-keep).join('/');
30
- }
31
-
32
- //@C:F ID=F.UI.TopToolbar;K=F;V=1.2;P=toolbar;D=CLI;M=cli;S=ui;In=Props;Out=JSX.Element
33
- export const TopToolbar: React.FC<Props> = memo(({ ready, page, animEnabled, tipsEnabled }) => {
34
- const [theme] = useTheme();
35
-
36
- // Only read config and trust status when ready
37
- const { cwd, trustAccepted, trustedPath, projectName } = useMemo(() => {
38
- if (!ready) {
39
- return { cwd: '', trustAccepted: undefined as undefined|boolean, trustedPath: undefined as undefined|boolean, projectName: '' };
40
- }
41
- const _cwd = getCwd();
42
- const _trustAccepted = checkHasTrustDialogAccepted();
43
- const _trustedPath = isPathTrusted(_cwd);
44
- let _projectName = '';
45
- try {
46
- const prj = getCurrentProjectConfig();
47
- _projectName = (prj && (prj.name || prj.projectName || prj.id)) || basename(_cwd);
48
- } catch {
49
- _projectName = basename(_cwd);
50
- }
51
- return { cwd: _cwd, trustAccepted: _trustAccepted, trustedPath: _trustedPath, projectName: _projectName };
52
- }, [ready]);
53
-
54
- const compact = page !== null;
55
- const cwdShort = useMemo(() => ellipsisPath(cwd, compact ? 2 : 3), [cwd, compact]);
56
-
57
- // Theme name
58
- const themeLabel = String(theme || (ready ? (getGlobalConfig()?.theme ?? 'system') : '…'));
59
-
60
- // Static Clawd pose
61
- const clawdPose: ClawdPose = useMemo(() => {
62
- if (!ready) return 'default';
63
- if (page === null) return animEnabled ? 'arms-up' : 'default';
64
- return tipsEnabled ? 'look-left' : 'look-right';
65
- }, [ready, page, animEnabled, tipsEnabled]);
66
-
67
- const uiTone = (String(theme) === 'dark') ? 'accent' : (String(theme) === 'highContrast' ? 'warning' : 'info');
68
-
69
- return (
70
- <Box flexDirection="column" minHeight={3}>
71
- <ChipRow>
72
- {/* Left: Clawd + Core Status */}
73
- <Box>
74
- <Box marginRight={2}>
75
- {animEnabled ? <AnimatedClawd /> : <Clawd pose={clawdPose} />}
76
- </Box>
77
-
78
- <Chip label="Theme" value={themeLabel} tone="accent" />
79
- <Chip label="Project" value={projectName || ''} tone="info" />
80
- <Chip label="CWD" value={cwdShort || '—'} tone="subtle" />
81
- {trustedPath === undefined || trustAccepted === undefined ? (
82
- <Chip label="Trust" value="…" tone="subtle" />
83
- ) : trustedPath && trustAccepted ? (
84
- <Chip label="Trust" value="✅ Trusted" tone="success" />
85
- ) : (
86
- <Chip label="Trust" value="🔒 Untrusted" tone="warning" />
87
- )}
88
- </Box>
89
-
90
- {/* Right: UI Status merged display */}
91
- <Box>
92
- <Chip
93
- label="UI"
94
- value={`Anim ${animEnabled ? 'On' : 'Off'} · Tips ${tipsEnabled ? 'On' : 'Off'}`}
95
- tone={uiTone as any}
96
- />
97
- </Box>
98
- </ChipRow>
99
-
100
- {!compact && (
101
- <ChipRow>
102
- <Box>
103
- <Chip label="Shortcuts" value="N New · R Resume · P Provider · G Theme · ? Help" tone="subtle" />
104
- </Box>
105
- </ChipRow>
106
- )}
107
- </Box>
108
- );
109
- });
110
-
111
- export default TopToolbar;
1
+ //@C:M ID=M.UI.TopToolbar;K=M;V=1.2;P=top toolbar;D=CLI;M=cli;S=ui
2
+ import React, { memo, useMemo } from 'react';
3
+ import { Box } from 'ink';
4
+ import { Chip } from './CliMenuUi.tsx';
5
+ import { useTheme } from '../components/design-system/ThemeProvider.tsx';
6
+ import { getGlobalConfig, getCurrentProjectConfig } from '../utils/config.ts';
7
+ import { getCwd } from '../utils/cwd.js';
8
+ import type { ClawdPose } from '../components/LogoV2/Clawd.tsx';
9
+ import { Clawd } from '../components/LogoV2/Clawd.tsx';
10
+ import { AnimatedClawd } from '../components/LogoV2/AnimatedClawd.tsx';
11
+
12
+ import fs from 'fs';
13
+ import path from 'path';
14
+ import os from 'os';
15
+
16
+ type Props = {
17
+ ready: boolean;
18
+ page: string | null;
19
+ animEnabled: boolean;
20
+ tipsEnabled: boolean;
21
+ };
22
+
23
+ function countLeases(): number {
24
+ try {
25
+ const LEASES_DIR = path.join(os.homedir(), '.claude-cli', 'runtime', 'leases');
26
+ if (!fs.existsSync(LEASES_DIR)) return 0;
27
+ const files = fs.readdirSync(LEASES_DIR);
28
+ let alive = 0;
29
+ for (const f of files) {
30
+ try {
31
+ const p = path.join(LEASES_DIR, f);
32
+ const raw = fs.readFileSync(p, 'utf-8');
33
+ const data = JSON.parse(raw);
34
+ if (data?.pid) {
35
+ try {
36
+ process.kill(data.pid, 0);
37
+ alive++;
38
+ } catch {
39
+ // PID not alive
40
+ }
41
+ }
42
+ } catch {}
43
+ }
44
+ return alive;
45
+ } catch {
46
+ return 0;
47
+ }
48
+ }
49
+
50
+ function basename(p: string) {
51
+ if (!p) return '';
52
+ const parts = p.split(/[/\\]/).filter(Boolean);
53
+ return parts[parts.length - 1] || p;
54
+ }
55
+
56
+ export const TopToolbar: React.FC<Props> = memo(({ ready, page, animEnabled, tipsEnabled }) => {
57
+ const [theme] = useTheme();
58
+
59
+ // Polling for window count
60
+ const [windowCount, setWindowCount] = React.useState(0);
61
+ React.useEffect(() => {
62
+ const update = () => setWindowCount(countLeases());
63
+ update();
64
+ const id = setInterval(update, 10000);
65
+ return () => clearInterval(id);
66
+ }, []);
67
+
68
+ // Only read config when ready
69
+ const { projectName } = useMemo(() => {
70
+ if (!ready) {
71
+ return { projectName: '' };
72
+ }
73
+ const _cwd = getCwd();
74
+ let _projectName = '';
75
+ try {
76
+ const prj = getCurrentProjectConfig();
77
+ _projectName = (prj && (prj.name || prj.projectName || prj.id)) || (typeof _cwd === 'string' ? basename(_cwd) : '');
78
+ } catch {
79
+ _projectName = typeof _cwd === 'string' ? basename(_cwd) : '';
80
+ }
81
+ return { projectName: _projectName };
82
+ }, [ready]);
83
+
84
+ // Theme name
85
+ const themeLabel = String(theme || (ready ? (getGlobalConfig()?.theme ?? 'system') : '…'));
86
+
87
+ // Static Clawd pose
88
+ const clawdPose: ClawdPose = useMemo(() => {
89
+ if (!ready) return 'default';
90
+ if (page === null) return animEnabled ? 'arms-up' : 'default';
91
+ return tipsEnabled ? 'look-left' : 'look-right';
92
+ }, [ready, page, animEnabled, tipsEnabled]);
93
+
94
+ const uiTone = (String(theme) === 'dark') ? 'accent' : (String(theme) === 'highContrast' ? 'warning' : 'info');
95
+
96
+ return (
97
+ <Box flexDirection="row" width="100%" alignItems="center" justifyContent="space-between" minHeight={3}>
98
+ {/* Left: Clawd Icon + Window Indicators */}
99
+ <Box alignItems="center">
100
+ <Box marginRight={2}>
101
+ {animEnabled ? <AnimatedClawd /> : <Clawd pose={clawdPose} />}
102
+ </Box>
103
+
104
+ {/* Visual Window Grid (Mini-mobs) */}
105
+ <Box flexDirection="row" flexWrap="wrap">
106
+ {Array.from({ length: windowCount }).map((_, i) => (
107
+ <Box key={i} marginRight={1}>
108
+ <Clawd pose="default" />
109
+ </Box>
110
+ ))}
111
+ </Box>
112
+ </Box>
113
+
114
+ {/* Right: Status Info Chips */}
115
+ <Box flexDirection="row">
116
+ <Chip label="Theme" value={themeLabel} tone="accent" />
117
+ <Chip label="Project" value={projectName || '—'} tone="info" />
118
+ <Chip
119
+ label="UI"
120
+ value={`Anim ${animEnabled ? 'On' : 'Off'} · Tips ${tipsEnabled ? 'On' : 'Off'}`}
121
+ tone={uiTone as any}
122
+ />
123
+ </Box>
124
+ </Box>
125
+ );
126
+ });
127
+
128
+ export default TopToolbar;
@@ -1,9 +0,0 @@
1
- {
2
- "permissions": {
3
- "allow": [
4
- "Read(//home/**)",
5
- "Read(//c/Users/qi.lin/**)",
6
- "Bash(find ~/.claude/Skills -maxdepth 4 -name *.ts -o -name *.json -o -name *.md)"
7
- ]
8
- }
9
- }