feat(goose): complete v1.49 phase3 closeout gates and context fusion plan
Expand Goose v1.49 smoke coverage (memory chat, portal resume, page e2e, multiturn provider), add canary memory policy lock, refresh baselines, and ignore one-off evidence artifacts. Document headroom-based context runtime fusion plan; include auth, scheduled-task, and wechat intent fixes on branch. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+104
-71
@@ -1937,6 +1937,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,
|
||||
{
|
||||
@@ -1952,13 +2025,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,
|
||||
@@ -1971,71 +2064,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