@fias/plugin-dev-harness 1.5.11 → 1.5.13
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.
- package/dist/server/static/harness.js +27 -36
- package/package.json +1 -1
|
@@ -267,6 +267,7 @@
|
|
|
267
267
|
|
|
268
268
|
// Streaming path for entity_invoke with stream: true
|
|
269
269
|
if (data.type === 'entity_invoke' && data.payload && data.payload.stream) {
|
|
270
|
+
logMessage('info', 'Streaming request detected (mode: ' + currentMode + ')');
|
|
270
271
|
handleStreamingRequest(data);
|
|
271
272
|
return;
|
|
272
273
|
}
|
|
@@ -374,78 +375,64 @@
|
|
|
374
375
|
return;
|
|
375
376
|
}
|
|
376
377
|
|
|
377
|
-
// Live mode:
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
.
|
|
382
|
-
|
|
383
|
-
return r.json();
|
|
384
|
-
})
|
|
385
|
-
.then(function (config) {
|
|
386
|
-
return fetch(config.apiUrl + '/developer/bridge', {
|
|
387
|
-
method: 'POST',
|
|
388
|
-
headers: {
|
|
389
|
-
'Content-Type': 'application/json',
|
|
390
|
-
Authorization: 'Bearer ' + config.authToken,
|
|
391
|
-
'X-Plugin-Permissions': config.permissions.join(','),
|
|
392
|
-
},
|
|
393
|
-
body: JSON.stringify({
|
|
394
|
-
type: data.type,
|
|
395
|
-
payload: Object.assign({}, data.payload, { stream: true }),
|
|
396
|
-
}),
|
|
397
|
-
});
|
|
398
|
-
})
|
|
378
|
+
// Live mode: proxy through local Express SSE endpoint
|
|
379
|
+
fetch('/api/bridge/stream', {
|
|
380
|
+
method: 'POST',
|
|
381
|
+
headers: { 'Content-Type': 'application/json' },
|
|
382
|
+
body: JSON.stringify({ type: data.type, payload: data.payload }),
|
|
383
|
+
})
|
|
399
384
|
.then(function (response) {
|
|
400
385
|
if (!response.ok) {
|
|
401
386
|
return response.json().then(function (err) {
|
|
402
|
-
throw new Error(
|
|
387
|
+
throw new Error(err.error || 'Bridge streaming call failed');
|
|
403
388
|
});
|
|
404
389
|
}
|
|
405
390
|
|
|
406
391
|
var contentType = response.headers.get('content-type') || '';
|
|
392
|
+
logMessage('info', 'SSE response content-type: ' + contentType);
|
|
407
393
|
if (contentType.indexOf('text/event-stream') === -1) {
|
|
394
|
+
logMessage('warn', 'Not SSE — falling back to JSON');
|
|
408
395
|
return response.json().then(function (result) {
|
|
409
396
|
sendToPlugin({ type: 'response', messageId: data.messageId, payload: result });
|
|
410
397
|
});
|
|
411
398
|
}
|
|
412
399
|
|
|
413
|
-
// Consume SSE stream directly — same pattern as production PluginBridgeHost
|
|
414
400
|
var reader = response.body.getReader();
|
|
415
401
|
var decoder = new TextDecoder();
|
|
416
402
|
var buffer = '';
|
|
417
|
-
var
|
|
403
|
+
var finalPayload = null;
|
|
404
|
+
var tokenCount = 0;
|
|
405
|
+
var chunkCount = 0;
|
|
418
406
|
|
|
419
407
|
function pump() {
|
|
420
408
|
return reader.read().then(function (chunk) {
|
|
421
409
|
if (chunk.done) {
|
|
422
|
-
logMessage('
|
|
423
|
-
|
|
424
|
-
type: 'response',
|
|
425
|
-
|
|
426
|
-
payload: { output: fullOutput },
|
|
427
|
-
});
|
|
410
|
+
logMessage('info', 'Stream complete — ' + tokenCount + ' tokens in ' + chunkCount + ' chunks');
|
|
411
|
+
if (finalPayload) {
|
|
412
|
+
sendToPlugin({ type: 'response', messageId: data.messageId, payload: finalPayload });
|
|
413
|
+
}
|
|
428
414
|
return;
|
|
429
415
|
}
|
|
430
416
|
|
|
417
|
+
chunkCount++;
|
|
431
418
|
buffer += decoder.decode(chunk.value, { stream: true });
|
|
432
419
|
var lines = buffer.split('\n');
|
|
433
420
|
buffer = lines.pop() || '';
|
|
421
|
+
var tokensThisChunk = 0;
|
|
434
422
|
|
|
435
423
|
for (var i = 0; i < lines.length; i++) {
|
|
436
424
|
var line = lines[i];
|
|
437
425
|
if (line.indexOf('data: ') !== 0) continue;
|
|
438
|
-
var lineData = line.slice(6);
|
|
439
|
-
if (lineData === '[DONE]') continue;
|
|
440
426
|
try {
|
|
441
|
-
var parsed = JSON.parse(
|
|
427
|
+
var parsed = JSON.parse(line.slice(6));
|
|
442
428
|
if (parsed.error) throw new Error(parsed.error);
|
|
443
429
|
if (parsed.text) {
|
|
444
|
-
|
|
430
|
+
tokenCount++;
|
|
431
|
+
tokensThisChunk++;
|
|
445
432
|
sendToPlugin({ type: 'stream_token', messageId: data.messageId, text: parsed.text });
|
|
446
433
|
}
|
|
447
434
|
if (parsed.done) {
|
|
448
|
-
|
|
435
|
+
finalPayload = { output: parsed.output, metadata: parsed.metadata };
|
|
449
436
|
if (parsed.metadata && parsed.metadata.cost > 0) {
|
|
450
437
|
logMessage('cost', 'Credits used: ' + parsed.metadata.cost.toFixed(4));
|
|
451
438
|
fetchCredits();
|
|
@@ -457,6 +444,10 @@
|
|
|
457
444
|
}
|
|
458
445
|
}
|
|
459
446
|
|
|
447
|
+
if (tokensThisChunk > 0) {
|
|
448
|
+
logMessage('info', 'chunk #' + chunkCount + ': ' + tokensThisChunk + ' tokens');
|
|
449
|
+
}
|
|
450
|
+
|
|
460
451
|
return pump();
|
|
461
452
|
});
|
|
462
453
|
}
|