Skip to content

Commit 74a49aa

Browse files
authored
feat: better error message + allow agent to restart the sandbox dev server (#2584)
* allow agent to restart the sandbox dev server * surface better error messages
1 parent 51f4826 commit 74a49aa

File tree

8 files changed

+57
-4
lines changed

8 files changed

+57
-4
lines changed

apps/web/client/src/app/api/chat/route.ts

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,9 +186,28 @@ export const streamResponse = async (req: NextRequest) => {
186186
.then(({ api }) => api.usage.revertIncrement({ usageRecordId, rateLimitId }))
187187
.catch(error => console.error('Error in chat usage decrement', error));
188188
}
189-
throw error;
190189
},
191190
});
192191

193-
return result.toDataStreamResponse();
192+
return result.toDataStreamResponse(
193+
{
194+
getErrorMessage: errorHandler,
195+
}
196+
);
197+
}
198+
199+
export function errorHandler(error: unknown) {
200+
if (error == null) {
201+
return 'unknown error';
202+
}
203+
204+
if (typeof error === 'string') {
205+
return error;
206+
}
207+
208+
if (error instanceof Error) {
209+
return error.message;
210+
}
211+
212+
return JSON.stringify(error);
194213
}

apps/web/client/src/app/project/[id]/_components/right-panel/chat-tab/chat-messages/message-content/tool-call-simple.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
ONLOOK_INSTRUCTIONS_TOOL_NAME,
66
READ_FILES_TOOL_NAME,
77
READ_STYLE_GUIDE_TOOL_NAME,
8+
SANDBOX_TOOL_NAME,
89
SCRAPE_URL_TOOL_NAME,
910
TERMINAL_COMMAND_TOOL_NAME
1011
} from '@onlook/ai';
@@ -22,6 +23,7 @@ const TOOL_ICONS: Record<string, any> = {
2223
[CREATE_FILE_TOOL_NAME]: Icons.FilePlus,
2324
[TERMINAL_COMMAND_TOOL_NAME]: Icons.Terminal,
2425
[SCRAPE_URL_TOOL_NAME]: Icons.Globe,
26+
[SANDBOX_TOOL_NAME]: Icons.Cube,
2527
};
2628

2729
export function ToolCallSimple({

apps/web/client/src/app/project/[id]/_hooks/use-chat.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,6 @@ export function ChatProvider({ children }: { children: React.ReactNode }) {
3636
editorEngine.chat.error.handleChatError(new Error('Output length limit reached'));
3737
} else if (finishReason === 'content-filter') {
3838
editorEngine.chat.error.handleChatError(new Error('Content filter error'));
39-
} else if (finishReason === 'error') {
40-
editorEngine.chat.error.handleChatError(new Error('Error in chat'));
4139
} else if (finishReason === 'other' || finishReason === 'unknown') {
4240
editorEngine.chat.error.handleChatError(new Error('Unknown finish reason'));
4341
}

apps/web/client/src/components/store/editor/sandbox/session.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,15 @@ export class SessionManager {
3232
await this.createTerminalSessions(this.session);
3333
}
3434

35+
async restartDevServer(): Promise<boolean> {
36+
const task = await this.session?.tasks.get('dev');
37+
if (task) {
38+
await task.restart();
39+
return true;
40+
}
41+
return false;
42+
}
43+
3544
getTerminalSession(id: string) {
3645
return this.terminalSessions.get(id) as TerminalSession | undefined;
3746
}

apps/web/client/src/components/tools.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
ONLOOK_INSTRUCTIONS_TOOL_NAME,
1717
READ_FILES_TOOL_NAME,
1818
READ_STYLE_GUIDE_TOOL_NAME,
19+
SANDBOX_TOOL_NAME,
1920
SCRAPE_URL_TOOL_NAME,
2021
TERMINAL_COMMAND_TOOL_NAME,
2122
} from '@onlook/ai';
@@ -62,6 +63,8 @@ export async function handleToolCall(toolCall: ToolCall<string, unknown>, editor
6263
return await handleScrapeUrlTool(
6364
toolCall.args as z.infer<typeof SCRAPE_URL_TOOL_PARAMETERS>,
6465
);
66+
} else if (toolName === SANDBOX_TOOL_NAME) {
67+
return await handleSandboxTool(editorEngine);
6568
} else {
6669
throw new Error(`Unknown tool call: ${toolCall.toolName}`);
6770
}
@@ -209,4 +212,13 @@ async function handleScrapeUrlTool(
209212
console.error('Error scraping URL:', error);
210213
throw new Error(`Failed to scrape URL ${args.url}: ${error instanceof Error ? error.message : 'Unknown error'}`);
211214
}
215+
}
216+
217+
async function handleSandboxTool(editorEngine: EditorEngine): Promise<string> {
218+
const result = await editorEngine.sandbox.session.restartDevServer();
219+
if (result) {
220+
return 'Dev server restarted';
221+
} else {
222+
return 'Failed to restart dev server';
223+
}
212224
}

packages/ai/src/tools/files.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,11 @@ export const terminalCommandTool = tool({
6363
description: 'Run a Bash command in the terminal',
6464
parameters: TERMINAL_COMMAND_TOOL_PARAMETERS,
6565
});
66+
67+
export const SANDBOX_TOOL_NAME = 'restart_dev_server';
68+
export const SANDBOX_TOOL_PARAMETERS = z.object({});
69+
export const sandboxTool = tool({
70+
description:
71+
'Restart the development server. This should only be used if absolutely necessary such as if updating dependencies, clearing next cache, or if the server is not responding.',
72+
parameters: SANDBOX_TOOL_PARAMETERS,
73+
});

packages/ai/src/tools/tools.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import {
88
listFilesTool,
99
READ_FILES_TOOL_NAME,
1010
readFilesTool,
11+
SANDBOX_TOOL_NAME,
12+
sandboxTool,
1113
TERMINAL_COMMAND_TOOL_NAME,
1214
terminalCommandTool,
1315
} from './files';
@@ -28,6 +30,7 @@ export const buildToolSet: ToolSet = {
2830
[CREATE_FILE_TOOL_NAME]: createFileTool,
2931
[TERMINAL_COMMAND_TOOL_NAME]: terminalCommandTool,
3032
[SCRAPE_URL_TOOL_NAME]: scrapeUrlTool,
33+
[SANDBOX_TOOL_NAME]: sandboxTool,
3134
};
3235

3336
export const askToolSet: ToolSet = {

packages/ui/src/components/icons/index.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020
BorderSolidIcon,
2121
BorderTopIcon,
2222
BoxIcon,
23+
BoxModelIcon,
2324
ButtonIcon,
2425
ChatBubbleIcon,
2526
CheckCircledIcon,
@@ -1460,6 +1461,7 @@ export const Icons = {
14601461
Button: ButtonIcon,
14611462
Bookmark: BookmarkIcon,
14621463
BookmarkFilled: BookmarkFilledIcon,
1464+
BoxModel: BoxModelIcon,
14631465

14641466
ChatBubble: ChatBubbleIcon,
14651467
Check: CheckIcon,

0 commit comments

Comments
 (0)