feat: finalize mindspace service extraction phase a
This commit is contained in:
+26
-7
@@ -265,11 +265,25 @@ function mergeDeveloperTools(capabilities) {
|
||||
return tools;
|
||||
}
|
||||
|
||||
function resolveSandboxMcpLocalRoot(sandboxMcp) {
|
||||
const localRoot = sandboxMcp?.workspaceRoot || sandboxMcp?.sandboxRoot || '';
|
||||
return localRoot ? String(localRoot) : '';
|
||||
}
|
||||
|
||||
function resolveSandboxMcpCompatRoot(sandboxMcp) {
|
||||
const compatRoot = sandboxMcp?.sandboxRoot || sandboxMcp?.workspaceRoot || '';
|
||||
return compatRoot ? String(compatRoot) : '';
|
||||
}
|
||||
|
||||
function sandboxMcpEnvs(sandboxMcp, mcpTools) {
|
||||
const localRoot = resolveSandboxMcpLocalRoot(sandboxMcp);
|
||||
const compatRoot = resolveSandboxMcpCompatRoot(sandboxMcp);
|
||||
const envs = {
|
||||
SANDBOX_ROOT: sandboxMcp.sandboxRoot,
|
||||
ALLOWED_TOOLS: mcpTools.join(','),
|
||||
};
|
||||
if (compatRoot) envs.SANDBOX_ROOT = compatRoot;
|
||||
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 of [
|
||||
'DATABASE_URL',
|
||||
@@ -289,9 +303,11 @@ function sandboxMcpEnvs(sandboxMcp, mcpTools) {
|
||||
* Build goose agent/start extension_overrides from resolved capability flags.
|
||||
* Returns null when the caller should use server defaults (admin / unrestricted).
|
||||
*
|
||||
* sandboxMcp: { serverPath, sandboxRoot, nodeExecPath? }
|
||||
* When provided for a static_publish user, the built-in developer extension is replaced
|
||||
* by a sandboxed stdio MCP that enforces filesystem boundaries at the OS level.
|
||||
* sandboxMcp: { serverPath, sandboxRoot?, workspaceRoot?, workspaceRef?, nodeExecPath? }
|
||||
* `sandboxRoot` remains the legacy local-path compatibility field.
|
||||
* `workspaceRoot` is the preferred local adapter field for future MindSpace runtime extraction.
|
||||
* When a local root is available for a static_publish user, the built-in developer extension
|
||||
* is replaced by a sandboxed stdio MCP that enforces filesystem boundaries at the OS level.
|
||||
*/
|
||||
export function buildAgentExtensionPolicy(
|
||||
capabilities,
|
||||
@@ -303,7 +319,9 @@ export function buildAgentExtensionPolicy(
|
||||
|
||||
const extensions = [];
|
||||
if (capabilities.static_publish || (capabilities.private_data_space && sandboxMcp)) {
|
||||
if (sandboxMcp?.serverPath && sandboxMcp?.sandboxRoot) {
|
||||
const localRoot = resolveSandboxMcpLocalRoot(sandboxMcp);
|
||||
const compatRoot = resolveSandboxMcpCompatRoot(sandboxMcp);
|
||||
if (sandboxMcp?.serverPath && localRoot) {
|
||||
// Sandboxed stdio MCP: enforces SANDBOX_ROOT at the OS level.
|
||||
// Replaces the built-in developer extension so path traversal is impossible.
|
||||
const mcpTools = sandboxMcpTools(capabilities);
|
||||
@@ -316,8 +334,9 @@ export function buildAgentExtensionPolicy(
|
||||
display_name: 'sandbox-fs',
|
||||
bundled: false,
|
||||
cmd: resolveSandboxMcpNodeExecPath(sandboxMcp.nodeExecPath),
|
||||
// sandboxRoot passed as argv[2] so it works even if goosed doesn't forward envs
|
||||
args: [sandboxMcp.serverPath, sandboxMcp.sandboxRoot],
|
||||
// Legacy MCP still accepts a local filesystem root as argv[2] even when the source
|
||||
// capability is named workspaceRoot instead of sandboxRoot.
|
||||
args: [sandboxMcp.serverPath, compatRoot],
|
||||
// envs (goosed field name) as belt-and-suspenders backup
|
||||
envs: sandboxMcpEnvs(sandboxMcp, mcpTools),
|
||||
available_tools: mcpTools,
|
||||
|
||||
Reference in New Issue
Block a user