merge: server architecture modularization

This commit is contained in:
john
2026-07-24 19:18:14 +08:00
113 changed files with 29618 additions and 5864 deletions
+73 -11
View File
@@ -2,11 +2,25 @@ import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { resolveAgentGooseMode } from './policies.mjs';
/** Spawned as a separate Node process by goosed; must sit beside bundled portal runtime. */
export function resolveSandboxMcpServerPath(overridePath) {
function resolveBundledMcpServerPath(filename, overridePath, runtimeRoot) {
const normalized = String(overridePath ?? '').trim();
if (normalized) return normalized;
return path.join(path.dirname(fileURLToPath(import.meta.url)), 'mindspace-sandbox-mcp.mjs');
const normalizedRuntimeRoot = String(
runtimeRoot ?? process.env.MEMIND_PORTAL_H5_ROOT ?? '',
).trim();
return path.join(
normalizedRuntimeRoot || path.dirname(fileURLToPath(import.meta.url)),
filename,
);
}
/** Spawned as a separate Node process by goosed; must sit beside bundled portal runtime. */
export function resolveSandboxMcpServerPath(overridePath, runtimeRoot) {
return resolveBundledMcpServerPath(
'mindspace-sandbox-mcp.mjs',
overridePath,
runtimeRoot,
);
}
export function resolveSandboxMcpNodeExecPath(overridePath) {
@@ -17,6 +31,25 @@ export function resolveSandboxMcpNodeExecPath(overridePath) {
const LOOPBACK_PG_HOSTS = new Set(['127.0.0.1', 'localhost', '::1']);
function rewritePgUnixSocketUrlForContainer(sourceUrl, hostGateway) {
const raw = String(sourceUrl ?? '').trim();
const authorityMatch = raw.match(/^(postgres(?:ql)?:\/\/[^@/]+@)\/(.*)$/i);
if (!authorityMatch) return null;
try {
const parsed = new URL(`${authorityMatch[1]}localhost/${authorityMatch[2]}`);
const socketHost = String(parsed.searchParams.get('host') ?? '').trim();
if (!socketHost.startsWith('/')) return null;
const port = String(parsed.searchParams.get('port') ?? '5432').trim() || '5432';
parsed.hostname = String(hostGateway || 'host.docker.internal').trim();
parsed.port = port;
parsed.searchParams.delete('host');
parsed.searchParams.delete('port');
return parsed.toString();
} catch {
return null;
}
}
export function resolveSandboxMcpUserDataPgUrl({
portalUrl,
mcpUrl,
@@ -36,16 +69,30 @@ export function resolveSandboxMcpUserDataPgUrl({
}
return parsed.toString();
} catch {
const rewrittenSocketUrl = rewritePgUnixSocketUrlForContainer(sourceUrl, hostGateway);
if (rewrittenSocketUrl) {
const parsed = new URL(rewrittenSocketUrl);
if (!parsed.password) {
const error = new Error(
'Containerized private-data MCP cannot convert a passwordless PostgreSQL Unix-socket DSN to TCP. Configure MINDSPACE_USERDATA_MCP_PG_URL with a container-reachable authenticated DSN.',
);
error.code = 'MINDSPACE_USERDATA_MCP_PG_URL_REQUIRED';
throw error;
}
return rewrittenSocketUrl;
}
// Preserve the configured value so the MCP reports the real configuration
// error instead of silently falling back to its local Unix socket default.
return sourceUrl;
}
}
export function resolveMindSearchMcpServerPath(overridePath) {
const normalized = String(overridePath ?? '').trim();
if (normalized) return normalized;
return path.join(path.dirname(fileURLToPath(import.meta.url)), 'tkmind-search-mcp.mjs');
export function resolveMindSearchMcpServerPath(overridePath, runtimeRoot) {
return resolveBundledMcpServerPath(
'tkmind-search-mcp.mjs',
overridePath,
runtimeRoot,
);
}
export function resolveMindSearchMcpEndpoint(
@@ -65,10 +112,12 @@ export function resolveMindSearchMcpEndpoint(
}
}
export function resolveExcelMcpServerPath(overridePath) {
const normalized = String(overridePath ?? '').trim();
if (normalized) return normalized;
return path.join(path.dirname(fileURLToPath(import.meta.url)), 'tkmind-excel-mcp.mjs');
export function resolveExcelMcpServerPath(overridePath, runtimeRoot) {
return resolveBundledMcpServerPath(
'tkmind-excel-mcp.mjs',
overridePath,
runtimeRoot,
);
}
export const CAPABILITY_CATALOG = [
@@ -369,6 +418,19 @@ function sandboxMcpEnvs(sandboxMcp, mcpTools) {
if (sandboxMcp.workspaceRoot || localRoot) envs.MINDSPACE_WORKSPACE_ROOT = sandboxMcp.workspaceRoot || localRoot;
if (sandboxMcp.workspaceRef) envs.MINDSPACE_WORKSPACE_REF = sandboxMcp.workspaceRef;
if (sandboxMcp.userId) envs.PRIVATE_DATA_USER_ID = sandboxMcp.userId;
for (const [key, value] of [
['H5_PUBLIC_BASE_URL', sandboxMcp.publicBaseUrl],
['H5_PORTAL_BASE_URL', sandboxMcp.portalBaseUrl],
['H5_PORT', sandboxMcp.portalPort],
[
'MEMIND_PAGE_DATA_DELIVERY_BASE_URL',
sandboxMcp.pageDataDeliveryBaseUrl,
],
]) {
if (value != null && String(value).trim()) {
envs[key] = String(value).trim();
}
}
if (mcpTools.includes('generate_image')) {
if (sandboxMcp.agentApiBaseUrl) {
envs.MINDSPACE_AGENT_API_BASE_URL = sandboxMcp.agentApiBaseUrl;