fix: stream-json for real token streaming
This commit is contained in:
27
server.js
27
server.js
@@ -40,13 +40,36 @@ app.post('/api/chat', (req, res) => {
|
|||||||
|
|
||||||
const env = { ...process.env, CLAUDE_CONFIG_DIR: configDir };
|
const env = { ...process.env, CLAUDE_CONFIG_DIR: configDir };
|
||||||
|
|
||||||
const proc = spawn(CLAUDE_BIN, ['-p', text, '--model', modelId, '--output-format', 'text'], {
|
const proc = spawn(CLAUDE_BIN, ['-p', text, '--model', modelId, '--output-format', 'stream-json', '--verbose'], {
|
||||||
env,
|
env,
|
||||||
stdio: ['ignore', 'pipe', 'pipe'],
|
stdio: ['ignore', 'pipe', 'pipe'],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let buf = '';
|
||||||
proc.stdout.on('data', (chunk) => {
|
proc.stdout.on('data', (chunk) => {
|
||||||
res.write(`data: ${JSON.stringify({ text: chunk.toString() })}\n\n`);
|
buf += chunk.toString();
|
||||||
|
const lines = buf.split('\n');
|
||||||
|
buf = lines.pop(); // keep incomplete line
|
||||||
|
for (const line of lines) {
|
||||||
|
if (!line.trim()) continue;
|
||||||
|
try {
|
||||||
|
const obj = JSON.parse(line);
|
||||||
|
// streaming delta
|
||||||
|
if (obj.type === 'content_block_delta' && obj.delta?.type === 'text_delta') {
|
||||||
|
res.write(`data: ${JSON.stringify({ text: obj.delta.text })}\n\n`);
|
||||||
|
}
|
||||||
|
// fallback: full assistant message
|
||||||
|
else if (obj.type === 'assistant' && obj.message?.content) {
|
||||||
|
for (const block of obj.message.content) {
|
||||||
|
if (block.type === 'text') res.write(`data: ${JSON.stringify({ text: block.text })}\n\n`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// error in result
|
||||||
|
else if (obj.type === 'result' && obj.is_error) {
|
||||||
|
res.write(`data: ${JSON.stringify({ error: obj.result || 'unknown error' })}\n\n`);
|
||||||
|
}
|
||||||
|
} catch (e) {}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let stderrBuf = '';
|
let stderrBuf = '';
|
||||||
|
|||||||
Reference in New Issue
Block a user