@fias/plugin-dev-harness 1.5.9 → 1.5.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -313,7 +313,69 @@
|
|
|
313
313
|
});
|
|
314
314
|
}
|
|
315
315
|
|
|
316
|
+
/**
|
|
317
|
+
* Simulate streaming in the browser by dispatching tokens one at a time.
|
|
318
|
+
* Each token gets its own macrotask (via setTimeout) so React can render
|
|
319
|
+
* between them — this mirrors how the production PluginBridgeHost works.
|
|
320
|
+
*/
|
|
321
|
+
function simulateStreamInBrowser(messageId, text, metadata) {
|
|
322
|
+
var words = text.split(/(\s+)/);
|
|
323
|
+
var delay = Math.max(30, Math.floor(1000 / Math.max(words.length, 1)));
|
|
324
|
+
var index = 0;
|
|
325
|
+
|
|
326
|
+
function next() {
|
|
327
|
+
if (index < words.length) {
|
|
328
|
+
sendToPlugin({ type: 'stream_token', messageId: messageId, text: words[index] });
|
|
329
|
+
index++;
|
|
330
|
+
setTimeout(next, delay);
|
|
331
|
+
} else {
|
|
332
|
+
logMessage('send', 'response', { output: text });
|
|
333
|
+
sendToPlugin({
|
|
334
|
+
type: 'response',
|
|
335
|
+
messageId: messageId,
|
|
336
|
+
payload: { output: text, metadata: metadata },
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
setTimeout(next, delay);
|
|
342
|
+
}
|
|
343
|
+
|
|
316
344
|
function handleStreamingRequest(data) {
|
|
345
|
+
// In mock mode, bypass SSE entirely: get the full response then simulate
|
|
346
|
+
// streaming in the browser. This matches the production PluginBridgeHost
|
|
347
|
+
// architecture where token forwarding happens in the same browser context.
|
|
348
|
+
if (currentMode === 'mock') {
|
|
349
|
+
fetch('/api/bridge', {
|
|
350
|
+
method: 'POST',
|
|
351
|
+
headers: { 'Content-Type': 'application/json' },
|
|
352
|
+
body: JSON.stringify({ type: data.type, payload: data.payload }),
|
|
353
|
+
})
|
|
354
|
+
.then(function (response) {
|
|
355
|
+
if (!response.ok) {
|
|
356
|
+
return response.json().then(function (err) {
|
|
357
|
+
throw new Error(err.error || 'Bridge call failed');
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
return response.json();
|
|
361
|
+
})
|
|
362
|
+
.then(function (result) {
|
|
363
|
+
simulateStreamInBrowser(data.messageId, result.output, result.metadata);
|
|
364
|
+
})
|
|
365
|
+
.catch(function (err) {
|
|
366
|
+
logMessage('error', err.message);
|
|
367
|
+
sendToPlugin({
|
|
368
|
+
type: 'response',
|
|
369
|
+
messageId: data.messageId,
|
|
370
|
+
payload: null,
|
|
371
|
+
error: err.message,
|
|
372
|
+
});
|
|
373
|
+
});
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// Live mode: use SSE streaming from the server (real API has natural
|
|
378
|
+
// network latency so tokens stream properly)
|
|
317
379
|
fetch('/api/bridge/stream', {
|
|
318
380
|
method: 'POST',
|
|
319
381
|
headers: { 'Content-Type': 'application/json' },
|