wuyiqunLu commited on
Commit
eae2367
Β·
unverified Β·
1 Parent(s): 8449c08

feat: enqueue final error to ui on streaming error and timeout (#83)

Browse files

![image](https://github.com/landing-ai/vision-agent-ui/assets/132986242/dbe9bedf-60d7-4422-b1f0-04ca232b7a53)
<img width="1423" alt="image"
src="https://github.com/landing-ai/vision-agent-ui/assets/132986242/c2cb87c1-aed5-42a4-802d-1b75bab0968e">

app/api/vision-agent/route.ts CHANGED
@@ -11,7 +11,7 @@ import { getPresignedUrl } from '@/lib/aws';
11
  // export const runtime = 'edge';
12
  export const dynamic = 'force-dynamic';
13
  export const maxDuration = 300; // This function can run for a maximum of 5 minutes
14
- const TIMEOUT_MILI_SECONDS = 5 * 60 * 1000;
15
 
16
  const uploadBase64 = async (
17
  base64: string,
@@ -172,9 +172,21 @@ export const POST = withLogging(
172
  request,
173
  '__Agent_timeout__',
174
  );
175
- controller.error(
176
- `Haven't received any response in last ${TIMEOUT_MILI_SECONDS / 60000} minutes, agent timed out.`,
 
 
 
 
 
 
 
 
 
 
177
  );
 
 
178
  }
179
  } else {
180
  time = Date.now();
@@ -187,6 +199,9 @@ export const POST = withLogging(
187
  ) => {
188
  try {
189
  const msg = JSON.parse(line);
 
 
 
190
  if (
191
  msg.type !== 'final_code' &&
192
  (msg.type !== 'code' ||
@@ -231,7 +246,6 @@ export const POST = withLogging(
231
  if (mp4) result.results[index].mp4 = resp;
232
  }
233
  msg.payload.result = JSON.stringify(result);
234
- done = true;
235
  return JSON.stringify(msg);
236
  } catch (e) {
237
  errorCallback?.(e as Error);
 
11
  // export const runtime = 'edge';
12
  export const dynamic = 'force-dynamic';
13
  export const maxDuration = 300; // This function can run for a maximum of 5 minutes
14
+ const TIMEOUT_MILI_SECONDS = 2 * 60 * 1000;
15
 
16
  const uploadBase64 = async (
17
  base64: string,
 
172
  request,
173
  '__Agent_timeout__',
174
  );
175
+ controller.enqueue(
176
+ encoder.encode(
177
+ JSON.stringify({
178
+ type: 'final_error',
179
+ status: 'failed',
180
+ payload: {
181
+ name: 'AgentTimeout',
182
+ value: `Haven't received any response in last ${TIMEOUT_MILI_SECONDS / 60000} minutes, agent timed out.`,
183
+ traceback_raw: [],
184
+ },
185
+ }) + '\n',
186
+ ),
187
  );
188
+ controller.close();
189
+ return;
190
  }
191
  } else {
192
  time = Date.now();
 
199
  ) => {
200
  try {
201
  const msg = JSON.parse(line);
202
+ if (msg.type === 'final_code' || msg.type === 'final_error') {
203
+ done = true;
204
+ }
205
  if (
206
  msg.type !== 'final_code' &&
207
  (msg.type !== 'code' ||
 
246
  if (mp4) result.results[index].mp4 = resp;
247
  }
248
  msg.payload.result = JSON.stringify(result);
 
249
  return JSON.stringify(msg);
250
  } catch (e) {
251
  errorCallback?.(e as Error);
lib/utils/content.ts CHANGED
@@ -72,55 +72,6 @@ type ReflectionBody =
72
  payload: { feedback: string; success: boolean };
73
  };
74
 
75
- type MessageBody =
76
- | PlansBody
77
- | ToolsBody
78
- | CodeBody
79
- | ReflectionBody
80
- | PrismaJson.FinalChatResult;
81
-
82
- const getMessageTitle = (json: MessageBody) => {
83
- switch (json.type) {
84
- case 'plans':
85
- if (json.status === 'started') {
86
- return '🎬 Start generating plans...\n';
87
- } else {
88
- return 'βœ… Going to run the following plan(s) in sequence:\n';
89
- }
90
- case 'tools':
91
- if (json.status === 'started') {
92
- return '🎬 Start retrieving tools...\n';
93
- } else {
94
- return 'βœ… Tools retrieved:\n';
95
- }
96
- case 'code':
97
- if (json.status === 'started') {
98
- return '🎬 Start generating code...\n';
99
- } else if (json.status === 'running') {
100
- return '🎬 Code generated, start execution... ';
101
- } else if (json.status === 'completed') {
102
- return 'βœ… Code executed successfully. ';
103
- } else {
104
- return '❌ Code execution failed. ';
105
- }
106
- case 'self_reflection':
107
- if (json.status === 'started') {
108
- return '🎬 Start self reflection...\n';
109
- } else if (json.status === 'completed') {
110
- return 'βœ… Self reflection completed: \n';
111
- } else {
112
- return '❌ Self reflection failed: \n';
113
- }
114
- case 'final_code':
115
- if (json.status === 'completed') {
116
- return 'βœ… The vision agent has concluded the chat, the last execution is successful. \n';
117
- } else {
118
- return '❌ The vision agent has concluded the chat, the last execution is failed. \n';
119
- }
120
- default:
121
- throw 'Not supported type';
122
- }
123
- };
124
 
125
  export type CodeResult = {
126
  code: string;
@@ -130,7 +81,7 @@ export type CodeResult = {
130
 
131
  export type ChunkBody =
132
  | {
133
- type: 'plans' | 'tools' | 'code' | 'final_code';
134
  status: 'started' | 'completed' | 'failed' | 'running';
135
  payload:
136
  | Array<Record<string, string>> // PlansBody | ToolsBody
 
72
  payload: { feedback: string; success: boolean };
73
  };
74
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
 
76
  export type CodeResult = {
77
  code: string;
 
81
 
82
  export type ChunkBody =
83
  | {
84
+ type: 'plans' | 'tools' | 'code' | 'final_code' | 'final_error';
85
  status: 'started' | 'completed' | 'failed' | 'running';
86
  payload:
87
  | Array<Record<string, string>> // PlansBody | ToolsBody