@promptbook/browser 0.112.0-73 → 0.112.0-79
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/README.md +9 -9
- package/esm/index.es.js +822 -370
- package/esm/index.es.js.map +1 -1
- package/esm/src/avatars/types/AvatarVisualDefinition.d.ts +1 -1
- package/esm/src/avatars/visuals/octopus3d2AvatarVisual.d.ts +7 -0
- package/esm/src/avatars/visuals/octopus3dAvatarVisualShared.d.ts +37 -0
- package/esm/src/book-components/Chat/save/_common/chatExportRendering.d.ts +47 -0
- package/esm/src/book-components/Chat/save/html/htmlSaveFormatDefinition.d.ts +12 -0
- package/esm/src/book-components/Chat/save/index.d.ts +2 -2
- package/esm/src/book-components/Chat/save/markdown/mdSaveFormatDefinition.d.ts +5 -3
- package/esm/src/book-components/Chat/save/pdf/buildChatPdf.d.ts +3 -3
- package/esm/src/book-components/Chat/save/pdf/pdfSaveFormatDefinition.d.ts +1 -1
- package/esm/src/cli/cli-commands/agent/agentProjectPaths.d.ts +8 -8
- package/esm/src/cli/cli-commands/agent/initializeAgentRunnerCommand.d.ts +1 -1
- package/esm/src/cli/cli-commands/agents-server/buildAgentsServer.d.ts +56 -0
- package/esm/src/cli/cli-commands/agents-server/buildAgentsServer.test.d.ts +1 -0
- package/esm/src/cli/cli-commands/agents-server/ensureAgentsServerEnvFile.d.ts +7 -0
- package/esm/src/cli/cli-commands/agents-server/ensureAgentsServerGitignoreFile.d.ts +7 -0
- package/esm/src/cli/cli-commands/agents-server/init.d.ts +9 -0
- package/esm/src/cli/cli-commands/agents-server/init.test.d.ts +1 -0
- package/esm/src/cli/cli-commands/agents-server/initializeAgentsServerProjectConfiguration.d.ts +17 -0
- package/esm/src/cli/cli-commands/agents-server/printAgentsServerInitializationSummary.d.ts +7 -0
- package/esm/src/cli/cli-commands/agents-server/run.d.ts +14 -0
- package/esm/src/cli/cli-commands/agents-server/run.test.d.ts +1 -0
- package/esm/src/cli/cli-commands/agents-server/startAgentsServer.d.ts +23 -0
- package/esm/src/cli/cli-commands/agents-server.d.ts +8 -0
- package/esm/src/cli/cli-commands/common/projectInitialization.d.ts +65 -0
- package/esm/src/cli/cli-commands/common/promptRunnerCliOptions.d.ts +44 -0
- package/esm/src/cli/common/$deprecateCliCommand.d.ts +8 -0
- package/esm/src/cli/common/$deprecateCliCommand.test.d.ts +1 -0
- package/esm/src/utils/color/Color.d.ts +4 -44
- package/esm/src/utils/color/ColorValue.d.ts +55 -0
- package/esm/src/utils/color/isHexColorString.d.ts +10 -0
- package/esm/src/utils/color/parseColorString.d.ts +11 -0
- package/esm/src/version.d.ts +1 -1
- package/package.json +2 -2
- package/umd/index.umd.js +822 -370
- package/umd/index.umd.js.map +1 -1
- package/umd/src/avatars/types/AvatarVisualDefinition.d.ts +1 -1
- package/umd/src/avatars/visuals/octopus3d2AvatarVisual.d.ts +7 -0
- package/umd/src/avatars/visuals/octopus3dAvatarVisualShared.d.ts +37 -0
- package/umd/src/book-components/Chat/save/_common/chatExportRendering.d.ts +47 -0
- package/umd/src/book-components/Chat/save/html/htmlSaveFormatDefinition.d.ts +12 -0
- package/umd/src/book-components/Chat/save/index.d.ts +2 -2
- package/umd/src/book-components/Chat/save/markdown/mdSaveFormatDefinition.d.ts +5 -3
- package/umd/src/book-components/Chat/save/pdf/buildChatPdf.d.ts +3 -3
- package/umd/src/book-components/Chat/save/pdf/pdfSaveFormatDefinition.d.ts +1 -1
- package/umd/src/cli/cli-commands/agent/agentProjectPaths.d.ts +8 -8
- package/umd/src/cli/cli-commands/agent/initializeAgentRunnerCommand.d.ts +1 -1
- package/umd/src/cli/cli-commands/agents-server/buildAgentsServer.d.ts +56 -0
- package/umd/src/cli/cli-commands/agents-server/buildAgentsServer.test.d.ts +1 -0
- package/umd/src/cli/cli-commands/agents-server/ensureAgentsServerEnvFile.d.ts +7 -0
- package/umd/src/cli/cli-commands/agents-server/ensureAgentsServerGitignoreFile.d.ts +7 -0
- package/umd/src/cli/cli-commands/agents-server/init.d.ts +9 -0
- package/umd/src/cli/cli-commands/agents-server/init.test.d.ts +1 -0
- package/umd/src/cli/cli-commands/agents-server/initializeAgentsServerProjectConfiguration.d.ts +17 -0
- package/umd/src/cli/cli-commands/agents-server/printAgentsServerInitializationSummary.d.ts +7 -0
- package/umd/src/cli/cli-commands/agents-server/run.d.ts +14 -0
- package/umd/src/cli/cli-commands/agents-server/run.test.d.ts +1 -0
- package/umd/src/cli/cli-commands/agents-server/startAgentsServer.d.ts +23 -0
- package/umd/src/cli/cli-commands/agents-server.d.ts +8 -0
- package/umd/src/cli/cli-commands/common/projectInitialization.d.ts +65 -0
- package/umd/src/cli/cli-commands/common/promptRunnerCliOptions.d.ts +44 -0
- package/umd/src/cli/common/$deprecateCliCommand.d.ts +8 -0
- package/umd/src/cli/common/$deprecateCliCommand.test.d.ts +1 -0
- package/umd/src/utils/color/Color.d.ts +4 -44
- package/umd/src/utils/color/ColorValue.d.ts +55 -0
- package/umd/src/utils/color/isHexColorString.d.ts +10 -0
- package/umd/src/utils/color/parseColorString.d.ts +11 -0
- package/umd/src/version.d.ts +1 -1
- package/esm/src/cli/cli-commands/coder/appendBlock.d.ts +0 -6
- package/esm/src/cli/cli-commands/coder/readTextFileIfExists.d.ts +0 -6
- package/umd/src/cli/cli-commands/coder/appendBlock.d.ts +0 -6
- package/umd/src/cli/cli-commands/coder/readTextFileIfExists.d.ts +0 -6
package/esm/index.es.js
CHANGED
|
@@ -29,7 +29,7 @@ const BOOK_LANGUAGE_VERSION = '2.0.0';
|
|
|
29
29
|
* @generated
|
|
30
30
|
* @see https://github.com/webgptorg/promptbook
|
|
31
31
|
*/
|
|
32
|
-
const PROMPTBOOK_ENGINE_VERSION = '0.112.0-
|
|
32
|
+
const PROMPTBOOK_ENGINE_VERSION = '0.112.0-79';
|
|
33
33
|
/**
|
|
34
34
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
|
35
35
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -279,6 +279,111 @@ function checkChannelValue(channelName, value) {
|
|
|
279
279
|
}
|
|
280
280
|
}
|
|
281
281
|
|
|
282
|
+
/**
|
|
283
|
+
* Shared immutable channel storage and serialization helpers for `Color`.
|
|
284
|
+
*
|
|
285
|
+
* @private base class of Color
|
|
286
|
+
*/
|
|
287
|
+
class ColorValue {
|
|
288
|
+
constructor(red, green, blue, alpha = 255) {
|
|
289
|
+
this.red = red;
|
|
290
|
+
this.green = green;
|
|
291
|
+
this.blue = blue;
|
|
292
|
+
this.alpha = alpha;
|
|
293
|
+
checkChannelValue('Red', red);
|
|
294
|
+
checkChannelValue('Green', green);
|
|
295
|
+
checkChannelValue('Blue', blue);
|
|
296
|
+
checkChannelValue('Alpha', alpha);
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Shortcut for `red` property
|
|
300
|
+
* Number from 0 to 255
|
|
301
|
+
* @alias red
|
|
302
|
+
*/
|
|
303
|
+
get r() {
|
|
304
|
+
return this.red;
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Shortcut for `green` property
|
|
308
|
+
* Number from 0 to 255
|
|
309
|
+
* @alias green
|
|
310
|
+
*/
|
|
311
|
+
get g() {
|
|
312
|
+
return this.green;
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Shortcut for `blue` property
|
|
316
|
+
* Number from 0 to 255
|
|
317
|
+
* @alias blue
|
|
318
|
+
*/
|
|
319
|
+
get b() {
|
|
320
|
+
return this.blue;
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Shortcut for `alpha` property
|
|
324
|
+
* Number from 0 (transparent) to 255 (opaque)
|
|
325
|
+
* @alias alpha
|
|
326
|
+
*/
|
|
327
|
+
get a() {
|
|
328
|
+
return this.alpha;
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* Shortcut for `alpha` property
|
|
332
|
+
* Number from 0 (transparent) to 255 (opaque)
|
|
333
|
+
* @alias alpha
|
|
334
|
+
*/
|
|
335
|
+
get opacity() {
|
|
336
|
+
return this.alpha;
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* Shortcut for 1-`alpha` property
|
|
340
|
+
*/
|
|
341
|
+
get transparency() {
|
|
342
|
+
return 255 - this.alpha;
|
|
343
|
+
}
|
|
344
|
+
clone() {
|
|
345
|
+
return take(this.createColor(this.red, this.green, this.blue, this.alpha));
|
|
346
|
+
}
|
|
347
|
+
toString() {
|
|
348
|
+
return this.toHex();
|
|
349
|
+
}
|
|
350
|
+
toHex() {
|
|
351
|
+
if (this.alpha === 255) {
|
|
352
|
+
return `#${this.red.toString(16).padStart(2, '0')}${this.green.toString(16).padStart(2, '0')}${this.blue
|
|
353
|
+
.toString(16)
|
|
354
|
+
.padStart(2, '0')}`;
|
|
355
|
+
}
|
|
356
|
+
else {
|
|
357
|
+
return `#${this.red.toString(16).padStart(2, '0')}${this.green.toString(16).padStart(2, '0')}${this.blue
|
|
358
|
+
.toString(16)
|
|
359
|
+
.padStart(2, '0')}${this.alpha.toString(16).padStart(2, '0')}`;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
toRgb() {
|
|
363
|
+
if (this.alpha === 255) {
|
|
364
|
+
return `rgb(${this.red}, ${this.green}, ${this.blue})`;
|
|
365
|
+
}
|
|
366
|
+
else {
|
|
367
|
+
return `rgba(${this.red}, ${this.green}, ${this.blue}, ${Math.round((this.alpha / 255) * 100)}%)`;
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
toHsl() {
|
|
371
|
+
throw new Error(`Getting HSL is not implemented`);
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* Checks if the given value is a valid hex color string
|
|
377
|
+
*
|
|
378
|
+
* @param value - value to check
|
|
379
|
+
* @returns true if the value is a valid hex color string (e.g., `#009edd`, `#fff`, etc.)
|
|
380
|
+
*
|
|
381
|
+
* @private function of Color
|
|
382
|
+
*/
|
|
383
|
+
function isHexColorString(value) {
|
|
384
|
+
return (typeof value === 'string' && /^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/.test(value));
|
|
385
|
+
}
|
|
386
|
+
|
|
282
387
|
/**
|
|
283
388
|
* Constant for short hex lengths.
|
|
284
389
|
*/
|
|
@@ -490,16 +595,53 @@ function parseAlphaValue(value) {
|
|
|
490
595
|
|
|
491
596
|
/**
|
|
492
597
|
* Pattern matching hsl regex.
|
|
598
|
+
*
|
|
599
|
+
* @private function of Color
|
|
493
600
|
*/
|
|
494
601
|
const HSL_REGEX_PATTERN = /^hsl\(\s*([0-9.]+)\s*,\s*([0-9.]+)%\s*,\s*([0-9.]+)%\s*\)$/;
|
|
495
602
|
/**
|
|
496
603
|
* Pattern matching RGB regex.
|
|
604
|
+
*
|
|
605
|
+
* @private function of Color
|
|
497
606
|
*/
|
|
498
607
|
const RGB_REGEX_PATTERN = /^rgb\(\s*([0-9.%-]+)\s*,\s*([0-9.%-]+)\s*,\s*([0-9.%-]+)\s*\)$/;
|
|
499
608
|
/**
|
|
500
609
|
* Pattern matching rgba regex.
|
|
610
|
+
*
|
|
611
|
+
* @private function of Color
|
|
501
612
|
*/
|
|
502
613
|
const RGBA_REGEX_PATTERN = /^rgba\(\s*([0-9.%-]+)\s*,\s*([0-9.%-]+)\s*,\s*([0-9.%-]+)\s*,\s*([0-9.%-]+)\s*\)$/;
|
|
614
|
+
/**
|
|
615
|
+
* Parses a supported color string into RGBA channels.
|
|
616
|
+
*
|
|
617
|
+
* @param color as a string for example `#009edd`, `rgb(0,158,221)`, `rgb(0%,62%,86.7%)`, `hsl(197.1,100%,43.3%)`, `red`, `darkgrey`,...
|
|
618
|
+
* @returns RGBA channel values.
|
|
619
|
+
*
|
|
620
|
+
* @private function of Color
|
|
621
|
+
*/
|
|
622
|
+
function parseColorString(color) {
|
|
623
|
+
const trimmed = color.trim();
|
|
624
|
+
const cssColor = CSS_COLORS[trimmed];
|
|
625
|
+
if (cssColor) {
|
|
626
|
+
return parseColorString(cssColor);
|
|
627
|
+
}
|
|
628
|
+
else if (isHexColorString(trimmed)) {
|
|
629
|
+
return parseHexColor(trimmed);
|
|
630
|
+
}
|
|
631
|
+
if (HSL_REGEX_PATTERN.test(trimmed)) {
|
|
632
|
+
return parseHslColor(trimmed);
|
|
633
|
+
}
|
|
634
|
+
else if (RGB_REGEX_PATTERN.test(trimmed)) {
|
|
635
|
+
return parseRgbColor(trimmed);
|
|
636
|
+
}
|
|
637
|
+
else if (RGBA_REGEX_PATTERN.test(trimmed)) {
|
|
638
|
+
return parseRgbaColor(trimmed);
|
|
639
|
+
}
|
|
640
|
+
else {
|
|
641
|
+
throw new Error(`Can not create a new Color instance from string "${trimmed}".`);
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
|
|
503
645
|
/**
|
|
504
646
|
* Color object represents an RGB color with alpha channel
|
|
505
647
|
*
|
|
@@ -507,7 +649,7 @@ const RGBA_REGEX_PATTERN = /^rgba\(\s*([0-9.%-]+)\s*,\s*([0-9.%-]+)\s*,\s*([0-9.
|
|
|
507
649
|
*
|
|
508
650
|
* @public exported from `@promptbook/color`
|
|
509
651
|
*/
|
|
510
|
-
class Color {
|
|
652
|
+
class Color extends ColorValue {
|
|
511
653
|
/**
|
|
512
654
|
* Creates a new Color instance from miscellaneous formats
|
|
513
655
|
* - It can receive Color instance and just return the same instance
|
|
@@ -580,25 +722,7 @@ class Color {
|
|
|
580
722
|
* @returns Color object
|
|
581
723
|
*/
|
|
582
724
|
static fromString(color) {
|
|
583
|
-
|
|
584
|
-
if (CSS_COLORS[trimmed]) {
|
|
585
|
-
return Color.fromString(CSS_COLORS[trimmed]);
|
|
586
|
-
}
|
|
587
|
-
else if (Color.isHexColorString(trimmed)) {
|
|
588
|
-
return Color.fromHex(trimmed);
|
|
589
|
-
}
|
|
590
|
-
if (HSL_REGEX_PATTERN.test(trimmed)) {
|
|
591
|
-
return Color.fromHsl(trimmed);
|
|
592
|
-
}
|
|
593
|
-
else if (RGB_REGEX_PATTERN.test(trimmed)) {
|
|
594
|
-
return Color.fromRgbString(trimmed);
|
|
595
|
-
}
|
|
596
|
-
else if (RGBA_REGEX_PATTERN.test(trimmed)) {
|
|
597
|
-
return Color.fromRgbaString(trimmed);
|
|
598
|
-
}
|
|
599
|
-
else {
|
|
600
|
-
throw new Error(`Can not create a new Color instance from string "${trimmed}".`);
|
|
601
|
-
}
|
|
725
|
+
return Color.fromColorChannels(parseColorString(color));
|
|
602
726
|
}
|
|
603
727
|
/**
|
|
604
728
|
* Gets common color
|
|
@@ -628,8 +752,7 @@ class Color {
|
|
|
628
752
|
* @returns Color object
|
|
629
753
|
*/
|
|
630
754
|
static fromHex(hex) {
|
|
631
|
-
|
|
632
|
-
return take(new Color(red, green, blue, alpha));
|
|
755
|
+
return Color.fromColorChannels(parseHexColor(hex));
|
|
633
756
|
}
|
|
634
757
|
/**
|
|
635
758
|
* Creates a new Color instance from color in hsl format
|
|
@@ -638,8 +761,7 @@ class Color {
|
|
|
638
761
|
* @returns Color object
|
|
639
762
|
*/
|
|
640
763
|
static fromHsl(hsl) {
|
|
641
|
-
|
|
642
|
-
return take(new Color(red, green, blue, alpha));
|
|
764
|
+
return Color.fromColorChannels(parseHslColor(hsl));
|
|
643
765
|
}
|
|
644
766
|
/**
|
|
645
767
|
* Creates a new Color instance from color in rgb format
|
|
@@ -648,8 +770,7 @@ class Color {
|
|
|
648
770
|
* @returns Color object
|
|
649
771
|
*/
|
|
650
772
|
static fromRgbString(rgb) {
|
|
651
|
-
|
|
652
|
-
return take(new Color(red, green, blue, alpha));
|
|
773
|
+
return Color.fromColorChannels(parseRgbColor(rgb));
|
|
653
774
|
}
|
|
654
775
|
/**
|
|
655
776
|
* Creates a new Color instance from color in rbga format
|
|
@@ -658,8 +779,7 @@ class Color {
|
|
|
658
779
|
* @returns Color object
|
|
659
780
|
*/
|
|
660
781
|
static fromRgbaString(rgba) {
|
|
661
|
-
|
|
662
|
-
return take(new Color(red, green, blue, alpha));
|
|
782
|
+
return Color.fromColorChannels(parseRgbaColor(rgba));
|
|
663
783
|
}
|
|
664
784
|
/**
|
|
665
785
|
* Creates a new Color for color channels values
|
|
@@ -671,7 +791,7 @@ class Color {
|
|
|
671
791
|
* @returns Color object
|
|
672
792
|
*/
|
|
673
793
|
static fromValues(red, green, blue, alpha = 255) {
|
|
674
|
-
return
|
|
794
|
+
return Color.fromColorChannels({ red, green, blue, alpha });
|
|
675
795
|
}
|
|
676
796
|
/**
|
|
677
797
|
* Checks if the given value is a valid Color object.
|
|
@@ -704,8 +824,7 @@ class Color {
|
|
|
704
824
|
* @returns true if the value is a valid hex color string (e.g., `#009edd`, `#fff`, etc.)
|
|
705
825
|
*/
|
|
706
826
|
static isHexColorString(value) {
|
|
707
|
-
return (
|
|
708
|
-
/^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/.test(value));
|
|
827
|
+
return isHexColorString(value);
|
|
709
828
|
}
|
|
710
829
|
/**
|
|
711
830
|
* Creates new Color object
|
|
@@ -718,89 +837,13 @@ class Color {
|
|
|
718
837
|
* @param alpha number from 0 (transparent) to 255 (opaque)
|
|
719
838
|
*/
|
|
720
839
|
constructor(red, green, blue, alpha = 255) {
|
|
721
|
-
|
|
722
|
-
this.green = green;
|
|
723
|
-
this.blue = blue;
|
|
724
|
-
this.alpha = alpha;
|
|
725
|
-
checkChannelValue('Red', red);
|
|
726
|
-
checkChannelValue('Green', green);
|
|
727
|
-
checkChannelValue('Blue', blue);
|
|
728
|
-
checkChannelValue('Alpha', alpha);
|
|
840
|
+
super(red, green, blue, alpha);
|
|
729
841
|
}
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
* Number from 0 to 255
|
|
733
|
-
* @alias red
|
|
734
|
-
*/
|
|
735
|
-
get r() {
|
|
736
|
-
return this.red;
|
|
737
|
-
}
|
|
738
|
-
/**
|
|
739
|
-
* Shortcut for `green` property
|
|
740
|
-
* Number from 0 to 255
|
|
741
|
-
* @alias green
|
|
742
|
-
*/
|
|
743
|
-
get g() {
|
|
744
|
-
return this.green;
|
|
745
|
-
}
|
|
746
|
-
/**
|
|
747
|
-
* Shortcut for `blue` property
|
|
748
|
-
* Number from 0 to 255
|
|
749
|
-
* @alias blue
|
|
750
|
-
*/
|
|
751
|
-
get b() {
|
|
752
|
-
return this.blue;
|
|
753
|
-
}
|
|
754
|
-
/**
|
|
755
|
-
* Shortcut for `alpha` property
|
|
756
|
-
* Number from 0 (transparent) to 255 (opaque)
|
|
757
|
-
* @alias alpha
|
|
758
|
-
*/
|
|
759
|
-
get a() {
|
|
760
|
-
return this.alpha;
|
|
842
|
+
createColor(red, green, blue, alpha) {
|
|
843
|
+
return new Color(red, green, blue, alpha);
|
|
761
844
|
}
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
* Number from 0 (transparent) to 255 (opaque)
|
|
765
|
-
* @alias alpha
|
|
766
|
-
*/
|
|
767
|
-
get opacity() {
|
|
768
|
-
return this.alpha;
|
|
769
|
-
}
|
|
770
|
-
/**
|
|
771
|
-
* Shortcut for 1-`alpha` property
|
|
772
|
-
*/
|
|
773
|
-
get transparency() {
|
|
774
|
-
return 255 - this.alpha;
|
|
775
|
-
}
|
|
776
|
-
clone() {
|
|
777
|
-
return take(new Color(this.red, this.green, this.blue, this.alpha));
|
|
778
|
-
}
|
|
779
|
-
toString() {
|
|
780
|
-
return this.toHex();
|
|
781
|
-
}
|
|
782
|
-
toHex() {
|
|
783
|
-
if (this.alpha === 255) {
|
|
784
|
-
return `#${this.red.toString(16).padStart(2, '0')}${this.green.toString(16).padStart(2, '0')}${this.blue
|
|
785
|
-
.toString(16)
|
|
786
|
-
.padStart(2, '0')}`;
|
|
787
|
-
}
|
|
788
|
-
else {
|
|
789
|
-
return `#${this.red.toString(16).padStart(2, '0')}${this.green.toString(16).padStart(2, '0')}${this.blue
|
|
790
|
-
.toString(16)
|
|
791
|
-
.padStart(2, '0')}${this.alpha.toString(16).padStart(2, '0')}`;
|
|
792
|
-
}
|
|
793
|
-
}
|
|
794
|
-
toRgb() {
|
|
795
|
-
if (this.alpha === 255) {
|
|
796
|
-
return `rgb(${this.red}, ${this.green}, ${this.blue})`;
|
|
797
|
-
}
|
|
798
|
-
else {
|
|
799
|
-
return `rgba(${this.red}, ${this.green}, ${this.blue}, ${Math.round((this.alpha / 255) * 100)}%)`;
|
|
800
|
-
}
|
|
801
|
-
}
|
|
802
|
-
toHsl() {
|
|
803
|
-
throw new Error(`Getting HSL is not implemented`);
|
|
845
|
+
static fromColorChannels({ red, green, blue, alpha }) {
|
|
846
|
+
return take(new Color(red, green, blue, alpha));
|
|
804
847
|
}
|
|
805
848
|
}
|
|
806
849
|
|
|
@@ -6594,7 +6637,7 @@ function fillTextureRect(texture, x, y, width, height, color) {
|
|
|
6594
6637
|
*
|
|
6595
6638
|
* @private helper of `minecraft2AvatarVisual`
|
|
6596
6639
|
*/
|
|
6597
|
-
const LIGHT_DIRECTION$
|
|
6640
|
+
const LIGHT_DIRECTION$2 = normalizeVector3({
|
|
6598
6641
|
x: 0.4,
|
|
6599
6642
|
y: -0.65,
|
|
6600
6643
|
z: 0.92,
|
|
@@ -6806,7 +6849,7 @@ function resolveVisibleCuboidFaces(cuboid, size, sceneCenterX, sceneCenterY) {
|
|
|
6806
6849
|
corners: projectedCorners,
|
|
6807
6850
|
texture: faceDefinition.texture,
|
|
6808
6851
|
averageDepth: transformedCorners.reduce((depthSum, corner) => depthSum + corner.z, 0) / transformedCorners.length,
|
|
6809
|
-
lightIntensity: clampNumber$1(dotProduct3D(faceNormal, LIGHT_DIRECTION$
|
|
6852
|
+
lightIntensity: clampNumber$1(dotProduct3D(faceNormal, LIGHT_DIRECTION$2), -1, 1),
|
|
6810
6853
|
outlineColor: cuboid.outlineColor,
|
|
6811
6854
|
};
|
|
6812
6855
|
});
|
|
@@ -7866,13 +7909,138 @@ function drawSeededEye(context, centerX, centerY, radiusX, radiusY, rotation, pa
|
|
|
7866
7909
|
context.restore();
|
|
7867
7910
|
}
|
|
7868
7911
|
|
|
7912
|
+
/* eslint-disable no-magic-numbers */
|
|
7913
|
+
/**
|
|
7914
|
+
* Draws one projected eye on a rotated octopus surface.
|
|
7915
|
+
*
|
|
7916
|
+
* @private helper of the 3D octopus avatar visuals
|
|
7917
|
+
*/
|
|
7918
|
+
function drawProjectedOrganicEye(context, localCenter, radiusX, radiusY, center, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, phase, interaction, eyeStyle) {
|
|
7919
|
+
const centerScenePoint = transformScenePoint(localCenter, center, rotationX, rotationY);
|
|
7920
|
+
if (centerScenePoint.z <= center.z) {
|
|
7921
|
+
return;
|
|
7922
|
+
}
|
|
7923
|
+
const horizontalScenePoint = transformScenePoint({ x: localCenter.x + radiusX, y: localCenter.y, z: localCenter.z }, center, rotationX, rotationY);
|
|
7924
|
+
const verticalScenePoint = transformScenePoint({ x: localCenter.x, y: localCenter.y + radiusY, z: localCenter.z }, center, rotationX, rotationY);
|
|
7925
|
+
const projectedCenterPoint = projectScenePoint(centerScenePoint, size, sceneCenterX, sceneCenterY);
|
|
7926
|
+
const projectedHorizontalPoint = projectScenePoint(horizontalScenePoint, size, sceneCenterX, sceneCenterY);
|
|
7927
|
+
const projectedVerticalPoint = projectScenePoint(verticalScenePoint, size, sceneCenterX, sceneCenterY);
|
|
7928
|
+
const projectedRadiusX = Math.hypot(projectedHorizontalPoint.x - projectedCenterPoint.x, projectedHorizontalPoint.y - projectedCenterPoint.y);
|
|
7929
|
+
const projectedRadiusY = Math.hypot(projectedVerticalPoint.x - projectedCenterPoint.x, projectedVerticalPoint.y - projectedCenterPoint.y);
|
|
7930
|
+
if (projectedRadiusX < size * 0.008 || projectedRadiusY < size * 0.008) {
|
|
7931
|
+
return;
|
|
7932
|
+
}
|
|
7933
|
+
const { pupilOffsetX, pupilOffsetY } = resolveOrganicEyeMotion({
|
|
7934
|
+
radiusX: projectedRadiusX,
|
|
7935
|
+
radiusY: projectedRadiusY,
|
|
7936
|
+
timeMs,
|
|
7937
|
+
phase,
|
|
7938
|
+
interaction,
|
|
7939
|
+
});
|
|
7940
|
+
const rotation = Math.atan2(projectedHorizontalPoint.y - projectedCenterPoint.y, projectedHorizontalPoint.x - projectedCenterPoint.x);
|
|
7941
|
+
context.save();
|
|
7942
|
+
context.translate(projectedCenterPoint.x, projectedCenterPoint.y);
|
|
7943
|
+
context.rotate(rotation);
|
|
7944
|
+
context.beginPath();
|
|
7945
|
+
context.ellipse(0, 0, projectedRadiusX, projectedRadiusY, 0, 0, Math.PI * 2);
|
|
7946
|
+
context.fillStyle = '#f8fbff';
|
|
7947
|
+
context.fill();
|
|
7948
|
+
context.clip();
|
|
7949
|
+
const irisGradient = context.createRadialGradient(-projectedRadiusX * 0.2, -projectedRadiusY * 0.26, projectedRadiusX * 0.05, 0, 0, projectedRadiusX * 0.92);
|
|
7950
|
+
irisGradient.addColorStop(0, palette.highlight);
|
|
7951
|
+
irisGradient.addColorStop(0.56, palette.secondary);
|
|
7952
|
+
irisGradient.addColorStop(1, palette.shadow);
|
|
7953
|
+
context.beginPath();
|
|
7954
|
+
context.ellipse(pupilOffsetX, pupilOffsetY, projectedRadiusX * 0.62 * eyeStyle.irisScale, projectedRadiusY * 0.72 * eyeStyle.irisScale, 0, 0, Math.PI * 2);
|
|
7955
|
+
context.fillStyle = irisGradient;
|
|
7956
|
+
context.fill();
|
|
7957
|
+
context.beginPath();
|
|
7958
|
+
context.ellipse(pupilOffsetX, pupilOffsetY, projectedRadiusX * 0.15 * eyeStyle.pupilWidthScale, projectedRadiusY * 0.48 * eyeStyle.pupilHeightScale, 0, 0, Math.PI * 2);
|
|
7959
|
+
context.fillStyle = palette.ink;
|
|
7960
|
+
context.fill();
|
|
7961
|
+
context.beginPath();
|
|
7962
|
+
context.ellipse(pupilOffsetX - projectedRadiusX * 0.22, pupilOffsetY - projectedRadiusY * 0.24, projectedRadiusX * 0.12, projectedRadiusY * 0.14, 0, 0, Math.PI * 2);
|
|
7963
|
+
context.fillStyle = '#ffffff';
|
|
7964
|
+
context.fill();
|
|
7965
|
+
context.restore();
|
|
7966
|
+
context.save();
|
|
7967
|
+
context.translate(projectedCenterPoint.x, projectedCenterPoint.y);
|
|
7968
|
+
context.rotate(rotation);
|
|
7969
|
+
context.beginPath();
|
|
7970
|
+
context.ellipse(0, 0, projectedRadiusX, projectedRadiusY, 0, 0, Math.PI * 2);
|
|
7971
|
+
context.strokeStyle = `${palette.shadow}cc`;
|
|
7972
|
+
context.lineWidth = projectedRadiusX * 0.16;
|
|
7973
|
+
context.stroke();
|
|
7974
|
+
context.beginPath();
|
|
7975
|
+
context.moveTo(-projectedRadiusX * 0.88, -projectedRadiusY * eyeStyle.upperLidInsetRatio);
|
|
7976
|
+
context.quadraticCurveTo(0, -projectedRadiusY * (eyeStyle.upperLidArchRatio - interaction.gazeY * 0.16 + interaction.intensity * 0.08), projectedRadiusX * 0.88, -projectedRadiusY * eyeStyle.upperLidInsetRatio);
|
|
7977
|
+
context.strokeStyle = `${palette.shadow}73`;
|
|
7978
|
+
context.lineWidth = projectedRadiusX * 0.14;
|
|
7979
|
+
context.lineCap = 'round';
|
|
7980
|
+
context.stroke();
|
|
7981
|
+
if (eyeStyle.lowerLidOpacity > 0) {
|
|
7982
|
+
context.beginPath();
|
|
7983
|
+
context.moveTo(-projectedRadiusX * 0.74, projectedRadiusY * 0.2);
|
|
7984
|
+
context.quadraticCurveTo(0, projectedRadiusY * 0.38, projectedRadiusX * 0.74, projectedRadiusY * 0.2);
|
|
7985
|
+
context.strokeStyle = `${palette.highlight}${formatAlphaHex(eyeStyle.lowerLidOpacity)}`;
|
|
7986
|
+
context.lineWidth = projectedRadiusX * 0.08;
|
|
7987
|
+
context.lineCap = 'round';
|
|
7988
|
+
context.stroke();
|
|
7989
|
+
}
|
|
7990
|
+
context.restore();
|
|
7991
|
+
}
|
|
7992
|
+
/**
|
|
7993
|
+
* Draws a subtle projected mouth arc across the front of a rotated octopus surface.
|
|
7994
|
+
*
|
|
7995
|
+
* @private helper of the 3D octopus avatar visuals
|
|
7996
|
+
*/
|
|
7997
|
+
function drawProjectedOrganicMouth(context, localPoints, center, rotationX, rotationY, sceneCenterX, sceneCenterY, palette, size) {
|
|
7998
|
+
const scenePoints = localPoints.map((localPoint) => transformScenePoint(localPoint, center, rotationX, rotationY));
|
|
7999
|
+
if (scenePoints.some((scenePoint) => scenePoint.z <= center.z)) {
|
|
8000
|
+
return;
|
|
8001
|
+
}
|
|
8002
|
+
const projectedPoints = scenePoints.map((scenePoint) => projectScenePoint(scenePoint, size, sceneCenterX, sceneCenterY));
|
|
8003
|
+
context.beginPath();
|
|
8004
|
+
context.moveTo(projectedPoints[0].x, projectedPoints[0].y);
|
|
8005
|
+
context.quadraticCurveTo(projectedPoints[1].x, projectedPoints[1].y, projectedPoints[2].x, projectedPoints[2].y);
|
|
8006
|
+
context.strokeStyle = `${palette.ink}b8`;
|
|
8007
|
+
context.lineWidth = Math.max(1.1, size * 0.009);
|
|
8008
|
+
context.lineCap = 'round';
|
|
8009
|
+
context.stroke();
|
|
8010
|
+
}
|
|
8011
|
+
/**
|
|
8012
|
+
* Draws one filled projected quad.
|
|
8013
|
+
*
|
|
8014
|
+
* @private helper of the 3D octopus avatar visuals
|
|
8015
|
+
*/
|
|
8016
|
+
function drawProjectedQuad(context, corners, fillStyle) {
|
|
8017
|
+
context.beginPath();
|
|
8018
|
+
context.moveTo(corners[0].x, corners[0].y);
|
|
8019
|
+
context.lineTo(corners[1].x, corners[1].y);
|
|
8020
|
+
context.lineTo(corners[2].x, corners[2].y);
|
|
8021
|
+
context.lineTo(corners[3].x, corners[3].y);
|
|
8022
|
+
context.closePath();
|
|
8023
|
+
context.fillStyle = fillStyle;
|
|
8024
|
+
context.fill();
|
|
8025
|
+
}
|
|
8026
|
+
/**
|
|
8027
|
+
* Converts an opacity ratio into a two-digit hexadecimal alpha suffix.
|
|
8028
|
+
*
|
|
8029
|
+
* @private helper of the 3D octopus avatar visuals
|
|
8030
|
+
*/
|
|
8031
|
+
function formatAlphaHex(opacity) {
|
|
8032
|
+
return Math.round(clampNumber$1(opacity, 0, 1) * 255)
|
|
8033
|
+
.toString(16)
|
|
8034
|
+
.padStart(2, '0');
|
|
8035
|
+
}
|
|
8036
|
+
|
|
7869
8037
|
/* eslint-disable no-magic-numbers */
|
|
7870
8038
|
/**
|
|
7871
8039
|
* Light direction used by the organic 3D octopus shading.
|
|
7872
8040
|
*
|
|
7873
8041
|
* @private helper of `octopus3dAvatarVisual`
|
|
7874
8042
|
*/
|
|
7875
|
-
const LIGHT_DIRECTION = normalizeVector3({
|
|
8043
|
+
const LIGHT_DIRECTION$1 = normalizeVector3({
|
|
7876
8044
|
x: 0.48,
|
|
7877
8045
|
y: -0.62,
|
|
7878
8046
|
z: 0.94,
|
|
@@ -7985,17 +8153,17 @@ const octopus3dAvatarVisual = {
|
|
|
7985
8153
|
for (const tentacleStroke of tentacleStrokes.filter((candidateTentacleStroke) => candidateTentacleStroke.isFrontFacing)) {
|
|
7986
8154
|
drawTentacleStroke(context, tentacleStroke, palette);
|
|
7987
8155
|
}
|
|
7988
|
-
|
|
8156
|
+
drawProjectedOrganicEye(context, {
|
|
7989
8157
|
x: -faceEyeSpacing,
|
|
7990
8158
|
y: faceEyeYOffset,
|
|
7991
8159
|
z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, -faceEyeSpacing, faceEyeYOffset),
|
|
7992
8160
|
}, faceEyeRadiusX, faceEyeRadiusY, mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + eyeRandom() * 0.6, interaction, morphologyProfile.face.eyeStyle);
|
|
7993
|
-
|
|
8161
|
+
drawProjectedOrganicEye(context, {
|
|
7994
8162
|
x: faceEyeSpacing,
|
|
7995
8163
|
y: faceEyeYOffset,
|
|
7996
8164
|
z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, faceEyeSpacing, faceEyeYOffset),
|
|
7997
8165
|
}, faceEyeRadiusX, faceEyeRadiusY, mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + 0.7 + eyeRandom() * 0.6, interaction, morphologyProfile.face.eyeStyle);
|
|
7998
|
-
|
|
8166
|
+
drawProjectedOrganicMouth(context, [
|
|
7999
8167
|
{
|
|
8000
8168
|
x: -mouthHalfWidth,
|
|
8001
8169
|
y: mouthY,
|
|
@@ -8082,7 +8250,7 @@ function resolveVisibleEllipsoidPatches(options) {
|
|
|
8082
8250
|
corners: projectedCorners,
|
|
8083
8251
|
averageDepth: transformedCorners.reduce((depthSum, transformedCorner) => depthSum + transformedCorner.z, 0) /
|
|
8084
8252
|
transformedCorners.length,
|
|
8085
|
-
lightIntensity: clampNumber$1(dotProduct3D(surfaceNormal, LIGHT_DIRECTION), -1, 1),
|
|
8253
|
+
lightIntensity: clampNumber$1(dotProduct3D(surfaceNormal, LIGHT_DIRECTION$1), -1, 1),
|
|
8086
8254
|
fillStyle: resolveSurfacePatchFillStyle(palette, verticalProgress + verticalColorBias),
|
|
8087
8255
|
outlineColor,
|
|
8088
8256
|
});
|
|
@@ -8264,128 +8432,260 @@ function resolveEllipsoidSurfaceDepth(radiusX, radiusY, radiusZ, x, y) {
|
|
|
8264
8432
|
const remainingDepthRatio = Math.max(0, 1 - normalizedX * normalizedX - normalizedY * normalizedY);
|
|
8265
8433
|
return Math.sqrt(remainingDepthRatio) * radiusZ;
|
|
8266
8434
|
}
|
|
8435
|
+
|
|
8436
|
+
/* eslint-disable no-magic-numbers */
|
|
8267
8437
|
/**
|
|
8268
|
-
*
|
|
8438
|
+
* Light direction used by the single-mesh octopus shading.
|
|
8269
8439
|
*
|
|
8270
|
-
* @private helper of `
|
|
8440
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
8271
8441
|
*/
|
|
8272
|
-
|
|
8273
|
-
|
|
8274
|
-
|
|
8275
|
-
|
|
8276
|
-
|
|
8277
|
-
|
|
8278
|
-
|
|
8279
|
-
|
|
8280
|
-
|
|
8281
|
-
|
|
8282
|
-
|
|
8283
|
-
|
|
8284
|
-
|
|
8285
|
-
|
|
8286
|
-
|
|
8287
|
-
|
|
8288
|
-
|
|
8289
|
-
|
|
8290
|
-
|
|
8291
|
-
|
|
8292
|
-
|
|
8293
|
-
|
|
8294
|
-
|
|
8442
|
+
const LIGHT_DIRECTION = normalizeVector3({
|
|
8443
|
+
x: 0.38,
|
|
8444
|
+
y: -0.6,
|
|
8445
|
+
z: 0.98,
|
|
8446
|
+
});
|
|
8447
|
+
/**
|
|
8448
|
+
* Octopus 3D 2 avatar visual.
|
|
8449
|
+
*
|
|
8450
|
+
* @private built-in avatar visual
|
|
8451
|
+
*/
|
|
8452
|
+
const octopus3d2AvatarVisual = {
|
|
8453
|
+
id: 'octopus3d2',
|
|
8454
|
+
title: 'Octopus 3D 2',
|
|
8455
|
+
description: 'Continuous blobby 3D octopus portrait with one soft mesh, turning silhouette, and cursor-aware eyes.',
|
|
8456
|
+
isAnimated: true,
|
|
8457
|
+
supportsPointerTracking: true,
|
|
8458
|
+
render({ context, size, palette, createRandom, timeMs, interaction }) {
|
|
8459
|
+
const morphologyProfile = createOctopus3MorphologyProfile(createRandom);
|
|
8460
|
+
const animationRandom = createRandom('octopus3d2-animation-profile');
|
|
8461
|
+
const eyeRandom = createRandom('octopus3d2-eye-profile');
|
|
8462
|
+
const animationPhase = animationRandom() * Math.PI * 2;
|
|
8463
|
+
const sceneCenterX = size * 0.5;
|
|
8464
|
+
const sceneCenterY = size * 0.575;
|
|
8465
|
+
const bob = Math.sin(timeMs / 940 + animationPhase) * size * 0.013;
|
|
8466
|
+
const meshCenter = {
|
|
8467
|
+
x: interaction.bodyOffsetX * size * 0.044 + size * morphologyProfile.body.centerXJitterRatio * 0.5,
|
|
8468
|
+
y: -size * 0.03 + interaction.bodyOffsetY * size * 0.026 + bob,
|
|
8469
|
+
z: interaction.intensity * size * 0.018,
|
|
8470
|
+
};
|
|
8471
|
+
const rotationY = -0.14 +
|
|
8472
|
+
Math.sin(timeMs / 2600 + animationPhase) * 0.04 +
|
|
8473
|
+
interaction.bodyOffsetX * 0.2 +
|
|
8474
|
+
interaction.gazeX * 0.78;
|
|
8475
|
+
const rotationX = -0.06 +
|
|
8476
|
+
Math.cos(timeMs / 3000 + animationPhase * 0.7) * 0.02 -
|
|
8477
|
+
interaction.bodyOffsetY * 0.08 -
|
|
8478
|
+
interaction.gazeY * 0.34;
|
|
8479
|
+
const surfaceOptions = {
|
|
8480
|
+
radiusX: size * morphologyProfile.body.bodyRadiusRatio * morphologyProfile.body.horizontalStretch * 1.02,
|
|
8481
|
+
radiusY: size * morphologyProfile.body.bodyRadiusRatio * morphologyProfile.body.verticalStretch * 1.22,
|
|
8482
|
+
radiusZ: size *
|
|
8483
|
+
morphologyProfile.body.bodyRadiusRatio *
|
|
8484
|
+
(0.98 + (morphologyProfile.body.horizontalStretch - 1) * 0.2),
|
|
8485
|
+
morphologyProfile,
|
|
8486
|
+
timeMs,
|
|
8487
|
+
animationPhase,
|
|
8488
|
+
};
|
|
8489
|
+
const surfacePatches = resolveVisibleBlobbyOctopusPatches({
|
|
8490
|
+
...surfaceOptions,
|
|
8491
|
+
center: meshCenter,
|
|
8492
|
+
rotationX,
|
|
8493
|
+
rotationY,
|
|
8494
|
+
sceneCenterX,
|
|
8495
|
+
sceneCenterY,
|
|
8496
|
+
size,
|
|
8497
|
+
palette,
|
|
8498
|
+
});
|
|
8499
|
+
const eyeLatitude = clampNumber$1(morphologyProfile.face.eyeCenterYOffsetRatio * 4.4, -0.16, 0.11);
|
|
8500
|
+
const eyeLongitude = clampNumber$1(morphologyProfile.face.eyeSpacingRatio * 3.25, 0.2, 0.34);
|
|
8501
|
+
const mouthLatitude = clampNumber$1(eyeLatitude + 0.19 + morphologyProfile.face.mouthYOffsetRatio * 1.08, 0.08, 0.34);
|
|
8502
|
+
const mouthCenterLongitude = clampNumber$1(morphologyProfile.face.mouthCenterOffsetRatio * 5.8, -0.08, 0.08);
|
|
8503
|
+
const mouthHalfLongitude = clampNumber$1(eyeLongitude * 0.82, 0.16, 0.29);
|
|
8504
|
+
const mouthCurveLatitude = clampNumber$1(mouthLatitude + morphologyProfile.face.mouthCurveDepthRatio * 0.85, mouthLatitude + 0.03, 0.42);
|
|
8505
|
+
drawAvatarFrame(context, size, palette);
|
|
8506
|
+
drawBlobbyOctopusAtmosphere(context, size, palette, sceneCenterX, sceneCenterY, interaction, timeMs);
|
|
8507
|
+
drawBlobbyOctopusShadow(context, size, palette, interaction, timeMs, morphologyProfile);
|
|
8508
|
+
for (const surfacePatch of surfacePatches.sort((firstSurfacePatch, secondSurfacePatch) => firstSurfacePatch.averageDepth - secondSurfacePatch.averageDepth)) {
|
|
8509
|
+
drawBlobbySurfacePatch(context, surfacePatch);
|
|
8510
|
+
}
|
|
8511
|
+
const leftEyeLocalCenter = sampleBlobbyOctopusSurfacePoint(surfaceOptions, eyeLatitude, -eyeLongitude);
|
|
8512
|
+
const rightEyeLocalCenter = sampleBlobbyOctopusSurfacePoint(surfaceOptions, eyeLatitude, eyeLongitude);
|
|
8513
|
+
const eyeRadiusX = size * morphologyProfile.face.eyeRadiusXRatio * 0.78;
|
|
8514
|
+
const eyeRadiusY = eyeRadiusX * morphologyProfile.face.eyeHeightRatio * 0.92;
|
|
8515
|
+
drawProjectedOrganicEye(context, leftEyeLocalCenter, eyeRadiusX, eyeRadiusY, meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + eyeRandom() * 0.7, interaction, morphologyProfile.face.eyeStyle);
|
|
8516
|
+
drawProjectedOrganicEye(context, rightEyeLocalCenter, eyeRadiusX, eyeRadiusY, meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + 0.9 + eyeRandom() * 0.7, interaction, morphologyProfile.face.eyeStyle);
|
|
8517
|
+
drawProjectedOrganicMouth(context, [
|
|
8518
|
+
sampleBlobbyOctopusSurfacePoint(surfaceOptions, mouthLatitude, mouthCenterLongitude - mouthHalfLongitude),
|
|
8519
|
+
sampleBlobbyOctopusSurfacePoint(surfaceOptions, mouthCurveLatitude, mouthCenterLongitude),
|
|
8520
|
+
sampleBlobbyOctopusSurfacePoint(surfaceOptions, mouthLatitude, mouthCenterLongitude + mouthHalfLongitude),
|
|
8521
|
+
], meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, palette, size);
|
|
8522
|
+
},
|
|
8523
|
+
};
|
|
8524
|
+
/**
|
|
8525
|
+
* Draws the deep-water glow behind the continuous octopus mesh.
|
|
8526
|
+
*
|
|
8527
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
8528
|
+
*/
|
|
8529
|
+
function drawBlobbyOctopusAtmosphere(context, size, palette, sceneCenterX, sceneCenterY, interaction, timeMs) {
|
|
8530
|
+
const glowGradient = context.createRadialGradient(sceneCenterX + interaction.gazeX * size * 0.11, sceneCenterY - size * 0.17 + interaction.gazeY * size * 0.05, size * 0.05, sceneCenterX, sceneCenterY - size * 0.03, size * 0.66);
|
|
8531
|
+
glowGradient.addColorStop(0, `${palette.highlight}5e`);
|
|
8532
|
+
glowGradient.addColorStop(0.38, `${palette.accent}26`);
|
|
8533
|
+
glowGradient.addColorStop(1, `${palette.highlight}00`);
|
|
8534
|
+
context.fillStyle = glowGradient;
|
|
8535
|
+
context.fillRect(0, 0, size, size);
|
|
8536
|
+
const lowerGradient = context.createRadialGradient(sceneCenterX + Math.sin(timeMs / 1650) * size * 0.045, sceneCenterY + size * 0.28, size * 0.06, sceneCenterX, sceneCenterY + size * 0.28, size * 0.52);
|
|
8537
|
+
lowerGradient.addColorStop(0, `${palette.secondary}22`);
|
|
8538
|
+
lowerGradient.addColorStop(1, `${palette.secondary}00`);
|
|
8539
|
+
context.fillStyle = lowerGradient;
|
|
8540
|
+
context.fillRect(0, 0, size, size);
|
|
8541
|
+
}
|
|
8542
|
+
/**
|
|
8543
|
+
* Draws the soft floor shadow that anchors the single mesh in the frame.
|
|
8544
|
+
*
|
|
8545
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
8546
|
+
*/
|
|
8547
|
+
function drawBlobbyOctopusShadow(context, size, palette, interaction, timeMs, morphologyProfile) {
|
|
8295
8548
|
context.save();
|
|
8296
|
-
context.
|
|
8297
|
-
context.
|
|
8298
|
-
context.beginPath();
|
|
8299
|
-
context.ellipse(0, 0, projectedRadiusX, projectedRadiusY, 0, 0, Math.PI * 2);
|
|
8300
|
-
context.fillStyle = '#f8fbff';
|
|
8301
|
-
context.fill();
|
|
8302
|
-
context.clip();
|
|
8303
|
-
const irisGradient = context.createRadialGradient(-projectedRadiusX * 0.2, -projectedRadiusY * 0.26, projectedRadiusX * 0.05, 0, 0, projectedRadiusX * 0.92);
|
|
8304
|
-
irisGradient.addColorStop(0, palette.highlight);
|
|
8305
|
-
irisGradient.addColorStop(0.56, palette.secondary);
|
|
8306
|
-
irisGradient.addColorStop(1, palette.shadow);
|
|
8307
|
-
context.beginPath();
|
|
8308
|
-
context.ellipse(pupilOffsetX, pupilOffsetY, projectedRadiusX * 0.62 * eyeStyle.irisScale, projectedRadiusY * 0.72 * eyeStyle.irisScale, 0, 0, Math.PI * 2);
|
|
8309
|
-
context.fillStyle = irisGradient;
|
|
8310
|
-
context.fill();
|
|
8311
|
-
context.beginPath();
|
|
8312
|
-
context.ellipse(pupilOffsetX, pupilOffsetY, projectedRadiusX * 0.15 * eyeStyle.pupilWidthScale, projectedRadiusY * 0.48 * eyeStyle.pupilHeightScale, 0, 0, Math.PI * 2);
|
|
8313
|
-
context.fillStyle = palette.ink;
|
|
8314
|
-
context.fill();
|
|
8549
|
+
context.fillStyle = `${palette.shadow}66`;
|
|
8550
|
+
context.filter = `blur(${size * 0.024}px)`;
|
|
8315
8551
|
context.beginPath();
|
|
8316
|
-
context.ellipse(
|
|
8317
|
-
context.fillStyle = '#ffffff';
|
|
8552
|
+
context.ellipse(size * 0.5 + interaction.gazeX * size * 0.045, size * 0.88 + Math.sin(timeMs / 940) * size * 0.008, size * (0.18 + (morphologyProfile.body.horizontalStretch - 1) * 0.04 + interaction.intensity * 0.018), size * 0.062, 0, 0, Math.PI * 2);
|
|
8318
8553
|
context.fill();
|
|
8319
8554
|
context.restore();
|
|
8320
|
-
|
|
8321
|
-
|
|
8322
|
-
|
|
8323
|
-
|
|
8324
|
-
|
|
8325
|
-
|
|
8326
|
-
|
|
8327
|
-
|
|
8328
|
-
|
|
8329
|
-
|
|
8330
|
-
|
|
8331
|
-
|
|
8332
|
-
|
|
8333
|
-
|
|
8334
|
-
|
|
8335
|
-
|
|
8336
|
-
|
|
8337
|
-
|
|
8338
|
-
|
|
8339
|
-
|
|
8340
|
-
|
|
8341
|
-
|
|
8342
|
-
|
|
8555
|
+
}
|
|
8556
|
+
/**
|
|
8557
|
+
* Resolves all visible projected patches for the single blobby octopus mesh.
|
|
8558
|
+
*
|
|
8559
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
8560
|
+
*/
|
|
8561
|
+
function resolveVisibleBlobbyOctopusPatches(options) {
|
|
8562
|
+
const { center, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, morphologyProfile, animationPhase, timeMs, } = options;
|
|
8563
|
+
const latitudePatchCount = 12;
|
|
8564
|
+
const longitudePatchCount = 24;
|
|
8565
|
+
const surfacePatches = [];
|
|
8566
|
+
for (let latitudeIndex = 0; latitudeIndex < latitudePatchCount; latitudeIndex++) {
|
|
8567
|
+
const startLatitude = -Math.PI / 2 + (latitudeIndex / latitudePatchCount) * Math.PI;
|
|
8568
|
+
const endLatitude = -Math.PI / 2 + ((latitudeIndex + 1) / latitudePatchCount) * Math.PI;
|
|
8569
|
+
const centerLatitude = (startLatitude + endLatitude) / 2;
|
|
8570
|
+
const verticalProgress = (Math.sin(centerLatitude) + 1) / 2;
|
|
8571
|
+
for (let longitudeIndex = 0; longitudeIndex < longitudePatchCount; longitudeIndex++) {
|
|
8572
|
+
const startLongitude = -Math.PI + (longitudeIndex / longitudePatchCount) * Math.PI * 2;
|
|
8573
|
+
const endLongitude = -Math.PI + ((longitudeIndex + 1) / longitudePatchCount) * Math.PI * 2;
|
|
8574
|
+
const centerLongitude = (startLongitude + endLongitude) / 2;
|
|
8575
|
+
const localCorners = [
|
|
8576
|
+
sampleBlobbyOctopusSurfacePoint(options, startLatitude, startLongitude),
|
|
8577
|
+
sampleBlobbyOctopusSurfacePoint(options, startLatitude, endLongitude),
|
|
8578
|
+
sampleBlobbyOctopusSurfacePoint(options, endLatitude, endLongitude),
|
|
8579
|
+
sampleBlobbyOctopusSurfacePoint(options, endLatitude, startLongitude),
|
|
8580
|
+
];
|
|
8581
|
+
const transformedCorners = localCorners.map((localCorner) => transformScenePoint(localCorner, center, rotationX, rotationY));
|
|
8582
|
+
const surfaceNormal = normalizeVector3(crossProduct3D(subtractPoint3D(transformedCorners[1], transformedCorners[0]), subtractPoint3D(transformedCorners[2], transformedCorners[0])));
|
|
8583
|
+
if (surfaceNormal.z <= 0.01) {
|
|
8584
|
+
continue;
|
|
8585
|
+
}
|
|
8586
|
+
const projectedCorners = transformedCorners.map((transformedCorner) => projectScenePoint(transformedCorner, size, sceneCenterX, sceneCenterY));
|
|
8587
|
+
surfacePatches.push({
|
|
8588
|
+
corners: projectedCorners,
|
|
8589
|
+
averageDepth: transformedCorners.reduce((depthSum, transformedCorner) => depthSum + transformedCorner.z, 0) /
|
|
8590
|
+
transformedCorners.length,
|
|
8591
|
+
lightIntensity: clampNumber$1(dotProduct3D(surfaceNormal, LIGHT_DIRECTION), -1, 1),
|
|
8592
|
+
fillStyle: resolveBlobbySurfacePatchFillStyle(palette, verticalProgress, Math.max(0, Math.cos(centerLongitude)), resolveLowerLobeWave(centerLongitude, morphologyProfile, animationPhase, timeMs)),
|
|
8593
|
+
outlineColor: verticalProgress < 0.58 ? `${palette.highlight}73` : `${palette.shadow}8a`,
|
|
8594
|
+
});
|
|
8595
|
+
}
|
|
8343
8596
|
}
|
|
8344
|
-
|
|
8597
|
+
return surfacePatches;
|
|
8598
|
+
}
|
|
8599
|
+
/**
|
|
8600
|
+
* Samples one point on the continuous Octopus 3D 2 surface.
|
|
8601
|
+
*
|
|
8602
|
+
* The lower hemisphere widens and falls into soft lobe waves so the octopus stays one connected mesh
|
|
8603
|
+
* instead of switching to separately rendered tentacles.
|
|
8604
|
+
*
|
|
8605
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
8606
|
+
*/
|
|
8607
|
+
function sampleBlobbyOctopusSurfacePoint(options, latitude, longitude) {
|
|
8608
|
+
const { radiusX, radiusY, radiusZ, morphologyProfile, timeMs, animationPhase } = options;
|
|
8609
|
+
const cosineLatitude = Math.max(0, Math.cos(latitude));
|
|
8610
|
+
const verticalProgress = (Math.sin(latitude) + 1) / 2;
|
|
8611
|
+
const upperBlend = Math.pow(1 - verticalProgress, 1.2);
|
|
8612
|
+
const lowerBlend = Math.pow(verticalProgress, 1.42);
|
|
8613
|
+
const lowerLobeWave = resolveLowerLobeWave(longitude, morphologyProfile, animationPhase, timeMs);
|
|
8614
|
+
const skirtEnvelope = Math.pow(cosineLatitude, 0.5) * lowerBlend;
|
|
8615
|
+
const horizontalScale = 1.02 +
|
|
8616
|
+
skirtEnvelope * (0.34 + (morphologyProfile.tentacles.rootSpreadScale - 1) * 0.22 + lowerLobeWave * 0.22) -
|
|
8617
|
+
upperBlend * 0.08;
|
|
8618
|
+
const depthScale = 1.04 +
|
|
8619
|
+
upperBlend * 0.16 +
|
|
8620
|
+
Math.max(0, Math.cos(longitude)) * 0.1 +
|
|
8621
|
+
skirtEnvelope * (0.08 + lowerLobeWave * 0.06) -
|
|
8622
|
+
Math.max(0, -Math.cos(longitude)) * 0.04;
|
|
8623
|
+
const lowerDrop = skirtEnvelope *
|
|
8624
|
+
radiusY *
|
|
8625
|
+
(0.28 + lowerLobeWave * 0.14 + (morphologyProfile.tentacles.flowLengthScale - 1) * 0.12);
|
|
8626
|
+
const swayX = Math.sin(timeMs / 1250 + longitude * 1.8 + animationPhase) * skirtEnvelope * radiusX * 0.05;
|
|
8627
|
+
const swayZ = Math.cos(timeMs / 1480 + longitude * 1.2 - animationPhase * 0.7) * skirtEnvelope * radiusZ * 0.03;
|
|
8628
|
+
return {
|
|
8629
|
+
x: Math.sin(longitude) * cosineLatitude * radiusX * horizontalScale + swayX,
|
|
8630
|
+
y: Math.sin(latitude) * radiusY * (1 + upperBlend * 0.14) -
|
|
8631
|
+
upperBlend * radiusY * 0.1 +
|
|
8632
|
+
lowerDrop +
|
|
8633
|
+
Math.sin(timeMs / 1780 + animationPhase + latitude * 1.4) * skirtEnvelope * radiusY * 0.02,
|
|
8634
|
+
z: Math.cos(longitude) * cosineLatitude * radiusZ * depthScale + swayZ,
|
|
8635
|
+
};
|
|
8345
8636
|
}
|
|
8346
8637
|
/**
|
|
8347
|
-
*
|
|
8638
|
+
* Resolves the soft lower-lobe wave that makes the silhouette read more like a real octopus.
|
|
8348
8639
|
*
|
|
8349
|
-
* @private helper of `
|
|
8640
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
8350
8641
|
*/
|
|
8351
|
-
function
|
|
8352
|
-
const
|
|
8353
|
-
|
|
8354
|
-
return;
|
|
8355
|
-
}
|
|
8356
|
-
const projectedPoints = scenePoints.map((scenePoint) => projectScenePoint(scenePoint, size, sceneCenterX, sceneCenterY));
|
|
8357
|
-
context.beginPath();
|
|
8358
|
-
context.moveTo(projectedPoints[0].x, projectedPoints[0].y);
|
|
8359
|
-
context.quadraticCurveTo(projectedPoints[1].x, projectedPoints[1].y, projectedPoints[2].x, projectedPoints[2].y);
|
|
8360
|
-
context.strokeStyle = `${palette.ink}b8`;
|
|
8361
|
-
context.lineWidth = Math.max(1.1, size * 0.009);
|
|
8362
|
-
context.lineCap = 'round';
|
|
8363
|
-
context.stroke();
|
|
8642
|
+
function resolveLowerLobeWave(longitude, morphologyProfile, animationPhase, timeMs) {
|
|
8643
|
+
const lobeCount = Math.max(4, Math.round((morphologyProfile.body.lobeCount + morphologyProfile.tentacles.count) / 2));
|
|
8644
|
+
return (Math.cos(longitude * lobeCount + animationPhase + timeMs / 1040) + 1) / 2;
|
|
8364
8645
|
}
|
|
8365
8646
|
/**
|
|
8366
|
-
*
|
|
8647
|
+
* Resolves one base fill tone for a surface patch on the single octopus mesh.
|
|
8367
8648
|
*
|
|
8368
|
-
* @private helper of `
|
|
8649
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
8369
8650
|
*/
|
|
8370
|
-
function
|
|
8371
|
-
|
|
8372
|
-
|
|
8373
|
-
|
|
8374
|
-
|
|
8375
|
-
|
|
8376
|
-
|
|
8377
|
-
|
|
8378
|
-
|
|
8651
|
+
function resolveBlobbySurfacePatchFillStyle(palette, verticalProgress, forwardness, lowerLobeWave) {
|
|
8652
|
+
const tonalProgress = clampNumber$1(verticalProgress + lowerLobeWave * 0.12 - forwardness * 0.07, 0, 1);
|
|
8653
|
+
if (tonalProgress < 0.16) {
|
|
8654
|
+
return palette.highlight;
|
|
8655
|
+
}
|
|
8656
|
+
if (tonalProgress < 0.34) {
|
|
8657
|
+
return palette.secondary;
|
|
8658
|
+
}
|
|
8659
|
+
if (tonalProgress < 0.72) {
|
|
8660
|
+
return forwardness > 0.58 ? palette.secondary : palette.primary;
|
|
8661
|
+
}
|
|
8662
|
+
return `${palette.shadow}f2`;
|
|
8379
8663
|
}
|
|
8380
8664
|
/**
|
|
8381
|
-
*
|
|
8665
|
+
* Draws one projected patch with soft octopus shading.
|
|
8382
8666
|
*
|
|
8383
|
-
* @private helper of `
|
|
8667
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
8384
8668
|
*/
|
|
8385
|
-
function
|
|
8386
|
-
|
|
8387
|
-
|
|
8388
|
-
.
|
|
8669
|
+
function drawBlobbySurfacePatch(context, surfacePatch) {
|
|
8670
|
+
drawProjectedQuad(context, surfacePatch.corners, surfacePatch.fillStyle);
|
|
8671
|
+
if (surfacePatch.lightIntensity > 0) {
|
|
8672
|
+
drawProjectedQuad(context, surfacePatch.corners, `rgba(255, 255, 255, ${0.16 * surfacePatch.lightIntensity})`);
|
|
8673
|
+
}
|
|
8674
|
+
else if (surfacePatch.lightIntensity < 0) {
|
|
8675
|
+
drawProjectedQuad(context, surfacePatch.corners, `rgba(0, 0, 0, ${0.24 * Math.abs(surfacePatch.lightIntensity)})`);
|
|
8676
|
+
}
|
|
8677
|
+
context.save();
|
|
8678
|
+
context.beginPath();
|
|
8679
|
+
context.moveTo(surfacePatch.corners[0].x, surfacePatch.corners[0].y);
|
|
8680
|
+
for (let cornerIndex = 1; cornerIndex < surfacePatch.corners.length; cornerIndex++) {
|
|
8681
|
+
context.lineTo(surfacePatch.corners[cornerIndex].x, surfacePatch.corners[cornerIndex].y);
|
|
8682
|
+
}
|
|
8683
|
+
context.closePath();
|
|
8684
|
+
context.strokeStyle = surfacePatch.outlineColor;
|
|
8685
|
+
context.lineWidth = Math.max(1, getProjectedQuadPerimeter(surfacePatch.corners) * 0.0042);
|
|
8686
|
+
context.lineJoin = 'round';
|
|
8687
|
+
context.stroke();
|
|
8688
|
+
context.restore();
|
|
8389
8689
|
}
|
|
8390
8690
|
|
|
8391
8691
|
/* eslint-disable no-magic-numbers */
|
|
@@ -9157,6 +9457,7 @@ const AVATAR_VISUALS = [
|
|
|
9157
9457
|
octopus2AvatarVisual,
|
|
9158
9458
|
octopus3AvatarVisual,
|
|
9159
9459
|
octopus3dAvatarVisual,
|
|
9460
|
+
octopus3d2AvatarVisual,
|
|
9160
9461
|
asciiOctopusAvatarVisual,
|
|
9161
9462
|
minecraftAvatarVisual,
|
|
9162
9463
|
minecraft2AvatarVisual,
|
|
@@ -14821,11 +15122,11 @@ function buildCandidateEncodings(options) {
|
|
|
14821
15122
|
});
|
|
14822
15123
|
}
|
|
14823
15124
|
/**
|
|
14824
|
-
*
|
|
15125
|
+
* Prepares one attachment for best-effort text decoding.
|
|
14825
15126
|
*
|
|
14826
|
-
* @private
|
|
15127
|
+
* @private function of decodeAttachmentAsText
|
|
14827
15128
|
*/
|
|
14828
|
-
function
|
|
15129
|
+
function createDecodeAttachmentPreparation(input, options) {
|
|
14829
15130
|
var _a;
|
|
14830
15131
|
const maxBytes = Math.max(1, Math.floor((_a = options.maxBytes) !== null && _a !== void 0 ? _a : DEFAULT_ATTACHMENT_TEXT_DECODE_BYTES));
|
|
14831
15132
|
const forceText = options.forceText === true;
|
|
@@ -14839,54 +15140,102 @@ function decodeAttachmentAsText(input, options = {}) {
|
|
|
14839
15140
|
const inspection = inspectBytes(truncatedBytes);
|
|
14840
15141
|
const trustedTextMime = isTrustedTextMimeType(mimeType);
|
|
14841
15142
|
const trustedBinaryMime = isTrustedBinaryMimeType(mimeType);
|
|
15143
|
+
const shouldTreatAsBinary = (trustedBinaryMime || inspection.looksBinary) && !trustedTextMime;
|
|
14842
15144
|
if (isTruncated) {
|
|
14843
15145
|
warnings.push(`Decoded only the first ${maxBytes} bytes of \`${input.filename}\` because the attachment exceeded the text preview limit.`);
|
|
14844
15146
|
}
|
|
14845
|
-
|
|
14846
|
-
|
|
14847
|
-
|
|
14848
|
-
|
|
14849
|
-
|
|
14850
|
-
|
|
14851
|
-
|
|
14852
|
-
|
|
14853
|
-
|
|
14854
|
-
|
|
14855
|
-
|
|
15147
|
+
return {
|
|
15148
|
+
warnings,
|
|
15149
|
+
charset,
|
|
15150
|
+
bom,
|
|
15151
|
+
inspection,
|
|
15152
|
+
truncatedBytes,
|
|
15153
|
+
isTruncated,
|
|
15154
|
+
forceText,
|
|
15155
|
+
shouldTreatAsBinary,
|
|
15156
|
+
};
|
|
15157
|
+
}
|
|
15158
|
+
/**
|
|
15159
|
+
* Returns an early result when the attachment should stay classified as binary.
|
|
15160
|
+
*
|
|
15161
|
+
* @private function of decodeAttachmentAsText
|
|
15162
|
+
*/
|
|
15163
|
+
function createBinaryDecodeResult(preparation) {
|
|
15164
|
+
if (!preparation.shouldTreatAsBinary) {
|
|
15165
|
+
return null;
|
|
14856
15166
|
}
|
|
14857
|
-
if (
|
|
14858
|
-
warnings.push('File content looks binary, but text decoding was forced with `forceText`.');
|
|
15167
|
+
if (preparation.forceText) {
|
|
15168
|
+
preparation.warnings.push('File content looks binary, but text decoding was forced with `forceText`.');
|
|
15169
|
+
return null;
|
|
14859
15170
|
}
|
|
14860
|
-
|
|
14861
|
-
|
|
15171
|
+
preparation.warnings.push('File content looks binary, so text decoding was skipped.');
|
|
15172
|
+
return {
|
|
15173
|
+
text: '',
|
|
15174
|
+
encodingUsed: 'binary',
|
|
15175
|
+
confidence: 1,
|
|
15176
|
+
warnings: preparation.warnings,
|
|
15177
|
+
wasBinary: true,
|
|
15178
|
+
isTruncated: preparation.isTruncated,
|
|
15179
|
+
};
|
|
15180
|
+
}
|
|
15181
|
+
/**
|
|
15182
|
+
* Warns when the declared charset cannot be used by the runtime decoder.
|
|
15183
|
+
*
|
|
15184
|
+
* @private function of decodeAttachmentAsText
|
|
15185
|
+
*/
|
|
15186
|
+
function addUnsupportedCharsetWarning(preparation) {
|
|
15187
|
+
if (preparation.charset && !isSupportedEncoding(preparation.charset)) {
|
|
15188
|
+
preparation.warnings.push(`Ignored unsupported declared charset \`${preparation.charset}\` and used best-effort detection instead.`);
|
|
14862
15189
|
}
|
|
14863
|
-
|
|
14864
|
-
|
|
14865
|
-
|
|
14866
|
-
|
|
14867
|
-
|
|
14868
|
-
|
|
14869
|
-
|
|
14870
|
-
|
|
15190
|
+
}
|
|
15191
|
+
/**
|
|
15192
|
+
* Returns the byte slice that should actually be decoded as text.
|
|
15193
|
+
*
|
|
15194
|
+
* @private function of decodeAttachmentAsText
|
|
15195
|
+
*/
|
|
15196
|
+
function getBytesToDecode(preparation) {
|
|
15197
|
+
return preparation.bom ? preparation.truncatedBytes.subarray(preparation.bom.offset) : preparation.truncatedBytes;
|
|
15198
|
+
}
|
|
15199
|
+
/**
|
|
15200
|
+
* Decodes all candidate encodings and sorts the successful results by score.
|
|
15201
|
+
*
|
|
15202
|
+
* @private function of decodeAttachmentAsText
|
|
15203
|
+
*/
|
|
15204
|
+
function decodeAttachmentCandidates(preparation) {
|
|
15205
|
+
return buildCandidateEncodings({
|
|
15206
|
+
charset: preparation.charset && isSupportedEncoding(preparation.charset) ? preparation.charset : null,
|
|
15207
|
+
bom: preparation.bom,
|
|
15208
|
+
inspection: preparation.inspection,
|
|
15209
|
+
})
|
|
14871
15210
|
.map(({ encoding, source }) => {
|
|
14872
|
-
const decoded = decodeWithEncoding(
|
|
15211
|
+
const decoded = decodeWithEncoding(getBytesToDecode(preparation), encoding);
|
|
14873
15212
|
return decoded ? { ...decoded, source } : null;
|
|
14874
15213
|
})
|
|
14875
15214
|
.filter((candidate) => candidate !== null)
|
|
14876
15215
|
.sort((left, right) => left.score - right.score);
|
|
14877
|
-
|
|
14878
|
-
|
|
14879
|
-
|
|
14880
|
-
|
|
14881
|
-
|
|
14882
|
-
|
|
14883
|
-
|
|
14884
|
-
|
|
14885
|
-
|
|
14886
|
-
|
|
14887
|
-
|
|
14888
|
-
|
|
14889
|
-
|
|
15216
|
+
}
|
|
15217
|
+
/**
|
|
15218
|
+
* Returns the fallback result used when no text decoder could be applied.
|
|
15219
|
+
*
|
|
15220
|
+
* @private function of decodeAttachmentAsText
|
|
15221
|
+
*/
|
|
15222
|
+
function createNoDecoderAvailableResult(preparation) {
|
|
15223
|
+
preparation.warnings.push('No supported text decoder was available.');
|
|
15224
|
+
return {
|
|
15225
|
+
text: '',
|
|
15226
|
+
encodingUsed: 'binary',
|
|
15227
|
+
confidence: 0,
|
|
15228
|
+
warnings: preparation.warnings,
|
|
15229
|
+
wasBinary: true,
|
|
15230
|
+
isTruncated: preparation.isTruncated,
|
|
15231
|
+
};
|
|
15232
|
+
}
|
|
15233
|
+
/**
|
|
15234
|
+
* Estimates confidence for the winning decoded text candidate.
|
|
15235
|
+
*
|
|
15236
|
+
* @private function of decodeAttachmentAsText
|
|
15237
|
+
*/
|
|
15238
|
+
function computeDecodeConfidence(bestCandidate, secondBestCandidate, preparation) {
|
|
14890
15239
|
const baseConfidence = bestCandidate.source === 'bom'
|
|
14891
15240
|
? 1
|
|
14892
15241
|
: bestCandidate.source === 'charset'
|
|
@@ -14899,27 +15248,62 @@ function decodeAttachmentAsText(input, options = {}) {
|
|
|
14899
15248
|
? 0.82
|
|
14900
15249
|
: 0.62;
|
|
14901
15250
|
const scoreMargin = secondBestCandidate ? Math.max(0, secondBestCandidate.score - bestCandidate.score) : 0.2;
|
|
14902
|
-
|
|
15251
|
+
return Math.max(0.2, Math.min(preparation.shouldTreatAsBinary && preparation.forceText ? 0.45 : 1, baseConfidence + Math.min(0.18, scoreMargin / 2)));
|
|
15252
|
+
}
|
|
15253
|
+
/**
|
|
15254
|
+
* Appends user-facing warnings derived from the chosen decoded text candidate.
|
|
15255
|
+
*
|
|
15256
|
+
* @private function of decodeAttachmentAsText
|
|
15257
|
+
*/
|
|
15258
|
+
function addDecodeWarnings(bestCandidate, confidence, preparation) {
|
|
14903
15259
|
if (bestCandidate.source === 'heuristic' && bestCandidate.encoding !== 'utf-8') {
|
|
14904
|
-
warnings.push(`Encoding was guessed as \`${bestCandidate.encoding}\`.`);
|
|
15260
|
+
preparation.warnings.push(`Encoding was guessed as \`${bestCandidate.encoding}\`.`);
|
|
14905
15261
|
}
|
|
14906
15262
|
if (bestCandidate.source === 'heuristic' &&
|
|
14907
15263
|
bestCandidate.encoding === 'utf-8' &&
|
|
14908
15264
|
bestCandidate.replacementCount > 0) {
|
|
14909
|
-
warnings.push('UTF-8 decoding produced replacement characters, so the extracted text may contain errors.');
|
|
15265
|
+
preparation.warnings.push('UTF-8 decoding produced replacement characters, so the extracted text may contain errors.');
|
|
14910
15266
|
}
|
|
14911
15267
|
if (confidence < 0.6) {
|
|
14912
|
-
warnings.push('Decoding confidence is low, so the extracted text may contain errors.');
|
|
15268
|
+
preparation.warnings.push('Decoding confidence is low, so the extracted text may contain errors.');
|
|
14913
15269
|
}
|
|
15270
|
+
}
|
|
15271
|
+
/**
|
|
15272
|
+
* Creates the final decoded-text result from the chosen candidate and accumulated metadata.
|
|
15273
|
+
*
|
|
15274
|
+
* @private function of decodeAttachmentAsText
|
|
15275
|
+
*/
|
|
15276
|
+
function createDecodedTextResult(bestCandidate, confidence, preparation) {
|
|
14914
15277
|
return {
|
|
14915
|
-
text: isTruncated ? appendTruncatedMarker(bestCandidate.text) : bestCandidate.text,
|
|
15278
|
+
text: preparation.isTruncated ? appendTruncatedMarker(bestCandidate.text) : bestCandidate.text,
|
|
14916
15279
|
encodingUsed: bestCandidate.encoding,
|
|
14917
15280
|
confidence,
|
|
14918
|
-
warnings,
|
|
15281
|
+
warnings: preparation.warnings,
|
|
14919
15282
|
wasBinary: false,
|
|
14920
|
-
isTruncated,
|
|
15283
|
+
isTruncated: preparation.isTruncated,
|
|
14921
15284
|
};
|
|
14922
15285
|
}
|
|
15286
|
+
/**
|
|
15287
|
+
* Best-effort decoder for uploaded or remote file bytes whose extension or encoding may be unknown.
|
|
15288
|
+
*
|
|
15289
|
+
* @private internal utility for shared text decoding
|
|
15290
|
+
*/
|
|
15291
|
+
function decodeAttachmentAsText(input, options = {}) {
|
|
15292
|
+
const preparation = createDecodeAttachmentPreparation(input, options);
|
|
15293
|
+
const binaryResult = createBinaryDecodeResult(preparation);
|
|
15294
|
+
if (binaryResult) {
|
|
15295
|
+
return binaryResult;
|
|
15296
|
+
}
|
|
15297
|
+
addUnsupportedCharsetWarning(preparation);
|
|
15298
|
+
const decodedCandidates = decodeAttachmentCandidates(preparation);
|
|
15299
|
+
const bestCandidate = decodedCandidates[0];
|
|
15300
|
+
if (!bestCandidate) {
|
|
15301
|
+
return createNoDecoderAvailableResult(preparation);
|
|
15302
|
+
}
|
|
15303
|
+
const confidence = computeDecodeConfidence(bestCandidate, decodedCandidates[1], preparation);
|
|
15304
|
+
addDecodeWarnings(bestCandidate, confidence, preparation);
|
|
15305
|
+
return createDecodedTextResult(bestCandidate, confidence, preparation);
|
|
15306
|
+
}
|
|
14923
15307
|
|
|
14924
15308
|
/**
|
|
14925
15309
|
* Convert file extension to mime type
|
|
@@ -19287,120 +19671,183 @@ function orderJson(options) {
|
|
|
19287
19671
|
* @public exported from `@promptbook/utils`
|
|
19288
19672
|
*/
|
|
19289
19673
|
function checkSerializableAsJson(options) {
|
|
19290
|
-
|
|
19674
|
+
checkSerializableValue(options);
|
|
19675
|
+
}
|
|
19676
|
+
// TODO: Can be return type more type-safe? like `asserts options.value is JsonValue`
|
|
19677
|
+
// TODO: [🧠][main] !!3 In-memory cache of same values to prevent multiple checks
|
|
19678
|
+
// Note: [🐠] This is how `checkSerializableAsJson` + `isSerializableAsJson` together can just retun true/false or rich error message
|
|
19679
|
+
/**
|
|
19680
|
+
* Checks one value and dispatches to the appropriate specialized validator.
|
|
19681
|
+
*
|
|
19682
|
+
* @private function of `checkSerializableAsJson`
|
|
19683
|
+
*/
|
|
19684
|
+
function checkSerializableValue(options) {
|
|
19685
|
+
const { value } = options;
|
|
19686
|
+
if (isSerializablePrimitive(value)) {
|
|
19687
|
+
return;
|
|
19688
|
+
}
|
|
19291
19689
|
if (value === undefined) {
|
|
19292
|
-
throw new UnexpectedError(`${name} is undefined`);
|
|
19690
|
+
throw new UnexpectedError(`${options.name} is undefined`);
|
|
19293
19691
|
}
|
|
19294
|
-
|
|
19295
|
-
|
|
19692
|
+
if (typeof value === 'symbol') {
|
|
19693
|
+
throw new UnexpectedError(`${options.name} is symbol`);
|
|
19296
19694
|
}
|
|
19297
|
-
|
|
19298
|
-
|
|
19695
|
+
if (typeof value === 'function') {
|
|
19696
|
+
throw new UnexpectedError(`${options.name} is function`);
|
|
19299
19697
|
}
|
|
19300
|
-
|
|
19698
|
+
if (Array.isArray(value)) {
|
|
19699
|
+
checkSerializableArray(options, value);
|
|
19301
19700
|
return;
|
|
19302
19701
|
}
|
|
19303
|
-
|
|
19702
|
+
if (value !== null && typeof value === 'object') {
|
|
19703
|
+
checkSerializableObject(options, value);
|
|
19304
19704
|
return;
|
|
19305
19705
|
}
|
|
19306
|
-
|
|
19307
|
-
|
|
19308
|
-
|
|
19309
|
-
|
|
19310
|
-
|
|
19311
|
-
|
|
19312
|
-
|
|
19313
|
-
|
|
19314
|
-
|
|
19315
|
-
|
|
19706
|
+
throwUnknownTypeError(options);
|
|
19707
|
+
}
|
|
19708
|
+
/**
|
|
19709
|
+
* Checks the primitive values that are directly JSON serializable.
|
|
19710
|
+
*
|
|
19711
|
+
* @private function of `checkSerializableAsJson`
|
|
19712
|
+
*/
|
|
19713
|
+
function isSerializablePrimitive(value) {
|
|
19714
|
+
return (value === null ||
|
|
19715
|
+
typeof value === 'boolean' ||
|
|
19716
|
+
(typeof value === 'number' && !isNaN(value)) ||
|
|
19717
|
+
typeof value === 'string');
|
|
19718
|
+
}
|
|
19719
|
+
/**
|
|
19720
|
+
* Recursively checks JSON array items.
|
|
19721
|
+
*
|
|
19722
|
+
* @private function of `checkSerializableAsJson`
|
|
19723
|
+
*/
|
|
19724
|
+
function checkSerializableArray(context, arrayValue) {
|
|
19725
|
+
for (let index = 0; index < arrayValue.length; index++) {
|
|
19726
|
+
checkSerializableAsJson({
|
|
19727
|
+
...context,
|
|
19728
|
+
name: `${context.name}[${index}]`,
|
|
19729
|
+
value: arrayValue[index],
|
|
19730
|
+
});
|
|
19316
19731
|
}
|
|
19317
|
-
|
|
19318
|
-
|
|
19319
|
-
|
|
19320
|
-
|
|
19732
|
+
}
|
|
19733
|
+
/**
|
|
19734
|
+
* Checks object-like values and dispatches special unsupported built-ins.
|
|
19735
|
+
*
|
|
19736
|
+
* @private function of `checkSerializableAsJson`
|
|
19737
|
+
*/
|
|
19738
|
+
function checkSerializableObject(context, objectValue) {
|
|
19739
|
+
checkUnsupportedObjectType(context, objectValue);
|
|
19740
|
+
checkSerializableObjectEntries(context, objectValue);
|
|
19741
|
+
assertJsonStringificationSucceeds(context, objectValue);
|
|
19742
|
+
}
|
|
19743
|
+
/**
|
|
19744
|
+
* Rejects built-in objects that must be converted before JSON serialization.
|
|
19745
|
+
*
|
|
19746
|
+
* @private function of `checkSerializableAsJson`
|
|
19747
|
+
*/
|
|
19748
|
+
function checkUnsupportedObjectType(context, objectValue) {
|
|
19749
|
+
if (objectValue instanceof Date) {
|
|
19750
|
+
throw new UnexpectedError(spaceTrim$1((block) => `
|
|
19751
|
+
\`${context.name}\` is Date
|
|
19321
19752
|
|
|
19322
|
-
|
|
19753
|
+
Use \`string_date_iso8601\` instead
|
|
19323
19754
|
|
|
19324
|
-
|
|
19325
|
-
|
|
19326
|
-
|
|
19327
|
-
|
|
19328
|
-
|
|
19329
|
-
|
|
19330
|
-
|
|
19331
|
-
|
|
19332
|
-
|
|
19333
|
-
|
|
19334
|
-
|
|
19335
|
-
|
|
19336
|
-
|
|
19337
|
-
|
|
19338
|
-
|
|
19339
|
-
|
|
19755
|
+
Additional message for \`${context.name}\`:
|
|
19756
|
+
${block(context.message || '(nothing)')}
|
|
19757
|
+
`));
|
|
19758
|
+
}
|
|
19759
|
+
if (objectValue instanceof Map) {
|
|
19760
|
+
throw new UnexpectedError(`${context.name} is Map`);
|
|
19761
|
+
}
|
|
19762
|
+
if (objectValue instanceof Set) {
|
|
19763
|
+
throw new UnexpectedError(`${context.name} is Set`);
|
|
19764
|
+
}
|
|
19765
|
+
if (objectValue instanceof RegExp) {
|
|
19766
|
+
throw new UnexpectedError(`${context.name} is RegExp`);
|
|
19767
|
+
}
|
|
19768
|
+
if (objectValue instanceof Error) {
|
|
19769
|
+
throw new UnexpectedError(spaceTrim$1((block) => `
|
|
19770
|
+
\`${context.name}\` is unserialized Error
|
|
19340
19771
|
|
|
19341
|
-
|
|
19772
|
+
Use function \`serializeError\`
|
|
19342
19773
|
|
|
19343
|
-
|
|
19344
|
-
|
|
19774
|
+
Additional message for \`${context.name}\`:
|
|
19775
|
+
${block(context.message || '(nothing)')}
|
|
19345
19776
|
|
|
19346
|
-
|
|
19777
|
+
`));
|
|
19778
|
+
}
|
|
19779
|
+
}
|
|
19780
|
+
/**
|
|
19781
|
+
* Recursively checks object properties while preserving omitted `undefined` keys.
|
|
19782
|
+
*
|
|
19783
|
+
* @private function of `checkSerializableAsJson`
|
|
19784
|
+
*/
|
|
19785
|
+
function checkSerializableObjectEntries(context, objectValue) {
|
|
19786
|
+
for (const [subName, subValue] of Object.entries(objectValue)) {
|
|
19787
|
+
if (subValue === undefined) {
|
|
19788
|
+
// Note: undefined in object is serializable - it is just omitted
|
|
19789
|
+
continue;
|
|
19347
19790
|
}
|
|
19348
|
-
|
|
19349
|
-
|
|
19350
|
-
|
|
19351
|
-
|
|
19352
|
-
|
|
19353
|
-
|
|
19354
|
-
|
|
19355
|
-
|
|
19356
|
-
|
|
19357
|
-
|
|
19358
|
-
|
|
19359
|
-
|
|
19360
|
-
|
|
19361
|
-
|
|
19362
|
-
|
|
19791
|
+
checkSerializableAsJson({
|
|
19792
|
+
...context,
|
|
19793
|
+
name: `${context.name}.${subName}`,
|
|
19794
|
+
value: subValue,
|
|
19795
|
+
});
|
|
19796
|
+
}
|
|
19797
|
+
}
|
|
19798
|
+
/**
|
|
19799
|
+
* Uses `JSON.stringify` as the final guard for cases like circular references.
|
|
19800
|
+
*
|
|
19801
|
+
* @private function of `checkSerializableAsJson`
|
|
19802
|
+
*/
|
|
19803
|
+
function assertJsonStringificationSucceeds(context, objectValue) {
|
|
19804
|
+
try {
|
|
19805
|
+
JSON.stringify(objectValue); // <- TODO: [0]
|
|
19806
|
+
}
|
|
19807
|
+
catch (error) {
|
|
19808
|
+
assertsError(error);
|
|
19809
|
+
throw new UnexpectedError(spaceTrim$1((block) => `
|
|
19810
|
+
\`${context.name}\` is not serializable
|
|
19363
19811
|
|
|
19364
|
-
|
|
19812
|
+
${block(error.stack || error.message)}
|
|
19365
19813
|
|
|
19366
|
-
|
|
19367
|
-
|
|
19368
|
-
|
|
19814
|
+
Additional message for \`${context.name}\`:
|
|
19815
|
+
${block(context.message || '(nothing)')}
|
|
19816
|
+
`));
|
|
19817
|
+
}
|
|
19818
|
+
/*
|
|
19819
|
+
TODO: [0] Is there some more elegant way to check circular references?
|
|
19820
|
+
const seen = new Set();
|
|
19821
|
+
const stack = [{ value }];
|
|
19822
|
+
while (stack.length > 0) {
|
|
19823
|
+
const { value } = stack.pop()!;
|
|
19824
|
+
if (typeof value === 'object' && value !== null) {
|
|
19825
|
+
if (seen.has(value)) {
|
|
19826
|
+
throw new UnexpectedError(`${name} has circular reference`);
|
|
19369
19827
|
}
|
|
19370
|
-
|
|
19371
|
-
|
|
19372
|
-
|
|
19373
|
-
|
|
19374
|
-
|
|
19375
|
-
const { value } = stack.pop()!;
|
|
19376
|
-
if (typeof value === 'object' && value !== null) {
|
|
19377
|
-
if (seen.has(value)) {
|
|
19378
|
-
throw new UnexpectedError(`${name} has circular reference`);
|
|
19379
|
-
}
|
|
19380
|
-
seen.add(value);
|
|
19381
|
-
if (Array.isArray(value)) {
|
|
19382
|
-
stack.push(...value.map((value) => ({ value })));
|
|
19383
|
-
} else {
|
|
19384
|
-
stack.push(...Object.values(value).map((value) => ({ value })));
|
|
19385
|
-
}
|
|
19386
|
-
}
|
|
19828
|
+
seen.add(value);
|
|
19829
|
+
if (Array.isArray(value)) {
|
|
19830
|
+
stack.push(...value.map((value) => ({ value })));
|
|
19831
|
+
} else {
|
|
19832
|
+
stack.push(...Object.values(value).map((value) => ({ value })));
|
|
19387
19833
|
}
|
|
19388
|
-
*/
|
|
19389
|
-
return;
|
|
19390
19834
|
}
|
|
19391
19835
|
}
|
|
19392
|
-
|
|
19393
|
-
|
|
19394
|
-
|
|
19836
|
+
*/
|
|
19837
|
+
}
|
|
19838
|
+
/**
|
|
19839
|
+
* Throws the fallback error for unsupported value types like `bigint` and `NaN`.
|
|
19840
|
+
*
|
|
19841
|
+
* @private function of `checkSerializableAsJson`
|
|
19842
|
+
*/
|
|
19843
|
+
function throwUnknownTypeError(context) {
|
|
19844
|
+
throw new UnexpectedError(spaceTrim$1((block) => `
|
|
19845
|
+
\`${context.name}\` is unknown type
|
|
19395
19846
|
|
|
19396
|
-
|
|
19397
|
-
|
|
19398
|
-
|
|
19399
|
-
}
|
|
19847
|
+
Additional message for \`${context.name}\`:
|
|
19848
|
+
${block(context.message || '(nothing)')}
|
|
19849
|
+
`));
|
|
19400
19850
|
}
|
|
19401
|
-
// TODO: Can be return type more type-safe? like `asserts options.value is JsonValue`
|
|
19402
|
-
// TODO: [🧠][main] !!3 In-memory cache of same values to prevent multiple checks
|
|
19403
|
-
// Note: [🐠] This is how `checkSerializableAsJson` + `isSerializableAsJson` together can just retun true/false or rich error message
|
|
19404
19851
|
|
|
19405
19852
|
/**
|
|
19406
19853
|
* Creates a deep clone of the given object
|
|
@@ -22353,7 +22800,7 @@ function createJokerCommands(task) {
|
|
|
22353
22800
|
*/
|
|
22354
22801
|
function createPostprocessingCommands(task) {
|
|
22355
22802
|
var _a;
|
|
22356
|
-
return ((_a = task.postprocessingFunctionNames) === null || _a === void 0 ? void 0 : _a.map((postprocessingFunctionName) => `POSTPROCESSING \`${postprocessingFunctionName}\``)) || [];
|
|
22803
|
+
return (((_a = task.postprocessingFunctionNames) === null || _a === void 0 ? void 0 : _a.map((postprocessingFunctionName) => `POSTPROCESSING \`${postprocessingFunctionName}\``)) || []);
|
|
22357
22804
|
}
|
|
22358
22805
|
/**
|
|
22359
22806
|
* Collects expectation commands.
|
|
@@ -22896,8 +23343,7 @@ function hasTaskJokers(task) {
|
|
|
22896
23343
|
* @private internal utility of `validatePipeline`
|
|
22897
23344
|
*/
|
|
22898
23345
|
function validateTaskSupportsJokers(task, pipelineIdentification) {
|
|
22899
|
-
if (task.format ||
|
|
22900
|
-
task.expectations /* <- TODO: Require at least 1 -> min <- expectation to use jokers */) {
|
|
23346
|
+
if (task.format || task.expectations /* <- TODO: Require at least 1 -> min <- expectation to use jokers */) {
|
|
22901
23347
|
return;
|
|
22902
23348
|
}
|
|
22903
23349
|
throw new PipelineLogicError(spaceTrim$1((block) => `
|
|
@@ -26262,9 +26708,7 @@ function createFailuresSummary($failedResults) {
|
|
|
26262
26708
|
${block(quoteMultilineText(((_b = failure.error) === null || _b === void 0 ? void 0 : _b.message) || ''))}
|
|
26263
26709
|
|
|
26264
26710
|
Result:
|
|
26265
|
-
${block(failure.result === null
|
|
26266
|
-
? 'null'
|
|
26267
|
-
: quoteMultilineText(spaceTrim$1(failure.result)))}
|
|
26711
|
+
${block(failure.result === null ? 'null' : quoteMultilineText(spaceTrim$1(failure.result)))}
|
|
26268
26712
|
`;
|
|
26269
26713
|
}))
|
|
26270
26714
|
.join('\n\n---\n\n');
|
|
@@ -30104,7 +30548,10 @@ class OpenAiCompatibleModelCatalog {
|
|
|
30104
30548
|
Cannot find model in ${this.options.getTitle()} models with name "${defaultModelName}" which should be used as default.
|
|
30105
30549
|
|
|
30106
30550
|
Available models:
|
|
30107
|
-
${block(this.options
|
|
30551
|
+
${block(this.options
|
|
30552
|
+
.getHardcodedModels()
|
|
30553
|
+
.map(({ modelName }) => `- "${modelName}"`)
|
|
30554
|
+
.join('\n'))}
|
|
30108
30555
|
|
|
30109
30556
|
Model "${defaultModelName}" is probably not available anymore, not installed, inaccessible or misconfigured.
|
|
30110
30557
|
|
|
@@ -30458,7 +30905,8 @@ class OpenAiCompatibleNonChatPromptCaller {
|
|
|
30458
30905
|
};
|
|
30459
30906
|
let rawPromptContent = templateParameters(content, { ...parameters, modelName });
|
|
30460
30907
|
if ('attachments' in prompt && Array.isArray(prompt.attachments) && prompt.attachments.length > 0) {
|
|
30461
|
-
rawPromptContent +=
|
|
30908
|
+
rawPromptContent +=
|
|
30909
|
+
'\n\n' + prompt.attachments.map((attachment) => `Image attachment: ${attachment.url}`).join('\n');
|
|
30462
30910
|
}
|
|
30463
30911
|
const rawRequest = {
|
|
30464
30912
|
...modelSettings,
|
|
@@ -30563,7 +31011,9 @@ class OpenAiCompatibleRequestManager {
|
|
|
30563
31011
|
* Schedules one request through the shared limiter and retry policy.
|
|
30564
31012
|
*/
|
|
30565
31013
|
async executeRateLimitedRequest(requestFn) {
|
|
30566
|
-
return this.limiter
|
|
31014
|
+
return this.limiter
|
|
31015
|
+
.schedule(() => this.makeRequestWithNetworkRetry(requestFn))
|
|
31016
|
+
.catch((error) => {
|
|
30567
31017
|
assertsError(error);
|
|
30568
31018
|
if (this.options.isVerbose) {
|
|
30569
31019
|
console.info(colors.bgRed('error'), error);
|
|
@@ -31770,7 +32220,9 @@ class OpenAiVectorStoreFileBatchPoller {
|
|
|
31770
32220
|
pollingState.lastProgressAtMs = nowMs;
|
|
31771
32221
|
pollingState.lastProgressKey = progressKey;
|
|
31772
32222
|
}
|
|
31773
|
-
if (this.options.isVerbose &&
|
|
32223
|
+
if (this.options.isVerbose &&
|
|
32224
|
+
(statusCountsKey !== pollingState.lastCountsKey ||
|
|
32225
|
+
nowMs - pollingState.lastLogAtMs >= progressLogIntervalMs)) {
|
|
31774
32226
|
console.info('[🤰]', 'Vector store file batch status', {
|
|
31775
32227
|
vectorStoreId,
|
|
31776
32228
|
batchId,
|