现象
导出的诊断包里 providers.broker 恒为 { connected: true, accountCount: 1 } —— 与用户是否真的登录过券商账号无关。
"broker": { "connected": true, "accountCount": 1 }
根因
apps/electron/src/main/kernelHost.ts:1592-1593
brokerConnected: providerSummaries.some((p) => p.id === 'longbridge-broker'),
brokerAccountCount: providerSummaries.some((p) => p.id === 'longbridge-broker') ? 1 : 0,
providerSummaries 来自 listFinancialProviders()(kernelHost.ts:2464-2476),而它只是 this.providerRouter.list() 的映射 —— 列出的是所有已注册的 provider。broker 在构造函数里被无条件注册(kernelHost.ts:341):
this.providerRouter.register(longbridgeBroker);
因此 some((p) => p.id === 'longbridge-broker') 是个常量 true:两个字段都退化成常量,账户数还是字面量 1,从未查询过真实账户。
同文件的正确写法是 entryFor(kernelHost.ts:1741-1753)——Connections 界面用的是 broker 自己的 accounts() 结果:
if (provider.kind === 'broker-account') {
const accounts = await provider.accounts();
if (accounts.ok) {
hasAccount = accounts.data.length > 0;
accountLabel = accounts.data[0]?.name ?? null;
}
}
LongbridgeBrokerAccountProvider.accounts()(packages/shared/src/providers/longbridge/broker.ts:72-92)在未登录时返回 { ok: false, error: { code: 'AUTH_EXPIRED' } },登录后返回 data.length === 1,因此它是这两个字段的准确来源。
复现
- 不执行任何券商登录,启动应用。
- 触发
diagnostics:collect / diagnostics:export(apps/electron/src/main/index.ts:396、:404)。
- 实际:
providers.broker = { connected: true, accountCount: 1 }。
- 预期:
{ connected: false, accountCount: 0 }。
反过来也一样:真正登录后无法从前端区分「已登录」与「只是注册了 provider」。
修复
apps/electron/src/main/kernelHost.ts 新增 brokerAccountFacts():
- 按
kind === 'broker-account' 取到 broker provider(不再重复硬编码 vendor id 字面量);
- 调用
accounts(),ok && data.length > 0 才算已连接,accountCount 取 data.length;
- 调用抛错时按未连接/0 上报;
collectDiagnostics 用其结果替换原来的两个常量表达式。
诊断包不应因为探测失败而失败,因此探测全程包在 try/catch 内,失败态即「未连接」。
验证
bun test apps/electron/src/main/kernelHost.test.ts
- 修复前:
13 pass / 1 fail
- 新增用例拿到
{ connected: true, accountCount: 1 },期望 { connected: false, accountCount: 0 }
- 修复后:
14 pass / 0 fail
- 另有一条反向用例:
accounts() 返回 1 个账户时上报 { connected: true, accountCount: 1 }
bun run typecheck:5 个 workspace 全部 Exited with code 0
测试侧顺带把 electron mock 的 app.getVersion / app.isPackaged 补上(原来只有 getPath),否则 collectDiagnostics 在本进程内不可调用。
影响范围
只影响诊断包里 broker 的两个字段,不改变 Connections 界面(listConnections/entryFor 路径),也不改变任何 IPC 契约形状。
现象
导出的诊断包里
providers.broker恒为{ connected: true, accountCount: 1 }—— 与用户是否真的登录过券商账号无关。根因
apps/electron/src/main/kernelHost.ts:1592-1593providerSummaries来自listFinancialProviders()(kernelHost.ts:2464-2476),而它只是this.providerRouter.list()的映射 —— 列出的是所有已注册的 provider。broker 在构造函数里被无条件注册(kernelHost.ts:341):因此
some((p) => p.id === 'longbridge-broker')是个常量true:两个字段都退化成常量,账户数还是字面量1,从未查询过真实账户。同文件的正确写法是
entryFor(kernelHost.ts:1741-1753)——Connections 界面用的是 broker 自己的accounts()结果:LongbridgeBrokerAccountProvider.accounts()(packages/shared/src/providers/longbridge/broker.ts:72-92)在未登录时返回{ ok: false, error: { code: 'AUTH_EXPIRED' } },登录后返回data.length === 1,因此它是这两个字段的准确来源。复现
diagnostics:collect/diagnostics:export(apps/electron/src/main/index.ts:396、:404)。providers.broker = { connected: true, accountCount: 1 }。{ connected: false, accountCount: 0 }。反过来也一样:真正登录后无法从前端区分「已登录」与「只是注册了 provider」。
修复
apps/electron/src/main/kernelHost.ts新增brokerAccountFacts():kind === 'broker-account'取到 broker provider(不再重复硬编码 vendor id 字面量);accounts(),ok && data.length > 0才算已连接,accountCount取data.length;collectDiagnostics用其结果替换原来的两个常量表达式。诊断包不应因为探测失败而失败,因此探测全程包在 try/catch 内,失败态即「未连接」。
验证
bun test apps/electron/src/main/kernelHost.test.ts13 pass / 1 fail{ connected: true, accountCount: 1 },期望{ connected: false, accountCount: 0 }14 pass / 0 failaccounts()返回 1 个账户时上报{ connected: true, accountCount: 1 }bun run typecheck:5 个 workspace 全部Exited with code 0测试侧顺带把 electron mock 的
app.getVersion/app.isPackaged补上(原来只有getPath),否则collectDiagnostics在本进程内不可调用。影响范围
只影响诊断包里 broker 的两个字段,不改变 Connections 界面(
listConnections/entryFor路径),也不改变任何 IPC 契约形状。