迭代18: QMT Bridge MCP 能力内建(R-020)—— 动态挂载 dsh-mcp-client + 状态出口(设置页/会话头部灯)
This commit is contained in:
+2
-2
@@ -60,8 +60,8 @@ const HANDLERS = [
|
||||
* @param {import('@deepseek-ai/cordis').Context} ctx
|
||||
* @param {object} runtime { manager, settings, dataSource, marketCache }
|
||||
*/
|
||||
export function registerApi(ctx, { manager, settings, dataSource, marketHub, marketFeed, qmtHealthMonitor, storage, tradeSync, positionSync, attribution }) {
|
||||
const runtime = { ctx, manager, settings, dataSource, marketHub, marketFeed, qmtHealthMonitor, storage, tradeSync, positionSync, attribution };
|
||||
export function registerApi(ctx, { manager, settings, dataSource, marketHub, marketFeed, qmtHealthMonitor, storage, tradeSync, positionSync, attribution, mcpManager }) {
|
||||
const runtime = { ctx, manager, settings, dataSource, marketHub, marketFeed, qmtHealthMonitor, storage, tradeSync, positionSync, attribution, mcpManager };
|
||||
|
||||
ctx.effect(() => ctx.webServer.register({
|
||||
kind: 'prefix',
|
||||
|
||||
+2
-1
@@ -42,7 +42,7 @@ function projectQuote(hub, code, snap) {
|
||||
* @param {object} args
|
||||
* @param {object} runtime { settings, dataSource, marketHub, marketFeed(=QuoteSync), qmtHealthMonitor, positionSync }
|
||||
*/
|
||||
export async function handleMarket(method, args, { settings, dataSource, marketHub, marketFeed: marketSync, qmtHealthMonitor, positionSync }) {
|
||||
export async function handleMarket(method, args, { settings, dataSource, marketHub, marketFeed: marketSync, qmtHealthMonitor, positionSync, mcpManager }) {
|
||||
switch (method) {
|
||||
case 'market-snapshot': {
|
||||
const codes = Array.isArray(args.codes) ? args.codes : [];
|
||||
@@ -86,6 +86,7 @@ export async function handleMarket(method, args, { settings, dataSource, marketH
|
||||
? { ...marketSync.getStatus(), state: state(marketSync.getStatus()) }
|
||||
: null,
|
||||
qmt: qmtHealthMonitor ? qmtHealthMonitor.getStatus() : null,
|
||||
mcp: mcpManager ? mcpManager.getStatus() : null, // R-020/迭代18:QMT MCP 状态(会话头部指示灯)
|
||||
};
|
||||
}
|
||||
case 'sync-now': {
|
||||
|
||||
@@ -28,6 +28,7 @@ export const QMT_METHODS = new Set([
|
||||
'qmt-connections/set-default',
|
||||
'qmt-connections/test',
|
||||
'qmt-connections/active-host',
|
||||
'qmt-connections/mcp-status', // R-020/迭代18:QMT MCP 状态(probe / 缓存)
|
||||
]);
|
||||
|
||||
/** 服务端代理测试连接:GET {baseUrl}/health(浏览器跨域规避,Q3 手动测试) */
|
||||
@@ -63,7 +64,7 @@ async function testQmtConnection(ctx, args) {
|
||||
* @param {object} args
|
||||
* @param {object} runtime { manager, settings, dataSource, marketCache }
|
||||
*/
|
||||
export async function handleQmt(method, args, { ctx, settings, dataSource, marketFeed, qmtHealthMonitor }) {
|
||||
export async function handleQmt(method, args, { ctx, settings, dataSource, marketFeed, qmtHealthMonitor, mcpManager }) {
|
||||
switch (method) {
|
||||
case 'qmt-connections': {
|
||||
const state = getQmtConnections(settings);
|
||||
@@ -80,6 +81,8 @@ export async function handleQmt(method, args, { ctx, settings, dataSource, marke
|
||||
marketFeed?.setBaseUrl(value.baseUrl);
|
||||
qmtHealthMonitor?.probe(); // 切换后立即补探健康
|
||||
ctx?.logger?.info('[one-divine-lot] 激活配置地址已变更,数据源热切换 → ' + value.baseUrl);
|
||||
// R-020/迭代18:MCP 目标地址随激活地址变更重挂
|
||||
mcpManager?.resync(value.baseUrl).catch(() => {});
|
||||
}
|
||||
return value;
|
||||
}
|
||||
@@ -94,6 +97,8 @@ export async function handleQmt(method, args, { ctx, settings, dataSource, marke
|
||||
qmtHealthMonitor?.probe(); // 切换后立即补探健康
|
||||
ctx?.logger?.info('[one-divine-lot] 激活配置已删除,自动切换 → ' + active.name + ' (' + active.baseUrl + ')');
|
||||
}
|
||||
// R-020/迭代18:激活已变(或列表清空)→ MCP 跟随新激活 / 卸载
|
||||
mcpManager?.resync(active?.baseUrl).catch(() => {});
|
||||
return { ...afterState, active, removedWasActive: result.removedWasActive, removedWasDefault: result.removedWasDefault };
|
||||
}
|
||||
case 'qmt-connections/activate': {
|
||||
@@ -105,6 +110,8 @@ export async function handleQmt(method, args, { ctx, settings, dataSource, marke
|
||||
qmtHealthMonitor?.probe(); // 切换后立即补探健康
|
||||
ctx?.logger?.info('[one-divine-lot] QMT 连接激活: ' + active.name + ' (' + active.baseUrl + ')');
|
||||
}
|
||||
// R-020/迭代18:激活切换 → MCP 实例跟随(卸旧挂新,url=新激活 baseUrl+/mcp)
|
||||
mcpManager?.resync(active?.baseUrl).catch(() => {});
|
||||
return { ...state, active };
|
||||
}
|
||||
case 'qmt-connections/set-default':
|
||||
@@ -132,6 +139,12 @@ export async function handleQmt(method, args, { ctx, settings, dataSource, marke
|
||||
} catch { /* baseUrl 非法时返回空 */ }
|
||||
return { name: active.name, baseUrl, host, wsUrl, activeId: state.activeId ?? '' };
|
||||
}
|
||||
case 'qmt-connections/mcp-status': {
|
||||
// R-020/迭代18:MCP 状态(缓存秒回;refresh=true 即时探测)
|
||||
if (!mcpManager) return { state: 'disabled', error: 'mcpManager 不可用', checkedAt: 0 };
|
||||
if (args.refresh) return await mcpManager.probe();
|
||||
return mcpManager.getStatus();
|
||||
}
|
||||
default:
|
||||
throw Object.assign(new Error('unknown qmt method: ' + method), { code: 'not-found' });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user