Aksel Joonas Reedi commited on
Commit
6ac731b
·
2 Parent(s): 39742ba642f202

feat: require sandbox_create approval before sandbox operations

Browse files
agent/tools/sandbox_tool.py CHANGED
@@ -149,14 +149,11 @@ def _make_tool_handler(sandbox_tool_name: str):
149
  """Factory: create a handler for a sandbox operation tool."""
150
 
151
  async def handler(args: dict[str, Any], session: Any = None) -> tuple[str, bool]:
152
- # Auto-create sandbox if not present
153
- try:
154
- sb, error = await _ensure_sandbox(session)
155
- except Exception as e:
156
- return f"Failed to auto-create sandbox: {e}", False
157
 
158
- if error:
159
- return error, False
160
 
161
  try:
162
  result = await asyncio.to_thread(sb.call_tool, sandbox_tool_name, args)
 
149
  """Factory: create a handler for a sandbox operation tool."""
150
 
151
  async def handler(args: dict[str, Any], session: Any = None) -> tuple[str, bool]:
152
+ # Require sandbox to exist — user must approve sandbox_create first
153
+ if not session or not getattr(session, "sandbox", None):
154
+ return "No sandbox running. Call sandbox_create first to start one.", False
 
 
155
 
156
+ sb = session.sandbox
 
157
 
158
  try:
159
  result = await asyncio.to_thread(sb.call_tool, sandbox_tool_name, args)
frontend/src/components/Chat/ToolCallGroup.tsx CHANGED
@@ -104,6 +104,20 @@ function InlineApproval({
104
 
105
  return (
106
  <Box sx={{ px: 1.5, py: 1.5, borderTop: '1px solid var(--tool-border)' }}>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107
  {toolName === 'hf_jobs' && args && (
108
  <Box sx={{ mb: 1.5 }}>
109
  <Typography variant="body2" sx={{ color: 'var(--muted-text)', fontSize: '0.75rem', mb: 1 }}>
 
104
 
105
  return (
106
  <Box sx={{ px: 1.5, py: 1.5, borderTop: '1px solid var(--tool-border)' }}>
107
+ {toolName === 'sandbox_create' && args && (
108
+ <Box sx={{ mb: 1.5 }}>
109
+ <Typography variant="body2" sx={{ color: 'var(--muted-text)', fontSize: '0.75rem', mb: 1 }}>
110
+ Create sandbox on{' '}
111
+ <Box component="span" sx={{ fontWeight: 500, color: 'var(--text)' }}>
112
+ {String(args.hardware || 'cpu-basic')}
113
+ </Box>
114
+ {args.private && (
115
+ <Box component="span" sx={{ color: 'var(--muted-text)' }}> (private)</Box>
116
+ )}
117
+ </Typography>
118
+ </Box>
119
+ )}
120
+
121
  {toolName === 'hf_jobs' && args && (
122
  <Box sx={{ mb: 1.5 }}>
123
  <Typography variant="body2" sx={{ color: 'var(--muted-text)', fontSize: '0.75rem', mb: 1 }}>