Spaces:
Sleeping
Sleeping
wuyiqunLu
commited on
fix: online stream message issue (#71)
Browse files- .gitignore +2 -1
- app/api/vision-agent/route.ts +31 -20
- components/chat/ChatMessage.tsx +1 -2
.gitignore
CHANGED
@@ -38,4 +38,5 @@ yarn-error.log*
|
|
38 |
.env*.local
|
39 |
|
40 |
# ts
|
41 |
-
tsconfig.tsbuildinfo
|
|
|
|
38 |
.env*.local
|
39 |
|
40 |
# ts
|
41 |
+
tsconfig.tsbuildinfo
|
42 |
+
certificates
|
app/api/vision-agent/route.ts
CHANGED
@@ -1,7 +1,8 @@
|
|
1 |
-
import { StreamingTextResponse } from 'ai';
|
2 |
|
3 |
// import { auth } from '@/auth';
|
4 |
import { MessageUI, SignedPayload } from '@/lib/types';
|
|
|
5 |
import { logger, withLogging } from '@/lib/logger';
|
6 |
import { CLEANED_SEPARATOR } from '@/lib/constants';
|
7 |
import { cleanAnswerMessage, cleanInputMessage } from '@/lib/utils/content';
|
@@ -145,29 +146,21 @@ export const POST = withLogging(
|
|
145 |
);
|
146 |
}
|
147 |
}
|
|
|
148 |
|
149 |
if (fetchResponse.body) {
|
150 |
const encoder = new TextEncoder();
|
151 |
const decoder = new TextDecoder('utf-8');
|
152 |
let maxChunkSize = 0;
|
153 |
-
const stream =
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
{
|
159 |
-
message: 'Streaming finished',
|
160 |
-
maxChunkSize,
|
161 |
-
},
|
162 |
-
request,
|
163 |
-
'__AGENT_DONE',
|
164 |
-
);
|
165 |
-
},
|
166 |
-
transform: async (chunk, controller) => {
|
167 |
-
const data = decoder.decode(chunk, { stream: true });
|
168 |
maxChunkSize = Math.max(data.length, maxChunkSize);
|
169 |
const lines = data.split('\n');
|
170 |
const results = [];
|
|
|
171 |
for (let line of lines) {
|
172 |
if (!line.trim()) {
|
173 |
continue;
|
@@ -194,6 +187,7 @@ export const POST = withLogging(
|
|
194 |
}
|
195 |
msg.payload.result = JSON.stringify(result);
|
196 |
results.push(JSON.stringify(msg));
|
|
|
197 |
} catch (e) {
|
198 |
console.error(e);
|
199 |
logger.error(
|
@@ -203,6 +197,7 @@ export const POST = withLogging(
|
|
203 |
},
|
204 |
request,
|
205 |
);
|
|
|
206 |
}
|
207 |
}
|
208 |
controller.enqueue(
|
@@ -210,10 +205,26 @@ export const POST = withLogging(
|
|
210 |
results.length === 0 ? '' : results.join('\n') + '\n',
|
211 |
),
|
212 |
);
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
217 |
} else {
|
218 |
return fetchResponse;
|
219 |
}
|
|
|
1 |
+
import { StreamingTextResponse, experimental_StreamData } from 'ai';
|
2 |
|
3 |
// import { auth } from '@/auth';
|
4 |
import { MessageUI, SignedPayload } from '@/lib/types';
|
5 |
+
|
6 |
import { logger, withLogging } from '@/lib/logger';
|
7 |
import { CLEANED_SEPARATOR } from '@/lib/constants';
|
8 |
import { cleanAnswerMessage, cleanInputMessage } from '@/lib/utils/content';
|
|
|
146 |
);
|
147 |
}
|
148 |
}
|
149 |
+
// const streamData = new experimental_StreamData();
|
150 |
|
151 |
if (fetchResponse.body) {
|
152 |
const encoder = new TextEncoder();
|
153 |
const decoder = new TextDecoder('utf-8');
|
154 |
let maxChunkSize = 0;
|
155 |
+
const stream = new ReadableStream({
|
156 |
+
async start(controller) {
|
157 |
+
// const parser = createParser(streamParser);
|
158 |
+
for await (const chunk of fetchResponse.body as any) {
|
159 |
+
const data = decoder.decode(chunk);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
160 |
maxChunkSize = Math.max(data.length, maxChunkSize);
|
161 |
const lines = data.split('\n');
|
162 |
const results = [];
|
163 |
+
let done = false;
|
164 |
for (let line of lines) {
|
165 |
if (!line.trim()) {
|
166 |
continue;
|
|
|
187 |
}
|
188 |
msg.payload.result = JSON.stringify(result);
|
189 |
results.push(JSON.stringify(msg));
|
190 |
+
done = true;
|
191 |
} catch (e) {
|
192 |
console.error(e);
|
193 |
logger.error(
|
|
|
197 |
},
|
198 |
request,
|
199 |
);
|
200 |
+
controller.error(e);
|
201 |
}
|
202 |
}
|
203 |
controller.enqueue(
|
|
|
205 |
results.length === 0 ? '' : results.join('\n') + '\n',
|
206 |
),
|
207 |
);
|
208 |
+
if (done) {
|
209 |
+
logger.info(
|
210 |
+
session,
|
211 |
+
{
|
212 |
+
message: 'Streaming finished',
|
213 |
+
maxChunkSize,
|
214 |
+
},
|
215 |
+
request,
|
216 |
+
'__AGENT_DONE',
|
217 |
+
);
|
218 |
+
controller.close();
|
219 |
+
}
|
220 |
+
}
|
221 |
+
},
|
222 |
+
});
|
223 |
+
return new Response(stream, {
|
224 |
+
headers: {
|
225 |
+
'Content-Type': 'application/x-ndjson',
|
226 |
+
},
|
227 |
+
});
|
228 |
} else {
|
229 |
return fetchResponse;
|
230 |
}
|
components/chat/ChatMessage.tsx
CHANGED
@@ -1,5 +1,4 @@
|
|
1 |
import { useMemo, useState } from 'react';
|
2 |
-
import { cn } from '@/lib/utils';
|
3 |
import { CodeBlock } from '@/components/ui/CodeBlock';
|
4 |
import {
|
5 |
IconCheckCircle,
|
@@ -114,7 +113,7 @@ const ChunkPayloadAction: React.FC<{
|
|
114 |
<IconListUnordered />
|
115 |
</Button>
|
116 |
</DialogTrigger>
|
117 |
-
<DialogContent className="max-w-5xl">
|
118 |
<Table>
|
119 |
<TableHeader>
|
120 |
<TableRow className="border-primary/50">
|
|
|
1 |
import { useMemo, useState } from 'react';
|
|
|
2 |
import { CodeBlock } from '@/components/ui/CodeBlock';
|
3 |
import {
|
4 |
IconCheckCircle,
|
|
|
113 |
<IconListUnordered />
|
114 |
</Button>
|
115 |
</DialogTrigger>
|
116 |
+
<DialogContent className="max-w-5xl" onOpenAutoFocus={e => e.preventDefault()}>
|
117 |
<Table>
|
118 |
<TableHeader>
|
119 |
<TableRow className="border-primary/50">
|