Merge branch 'feature/goose-v149-local-canary'
Memind CI / Test, build, and release guards (push) Has been cancelled

This commit is contained in:
john
2026-09-09 22:01:45 +08:00
129 changed files with 54037 additions and 97 deletions
+104 -71
View File
@@ -1944,6 +1944,79 @@ export function createUserAuth(pool, options = {}) {
};
};
const resolveAgentSandboxMcpForUser = async (
user,
effectiveCapabilities,
{ sessionId = null, packageId = null } = {},
) => {
if (
!effectiveCapabilities.static_publish &&
!effectiveCapabilities.private_data_space &&
!effectiveCapabilities.excel_analysis
) {
return null;
}
try {
const workspaceCapability = resolveMindSpaceAgentWorkspaceCapability({
h5Root,
env,
user,
});
const containerFlag = String(env.GOOSED_MCP_CONTAINERIZED ?? '').trim();
const containerized = containerFlag
? containerFlag === '1'
: Boolean(
env.GOOSED_MCP_NODE_PATH &&
path.resolve(env.GOOSED_MCP_NODE_PATH) !== path.resolve(process.execPath),
);
return {
// When goosed runs in a container its filesystem is split from the portal's,
// so the host paths the portal would otherwise send (node binary, MCP script)
// are not resolvable. These env overrides let the portal send container-canonical
// paths instead. Unset (e.g. local dev, co-located native goosed) => fall back to
// the portal's own paths, so behavior is unchanged.
serverPath: resolveSandboxMcpServerPath(env.GOOSED_MCP_SERVER_PATH),
sandboxRoot: workspaceCapability.sandboxRoot,
workspaceRoot: workspaceCapability.workspaceRoot,
workspaceRef: workspaceCapability.workspaceRef,
sessionId:
String(sessionId ?? '').trim() ||
null,
packageId:
String(packageId ?? '').trim() ||
(String(sessionId ?? '').trim()
? `cp_${String(
sessionId,
).trim()}`
: null),
mcpBaseUrl:
env.MINDSPACE_MCP_BASE_URL ??
env.MINDSPACE_REMOTE_BASE_URL,
mcpTokenSecret:
env.MINDSPACE_MCP_TOKEN_SECRET,
userId: user.id,
nodeExecPath: env.GOOSED_MCP_NODE_PATH,
containerized,
userDataBackend: env.MINDSPACE_USERDATA_BACKEND,
userDataPgUrl: env.MINDSPACE_USERDATA_PG_URL,
userDataMcpPgUrl: env.MINDSPACE_USERDATA_MCP_PG_URL,
userDataPgHostGateway: env.MINDSPACE_USERDATA_MCP_PG_HOST,
userDataAutoProvision: env.MINDSPACE_USERDATA_AUTO_PROVISION,
agentApiBaseUrl: env.MINDSPACE_AGENT_API_BASE_URL,
publicBaseUrl: env.H5_PUBLIC_BASE_URL,
portalBaseUrl: env.H5_PORTAL_BASE_URL,
portalPort: env.H5_PORT,
pageDataDeliveryBaseUrl:
env.MEMIND_PAGE_DATA_DELIVERY_BASE_URL,
internalAgentSecret:
env.MINDSPACE_INTERNAL_AGENT_SECRET ?? env.TKMIND_SERVER__SECRET_KEY,
};
} catch (err) {
console.warn('[getAgentSessionPolicy] sandbox MCP setup failed, falling back:', err?.message);
return null;
}
};
const getAgentSessionPolicy = async (
userId,
{
@@ -1959,13 +2032,33 @@ export function createUserAuth(pool, options = {}) {
const mindSearchConfig = getMindSearchConfig ? await getMindSearchConfig({ userId, user }) : null;
await syncUserSkillsForUser(user);
if (capabilityState.unrestricted) {
const sandboxMcp = await resolveAgentSandboxMcpForUser(
user,
capabilityState.capabilities,
{ sessionId, packageId },
);
const basePolicy = buildAgentExtensionPolicy(capabilityState.capabilities, {
unrestricted: true,
toolMode,
mindSearchConfig,
userId: user.id,
});
const mindSpacePolicy = sandboxMcp
? buildAgentExtensionPolicy(capabilityState.capabilities, {
unrestricted: false,
policies: {},
sandboxMcp,
toolMode,
mindSearchConfig,
userId: user.id,
})
: null;
return {
...buildAgentExtensionPolicy(capabilityState.capabilities, {
unrestricted: true,
toolMode,
mindSearchConfig,
userId: user.id,
}),
...basePolicy,
...(mindSpacePolicy?.extensionOverrides?.length
? { extensionOverrides: mindSpacePolicy.extensionOverrides }
: {}),
capabilities: capabilityState.capabilities,
policies: {},
unrestricted: true,
toolMode,
@@ -1978,71 +2071,11 @@ export function createUserAuth(pool, options = {}) {
// Wire up the sandbox MCP for user workspace tools and the private data space.
// File and Excel operations are OS-bound to the user's workspace;
// private_data_* tools only touch the user's isolated PostgreSQL schema.
let sandboxMcp = null;
if (
effectiveCapabilities.static_publish ||
effectiveCapabilities.private_data_space ||
effectiveCapabilities.excel_analysis
) {
try {
const workspaceCapability = resolveMindSpaceAgentWorkspaceCapability({
h5Root,
env,
user,
});
const containerFlag = String(env.GOOSED_MCP_CONTAINERIZED ?? '').trim();
const containerized = containerFlag
? containerFlag === '1'
: Boolean(
env.GOOSED_MCP_NODE_PATH &&
path.resolve(env.GOOSED_MCP_NODE_PATH) !== path.resolve(process.execPath),
);
sandboxMcp = {
// When goosed runs in a container its filesystem is split from the portal's,
// so the host paths the portal would otherwise send (node binary, MCP script)
// are not resolvable. These env overrides let the portal send container-canonical
// paths instead. Unset (e.g. local dev, co-located native goosed) => fall back to
// the portal's own paths, so behavior is unchanged.
serverPath: resolveSandboxMcpServerPath(env.GOOSED_MCP_SERVER_PATH),
sandboxRoot: workspaceCapability.sandboxRoot,
workspaceRoot: workspaceCapability.workspaceRoot,
workspaceRef: workspaceCapability.workspaceRef,
sessionId:
String(sessionId ?? '').trim() ||
null,
packageId:
String(packageId ?? '').trim() ||
(String(sessionId ?? '').trim()
? `cp_${String(
sessionId,
).trim()}`
: null),
mcpBaseUrl:
env.MINDSPACE_MCP_BASE_URL ??
env.MINDSPACE_REMOTE_BASE_URL,
mcpTokenSecret:
env.MINDSPACE_MCP_TOKEN_SECRET,
userId: user.id,
nodeExecPath: env.GOOSED_MCP_NODE_PATH,
containerized,
userDataBackend: env.MINDSPACE_USERDATA_BACKEND,
userDataPgUrl: env.MINDSPACE_USERDATA_PG_URL,
userDataMcpPgUrl: env.MINDSPACE_USERDATA_MCP_PG_URL,
userDataPgHostGateway: env.MINDSPACE_USERDATA_MCP_PG_HOST,
userDataAutoProvision: env.MINDSPACE_USERDATA_AUTO_PROVISION,
agentApiBaseUrl: env.MINDSPACE_AGENT_API_BASE_URL,
publicBaseUrl: env.H5_PUBLIC_BASE_URL,
portalBaseUrl: env.H5_PORTAL_BASE_URL,
portalPort: env.H5_PORT,
pageDataDeliveryBaseUrl:
env.MEMIND_PAGE_DATA_DELIVERY_BASE_URL,
internalAgentSecret:
env.MINDSPACE_INTERNAL_AGENT_SECRET ?? env.TKMIND_SERVER__SECRET_KEY,
};
} catch (err) {
console.warn('[getAgentSessionPolicy] sandbox MCP setup failed, falling back:', err?.message);
}
}
const sandboxMcp = await resolveAgentSandboxMcpForUser(
user,
effectiveCapabilities,
{ sessionId, packageId },
);
return {
...buildAgentExtensionPolicy(effectiveCapabilities, {
unrestricted: false,