Merge branch 'feature/goose-v149-local-canary'
Memind CI / Test, build, and release guards (push) Has been cancelled
Memind CI / Test, build, and release guards (push) Has been cancelled
This commit is contained in:
+104
-71
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user