Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions apps/electron/src/main/kernelHost.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,57 @@ describe('AgentKernelHost', () => {
host.dispose();
});

it('leaves the LongBridge action empty while the CLI is available', async () => {
const host = new AgentKernelHost();

const result = await host.getLongBridgeStatus();

expect(result.status).toBe('available');
expect(result.action).toBeUndefined();
host.dispose();
});

it('maps a LongBridge timeout to a retry action, not an install prompt', async () => {
const host = new AgentKernelHost();
const marketData = lastMarketData as unknown as {
getLongBridgeStatus: () => Promise<Record<string, unknown>>;
};
marketData.getLongBridgeStatus = async () => ({
installed: true,
authed: true,
available: false,
status: 'timeout',
error: { code: 'LONGBRIDGE_TIMEOUT', message: 'LongBridge CLI timed out.' },
});

const result = await host.getLongBridgeStatus();

expect(typeof result.action).toBe('string');
expect(result.action).toContain('timed out');
expect(result.action).not.toContain('Install the LongBridge CLI');
host.dispose();
});

it('maps an unrecognised LongBridge failure to its own action', async () => {
const host = new AgentKernelHost();
const marketData = lastMarketData as unknown as {
getLongBridgeStatus: () => Promise<Record<string, unknown>>;
};
marketData.getLongBridgeStatus = async () => ({
installed: true,
authed: false,
available: false,
status: 'unknown',
error: { code: 'LONGBRIDGE_UNKNOWN', message: 'Unexpected failure.' },
});

const result = await host.getLongBridgeStatus();

expect(typeof result.action).toBe('string');
expect(result.action).not.toContain('Install the LongBridge CLI');
host.dispose();
});

it('wraps market data errors into IPC results', async () => {
const host = new AgentKernelHost();
const { toIpcResult } = await import('./kernelHost.ts');
Expand Down
4 changes: 4 additions & 0 deletions apps/electron/src/main/kernelHost.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2591,6 +2591,10 @@ function getLongBridgeStatusAction(status: string) {
return 'Run longbridge auth login to authenticate the LongBridge CLI.';
case 'rate_limited':
return 'LongBridge is rate-limited; market data requests are paused. Try again later.';
case 'timeout':
return 'LongBridge CLI timed out; market data requests are paused. Check your network or proxy and retry.';
case 'unknown':
return 'LongBridge CLI reported an unexpected error; run `longbridge --version` in a terminal to verify the install and retry.';
default:
return undefined;
}
Expand Down
5 changes: 4 additions & 1 deletion packages/ui/src/components/layout/AppShell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,10 @@ const LongBridgeBanner: React.FC = () => {

const message = error ?? status?.message ?? 'LongBridge CLI status is unavailable.';
const action = status?.action ?? 'Install LongBridge CLI and run longbridge auth login.';
const title = status?.status === 'rate_limited' ? 'LongBridge paused: ' : 'LongBridge setup needed: ';
// `timeout` is a transient pause, not a setup problem: the CLI is installed
// and authenticated, the call just did not come back in time.
const paused = status?.status === 'rate_limited' || status?.status === 'timeout';
const title = paused ? 'LongBridge paused: ' : 'LongBridge setup needed: ';

return (
<div className="folio-banner border-b px-4 py-2">
Expand Down