201 lines
6.0 KiB
JavaScript
201 lines
6.0 KiB
JavaScript
import {
|
|
createAgentRunEventsHandler,
|
|
createGetAgentRunHandler,
|
|
createPostAgentRunsHandler,
|
|
} from '../agent-run-routes.mjs';
|
|
import { executeDeepSearchLlmGateway } from '../deep-search-llm-gateway.mjs';
|
|
|
|
function assertRouter(api) {
|
|
if (
|
|
!api ||
|
|
typeof api.get !== 'function' ||
|
|
typeof api.post !== 'function'
|
|
) {
|
|
throw new Error(
|
|
'attachPortalAgentRuntimeRoutes requires an Express-compatible router',
|
|
);
|
|
}
|
|
}
|
|
|
|
function runHandlerChain(chain, req, res, next) {
|
|
let index = 0;
|
|
const run = (error) => {
|
|
if (error) return next(error);
|
|
const layer = chain[index++];
|
|
if (!layer) return;
|
|
layer(req, res, run);
|
|
};
|
|
run();
|
|
}
|
|
|
|
export function attachPortalAgentRuntimeRoutes(
|
|
api,
|
|
{
|
|
waitForUserAuthReady = async () => {},
|
|
getUserAuth = () => null,
|
|
getTkmindProxy = () => null,
|
|
getLlmProviderService = () => null,
|
|
getAgentRunGateway = () => null,
|
|
getSessionAccess = () => null,
|
|
getMindSpaceAssetAgent = () => null,
|
|
getCodeRunPolicyService = () => null,
|
|
getUserToken = () => null,
|
|
getDeepSearchInternalSecret = () => null,
|
|
bearerToken = () => null,
|
|
ownsAgentSession = async () => false,
|
|
executeDeepSearchLlmGatewayFn =
|
|
executeDeepSearchLlmGateway,
|
|
createPostAgentRunsHandlerFn = createPostAgentRunsHandler,
|
|
createGetAgentRunHandlerFn = createGetAgentRunHandler,
|
|
createAgentRunEventsHandlerFn = createAgentRunEventsHandler,
|
|
logger = console,
|
|
} = {},
|
|
) {
|
|
assertRouter(api);
|
|
|
|
api.post('/internal/deep-search/llm', async (req, res) => {
|
|
try {
|
|
const result = await executeDeepSearchLlmGatewayFn({
|
|
llmProviderService: getLlmProviderService(),
|
|
expectedSecret: getDeepSearchInternalSecret(),
|
|
providedSecret:
|
|
bearerToken(req) ?? req.get('x-secret-key'),
|
|
input: req.body ?? {},
|
|
});
|
|
return res.status(result.status).json(result.body);
|
|
} catch (error) {
|
|
logger.warn('[deep-search] LLM gateway failed:', error);
|
|
return res.status(502).json({
|
|
ok: false,
|
|
message:
|
|
error instanceof Error
|
|
? error.message
|
|
: 'Deep Search LLM gateway failed',
|
|
});
|
|
}
|
|
});
|
|
|
|
api.post('/llm/apply-local-fallback', async (req, res) => {
|
|
// Client calls after creditsExhausted or relay 500 (see useTKMindChat).
|
|
await waitForUserAuthReady();
|
|
const userAuth = getUserAuth();
|
|
const llmProviderService = getLlmProviderService();
|
|
const tkmindProxy = getTkmindProxy();
|
|
if (!userAuth || !llmProviderService || !tkmindProxy) {
|
|
return res.status(503).json({ message: '未启用 LLM 配置' });
|
|
}
|
|
const me = await userAuth.getMe(getUserToken(req));
|
|
if (!me) return res.status(401).json({ message: '未登录' });
|
|
const sessionId = String(req.body?.session_id ?? '').trim();
|
|
if (!sessionId) return res.status(400).json({ message: '缺少 session_id' });
|
|
const owns = await ownsAgentSession(me.id, sessionId);
|
|
if (!owns) return res.status(403).json({ message: '无权访问该会话' });
|
|
try {
|
|
const result = await tkmindProxy.applyLocalFallbackForSession(sessionId);
|
|
if (!result.ok) return res.status(503).json(result);
|
|
return res.json(result);
|
|
} catch (error) {
|
|
return res.status(500).json({
|
|
message: error instanceof Error ? error.message : '切换本地 LLM 失败',
|
|
});
|
|
}
|
|
});
|
|
|
|
api.post('/agent/start', async (req, res, next) => {
|
|
await waitForUserAuthReady();
|
|
const userAuth = getUserAuth();
|
|
const tkmindProxy = getTkmindProxy();
|
|
if (!userAuth || !tkmindProxy) return next();
|
|
return runHandlerChain(
|
|
tkmindProxy.handlers['POST /agent/start'],
|
|
req,
|
|
res,
|
|
next,
|
|
);
|
|
});
|
|
|
|
api.post('/agent/runs', async (req, res, next) => {
|
|
await waitForUserAuthReady();
|
|
const userAuth = getUserAuth();
|
|
const tkmindProxy = getTkmindProxy();
|
|
const agentRunGateway = getAgentRunGateway();
|
|
if (!userAuth || !tkmindProxy || !agentRunGateway) return next();
|
|
return runHandlerChain(
|
|
[
|
|
tkmindProxy.requireUser,
|
|
tkmindProxy.ensureChatAllowed,
|
|
createPostAgentRunsHandlerFn({
|
|
userAuth,
|
|
sessionAccess: getSessionAccess(),
|
|
agentRunGateway,
|
|
mindSpaceAssetAgent: getMindSpaceAssetAgent(),
|
|
codeRunPolicyService: getCodeRunPolicyService(),
|
|
}),
|
|
],
|
|
req,
|
|
res,
|
|
next,
|
|
);
|
|
});
|
|
|
|
api.get('/agent/runs/:runId', async (req, res, next) => {
|
|
await waitForUserAuthReady();
|
|
const userAuth = getUserAuth();
|
|
const tkmindProxy = getTkmindProxy();
|
|
const agentRunGateway = getAgentRunGateway();
|
|
if (!userAuth || !tkmindProxy || !agentRunGateway) return next();
|
|
return runHandlerChain(
|
|
[
|
|
tkmindProxy.requireUser,
|
|
createGetAgentRunHandlerFn({ agentRunGateway }),
|
|
],
|
|
req,
|
|
res,
|
|
next,
|
|
);
|
|
});
|
|
|
|
api.get('/agent/runs/:runId/events', async (req, res, next) => {
|
|
await waitForUserAuthReady();
|
|
const userAuth = getUserAuth();
|
|
const tkmindProxy = getTkmindProxy();
|
|
const agentRunGateway = getAgentRunGateway();
|
|
if (!userAuth || !tkmindProxy || !agentRunGateway) return next();
|
|
return runHandlerChain(
|
|
[
|
|
tkmindProxy.requireUser,
|
|
createAgentRunEventsHandlerFn({ agentRunGateway }),
|
|
],
|
|
req,
|
|
res,
|
|
next,
|
|
);
|
|
});
|
|
|
|
api.post('/agent/resume', async (req, res, next) => {
|
|
await waitForUserAuthReady();
|
|
const userAuth = getUserAuth();
|
|
const tkmindProxy = getTkmindProxy();
|
|
if (!userAuth || !tkmindProxy) return next();
|
|
return runHandlerChain(
|
|
tkmindProxy.handlers['POST /agent/resume'],
|
|
req,
|
|
res,
|
|
next,
|
|
);
|
|
});
|
|
|
|
api.get('/sessions', async (req, res, next) => {
|
|
await waitForUserAuthReady();
|
|
const userAuth = getUserAuth();
|
|
const tkmindProxy = getTkmindProxy();
|
|
if (!userAuth || !tkmindProxy) return next();
|
|
return runHandlerChain(
|
|
tkmindProxy.handlers['GET /sessions'],
|
|
req,
|
|
res,
|
|
next,
|
|
);
|
|
});
|
|
}
|