total5 0.0.17-6 → 0.0.17-8
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/aimodel.js +397 -9
- package/builders.js +20 -0
- package/changelog.txt +5 -0
- package/flow-flowstream.js +3 -1
- package/flowstream.js +11 -0
- package/global.js +1 -1
- package/package.json +1 -1
- package/utils.js +55 -11
package/aimodel.js
CHANGED
|
@@ -235,17 +235,167 @@ function createTool(id, name) {
|
|
|
235
235
|
};
|
|
236
236
|
}
|
|
237
237
|
|
|
238
|
+
function parseJSON(value) {
|
|
239
|
+
try {
|
|
240
|
+
return JSON.parse(value);
|
|
241
|
+
} catch (e) {
|
|
242
|
+
return null;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
function createTool(id, name) {
|
|
247
|
+
return {
|
|
248
|
+
id: id || null,
|
|
249
|
+
name: name || null,
|
|
250
|
+
arguments: '',
|
|
251
|
+
input: null
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
function normalize(value) {
|
|
256
|
+
|
|
257
|
+
if (value == null)
|
|
258
|
+
return {};
|
|
259
|
+
|
|
260
|
+
if (typeof value === 'object')
|
|
261
|
+
return value;
|
|
262
|
+
|
|
263
|
+
if (typeof value !== 'string')
|
|
264
|
+
return value;
|
|
265
|
+
|
|
266
|
+
value = value.trim();
|
|
267
|
+
|
|
268
|
+
if (!value)
|
|
269
|
+
return {};
|
|
270
|
+
|
|
271
|
+
const json = parseJSON(value);
|
|
272
|
+
|
|
273
|
+
if (json)
|
|
274
|
+
return json;
|
|
275
|
+
|
|
276
|
+
return value;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
function parseJSON(value) {
|
|
280
|
+
try {
|
|
281
|
+
return JSON.parse(value);
|
|
282
|
+
} catch (e) {
|
|
283
|
+
return null;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
function createTool(id, name) {
|
|
288
|
+
return {
|
|
289
|
+
id: id || null,
|
|
290
|
+
name: name || null,
|
|
291
|
+
arguments: '',
|
|
292
|
+
input: null
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
function normalize(value) {
|
|
297
|
+
|
|
298
|
+
if (value == null)
|
|
299
|
+
return {};
|
|
300
|
+
|
|
301
|
+
if (typeof value === 'object')
|
|
302
|
+
return value;
|
|
303
|
+
|
|
304
|
+
if (typeof value !== 'string')
|
|
305
|
+
return value;
|
|
306
|
+
|
|
307
|
+
value = value.trim();
|
|
308
|
+
|
|
309
|
+
if (!value)
|
|
310
|
+
return {};
|
|
311
|
+
|
|
312
|
+
const json = parseJSON(value);
|
|
313
|
+
|
|
314
|
+
if (json)
|
|
315
|
+
return json;
|
|
316
|
+
|
|
317
|
+
return value;
|
|
318
|
+
}
|
|
319
|
+
|
|
238
320
|
class AIStreamParser {
|
|
239
321
|
|
|
240
|
-
constructor(provider) {
|
|
322
|
+
constructor(provider, ondata) {
|
|
241
323
|
this.provider = provider || 'generic';
|
|
324
|
+
|
|
242
325
|
this.content = '';
|
|
326
|
+
this.thinking = '';
|
|
243
327
|
this.tools = [];
|
|
244
328
|
this.reasoning = 'content';
|
|
329
|
+
|
|
245
330
|
this.buffer = Buffer.alloc(0);
|
|
246
331
|
this.toolmap = Object.create(null);
|
|
332
|
+
|
|
333
|
+
this.listeners = Object.create(null);
|
|
334
|
+
this.ondata = typeof ondata === 'function' ? ondata : null;
|
|
335
|
+
|
|
336
|
+
this.thinking_signature = null;
|
|
337
|
+
this.thought_signatures = [];
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
// ------------------------------------------------------------
|
|
341
|
+
// Events
|
|
342
|
+
// ------------------------------------------------------------
|
|
343
|
+
|
|
344
|
+
on(type, fn) {
|
|
345
|
+
if (!type || typeof fn !== 'function')
|
|
346
|
+
return this;
|
|
347
|
+
|
|
348
|
+
if (!this.listeners[type])
|
|
349
|
+
this.listeners[type] = [];
|
|
350
|
+
|
|
351
|
+
this.listeners[type].push(fn);
|
|
352
|
+
return this;
|
|
247
353
|
}
|
|
248
354
|
|
|
355
|
+
off(type, fn) {
|
|
356
|
+
const arr = this.listeners[type];
|
|
357
|
+
|
|
358
|
+
if (!arr)
|
|
359
|
+
return this;
|
|
360
|
+
|
|
361
|
+
const index = arr.indexOf(fn);
|
|
362
|
+
|
|
363
|
+
if (index !== -1)
|
|
364
|
+
arr.splice(index, 1);
|
|
365
|
+
|
|
366
|
+
return this;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
emit(type, data) {
|
|
370
|
+
const event = {
|
|
371
|
+
type,
|
|
372
|
+
...data
|
|
373
|
+
};
|
|
374
|
+
|
|
375
|
+
if (this.ondata)
|
|
376
|
+
this.ondata(event);
|
|
377
|
+
|
|
378
|
+
const listeners = this.listeners[type];
|
|
379
|
+
|
|
380
|
+
if (listeners) {
|
|
381
|
+
for (const fn of listeners)
|
|
382
|
+
fn(event);
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
const all = this.listeners['*'];
|
|
386
|
+
|
|
387
|
+
if (all) {
|
|
388
|
+
for (const fn of all)
|
|
389
|
+
fn(event);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
return event;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
// ------------------------------------------------------------
|
|
396
|
+
// Public API
|
|
397
|
+
// ------------------------------------------------------------
|
|
398
|
+
|
|
249
399
|
write(chunk) {
|
|
250
400
|
if (chunk == null)
|
|
251
401
|
return this.output();
|
|
@@ -265,11 +415,11 @@ class AIStreamParser {
|
|
|
265
415
|
|
|
266
416
|
let index;
|
|
267
417
|
|
|
268
|
-
while ((index = this.buffer.indexOf(0x0A)) !== -1) {
|
|
418
|
+
while ((index = this.buffer.indexOf(0x0A)) !== -1) {
|
|
269
419
|
let lineBuffer = this.buffer.subarray(0, index);
|
|
270
420
|
this.buffer = this.buffer.subarray(index + 1);
|
|
271
421
|
|
|
272
|
-
// CRLF support
|
|
422
|
+
// CRLF support
|
|
273
423
|
if (lineBuffer.length && lineBuffer[lineBuffer.length - 1] === 0x0D)
|
|
274
424
|
lineBuffer = lineBuffer.subarray(0, lineBuffer.length - 1);
|
|
275
425
|
|
|
@@ -311,6 +461,7 @@ class AIStreamParser {
|
|
|
311
461
|
return;
|
|
312
462
|
|
|
313
463
|
const json = parseJSON(line);
|
|
464
|
+
|
|
314
465
|
if (json)
|
|
315
466
|
this.writeObject(json);
|
|
316
467
|
}
|
|
@@ -318,9 +469,17 @@ class AIStreamParser {
|
|
|
318
469
|
end() {
|
|
319
470
|
if (this.buffer.length)
|
|
320
471
|
this.processLineBuffer(this.buffer);
|
|
472
|
+
|
|
321
473
|
this.buffer = Buffer.alloc(0);
|
|
322
474
|
this.finalizeTools();
|
|
323
|
-
|
|
475
|
+
|
|
476
|
+
const output = this.output();
|
|
477
|
+
|
|
478
|
+
this.emit('done', {
|
|
479
|
+
output
|
|
480
|
+
});
|
|
481
|
+
|
|
482
|
+
return output;
|
|
324
483
|
}
|
|
325
484
|
|
|
326
485
|
writeObject(chunk) {
|
|
@@ -328,17 +487,21 @@ class AIStreamParser {
|
|
|
328
487
|
case 'ollama':
|
|
329
488
|
this.parseOllama(chunk);
|
|
330
489
|
break;
|
|
490
|
+
|
|
331
491
|
case 'openai_chat':
|
|
332
492
|
case 'openai':
|
|
333
493
|
this.parseOpenAI(chunk);
|
|
334
494
|
break;
|
|
495
|
+
|
|
335
496
|
case 'openai_responses':
|
|
336
497
|
this.parseOpenAIresponse(chunk);
|
|
337
498
|
break;
|
|
499
|
+
|
|
338
500
|
case 'claude':
|
|
339
501
|
case 'anthropic':
|
|
340
502
|
this.parseClaude(chunk);
|
|
341
503
|
break;
|
|
504
|
+
|
|
342
505
|
case 'gemini':
|
|
343
506
|
case 'google':
|
|
344
507
|
this.parseGemini(chunk);
|
|
@@ -348,26 +511,85 @@ class AIStreamParser {
|
|
|
348
511
|
this.parseGeneric(chunk);
|
|
349
512
|
break;
|
|
350
513
|
}
|
|
514
|
+
|
|
351
515
|
return this.output();
|
|
352
516
|
}
|
|
353
517
|
|
|
518
|
+
// ------------------------------------------------------------
|
|
519
|
+
// Accumulators
|
|
520
|
+
// ------------------------------------------------------------
|
|
521
|
+
|
|
354
522
|
addContent(value) {
|
|
355
523
|
if (!value)
|
|
356
524
|
return;
|
|
525
|
+
|
|
526
|
+
if (typeof value !== 'string')
|
|
527
|
+
value = String(value);
|
|
528
|
+
|
|
357
529
|
this.content += value;
|
|
530
|
+
|
|
531
|
+
this.emit('content', {
|
|
532
|
+
delta: value,
|
|
533
|
+
content: this.content,
|
|
534
|
+
reasoning: 'content'
|
|
535
|
+
});
|
|
536
|
+
|
|
358
537
|
if (!this.tools.length)
|
|
359
538
|
this.reasoning = 'content';
|
|
360
539
|
}
|
|
361
540
|
|
|
541
|
+
addThinking(value) {
|
|
542
|
+
if (!value)
|
|
543
|
+
return;
|
|
544
|
+
|
|
545
|
+
if (typeof value === 'object') {
|
|
546
|
+
|
|
547
|
+
if (Array.isArray(value)) {
|
|
548
|
+
for (const item of value)
|
|
549
|
+
this.addThinking(item);
|
|
550
|
+
return;
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
if (value.text != null)
|
|
554
|
+
value = value.text;
|
|
555
|
+
else if (value.summary != null)
|
|
556
|
+
value = value.summary;
|
|
557
|
+
else if (value.content != null)
|
|
558
|
+
value = value.content;
|
|
559
|
+
else if (value.value != null)
|
|
560
|
+
value = value.value;
|
|
561
|
+
else
|
|
562
|
+
value = JSON.stringify(value);
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
if (!value)
|
|
566
|
+
return;
|
|
567
|
+
|
|
568
|
+
if (typeof value !== 'string')
|
|
569
|
+
value = String(value);
|
|
570
|
+
|
|
571
|
+
this.thinking += value;
|
|
572
|
+
this.reasoning = 'thinking';
|
|
573
|
+
|
|
574
|
+
this.emit('thinking', {
|
|
575
|
+
delta: value,
|
|
576
|
+
thinking: this.thinking,
|
|
577
|
+
reasoning: 'thinking'
|
|
578
|
+
});
|
|
579
|
+
}
|
|
580
|
+
|
|
362
581
|
getTool(key, id, name) {
|
|
363
582
|
|
|
364
583
|
key = key || id || name || String(this.tools.length);
|
|
365
584
|
|
|
366
585
|
let tool = this.toolmap[key];
|
|
586
|
+
let isnew = false;
|
|
587
|
+
|
|
367
588
|
if (!tool) {
|
|
368
589
|
tool = createTool(id, name);
|
|
369
590
|
this.toolmap[key] = tool;
|
|
370
591
|
this.tools.push(tool);
|
|
592
|
+
isnew = true;
|
|
371
593
|
}
|
|
372
594
|
|
|
373
595
|
if (id)
|
|
@@ -378,6 +600,11 @@ class AIStreamParser {
|
|
|
378
600
|
|
|
379
601
|
this.reasoning = 'tool';
|
|
380
602
|
|
|
603
|
+
this.emit(isnew ? 'tool_start' : 'tool_update', {
|
|
604
|
+
tool: this.cloneTool(tool),
|
|
605
|
+
reasoning: 'tool'
|
|
606
|
+
});
|
|
607
|
+
|
|
381
608
|
return tool;
|
|
382
609
|
}
|
|
383
610
|
|
|
@@ -389,10 +616,36 @@ class AIStreamParser {
|
|
|
389
616
|
if (typeof value === 'object') {
|
|
390
617
|
tool.input = value;
|
|
391
618
|
tool.arguments = JSON.stringify(value);
|
|
619
|
+
|
|
620
|
+
this.emit('tool_arguments', {
|
|
621
|
+
tool: this.cloneTool(tool),
|
|
622
|
+
delta: value,
|
|
623
|
+
arguments: tool.input,
|
|
624
|
+
reasoning: 'tool'
|
|
625
|
+
});
|
|
626
|
+
|
|
392
627
|
return;
|
|
393
628
|
}
|
|
394
629
|
|
|
630
|
+
if (typeof value !== 'string')
|
|
631
|
+
value = String(value);
|
|
632
|
+
|
|
395
633
|
tool.arguments += value;
|
|
634
|
+
|
|
635
|
+
this.emit('tool_arguments', {
|
|
636
|
+
tool: this.cloneTool(tool),
|
|
637
|
+
delta: value,
|
|
638
|
+
arguments: tool.arguments,
|
|
639
|
+
reasoning: 'tool'
|
|
640
|
+
});
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
cloneTool(tool) {
|
|
644
|
+
return {
|
|
645
|
+
id: tool.id,
|
|
646
|
+
name: tool.name,
|
|
647
|
+
arguments: tool.input || normalize(tool.arguments)
|
|
648
|
+
};
|
|
396
649
|
}
|
|
397
650
|
|
|
398
651
|
finalizeTools() {
|
|
@@ -404,8 +657,10 @@ class AIStreamParser {
|
|
|
404
657
|
|
|
405
658
|
output() {
|
|
406
659
|
this.finalizeTools();
|
|
407
|
-
|
|
660
|
+
|
|
661
|
+
const output = {
|
|
408
662
|
content: this.content,
|
|
663
|
+
thinking: this.thinking,
|
|
409
664
|
tools: this.tools.map(tool => ({
|
|
410
665
|
id: tool.id,
|
|
411
666
|
name: tool.name,
|
|
@@ -413,6 +668,14 @@ class AIStreamParser {
|
|
|
413
668
|
})),
|
|
414
669
|
reasoning: this.tools.length ? 'tool' : this.reasoning
|
|
415
670
|
};
|
|
671
|
+
|
|
672
|
+
if (this.thinking_signature)
|
|
673
|
+
output.thinking_signature = this.thinking_signature;
|
|
674
|
+
|
|
675
|
+
if (this.thought_signatures.length)
|
|
676
|
+
output.thought_signatures = this.thought_signatures;
|
|
677
|
+
|
|
678
|
+
return output;
|
|
416
679
|
}
|
|
417
680
|
|
|
418
681
|
// ------------------------------------------------------------
|
|
@@ -421,34 +684,80 @@ class AIStreamParser {
|
|
|
421
684
|
|
|
422
685
|
parseOllama(chunk) {
|
|
423
686
|
|
|
687
|
+
// Ollama OpenAI-compatible endpoint fallback
|
|
688
|
+
if (chunk.choices) {
|
|
689
|
+
this.parseOpenAI(chunk);
|
|
690
|
+
return;
|
|
691
|
+
}
|
|
692
|
+
|
|
424
693
|
const message = chunk.message || {};
|
|
425
694
|
|
|
695
|
+
// /api/chat thinking
|
|
696
|
+
if (message.thinking)
|
|
697
|
+
this.addThinking(message.thinking);
|
|
698
|
+
|
|
699
|
+
// /api/generate thinking
|
|
700
|
+
if (chunk.thinking)
|
|
701
|
+
this.addThinking(chunk.thinking);
|
|
702
|
+
|
|
703
|
+
// OpenAI-compatible / model-specific reasoning fields
|
|
704
|
+
if (message.reasoning_content)
|
|
705
|
+
this.addThinking(message.reasoning_content);
|
|
706
|
+
|
|
707
|
+
if (message.reasoning)
|
|
708
|
+
this.addThinking(message.reasoning);
|
|
709
|
+
|
|
710
|
+
if (message.reasoning_text)
|
|
711
|
+
this.addThinking(message.reasoning_text);
|
|
712
|
+
|
|
713
|
+
// /api/chat content
|
|
426
714
|
if (message.content)
|
|
427
715
|
this.addContent(message.content);
|
|
428
716
|
|
|
429
|
-
|
|
717
|
+
// /api/generate content
|
|
718
|
+
if (chunk.response)
|
|
719
|
+
this.addContent(chunk.response);
|
|
720
|
+
|
|
721
|
+
const calls = message.tool_calls || chunk.tool_calls || [];
|
|
430
722
|
|
|
431
723
|
for (let i = 0; i < calls.length; i++) {
|
|
432
724
|
const call = calls[i];
|
|
433
|
-
const fn = call.function ||
|
|
725
|
+
const fn = call.function || call;
|
|
434
726
|
const key = call.id || fn.name || `ollama_${i}`;
|
|
435
727
|
|
|
436
728
|
const tool = this.getTool(key, call.id, fn.name);
|
|
437
729
|
|
|
438
730
|
if (fn.arguments != null)
|
|
439
731
|
this.appendToolArguments(tool, fn.arguments);
|
|
732
|
+
else if (fn.args != null)
|
|
733
|
+
this.appendToolArguments(tool, fn.args);
|
|
734
|
+
else if (fn.input != null)
|
|
735
|
+
this.appendToolArguments(tool, fn.input);
|
|
440
736
|
}
|
|
441
737
|
}
|
|
442
738
|
|
|
443
739
|
// ------------------------------------------------------------
|
|
444
740
|
// OpenAI Chat Completions stream
|
|
445
741
|
// ------------------------------------------------------------
|
|
742
|
+
|
|
446
743
|
parseOpenAI(chunk) {
|
|
447
744
|
const choices = chunk.choices || [];
|
|
448
745
|
|
|
449
746
|
for (const choice of choices) {
|
|
450
747
|
const delta = choice.delta || {};
|
|
451
748
|
|
|
749
|
+
if (delta.reasoning_content)
|
|
750
|
+
this.addThinking(delta.reasoning_content);
|
|
751
|
+
|
|
752
|
+
if (delta.reasoning)
|
|
753
|
+
this.addThinking(delta.reasoning);
|
|
754
|
+
|
|
755
|
+
if (delta.thinking)
|
|
756
|
+
this.addThinking(delta.thinking);
|
|
757
|
+
|
|
758
|
+
if (delta.reasoning_text)
|
|
759
|
+
this.addThinking(delta.reasoning_text);
|
|
760
|
+
|
|
452
761
|
if (delta.content)
|
|
453
762
|
this.addContent(delta.content);
|
|
454
763
|
|
|
@@ -473,11 +782,19 @@ class AIStreamParser {
|
|
|
473
782
|
|
|
474
783
|
parseOpenAIresponse(chunk) {
|
|
475
784
|
switch (chunk.type) {
|
|
785
|
+
|
|
476
786
|
case 'response.output_text.delta':
|
|
477
787
|
case 'response.refusal.delta':
|
|
478
788
|
this.addContent(chunk.delta);
|
|
479
789
|
break;
|
|
480
790
|
|
|
791
|
+
case 'response.reasoning_summary_text.delta':
|
|
792
|
+
case 'response.reasoning_text.delta':
|
|
793
|
+
case 'response.reasoning_summary.delta':
|
|
794
|
+
case 'response.reasoning.delta':
|
|
795
|
+
this.addThinking(chunk.delta);
|
|
796
|
+
break;
|
|
797
|
+
|
|
481
798
|
case 'response.function_call_arguments.delta': {
|
|
482
799
|
const key = chunk.item_id || chunk.call_id || `openai_response_${chunk.output_index || 0}`;
|
|
483
800
|
const tool = this.getTool(key, chunk.call_id || chunk.item_id, chunk.name);
|
|
@@ -489,6 +806,17 @@ class AIStreamParser {
|
|
|
489
806
|
case 'response.output_item.added': {
|
|
490
807
|
const item = chunk.item || {};
|
|
491
808
|
|
|
809
|
+
if (item.type === 'reasoning') {
|
|
810
|
+
if (item.summary)
|
|
811
|
+
this.addThinking(item.summary);
|
|
812
|
+
|
|
813
|
+
if (item.content)
|
|
814
|
+
this.addThinking(item.content);
|
|
815
|
+
|
|
816
|
+
if (item.text)
|
|
817
|
+
this.addThinking(item.text);
|
|
818
|
+
}
|
|
819
|
+
|
|
492
820
|
if (item.type === 'function_call') {
|
|
493
821
|
const key = item.id || item.call_id;
|
|
494
822
|
const tool = this.getTool(key, item.call_id || item.id, item.name);
|
|
@@ -503,6 +831,17 @@ class AIStreamParser {
|
|
|
503
831
|
case 'response.output_item.done': {
|
|
504
832
|
const item = chunk.item || {};
|
|
505
833
|
|
|
834
|
+
if (item.type === 'reasoning') {
|
|
835
|
+
if (item.summary)
|
|
836
|
+
this.addThinking(item.summary);
|
|
837
|
+
|
|
838
|
+
if (item.content)
|
|
839
|
+
this.addThinking(item.content);
|
|
840
|
+
|
|
841
|
+
if (item.text)
|
|
842
|
+
this.addThinking(item.text);
|
|
843
|
+
}
|
|
844
|
+
|
|
506
845
|
if (item.type === 'function_call') {
|
|
507
846
|
const key = item.id || item.call_id;
|
|
508
847
|
const tool = this.getTool(key, item.call_id || item.id, item.name);
|
|
@@ -525,6 +864,11 @@ class AIStreamParser {
|
|
|
525
864
|
case 'content_block_start': {
|
|
526
865
|
const block = chunk.content_block || {};
|
|
527
866
|
|
|
867
|
+
if (block.type === 'thinking') {
|
|
868
|
+
if (block.thinking)
|
|
869
|
+
this.addThinking(block.thinking);
|
|
870
|
+
}
|
|
871
|
+
|
|
528
872
|
if (block.type === 'tool_use') {
|
|
529
873
|
const key = block.id || `claude_${chunk.index || 0}`;
|
|
530
874
|
const tool = this.getTool(key, block.id, block.name);
|
|
@@ -539,6 +883,12 @@ class AIStreamParser {
|
|
|
539
883
|
case 'content_block_delta': {
|
|
540
884
|
const delta = chunk.delta || {};
|
|
541
885
|
|
|
886
|
+
if (delta.type === 'thinking_delta')
|
|
887
|
+
this.addThinking(delta.thinking);
|
|
888
|
+
|
|
889
|
+
if (delta.type === 'signature_delta')
|
|
890
|
+
this.thinking_signature = delta.signature;
|
|
891
|
+
|
|
542
892
|
if (delta.type === 'text_delta')
|
|
543
893
|
this.addContent(delta.text);
|
|
544
894
|
|
|
@@ -576,8 +926,15 @@ class AIStreamParser {
|
|
|
576
926
|
for (let i = 0; i < parts.length; i++) {
|
|
577
927
|
const part = parts[i];
|
|
578
928
|
|
|
579
|
-
if (part.
|
|
580
|
-
this.
|
|
929
|
+
if (part.thoughtSignature)
|
|
930
|
+
this.thought_signatures.push(part.thoughtSignature);
|
|
931
|
+
|
|
932
|
+
if (part.text) {
|
|
933
|
+
if (part.thought)
|
|
934
|
+
this.addThinking(part.text);
|
|
935
|
+
else
|
|
936
|
+
this.addContent(part.text);
|
|
937
|
+
}
|
|
581
938
|
|
|
582
939
|
if (part.functionCall) {
|
|
583
940
|
const fn = part.functionCall;
|
|
@@ -595,6 +952,31 @@ class AIStreamParser {
|
|
|
595
952
|
// ------------------------------------------------------------
|
|
596
953
|
|
|
597
954
|
parseGeneric(chunk) {
|
|
955
|
+
|
|
956
|
+
if (chunk.thinking)
|
|
957
|
+
this.addThinking(chunk.thinking);
|
|
958
|
+
|
|
959
|
+
if (chunk.reasoning)
|
|
960
|
+
this.addThinking(chunk.reasoning);
|
|
961
|
+
|
|
962
|
+
if (chunk.reasoning_content)
|
|
963
|
+
this.addThinking(chunk.reasoning_content);
|
|
964
|
+
|
|
965
|
+
if (chunk.reasoning_text)
|
|
966
|
+
this.addThinking(chunk.reasoning_text);
|
|
967
|
+
|
|
968
|
+
if (chunk.message?.thinking)
|
|
969
|
+
this.addThinking(chunk.message.thinking);
|
|
970
|
+
|
|
971
|
+
if (chunk.message?.reasoning)
|
|
972
|
+
this.addThinking(chunk.message.reasoning);
|
|
973
|
+
|
|
974
|
+
if (chunk.message?.reasoning_content)
|
|
975
|
+
this.addThinking(chunk.message.reasoning_content);
|
|
976
|
+
|
|
977
|
+
if (chunk.message?.reasoning_text)
|
|
978
|
+
this.addThinking(chunk.message.reasoning_text);
|
|
979
|
+
|
|
598
980
|
if (chunk.content)
|
|
599
981
|
this.addContent(chunk.content);
|
|
600
982
|
|
|
@@ -622,10 +1004,16 @@ class AIStreamParser {
|
|
|
622
1004
|
|
|
623
1005
|
reset() {
|
|
624
1006
|
this.content = '';
|
|
1007
|
+
this.thinking = '';
|
|
625
1008
|
this.tools = [];
|
|
626
1009
|
this.reasoning = 'content';
|
|
1010
|
+
|
|
627
1011
|
this.buffer = Buffer.alloc(0);
|
|
628
1012
|
this.toolmap = Object.create(null);
|
|
1013
|
+
|
|
1014
|
+
this.thinking_signature = null;
|
|
1015
|
+
this.thought_signatures = [];
|
|
1016
|
+
|
|
629
1017
|
return this;
|
|
630
1018
|
}
|
|
631
1019
|
}
|
package/builders.js
CHANGED
|
@@ -1339,6 +1339,12 @@ function ActionCaller() {
|
|
|
1339
1339
|
setImmediate(ActionCallerExec, self);
|
|
1340
1340
|
}
|
|
1341
1341
|
|
|
1342
|
+
ActionCaller.prototype.config = function(value) {
|
|
1343
|
+
this.options.config = value;
|
|
1344
|
+
return this;
|
|
1345
|
+
};
|
|
1346
|
+
|
|
1347
|
+
|
|
1342
1348
|
ActionCaller.prototype.debug = function() {
|
|
1343
1349
|
this.options.debug = true;
|
|
1344
1350
|
return this;
|
|
@@ -1412,6 +1418,20 @@ ActionCaller.prototype.exec = function() {
|
|
|
1412
1418
|
$.controller = self.controller;
|
|
1413
1419
|
$.user = self.options.user;
|
|
1414
1420
|
$.config = action.config || EMPTYOBJECT;
|
|
1421
|
+
if (self.options.config) {
|
|
1422
|
+
|
|
1423
|
+
if ($.config === EMPTYOBJECT)
|
|
1424
|
+
$.config = {};
|
|
1425
|
+
else {
|
|
1426
|
+
let tmp = $.config;
|
|
1427
|
+
$.config = {};
|
|
1428
|
+
for (let key in tmp)
|
|
1429
|
+
$.config[key] = tmp[key];
|
|
1430
|
+
}
|
|
1431
|
+
|
|
1432
|
+
for (let key in self.options.config)
|
|
1433
|
+
$.config[key] = self.options.config[key];
|
|
1434
|
+
}
|
|
1415
1435
|
|
|
1416
1436
|
action.called++;
|
|
1417
1437
|
|
package/changelog.txt
CHANGED
|
@@ -16,6 +16,11 @@
|
|
|
16
16
|
- added `PROXYSERVER(endpoint, socketendpoint, [logger])` method
|
|
17
17
|
- added `AIMODEL.tool(content, [merge])` method
|
|
18
18
|
- added `AIPARSER(provider)` method for parsing AI responses
|
|
19
|
+
- extended `String.prototype` by adding the `String.parseContext()` method to parse a specific text file format
|
|
20
|
+
- added `ACTION().config(obj)` method
|
|
21
|
+
- added a new property `flow.instance.repo = {}` for storing additional data for Flow node instances
|
|
22
|
+
- fixed `Utils.filestreamer()` method
|
|
23
|
+
- improved `Utils.filestreamer()` method by adding percentage
|
|
19
24
|
|
|
20
25
|
========================
|
|
21
26
|
0.0.16
|
package/flow-flowstream.js
CHANGED
|
@@ -9,7 +9,7 @@ if (!global.F)
|
|
|
9
9
|
|
|
10
10
|
const W = F.Worker;
|
|
11
11
|
const Fork = F.Child.fork;
|
|
12
|
-
const VERSION =
|
|
12
|
+
const VERSION = 34;
|
|
13
13
|
const NOTIFYPATH = '/notify/';
|
|
14
14
|
|
|
15
15
|
var isFLOWSTREAMWORKER = false;
|
|
@@ -1939,6 +1939,7 @@ function MAKEFLOWSTREAM(meta) {
|
|
|
1939
1939
|
tmp.offset = com.offset;
|
|
1940
1940
|
tmp.size = com.size;
|
|
1941
1941
|
tmp.meta = com.meta;
|
|
1942
|
+
tmp.repo = com.repo;
|
|
1942
1943
|
tmp.schemaid = com.schemaid;
|
|
1943
1944
|
tmp.note = com.note;
|
|
1944
1945
|
tmp.schema = com.schema;
|
|
@@ -1994,6 +1995,7 @@ function MAKEFLOWSTREAM(meta) {
|
|
|
1994
1995
|
data.design = design;
|
|
1995
1996
|
data.variables = variables;
|
|
1996
1997
|
data.sources = sources;
|
|
1998
|
+
data.flowstream = VERSION;
|
|
1997
1999
|
return data;
|
|
1998
2000
|
};
|
|
1999
2001
|
|
package/flowstream.js
CHANGED
|
@@ -1486,6 +1486,13 @@ FP._use = function(schema, callback, reinit, insert) {
|
|
|
1486
1486
|
fi.size = instance.size;
|
|
1487
1487
|
fi.tab = instance.tab;
|
|
1488
1488
|
fi.ts = ts;
|
|
1489
|
+
|
|
1490
|
+
// From the view of the designer is the "repo" not visible
|
|
1491
|
+
if (instance.repo)
|
|
1492
|
+
fi.repo = instance.repo;
|
|
1493
|
+
else if (!fi.repo)
|
|
1494
|
+
fi.repo = {};
|
|
1495
|
+
|
|
1489
1496
|
if (JSON.stringify(fi.config) !== JSON.stringify(instance.config)) {
|
|
1490
1497
|
F.TUtils.extend(fi.config, instance.config);
|
|
1491
1498
|
fi.configure && fi.configure(fi.config);
|
|
@@ -1579,6 +1586,10 @@ FP.initcomponent = function(key, component) {
|
|
|
1579
1586
|
instance.isinstance = true;
|
|
1580
1587
|
instance.stats = { pending: 0, input: 0, output: 0, duration: 0, destroyed: 0 };
|
|
1581
1588
|
instance.cache = {};
|
|
1589
|
+
|
|
1590
|
+
if (!instance.repo)
|
|
1591
|
+
instance.repo = {};
|
|
1592
|
+
|
|
1582
1593
|
instance.id = key;
|
|
1583
1594
|
instance.module = component;
|
|
1584
1595
|
instance.ready = false;
|
package/global.js
CHANGED
package/package.json
CHANGED
package/utils.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Total.js Utils
|
|
2
2
|
// The MIT License
|
|
3
|
-
// Copyright 2012-
|
|
3
|
+
// Copyright 2012-2026 (c) Peter Širka <petersirka@gmail.com>
|
|
4
4
|
|
|
5
5
|
'use strict';
|
|
6
6
|
|
|
@@ -1627,30 +1627,49 @@ exports.aistreamer = function(online, onmessage) {
|
|
|
1627
1627
|
};
|
|
1628
1628
|
};
|
|
1629
1629
|
|
|
1630
|
-
exports.filestreamer = function(filename, onbuffer, onend, size) {
|
|
1630
|
+
exports.filestreamer = function(filename, onbuffer, onend, size = 1024 * 16, offset = 0) {
|
|
1631
1631
|
|
|
1632
1632
|
if (typeof(onend) === 'number') {
|
|
1633
1633
|
size = onend;
|
|
1634
1634
|
onend = null;
|
|
1635
1635
|
}
|
|
1636
1636
|
|
|
1637
|
-
|
|
1637
|
+
let Fd = null;
|
|
1638
|
+
let Stat = null;
|
|
1638
1639
|
|
|
1639
|
-
|
|
1640
|
-
|
|
1640
|
+
const read = function(offset) {
|
|
1641
|
+
const buffer = Buffer.alloc(size);
|
|
1641
1642
|
Total.Fs.read(Fd, buffer, 0, buffer.length, offset, function(err, bytes) {
|
|
1642
1643
|
if (err || !bytes) {
|
|
1643
|
-
onend && onend(err);
|
|
1644
1644
|
Total.Fs.close(Fd, NOOP);
|
|
1645
|
+
onend && onend(err);
|
|
1645
1646
|
} else {
|
|
1646
|
-
|
|
1647
|
+
const buff = buffer.length !== read ? buffer.slice(0, bytes) : buffer;
|
|
1648
|
+
Stat.read += buff.length;
|
|
1649
|
+
onbuffer(buff, function(stop) {
|
|
1650
|
+
if (stop === true) {
|
|
1651
|
+
Total.Fs.close(Fd, NOOP);
|
|
1652
|
+
onend && onend();
|
|
1653
|
+
} else
|
|
1654
|
+
read(offset + bytes);
|
|
1655
|
+
}, (Stat.read * 100) / Stat.size);
|
|
1647
1656
|
}
|
|
1648
1657
|
});
|
|
1649
1658
|
};
|
|
1650
1659
|
|
|
1651
|
-
Total.Fs.
|
|
1652
|
-
|
|
1653
|
-
|
|
1660
|
+
Total.Fs.lstat(filename, function(err, stat) {
|
|
1661
|
+
|
|
1662
|
+
if (err) {
|
|
1663
|
+
onend && onend(err);
|
|
1664
|
+
return;
|
|
1665
|
+
}
|
|
1666
|
+
|
|
1667
|
+
Stat = stat;
|
|
1668
|
+
Total.Fs.open(filename, function(err, fd) {
|
|
1669
|
+
Fd = fd;
|
|
1670
|
+
Stat.read = offset;
|
|
1671
|
+
read(offset);
|
|
1672
|
+
});
|
|
1654
1673
|
});
|
|
1655
1674
|
|
|
1656
1675
|
};
|
|
@@ -6051,6 +6070,31 @@ function extractnested(str, minDepth = 0) {
|
|
|
6051
6070
|
return { text: out, parts };
|
|
6052
6071
|
}
|
|
6053
6072
|
|
|
6073
|
+
SP.parseContext = function() {
|
|
6074
|
+
|
|
6075
|
+
const text = this;
|
|
6076
|
+
const REG = /-{20,}\s*\n([\s\S]*?)\n-{20,}\s*\n([\s\S]*?)(?=\n-{20,}\s*\n|$)/g;
|
|
6077
|
+
const output = [];
|
|
6078
|
+
|
|
6079
|
+
let match;
|
|
6080
|
+
|
|
6081
|
+
while ((match = REG.exec(text))) {
|
|
6082
|
+
const header = {};
|
|
6083
|
+
const body = match[2].trim();
|
|
6084
|
+
for (const line of match[1].split('\n')) {
|
|
6085
|
+
const index = line.indexOf(':');
|
|
6086
|
+
if (index === -1)
|
|
6087
|
+
continue;
|
|
6088
|
+
const key = line.substring(0, index).trim().toLowerCase();
|
|
6089
|
+
const value = line.substring(index + 1).trim();
|
|
6090
|
+
header[key] = value;
|
|
6091
|
+
}
|
|
6092
|
+
output.push({ ...header, body });
|
|
6093
|
+
}
|
|
6094
|
+
|
|
6095
|
+
return output;
|
|
6096
|
+
};
|
|
6097
|
+
|
|
6054
6098
|
SP.toJSONSchema = SP.parseSchema = function(name, url) {
|
|
6055
6099
|
|
|
6056
6100
|
let obj = {};
|
|
@@ -6314,7 +6358,7 @@ function jsonschemaaitool(name) {
|
|
|
6314
6358
|
let required = t.required;
|
|
6315
6359
|
for (let key in t.properties) {
|
|
6316
6360
|
let prop = t.properties[key];
|
|
6317
|
-
properties[key] = { type: prop.type, description: t.errors[key] };
|
|
6361
|
+
properties[key] = { type: prop.type, description: t.errors ? (t.errors[key] || '') : '' };
|
|
6318
6362
|
}
|
|
6319
6363
|
return {
|
|
6320
6364
|
type: 'function',
|