@promptbook/wizard 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 +823 -374
- 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 +823 -374
- 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/umd/index.umd.js
CHANGED
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
* @generated
|
|
50
50
|
* @see https://github.com/webgptorg/promptbook
|
|
51
51
|
*/
|
|
52
|
-
const PROMPTBOOK_ENGINE_VERSION = '0.112.0-
|
|
52
|
+
const PROMPTBOOK_ENGINE_VERSION = '0.112.0-79';
|
|
53
53
|
/**
|
|
54
54
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
|
55
55
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -313,6 +313,111 @@
|
|
|
313
313
|
}
|
|
314
314
|
}
|
|
315
315
|
|
|
316
|
+
/**
|
|
317
|
+
* Shared immutable channel storage and serialization helpers for `Color`.
|
|
318
|
+
*
|
|
319
|
+
* @private base class of Color
|
|
320
|
+
*/
|
|
321
|
+
class ColorValue {
|
|
322
|
+
constructor(red, green, blue, alpha = 255) {
|
|
323
|
+
this.red = red;
|
|
324
|
+
this.green = green;
|
|
325
|
+
this.blue = blue;
|
|
326
|
+
this.alpha = alpha;
|
|
327
|
+
checkChannelValue('Red', red);
|
|
328
|
+
checkChannelValue('Green', green);
|
|
329
|
+
checkChannelValue('Blue', blue);
|
|
330
|
+
checkChannelValue('Alpha', alpha);
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Shortcut for `red` property
|
|
334
|
+
* Number from 0 to 255
|
|
335
|
+
* @alias red
|
|
336
|
+
*/
|
|
337
|
+
get r() {
|
|
338
|
+
return this.red;
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Shortcut for `green` property
|
|
342
|
+
* Number from 0 to 255
|
|
343
|
+
* @alias green
|
|
344
|
+
*/
|
|
345
|
+
get g() {
|
|
346
|
+
return this.green;
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Shortcut for `blue` property
|
|
350
|
+
* Number from 0 to 255
|
|
351
|
+
* @alias blue
|
|
352
|
+
*/
|
|
353
|
+
get b() {
|
|
354
|
+
return this.blue;
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Shortcut for `alpha` property
|
|
358
|
+
* Number from 0 (transparent) to 255 (opaque)
|
|
359
|
+
* @alias alpha
|
|
360
|
+
*/
|
|
361
|
+
get a() {
|
|
362
|
+
return this.alpha;
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* Shortcut for `alpha` property
|
|
366
|
+
* Number from 0 (transparent) to 255 (opaque)
|
|
367
|
+
* @alias alpha
|
|
368
|
+
*/
|
|
369
|
+
get opacity() {
|
|
370
|
+
return this.alpha;
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* Shortcut for 1-`alpha` property
|
|
374
|
+
*/
|
|
375
|
+
get transparency() {
|
|
376
|
+
return 255 - this.alpha;
|
|
377
|
+
}
|
|
378
|
+
clone() {
|
|
379
|
+
return take(this.createColor(this.red, this.green, this.blue, this.alpha));
|
|
380
|
+
}
|
|
381
|
+
toString() {
|
|
382
|
+
return this.toHex();
|
|
383
|
+
}
|
|
384
|
+
toHex() {
|
|
385
|
+
if (this.alpha === 255) {
|
|
386
|
+
return `#${this.red.toString(16).padStart(2, '0')}${this.green.toString(16).padStart(2, '0')}${this.blue
|
|
387
|
+
.toString(16)
|
|
388
|
+
.padStart(2, '0')}`;
|
|
389
|
+
}
|
|
390
|
+
else {
|
|
391
|
+
return `#${this.red.toString(16).padStart(2, '0')}${this.green.toString(16).padStart(2, '0')}${this.blue
|
|
392
|
+
.toString(16)
|
|
393
|
+
.padStart(2, '0')}${this.alpha.toString(16).padStart(2, '0')}`;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
toRgb() {
|
|
397
|
+
if (this.alpha === 255) {
|
|
398
|
+
return `rgb(${this.red}, ${this.green}, ${this.blue})`;
|
|
399
|
+
}
|
|
400
|
+
else {
|
|
401
|
+
return `rgba(${this.red}, ${this.green}, ${this.blue}, ${Math.round((this.alpha / 255) * 100)}%)`;
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
toHsl() {
|
|
405
|
+
throw new Error(`Getting HSL is not implemented`);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* Checks if the given value is a valid hex color string
|
|
411
|
+
*
|
|
412
|
+
* @param value - value to check
|
|
413
|
+
* @returns true if the value is a valid hex color string (e.g., `#009edd`, `#fff`, etc.)
|
|
414
|
+
*
|
|
415
|
+
* @private function of Color
|
|
416
|
+
*/
|
|
417
|
+
function isHexColorString(value) {
|
|
418
|
+
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));
|
|
419
|
+
}
|
|
420
|
+
|
|
316
421
|
/**
|
|
317
422
|
* Constant for short hex lengths.
|
|
318
423
|
*/
|
|
@@ -524,16 +629,53 @@
|
|
|
524
629
|
|
|
525
630
|
/**
|
|
526
631
|
* Pattern matching hsl regex.
|
|
632
|
+
*
|
|
633
|
+
* @private function of Color
|
|
527
634
|
*/
|
|
528
635
|
const HSL_REGEX_PATTERN = /^hsl\(\s*([0-9.]+)\s*,\s*([0-9.]+)%\s*,\s*([0-9.]+)%\s*\)$/;
|
|
529
636
|
/**
|
|
530
637
|
* Pattern matching RGB regex.
|
|
638
|
+
*
|
|
639
|
+
* @private function of Color
|
|
531
640
|
*/
|
|
532
641
|
const RGB_REGEX_PATTERN = /^rgb\(\s*([0-9.%-]+)\s*,\s*([0-9.%-]+)\s*,\s*([0-9.%-]+)\s*\)$/;
|
|
533
642
|
/**
|
|
534
643
|
* Pattern matching rgba regex.
|
|
644
|
+
*
|
|
645
|
+
* @private function of Color
|
|
535
646
|
*/
|
|
536
647
|
const RGBA_REGEX_PATTERN = /^rgba\(\s*([0-9.%-]+)\s*,\s*([0-9.%-]+)\s*,\s*([0-9.%-]+)\s*,\s*([0-9.%-]+)\s*\)$/;
|
|
648
|
+
/**
|
|
649
|
+
* Parses a supported color string into RGBA channels.
|
|
650
|
+
*
|
|
651
|
+
* @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`,...
|
|
652
|
+
* @returns RGBA channel values.
|
|
653
|
+
*
|
|
654
|
+
* @private function of Color
|
|
655
|
+
*/
|
|
656
|
+
function parseColorString(color) {
|
|
657
|
+
const trimmed = color.trim();
|
|
658
|
+
const cssColor = CSS_COLORS[trimmed];
|
|
659
|
+
if (cssColor) {
|
|
660
|
+
return parseColorString(cssColor);
|
|
661
|
+
}
|
|
662
|
+
else if (isHexColorString(trimmed)) {
|
|
663
|
+
return parseHexColor(trimmed);
|
|
664
|
+
}
|
|
665
|
+
if (HSL_REGEX_PATTERN.test(trimmed)) {
|
|
666
|
+
return parseHslColor(trimmed);
|
|
667
|
+
}
|
|
668
|
+
else if (RGB_REGEX_PATTERN.test(trimmed)) {
|
|
669
|
+
return parseRgbColor(trimmed);
|
|
670
|
+
}
|
|
671
|
+
else if (RGBA_REGEX_PATTERN.test(trimmed)) {
|
|
672
|
+
return parseRgbaColor(trimmed);
|
|
673
|
+
}
|
|
674
|
+
else {
|
|
675
|
+
throw new Error(`Can not create a new Color instance from string "${trimmed}".`);
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
|
|
537
679
|
/**
|
|
538
680
|
* Color object represents an RGB color with alpha channel
|
|
539
681
|
*
|
|
@@ -541,7 +683,7 @@
|
|
|
541
683
|
*
|
|
542
684
|
* @public exported from `@promptbook/color`
|
|
543
685
|
*/
|
|
544
|
-
class Color {
|
|
686
|
+
class Color extends ColorValue {
|
|
545
687
|
/**
|
|
546
688
|
* Creates a new Color instance from miscellaneous formats
|
|
547
689
|
* - It can receive Color instance and just return the same instance
|
|
@@ -614,25 +756,7 @@
|
|
|
614
756
|
* @returns Color object
|
|
615
757
|
*/
|
|
616
758
|
static fromString(color) {
|
|
617
|
-
|
|
618
|
-
if (CSS_COLORS[trimmed]) {
|
|
619
|
-
return Color.fromString(CSS_COLORS[trimmed]);
|
|
620
|
-
}
|
|
621
|
-
else if (Color.isHexColorString(trimmed)) {
|
|
622
|
-
return Color.fromHex(trimmed);
|
|
623
|
-
}
|
|
624
|
-
if (HSL_REGEX_PATTERN.test(trimmed)) {
|
|
625
|
-
return Color.fromHsl(trimmed);
|
|
626
|
-
}
|
|
627
|
-
else if (RGB_REGEX_PATTERN.test(trimmed)) {
|
|
628
|
-
return Color.fromRgbString(trimmed);
|
|
629
|
-
}
|
|
630
|
-
else if (RGBA_REGEX_PATTERN.test(trimmed)) {
|
|
631
|
-
return Color.fromRgbaString(trimmed);
|
|
632
|
-
}
|
|
633
|
-
else {
|
|
634
|
-
throw new Error(`Can not create a new Color instance from string "${trimmed}".`);
|
|
635
|
-
}
|
|
759
|
+
return Color.fromColorChannels(parseColorString(color));
|
|
636
760
|
}
|
|
637
761
|
/**
|
|
638
762
|
* Gets common color
|
|
@@ -662,8 +786,7 @@
|
|
|
662
786
|
* @returns Color object
|
|
663
787
|
*/
|
|
664
788
|
static fromHex(hex) {
|
|
665
|
-
|
|
666
|
-
return take(new Color(red, green, blue, alpha));
|
|
789
|
+
return Color.fromColorChannels(parseHexColor(hex));
|
|
667
790
|
}
|
|
668
791
|
/**
|
|
669
792
|
* Creates a new Color instance from color in hsl format
|
|
@@ -672,8 +795,7 @@
|
|
|
672
795
|
* @returns Color object
|
|
673
796
|
*/
|
|
674
797
|
static fromHsl(hsl) {
|
|
675
|
-
|
|
676
|
-
return take(new Color(red, green, blue, alpha));
|
|
798
|
+
return Color.fromColorChannels(parseHslColor(hsl));
|
|
677
799
|
}
|
|
678
800
|
/**
|
|
679
801
|
* Creates a new Color instance from color in rgb format
|
|
@@ -682,8 +804,7 @@
|
|
|
682
804
|
* @returns Color object
|
|
683
805
|
*/
|
|
684
806
|
static fromRgbString(rgb) {
|
|
685
|
-
|
|
686
|
-
return take(new Color(red, green, blue, alpha));
|
|
807
|
+
return Color.fromColorChannels(parseRgbColor(rgb));
|
|
687
808
|
}
|
|
688
809
|
/**
|
|
689
810
|
* Creates a new Color instance from color in rbga format
|
|
@@ -692,8 +813,7 @@
|
|
|
692
813
|
* @returns Color object
|
|
693
814
|
*/
|
|
694
815
|
static fromRgbaString(rgba) {
|
|
695
|
-
|
|
696
|
-
return take(new Color(red, green, blue, alpha));
|
|
816
|
+
return Color.fromColorChannels(parseRgbaColor(rgba));
|
|
697
817
|
}
|
|
698
818
|
/**
|
|
699
819
|
* Creates a new Color for color channels values
|
|
@@ -705,7 +825,7 @@
|
|
|
705
825
|
* @returns Color object
|
|
706
826
|
*/
|
|
707
827
|
static fromValues(red, green, blue, alpha = 255) {
|
|
708
|
-
return
|
|
828
|
+
return Color.fromColorChannels({ red, green, blue, alpha });
|
|
709
829
|
}
|
|
710
830
|
/**
|
|
711
831
|
* Checks if the given value is a valid Color object.
|
|
@@ -738,8 +858,7 @@
|
|
|
738
858
|
* @returns true if the value is a valid hex color string (e.g., `#009edd`, `#fff`, etc.)
|
|
739
859
|
*/
|
|
740
860
|
static isHexColorString(value) {
|
|
741
|
-
return (
|
|
742
|
-
/^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/.test(value));
|
|
861
|
+
return isHexColorString(value);
|
|
743
862
|
}
|
|
744
863
|
/**
|
|
745
864
|
* Creates new Color object
|
|
@@ -752,89 +871,13 @@
|
|
|
752
871
|
* @param alpha number from 0 (transparent) to 255 (opaque)
|
|
753
872
|
*/
|
|
754
873
|
constructor(red, green, blue, alpha = 255) {
|
|
755
|
-
|
|
756
|
-
this.green = green;
|
|
757
|
-
this.blue = blue;
|
|
758
|
-
this.alpha = alpha;
|
|
759
|
-
checkChannelValue('Red', red);
|
|
760
|
-
checkChannelValue('Green', green);
|
|
761
|
-
checkChannelValue('Blue', blue);
|
|
762
|
-
checkChannelValue('Alpha', alpha);
|
|
763
|
-
}
|
|
764
|
-
/**
|
|
765
|
-
* Shortcut for `red` property
|
|
766
|
-
* Number from 0 to 255
|
|
767
|
-
* @alias red
|
|
768
|
-
*/
|
|
769
|
-
get r() {
|
|
770
|
-
return this.red;
|
|
771
|
-
}
|
|
772
|
-
/**
|
|
773
|
-
* Shortcut for `green` property
|
|
774
|
-
* Number from 0 to 255
|
|
775
|
-
* @alias green
|
|
776
|
-
*/
|
|
777
|
-
get g() {
|
|
778
|
-
return this.green;
|
|
779
|
-
}
|
|
780
|
-
/**
|
|
781
|
-
* Shortcut for `blue` property
|
|
782
|
-
* Number from 0 to 255
|
|
783
|
-
* @alias blue
|
|
784
|
-
*/
|
|
785
|
-
get b() {
|
|
786
|
-
return this.blue;
|
|
787
|
-
}
|
|
788
|
-
/**
|
|
789
|
-
* Shortcut for `alpha` property
|
|
790
|
-
* Number from 0 (transparent) to 255 (opaque)
|
|
791
|
-
* @alias alpha
|
|
792
|
-
*/
|
|
793
|
-
get a() {
|
|
794
|
-
return this.alpha;
|
|
795
|
-
}
|
|
796
|
-
/**
|
|
797
|
-
* Shortcut for `alpha` property
|
|
798
|
-
* Number from 0 (transparent) to 255 (opaque)
|
|
799
|
-
* @alias alpha
|
|
800
|
-
*/
|
|
801
|
-
get opacity() {
|
|
802
|
-
return this.alpha;
|
|
803
|
-
}
|
|
804
|
-
/**
|
|
805
|
-
* Shortcut for 1-`alpha` property
|
|
806
|
-
*/
|
|
807
|
-
get transparency() {
|
|
808
|
-
return 255 - this.alpha;
|
|
809
|
-
}
|
|
810
|
-
clone() {
|
|
811
|
-
return take(new Color(this.red, this.green, this.blue, this.alpha));
|
|
812
|
-
}
|
|
813
|
-
toString() {
|
|
814
|
-
return this.toHex();
|
|
815
|
-
}
|
|
816
|
-
toHex() {
|
|
817
|
-
if (this.alpha === 255) {
|
|
818
|
-
return `#${this.red.toString(16).padStart(2, '0')}${this.green.toString(16).padStart(2, '0')}${this.blue
|
|
819
|
-
.toString(16)
|
|
820
|
-
.padStart(2, '0')}`;
|
|
821
|
-
}
|
|
822
|
-
else {
|
|
823
|
-
return `#${this.red.toString(16).padStart(2, '0')}${this.green.toString(16).padStart(2, '0')}${this.blue
|
|
824
|
-
.toString(16)
|
|
825
|
-
.padStart(2, '0')}${this.alpha.toString(16).padStart(2, '0')}`;
|
|
826
|
-
}
|
|
874
|
+
super(red, green, blue, alpha);
|
|
827
875
|
}
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
return `rgb(${this.red}, ${this.green}, ${this.blue})`;
|
|
831
|
-
}
|
|
832
|
-
else {
|
|
833
|
-
return `rgba(${this.red}, ${this.green}, ${this.blue}, ${Math.round((this.alpha / 255) * 100)}%)`;
|
|
834
|
-
}
|
|
876
|
+
createColor(red, green, blue, alpha) {
|
|
877
|
+
return new Color(red, green, blue, alpha);
|
|
835
878
|
}
|
|
836
|
-
|
|
837
|
-
|
|
879
|
+
static fromColorChannels({ red, green, blue, alpha }) {
|
|
880
|
+
return take(new Color(red, green, blue, alpha));
|
|
838
881
|
}
|
|
839
882
|
}
|
|
840
883
|
|
|
@@ -1510,120 +1553,183 @@
|
|
|
1510
1553
|
* @public exported from `@promptbook/utils`
|
|
1511
1554
|
*/
|
|
1512
1555
|
function checkSerializableAsJson(options) {
|
|
1513
|
-
|
|
1556
|
+
checkSerializableValue(options);
|
|
1557
|
+
}
|
|
1558
|
+
// TODO: Can be return type more type-safe? like `asserts options.value is JsonValue`
|
|
1559
|
+
// TODO: [🧠][main] !!3 In-memory cache of same values to prevent multiple checks
|
|
1560
|
+
// Note: [🐠] This is how `checkSerializableAsJson` + `isSerializableAsJson` together can just retun true/false or rich error message
|
|
1561
|
+
/**
|
|
1562
|
+
* Checks one value and dispatches to the appropriate specialized validator.
|
|
1563
|
+
*
|
|
1564
|
+
* @private function of `checkSerializableAsJson`
|
|
1565
|
+
*/
|
|
1566
|
+
function checkSerializableValue(options) {
|
|
1567
|
+
const { value } = options;
|
|
1568
|
+
if (isSerializablePrimitive(value)) {
|
|
1569
|
+
return;
|
|
1570
|
+
}
|
|
1514
1571
|
if (value === undefined) {
|
|
1515
|
-
throw new UnexpectedError(`${name} is undefined`);
|
|
1572
|
+
throw new UnexpectedError(`${options.name} is undefined`);
|
|
1516
1573
|
}
|
|
1517
|
-
|
|
1518
|
-
|
|
1574
|
+
if (typeof value === 'symbol') {
|
|
1575
|
+
throw new UnexpectedError(`${options.name} is symbol`);
|
|
1519
1576
|
}
|
|
1520
|
-
|
|
1521
|
-
|
|
1577
|
+
if (typeof value === 'function') {
|
|
1578
|
+
throw new UnexpectedError(`${options.name} is function`);
|
|
1522
1579
|
}
|
|
1523
|
-
|
|
1580
|
+
if (Array.isArray(value)) {
|
|
1581
|
+
checkSerializableArray(options, value);
|
|
1524
1582
|
return;
|
|
1525
1583
|
}
|
|
1526
|
-
|
|
1584
|
+
if (value !== null && typeof value === 'object') {
|
|
1585
|
+
checkSerializableObject(options, value);
|
|
1527
1586
|
return;
|
|
1528
1587
|
}
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1588
|
+
throwUnknownTypeError(options);
|
|
1589
|
+
}
|
|
1590
|
+
/**
|
|
1591
|
+
* Checks the primitive values that are directly JSON serializable.
|
|
1592
|
+
*
|
|
1593
|
+
* @private function of `checkSerializableAsJson`
|
|
1594
|
+
*/
|
|
1595
|
+
function isSerializablePrimitive(value) {
|
|
1596
|
+
return (value === null ||
|
|
1597
|
+
typeof value === 'boolean' ||
|
|
1598
|
+
(typeof value === 'number' && !isNaN(value)) ||
|
|
1599
|
+
typeof value === 'string');
|
|
1600
|
+
}
|
|
1601
|
+
/**
|
|
1602
|
+
* Recursively checks JSON array items.
|
|
1603
|
+
*
|
|
1604
|
+
* @private function of `checkSerializableAsJson`
|
|
1605
|
+
*/
|
|
1606
|
+
function checkSerializableArray(context, arrayValue) {
|
|
1607
|
+
for (let index = 0; index < arrayValue.length; index++) {
|
|
1608
|
+
checkSerializableAsJson({
|
|
1609
|
+
...context,
|
|
1610
|
+
name: `${context.name}[${index}]`,
|
|
1611
|
+
value: arrayValue[index],
|
|
1612
|
+
});
|
|
1539
1613
|
}
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1614
|
+
}
|
|
1615
|
+
/**
|
|
1616
|
+
* Checks object-like values and dispatches special unsupported built-ins.
|
|
1617
|
+
*
|
|
1618
|
+
* @private function of `checkSerializableAsJson`
|
|
1619
|
+
*/
|
|
1620
|
+
function checkSerializableObject(context, objectValue) {
|
|
1621
|
+
checkUnsupportedObjectType(context, objectValue);
|
|
1622
|
+
checkSerializableObjectEntries(context, objectValue);
|
|
1623
|
+
assertJsonStringificationSucceeds(context, objectValue);
|
|
1624
|
+
}
|
|
1625
|
+
/**
|
|
1626
|
+
* Rejects built-in objects that must be converted before JSON serialization.
|
|
1627
|
+
*
|
|
1628
|
+
* @private function of `checkSerializableAsJson`
|
|
1629
|
+
*/
|
|
1630
|
+
function checkUnsupportedObjectType(context, objectValue) {
|
|
1631
|
+
if (objectValue instanceof Date) {
|
|
1632
|
+
throw new UnexpectedError(_spaceTrim.spaceTrim((block) => `
|
|
1633
|
+
\`${context.name}\` is Date
|
|
1544
1634
|
|
|
1545
|
-
|
|
1635
|
+
Use \`string_date_iso8601\` instead
|
|
1546
1636
|
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1637
|
+
Additional message for \`${context.name}\`:
|
|
1638
|
+
${block(context.message || '(nothing)')}
|
|
1639
|
+
`));
|
|
1640
|
+
}
|
|
1641
|
+
if (objectValue instanceof Map) {
|
|
1642
|
+
throw new UnexpectedError(`${context.name} is Map`);
|
|
1643
|
+
}
|
|
1644
|
+
if (objectValue instanceof Set) {
|
|
1645
|
+
throw new UnexpectedError(`${context.name} is Set`);
|
|
1646
|
+
}
|
|
1647
|
+
if (objectValue instanceof RegExp) {
|
|
1648
|
+
throw new UnexpectedError(`${context.name} is RegExp`);
|
|
1649
|
+
}
|
|
1650
|
+
if (objectValue instanceof Error) {
|
|
1651
|
+
throw new UnexpectedError(_spaceTrim.spaceTrim((block) => `
|
|
1652
|
+
\`${context.name}\` is unserialized Error
|
|
1563
1653
|
|
|
1564
|
-
|
|
1654
|
+
Use function \`serializeError\`
|
|
1565
1655
|
|
|
1566
|
-
|
|
1567
|
-
|
|
1656
|
+
Additional message for \`${context.name}\`:
|
|
1657
|
+
${block(context.message || '(nothing)')}
|
|
1568
1658
|
|
|
1569
|
-
|
|
1659
|
+
`));
|
|
1660
|
+
}
|
|
1661
|
+
}
|
|
1662
|
+
/**
|
|
1663
|
+
* Recursively checks object properties while preserving omitted `undefined` keys.
|
|
1664
|
+
*
|
|
1665
|
+
* @private function of `checkSerializableAsJson`
|
|
1666
|
+
*/
|
|
1667
|
+
function checkSerializableObjectEntries(context, objectValue) {
|
|
1668
|
+
for (const [subName, subValue] of Object.entries(objectValue)) {
|
|
1669
|
+
if (subValue === undefined) {
|
|
1670
|
+
// Note: undefined in object is serializable - it is just omitted
|
|
1671
|
+
continue;
|
|
1570
1672
|
}
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1673
|
+
checkSerializableAsJson({
|
|
1674
|
+
...context,
|
|
1675
|
+
name: `${context.name}.${subName}`,
|
|
1676
|
+
value: subValue,
|
|
1677
|
+
});
|
|
1678
|
+
}
|
|
1679
|
+
}
|
|
1680
|
+
/**
|
|
1681
|
+
* Uses `JSON.stringify` as the final guard for cases like circular references.
|
|
1682
|
+
*
|
|
1683
|
+
* @private function of `checkSerializableAsJson`
|
|
1684
|
+
*/
|
|
1685
|
+
function assertJsonStringificationSucceeds(context, objectValue) {
|
|
1686
|
+
try {
|
|
1687
|
+
JSON.stringify(objectValue); // <- TODO: [0]
|
|
1688
|
+
}
|
|
1689
|
+
catch (error) {
|
|
1690
|
+
assertsError(error);
|
|
1691
|
+
throw new UnexpectedError(_spaceTrim.spaceTrim((block) => `
|
|
1692
|
+
\`${context.name}\` is not serializable
|
|
1586
1693
|
|
|
1587
|
-
|
|
1694
|
+
${block(error.stack || error.message)}
|
|
1588
1695
|
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1696
|
+
Additional message for \`${context.name}\`:
|
|
1697
|
+
${block(context.message || '(nothing)')}
|
|
1698
|
+
`));
|
|
1699
|
+
}
|
|
1700
|
+
/*
|
|
1701
|
+
TODO: [0] Is there some more elegant way to check circular references?
|
|
1702
|
+
const seen = new Set();
|
|
1703
|
+
const stack = [{ value }];
|
|
1704
|
+
while (stack.length > 0) {
|
|
1705
|
+
const { value } = stack.pop()!;
|
|
1706
|
+
if (typeof value === 'object' && value !== null) {
|
|
1707
|
+
if (seen.has(value)) {
|
|
1708
|
+
throw new UnexpectedError(`${name} has circular reference`);
|
|
1592
1709
|
}
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
const { value } = stack.pop()!;
|
|
1599
|
-
if (typeof value === 'object' && value !== null) {
|
|
1600
|
-
if (seen.has(value)) {
|
|
1601
|
-
throw new UnexpectedError(`${name} has circular reference`);
|
|
1602
|
-
}
|
|
1603
|
-
seen.add(value);
|
|
1604
|
-
if (Array.isArray(value)) {
|
|
1605
|
-
stack.push(...value.map((value) => ({ value })));
|
|
1606
|
-
} else {
|
|
1607
|
-
stack.push(...Object.values(value).map((value) => ({ value })));
|
|
1608
|
-
}
|
|
1609
|
-
}
|
|
1710
|
+
seen.add(value);
|
|
1711
|
+
if (Array.isArray(value)) {
|
|
1712
|
+
stack.push(...value.map((value) => ({ value })));
|
|
1713
|
+
} else {
|
|
1714
|
+
stack.push(...Object.values(value).map((value) => ({ value })));
|
|
1610
1715
|
}
|
|
1611
|
-
*/
|
|
1612
|
-
return;
|
|
1613
1716
|
}
|
|
1614
1717
|
}
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1718
|
+
*/
|
|
1719
|
+
}
|
|
1720
|
+
/**
|
|
1721
|
+
* Throws the fallback error for unsupported value types like `bigint` and `NaN`.
|
|
1722
|
+
*
|
|
1723
|
+
* @private function of `checkSerializableAsJson`
|
|
1724
|
+
*/
|
|
1725
|
+
function throwUnknownTypeError(context) {
|
|
1726
|
+
throw new UnexpectedError(_spaceTrim.spaceTrim((block) => `
|
|
1727
|
+
\`${context.name}\` is unknown type
|
|
1618
1728
|
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
}
|
|
1729
|
+
Additional message for \`${context.name}\`:
|
|
1730
|
+
${block(context.message || '(nothing)')}
|
|
1731
|
+
`));
|
|
1623
1732
|
}
|
|
1624
|
-
// TODO: Can be return type more type-safe? like `asserts options.value is JsonValue`
|
|
1625
|
-
// TODO: [🧠][main] !!3 In-memory cache of same values to prevent multiple checks
|
|
1626
|
-
// Note: [🐠] This is how `checkSerializableAsJson` + `isSerializableAsJson` together can just retun true/false or rich error message
|
|
1627
1733
|
|
|
1628
1734
|
/**
|
|
1629
1735
|
* Creates a deep clone of the given object
|
|
@@ -5984,7 +6090,10 @@
|
|
|
5984
6090
|
Cannot find model in ${this.options.getTitle()} models with name "${defaultModelName}" which should be used as default.
|
|
5985
6091
|
|
|
5986
6092
|
Available models:
|
|
5987
|
-
${block(this.options
|
|
6093
|
+
${block(this.options
|
|
6094
|
+
.getHardcodedModels()
|
|
6095
|
+
.map(({ modelName }) => `- "${modelName}"`)
|
|
6096
|
+
.join('\n'))}
|
|
5988
6097
|
|
|
5989
6098
|
Model "${defaultModelName}" is probably not available anymore, not installed, inaccessible or misconfigured.
|
|
5990
6099
|
|
|
@@ -6338,7 +6447,8 @@
|
|
|
6338
6447
|
};
|
|
6339
6448
|
let rawPromptContent = templateParameters(content, { ...parameters, modelName });
|
|
6340
6449
|
if ('attachments' in prompt && Array.isArray(prompt.attachments) && prompt.attachments.length > 0) {
|
|
6341
|
-
rawPromptContent +=
|
|
6450
|
+
rawPromptContent +=
|
|
6451
|
+
'\n\n' + prompt.attachments.map((attachment) => `Image attachment: ${attachment.url}`).join('\n');
|
|
6342
6452
|
}
|
|
6343
6453
|
const rawRequest = {
|
|
6344
6454
|
...modelSettings,
|
|
@@ -6443,7 +6553,9 @@
|
|
|
6443
6553
|
* Schedules one request through the shared limiter and retry policy.
|
|
6444
6554
|
*/
|
|
6445
6555
|
async executeRateLimitedRequest(requestFn) {
|
|
6446
|
-
return this.limiter
|
|
6556
|
+
return this.limiter
|
|
6557
|
+
.schedule(() => this.makeRequestWithNetworkRetry(requestFn))
|
|
6558
|
+
.catch((error) => {
|
|
6447
6559
|
assertsError(error);
|
|
6448
6560
|
if (this.options.isVerbose) {
|
|
6449
6561
|
console.info(colors__default["default"].bgRed('error'), error);
|
|
@@ -9183,7 +9295,9 @@
|
|
|
9183
9295
|
pollingState.lastProgressAtMs = nowMs;
|
|
9184
9296
|
pollingState.lastProgressKey = progressKey;
|
|
9185
9297
|
}
|
|
9186
|
-
if (this.options.isVerbose &&
|
|
9298
|
+
if (this.options.isVerbose &&
|
|
9299
|
+
(statusCountsKey !== pollingState.lastCountsKey ||
|
|
9300
|
+
nowMs - pollingState.lastLogAtMs >= progressLogIntervalMs)) {
|
|
9187
9301
|
console.info('[🤰]', 'Vector store file batch status', {
|
|
9188
9302
|
vectorStoreId,
|
|
9189
9303
|
batchId,
|
|
@@ -11256,7 +11370,7 @@
|
|
|
11256
11370
|
*/
|
|
11257
11371
|
function createPostprocessingCommands(task) {
|
|
11258
11372
|
var _a;
|
|
11259
|
-
return ((_a = task.postprocessingFunctionNames) === null || _a === void 0 ? void 0 : _a.map((postprocessingFunctionName) => `POSTPROCESSING \`${postprocessingFunctionName}\``)) || [];
|
|
11373
|
+
return (((_a = task.postprocessingFunctionNames) === null || _a === void 0 ? void 0 : _a.map((postprocessingFunctionName) => `POSTPROCESSING \`${postprocessingFunctionName}\``)) || []);
|
|
11260
11374
|
}
|
|
11261
11375
|
/**
|
|
11262
11376
|
* Collects expectation commands.
|
|
@@ -11786,8 +11900,7 @@
|
|
|
11786
11900
|
* @private internal utility of `validatePipeline`
|
|
11787
11901
|
*/
|
|
11788
11902
|
function validateTaskSupportsJokers(task, pipelineIdentification) {
|
|
11789
|
-
if (task.format ||
|
|
11790
|
-
task.expectations /* <- TODO: Require at least 1 -> min <- expectation to use jokers */) {
|
|
11903
|
+
if (task.format || task.expectations /* <- TODO: Require at least 1 -> min <- expectation to use jokers */) {
|
|
11791
11904
|
return;
|
|
11792
11905
|
}
|
|
11793
11906
|
throw new PipelineLogicError(_spaceTrim.spaceTrim((block) => `
|
|
@@ -14982,9 +15095,7 @@
|
|
|
14982
15095
|
${block(quoteMultilineText(((_b = failure.error) === null || _b === void 0 ? void 0 : _b.message) || ''))}
|
|
14983
15096
|
|
|
14984
15097
|
Result:
|
|
14985
|
-
${block(failure.result === null
|
|
14986
|
-
? 'null'
|
|
14987
|
-
: quoteMultilineText(_spaceTrim.spaceTrim(failure.result)))}
|
|
15098
|
+
${block(failure.result === null ? 'null' : quoteMultilineText(_spaceTrim.spaceTrim(failure.result)))}
|
|
14988
15099
|
`;
|
|
14989
15100
|
}))
|
|
14990
15101
|
.join('\n\n---\n\n');
|
|
@@ -22470,7 +22581,7 @@
|
|
|
22470
22581
|
*
|
|
22471
22582
|
* @private helper of `minecraft2AvatarVisual`
|
|
22472
22583
|
*/
|
|
22473
|
-
const LIGHT_DIRECTION$
|
|
22584
|
+
const LIGHT_DIRECTION$2 = normalizeVector3({
|
|
22474
22585
|
x: 0.4,
|
|
22475
22586
|
y: -0.65,
|
|
22476
22587
|
z: 0.92,
|
|
@@ -22682,7 +22793,7 @@
|
|
|
22682
22793
|
corners: projectedCorners,
|
|
22683
22794
|
texture: faceDefinition.texture,
|
|
22684
22795
|
averageDepth: transformedCorners.reduce((depthSum, corner) => depthSum + corner.z, 0) / transformedCorners.length,
|
|
22685
|
-
lightIntensity: clampNumber$1(dotProduct3D(faceNormal, LIGHT_DIRECTION$
|
|
22796
|
+
lightIntensity: clampNumber$1(dotProduct3D(faceNormal, LIGHT_DIRECTION$2), -1, 1),
|
|
22686
22797
|
outlineColor: cuboid.outlineColor,
|
|
22687
22798
|
};
|
|
22688
22799
|
});
|
|
@@ -23742,13 +23853,138 @@
|
|
|
23742
23853
|
context.restore();
|
|
23743
23854
|
}
|
|
23744
23855
|
|
|
23856
|
+
/* eslint-disable no-magic-numbers */
|
|
23857
|
+
/**
|
|
23858
|
+
* Draws one projected eye on a rotated octopus surface.
|
|
23859
|
+
*
|
|
23860
|
+
* @private helper of the 3D octopus avatar visuals
|
|
23861
|
+
*/
|
|
23862
|
+
function drawProjectedOrganicEye(context, localCenter, radiusX, radiusY, center, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, phase, interaction, eyeStyle) {
|
|
23863
|
+
const centerScenePoint = transformScenePoint(localCenter, center, rotationX, rotationY);
|
|
23864
|
+
if (centerScenePoint.z <= center.z) {
|
|
23865
|
+
return;
|
|
23866
|
+
}
|
|
23867
|
+
const horizontalScenePoint = transformScenePoint({ x: localCenter.x + radiusX, y: localCenter.y, z: localCenter.z }, center, rotationX, rotationY);
|
|
23868
|
+
const verticalScenePoint = transformScenePoint({ x: localCenter.x, y: localCenter.y + radiusY, z: localCenter.z }, center, rotationX, rotationY);
|
|
23869
|
+
const projectedCenterPoint = projectScenePoint(centerScenePoint, size, sceneCenterX, sceneCenterY);
|
|
23870
|
+
const projectedHorizontalPoint = projectScenePoint(horizontalScenePoint, size, sceneCenterX, sceneCenterY);
|
|
23871
|
+
const projectedVerticalPoint = projectScenePoint(verticalScenePoint, size, sceneCenterX, sceneCenterY);
|
|
23872
|
+
const projectedRadiusX = Math.hypot(projectedHorizontalPoint.x - projectedCenterPoint.x, projectedHorizontalPoint.y - projectedCenterPoint.y);
|
|
23873
|
+
const projectedRadiusY = Math.hypot(projectedVerticalPoint.x - projectedCenterPoint.x, projectedVerticalPoint.y - projectedCenterPoint.y);
|
|
23874
|
+
if (projectedRadiusX < size * 0.008 || projectedRadiusY < size * 0.008) {
|
|
23875
|
+
return;
|
|
23876
|
+
}
|
|
23877
|
+
const { pupilOffsetX, pupilOffsetY } = resolveOrganicEyeMotion({
|
|
23878
|
+
radiusX: projectedRadiusX,
|
|
23879
|
+
radiusY: projectedRadiusY,
|
|
23880
|
+
timeMs,
|
|
23881
|
+
phase,
|
|
23882
|
+
interaction,
|
|
23883
|
+
});
|
|
23884
|
+
const rotation = Math.atan2(projectedHorizontalPoint.y - projectedCenterPoint.y, projectedHorizontalPoint.x - projectedCenterPoint.x);
|
|
23885
|
+
context.save();
|
|
23886
|
+
context.translate(projectedCenterPoint.x, projectedCenterPoint.y);
|
|
23887
|
+
context.rotate(rotation);
|
|
23888
|
+
context.beginPath();
|
|
23889
|
+
context.ellipse(0, 0, projectedRadiusX, projectedRadiusY, 0, 0, Math.PI * 2);
|
|
23890
|
+
context.fillStyle = '#f8fbff';
|
|
23891
|
+
context.fill();
|
|
23892
|
+
context.clip();
|
|
23893
|
+
const irisGradient = context.createRadialGradient(-projectedRadiusX * 0.2, -projectedRadiusY * 0.26, projectedRadiusX * 0.05, 0, 0, projectedRadiusX * 0.92);
|
|
23894
|
+
irisGradient.addColorStop(0, palette.highlight);
|
|
23895
|
+
irisGradient.addColorStop(0.56, palette.secondary);
|
|
23896
|
+
irisGradient.addColorStop(1, palette.shadow);
|
|
23897
|
+
context.beginPath();
|
|
23898
|
+
context.ellipse(pupilOffsetX, pupilOffsetY, projectedRadiusX * 0.62 * eyeStyle.irisScale, projectedRadiusY * 0.72 * eyeStyle.irisScale, 0, 0, Math.PI * 2);
|
|
23899
|
+
context.fillStyle = irisGradient;
|
|
23900
|
+
context.fill();
|
|
23901
|
+
context.beginPath();
|
|
23902
|
+
context.ellipse(pupilOffsetX, pupilOffsetY, projectedRadiusX * 0.15 * eyeStyle.pupilWidthScale, projectedRadiusY * 0.48 * eyeStyle.pupilHeightScale, 0, 0, Math.PI * 2);
|
|
23903
|
+
context.fillStyle = palette.ink;
|
|
23904
|
+
context.fill();
|
|
23905
|
+
context.beginPath();
|
|
23906
|
+
context.ellipse(pupilOffsetX - projectedRadiusX * 0.22, pupilOffsetY - projectedRadiusY * 0.24, projectedRadiusX * 0.12, projectedRadiusY * 0.14, 0, 0, Math.PI * 2);
|
|
23907
|
+
context.fillStyle = '#ffffff';
|
|
23908
|
+
context.fill();
|
|
23909
|
+
context.restore();
|
|
23910
|
+
context.save();
|
|
23911
|
+
context.translate(projectedCenterPoint.x, projectedCenterPoint.y);
|
|
23912
|
+
context.rotate(rotation);
|
|
23913
|
+
context.beginPath();
|
|
23914
|
+
context.ellipse(0, 0, projectedRadiusX, projectedRadiusY, 0, 0, Math.PI * 2);
|
|
23915
|
+
context.strokeStyle = `${palette.shadow}cc`;
|
|
23916
|
+
context.lineWidth = projectedRadiusX * 0.16;
|
|
23917
|
+
context.stroke();
|
|
23918
|
+
context.beginPath();
|
|
23919
|
+
context.moveTo(-projectedRadiusX * 0.88, -projectedRadiusY * eyeStyle.upperLidInsetRatio);
|
|
23920
|
+
context.quadraticCurveTo(0, -projectedRadiusY * (eyeStyle.upperLidArchRatio - interaction.gazeY * 0.16 + interaction.intensity * 0.08), projectedRadiusX * 0.88, -projectedRadiusY * eyeStyle.upperLidInsetRatio);
|
|
23921
|
+
context.strokeStyle = `${palette.shadow}73`;
|
|
23922
|
+
context.lineWidth = projectedRadiusX * 0.14;
|
|
23923
|
+
context.lineCap = 'round';
|
|
23924
|
+
context.stroke();
|
|
23925
|
+
if (eyeStyle.lowerLidOpacity > 0) {
|
|
23926
|
+
context.beginPath();
|
|
23927
|
+
context.moveTo(-projectedRadiusX * 0.74, projectedRadiusY * 0.2);
|
|
23928
|
+
context.quadraticCurveTo(0, projectedRadiusY * 0.38, projectedRadiusX * 0.74, projectedRadiusY * 0.2);
|
|
23929
|
+
context.strokeStyle = `${palette.highlight}${formatAlphaHex(eyeStyle.lowerLidOpacity)}`;
|
|
23930
|
+
context.lineWidth = projectedRadiusX * 0.08;
|
|
23931
|
+
context.lineCap = 'round';
|
|
23932
|
+
context.stroke();
|
|
23933
|
+
}
|
|
23934
|
+
context.restore();
|
|
23935
|
+
}
|
|
23936
|
+
/**
|
|
23937
|
+
* Draws a subtle projected mouth arc across the front of a rotated octopus surface.
|
|
23938
|
+
*
|
|
23939
|
+
* @private helper of the 3D octopus avatar visuals
|
|
23940
|
+
*/
|
|
23941
|
+
function drawProjectedOrganicMouth(context, localPoints, center, rotationX, rotationY, sceneCenterX, sceneCenterY, palette, size) {
|
|
23942
|
+
const scenePoints = localPoints.map((localPoint) => transformScenePoint(localPoint, center, rotationX, rotationY));
|
|
23943
|
+
if (scenePoints.some((scenePoint) => scenePoint.z <= center.z)) {
|
|
23944
|
+
return;
|
|
23945
|
+
}
|
|
23946
|
+
const projectedPoints = scenePoints.map((scenePoint) => projectScenePoint(scenePoint, size, sceneCenterX, sceneCenterY));
|
|
23947
|
+
context.beginPath();
|
|
23948
|
+
context.moveTo(projectedPoints[0].x, projectedPoints[0].y);
|
|
23949
|
+
context.quadraticCurveTo(projectedPoints[1].x, projectedPoints[1].y, projectedPoints[2].x, projectedPoints[2].y);
|
|
23950
|
+
context.strokeStyle = `${palette.ink}b8`;
|
|
23951
|
+
context.lineWidth = Math.max(1.1, size * 0.009);
|
|
23952
|
+
context.lineCap = 'round';
|
|
23953
|
+
context.stroke();
|
|
23954
|
+
}
|
|
23955
|
+
/**
|
|
23956
|
+
* Draws one filled projected quad.
|
|
23957
|
+
*
|
|
23958
|
+
* @private helper of the 3D octopus avatar visuals
|
|
23959
|
+
*/
|
|
23960
|
+
function drawProjectedQuad(context, corners, fillStyle) {
|
|
23961
|
+
context.beginPath();
|
|
23962
|
+
context.moveTo(corners[0].x, corners[0].y);
|
|
23963
|
+
context.lineTo(corners[1].x, corners[1].y);
|
|
23964
|
+
context.lineTo(corners[2].x, corners[2].y);
|
|
23965
|
+
context.lineTo(corners[3].x, corners[3].y);
|
|
23966
|
+
context.closePath();
|
|
23967
|
+
context.fillStyle = fillStyle;
|
|
23968
|
+
context.fill();
|
|
23969
|
+
}
|
|
23970
|
+
/**
|
|
23971
|
+
* Converts an opacity ratio into a two-digit hexadecimal alpha suffix.
|
|
23972
|
+
*
|
|
23973
|
+
* @private helper of the 3D octopus avatar visuals
|
|
23974
|
+
*/
|
|
23975
|
+
function formatAlphaHex(opacity) {
|
|
23976
|
+
return Math.round(clampNumber$1(opacity, 0, 1) * 255)
|
|
23977
|
+
.toString(16)
|
|
23978
|
+
.padStart(2, '0');
|
|
23979
|
+
}
|
|
23980
|
+
|
|
23745
23981
|
/* eslint-disable no-magic-numbers */
|
|
23746
23982
|
/**
|
|
23747
23983
|
* Light direction used by the organic 3D octopus shading.
|
|
23748
23984
|
*
|
|
23749
23985
|
* @private helper of `octopus3dAvatarVisual`
|
|
23750
23986
|
*/
|
|
23751
|
-
const LIGHT_DIRECTION = normalizeVector3({
|
|
23987
|
+
const LIGHT_DIRECTION$1 = normalizeVector3({
|
|
23752
23988
|
x: 0.48,
|
|
23753
23989
|
y: -0.62,
|
|
23754
23990
|
z: 0.94,
|
|
@@ -23861,17 +24097,17 @@
|
|
|
23861
24097
|
for (const tentacleStroke of tentacleStrokes.filter((candidateTentacleStroke) => candidateTentacleStroke.isFrontFacing)) {
|
|
23862
24098
|
drawTentacleStroke(context, tentacleStroke, palette);
|
|
23863
24099
|
}
|
|
23864
|
-
|
|
24100
|
+
drawProjectedOrganicEye(context, {
|
|
23865
24101
|
x: -faceEyeSpacing,
|
|
23866
24102
|
y: faceEyeYOffset,
|
|
23867
24103
|
z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, -faceEyeSpacing, faceEyeYOffset),
|
|
23868
24104
|
}, faceEyeRadiusX, faceEyeRadiusY, mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + eyeRandom() * 0.6, interaction, morphologyProfile.face.eyeStyle);
|
|
23869
|
-
|
|
24105
|
+
drawProjectedOrganicEye(context, {
|
|
23870
24106
|
x: faceEyeSpacing,
|
|
23871
24107
|
y: faceEyeYOffset,
|
|
23872
24108
|
z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, faceEyeSpacing, faceEyeYOffset),
|
|
23873
24109
|
}, faceEyeRadiusX, faceEyeRadiusY, mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + 0.7 + eyeRandom() * 0.6, interaction, morphologyProfile.face.eyeStyle);
|
|
23874
|
-
|
|
24110
|
+
drawProjectedOrganicMouth(context, [
|
|
23875
24111
|
{
|
|
23876
24112
|
x: -mouthHalfWidth,
|
|
23877
24113
|
y: mouthY,
|
|
@@ -23958,7 +24194,7 @@
|
|
|
23958
24194
|
corners: projectedCorners,
|
|
23959
24195
|
averageDepth: transformedCorners.reduce((depthSum, transformedCorner) => depthSum + transformedCorner.z, 0) /
|
|
23960
24196
|
transformedCorners.length,
|
|
23961
|
-
lightIntensity: clampNumber$1(dotProduct3D(surfaceNormal, LIGHT_DIRECTION), -1, 1),
|
|
24197
|
+
lightIntensity: clampNumber$1(dotProduct3D(surfaceNormal, LIGHT_DIRECTION$1), -1, 1),
|
|
23962
24198
|
fillStyle: resolveSurfacePatchFillStyle(palette, verticalProgress + verticalColorBias),
|
|
23963
24199
|
outlineColor,
|
|
23964
24200
|
});
|
|
@@ -24140,128 +24376,260 @@
|
|
|
24140
24376
|
const remainingDepthRatio = Math.max(0, 1 - normalizedX * normalizedX - normalizedY * normalizedY);
|
|
24141
24377
|
return Math.sqrt(remainingDepthRatio) * radiusZ;
|
|
24142
24378
|
}
|
|
24379
|
+
|
|
24380
|
+
/* eslint-disable no-magic-numbers */
|
|
24143
24381
|
/**
|
|
24144
|
-
*
|
|
24382
|
+
* Light direction used by the single-mesh octopus shading.
|
|
24145
24383
|
*
|
|
24146
|
-
* @private helper of `
|
|
24384
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
24147
24385
|
*/
|
|
24148
|
-
|
|
24149
|
-
|
|
24150
|
-
|
|
24151
|
-
|
|
24152
|
-
|
|
24153
|
-
|
|
24154
|
-
|
|
24155
|
-
|
|
24156
|
-
|
|
24157
|
-
|
|
24158
|
-
|
|
24159
|
-
|
|
24160
|
-
|
|
24161
|
-
|
|
24162
|
-
|
|
24163
|
-
|
|
24164
|
-
|
|
24165
|
-
|
|
24166
|
-
|
|
24167
|
-
|
|
24168
|
-
|
|
24169
|
-
|
|
24170
|
-
|
|
24386
|
+
const LIGHT_DIRECTION = normalizeVector3({
|
|
24387
|
+
x: 0.38,
|
|
24388
|
+
y: -0.6,
|
|
24389
|
+
z: 0.98,
|
|
24390
|
+
});
|
|
24391
|
+
/**
|
|
24392
|
+
* Octopus 3D 2 avatar visual.
|
|
24393
|
+
*
|
|
24394
|
+
* @private built-in avatar visual
|
|
24395
|
+
*/
|
|
24396
|
+
const octopus3d2AvatarVisual = {
|
|
24397
|
+
id: 'octopus3d2',
|
|
24398
|
+
title: 'Octopus 3D 2',
|
|
24399
|
+
description: 'Continuous blobby 3D octopus portrait with one soft mesh, turning silhouette, and cursor-aware eyes.',
|
|
24400
|
+
isAnimated: true,
|
|
24401
|
+
supportsPointerTracking: true,
|
|
24402
|
+
render({ context, size, palette, createRandom, timeMs, interaction }) {
|
|
24403
|
+
const morphologyProfile = createOctopus3MorphologyProfile(createRandom);
|
|
24404
|
+
const animationRandom = createRandom('octopus3d2-animation-profile');
|
|
24405
|
+
const eyeRandom = createRandom('octopus3d2-eye-profile');
|
|
24406
|
+
const animationPhase = animationRandom() * Math.PI * 2;
|
|
24407
|
+
const sceneCenterX = size * 0.5;
|
|
24408
|
+
const sceneCenterY = size * 0.575;
|
|
24409
|
+
const bob = Math.sin(timeMs / 940 + animationPhase) * size * 0.013;
|
|
24410
|
+
const meshCenter = {
|
|
24411
|
+
x: interaction.bodyOffsetX * size * 0.044 + size * morphologyProfile.body.centerXJitterRatio * 0.5,
|
|
24412
|
+
y: -size * 0.03 + interaction.bodyOffsetY * size * 0.026 + bob,
|
|
24413
|
+
z: interaction.intensity * size * 0.018,
|
|
24414
|
+
};
|
|
24415
|
+
const rotationY = -0.14 +
|
|
24416
|
+
Math.sin(timeMs / 2600 + animationPhase) * 0.04 +
|
|
24417
|
+
interaction.bodyOffsetX * 0.2 +
|
|
24418
|
+
interaction.gazeX * 0.78;
|
|
24419
|
+
const rotationX = -0.06 +
|
|
24420
|
+
Math.cos(timeMs / 3000 + animationPhase * 0.7) * 0.02 -
|
|
24421
|
+
interaction.bodyOffsetY * 0.08 -
|
|
24422
|
+
interaction.gazeY * 0.34;
|
|
24423
|
+
const surfaceOptions = {
|
|
24424
|
+
radiusX: size * morphologyProfile.body.bodyRadiusRatio * morphologyProfile.body.horizontalStretch * 1.02,
|
|
24425
|
+
radiusY: size * morphologyProfile.body.bodyRadiusRatio * morphologyProfile.body.verticalStretch * 1.22,
|
|
24426
|
+
radiusZ: size *
|
|
24427
|
+
morphologyProfile.body.bodyRadiusRatio *
|
|
24428
|
+
(0.98 + (morphologyProfile.body.horizontalStretch - 1) * 0.2),
|
|
24429
|
+
morphologyProfile,
|
|
24430
|
+
timeMs,
|
|
24431
|
+
animationPhase,
|
|
24432
|
+
};
|
|
24433
|
+
const surfacePatches = resolveVisibleBlobbyOctopusPatches({
|
|
24434
|
+
...surfaceOptions,
|
|
24435
|
+
center: meshCenter,
|
|
24436
|
+
rotationX,
|
|
24437
|
+
rotationY,
|
|
24438
|
+
sceneCenterX,
|
|
24439
|
+
sceneCenterY,
|
|
24440
|
+
size,
|
|
24441
|
+
palette,
|
|
24442
|
+
});
|
|
24443
|
+
const eyeLatitude = clampNumber$1(morphologyProfile.face.eyeCenterYOffsetRatio * 4.4, -0.16, 0.11);
|
|
24444
|
+
const eyeLongitude = clampNumber$1(morphologyProfile.face.eyeSpacingRatio * 3.25, 0.2, 0.34);
|
|
24445
|
+
const mouthLatitude = clampNumber$1(eyeLatitude + 0.19 + morphologyProfile.face.mouthYOffsetRatio * 1.08, 0.08, 0.34);
|
|
24446
|
+
const mouthCenterLongitude = clampNumber$1(morphologyProfile.face.mouthCenterOffsetRatio * 5.8, -0.08, 0.08);
|
|
24447
|
+
const mouthHalfLongitude = clampNumber$1(eyeLongitude * 0.82, 0.16, 0.29);
|
|
24448
|
+
const mouthCurveLatitude = clampNumber$1(mouthLatitude + morphologyProfile.face.mouthCurveDepthRatio * 0.85, mouthLatitude + 0.03, 0.42);
|
|
24449
|
+
drawAvatarFrame(context, size, palette);
|
|
24450
|
+
drawBlobbyOctopusAtmosphere(context, size, palette, sceneCenterX, sceneCenterY, interaction, timeMs);
|
|
24451
|
+
drawBlobbyOctopusShadow(context, size, palette, interaction, timeMs, morphologyProfile);
|
|
24452
|
+
for (const surfacePatch of surfacePatches.sort((firstSurfacePatch, secondSurfacePatch) => firstSurfacePatch.averageDepth - secondSurfacePatch.averageDepth)) {
|
|
24453
|
+
drawBlobbySurfacePatch(context, surfacePatch);
|
|
24454
|
+
}
|
|
24455
|
+
const leftEyeLocalCenter = sampleBlobbyOctopusSurfacePoint(surfaceOptions, eyeLatitude, -eyeLongitude);
|
|
24456
|
+
const rightEyeLocalCenter = sampleBlobbyOctopusSurfacePoint(surfaceOptions, eyeLatitude, eyeLongitude);
|
|
24457
|
+
const eyeRadiusX = size * morphologyProfile.face.eyeRadiusXRatio * 0.78;
|
|
24458
|
+
const eyeRadiusY = eyeRadiusX * morphologyProfile.face.eyeHeightRatio * 0.92;
|
|
24459
|
+
drawProjectedOrganicEye(context, leftEyeLocalCenter, eyeRadiusX, eyeRadiusY, meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + eyeRandom() * 0.7, interaction, morphologyProfile.face.eyeStyle);
|
|
24460
|
+
drawProjectedOrganicEye(context, rightEyeLocalCenter, eyeRadiusX, eyeRadiusY, meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + 0.9 + eyeRandom() * 0.7, interaction, morphologyProfile.face.eyeStyle);
|
|
24461
|
+
drawProjectedOrganicMouth(context, [
|
|
24462
|
+
sampleBlobbyOctopusSurfacePoint(surfaceOptions, mouthLatitude, mouthCenterLongitude - mouthHalfLongitude),
|
|
24463
|
+
sampleBlobbyOctopusSurfacePoint(surfaceOptions, mouthCurveLatitude, mouthCenterLongitude),
|
|
24464
|
+
sampleBlobbyOctopusSurfacePoint(surfaceOptions, mouthLatitude, mouthCenterLongitude + mouthHalfLongitude),
|
|
24465
|
+
], meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, palette, size);
|
|
24466
|
+
},
|
|
24467
|
+
};
|
|
24468
|
+
/**
|
|
24469
|
+
* Draws the deep-water glow behind the continuous octopus mesh.
|
|
24470
|
+
*
|
|
24471
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
24472
|
+
*/
|
|
24473
|
+
function drawBlobbyOctopusAtmosphere(context, size, palette, sceneCenterX, sceneCenterY, interaction, timeMs) {
|
|
24474
|
+
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);
|
|
24475
|
+
glowGradient.addColorStop(0, `${palette.highlight}5e`);
|
|
24476
|
+
glowGradient.addColorStop(0.38, `${palette.accent}26`);
|
|
24477
|
+
glowGradient.addColorStop(1, `${palette.highlight}00`);
|
|
24478
|
+
context.fillStyle = glowGradient;
|
|
24479
|
+
context.fillRect(0, 0, size, size);
|
|
24480
|
+
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);
|
|
24481
|
+
lowerGradient.addColorStop(0, `${palette.secondary}22`);
|
|
24482
|
+
lowerGradient.addColorStop(1, `${palette.secondary}00`);
|
|
24483
|
+
context.fillStyle = lowerGradient;
|
|
24484
|
+
context.fillRect(0, 0, size, size);
|
|
24485
|
+
}
|
|
24486
|
+
/**
|
|
24487
|
+
* Draws the soft floor shadow that anchors the single mesh in the frame.
|
|
24488
|
+
*
|
|
24489
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
24490
|
+
*/
|
|
24491
|
+
function drawBlobbyOctopusShadow(context, size, palette, interaction, timeMs, morphologyProfile) {
|
|
24171
24492
|
context.save();
|
|
24172
|
-
context.
|
|
24173
|
-
context.
|
|
24174
|
-
context.beginPath();
|
|
24175
|
-
context.ellipse(0, 0, projectedRadiusX, projectedRadiusY, 0, 0, Math.PI * 2);
|
|
24176
|
-
context.fillStyle = '#f8fbff';
|
|
24177
|
-
context.fill();
|
|
24178
|
-
context.clip();
|
|
24179
|
-
const irisGradient = context.createRadialGradient(-projectedRadiusX * 0.2, -projectedRadiusY * 0.26, projectedRadiusX * 0.05, 0, 0, projectedRadiusX * 0.92);
|
|
24180
|
-
irisGradient.addColorStop(0, palette.highlight);
|
|
24181
|
-
irisGradient.addColorStop(0.56, palette.secondary);
|
|
24182
|
-
irisGradient.addColorStop(1, palette.shadow);
|
|
24183
|
-
context.beginPath();
|
|
24184
|
-
context.ellipse(pupilOffsetX, pupilOffsetY, projectedRadiusX * 0.62 * eyeStyle.irisScale, projectedRadiusY * 0.72 * eyeStyle.irisScale, 0, 0, Math.PI * 2);
|
|
24185
|
-
context.fillStyle = irisGradient;
|
|
24186
|
-
context.fill();
|
|
24493
|
+
context.fillStyle = `${palette.shadow}66`;
|
|
24494
|
+
context.filter = `blur(${size * 0.024}px)`;
|
|
24187
24495
|
context.beginPath();
|
|
24188
|
-
context.ellipse(
|
|
24189
|
-
context.fillStyle = palette.ink;
|
|
24496
|
+
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);
|
|
24190
24497
|
context.fill();
|
|
24191
|
-
context.beginPath();
|
|
24192
|
-
context.ellipse(pupilOffsetX - projectedRadiusX * 0.22, pupilOffsetY - projectedRadiusY * 0.24, projectedRadiusX * 0.12, projectedRadiusY * 0.14, 0, 0, Math.PI * 2);
|
|
24193
|
-
context.fillStyle = '#ffffff';
|
|
24194
|
-
context.fill();
|
|
24195
|
-
context.restore();
|
|
24196
|
-
context.save();
|
|
24197
|
-
context.translate(projectedCenterPoint.x, projectedCenterPoint.y);
|
|
24198
|
-
context.rotate(rotation);
|
|
24199
|
-
context.beginPath();
|
|
24200
|
-
context.ellipse(0, 0, projectedRadiusX, projectedRadiusY, 0, 0, Math.PI * 2);
|
|
24201
|
-
context.strokeStyle = `${palette.shadow}cc`;
|
|
24202
|
-
context.lineWidth = projectedRadiusX * 0.16;
|
|
24203
|
-
context.stroke();
|
|
24204
|
-
context.beginPath();
|
|
24205
|
-
context.moveTo(-projectedRadiusX * 0.88, -projectedRadiusY * eyeStyle.upperLidInsetRatio);
|
|
24206
|
-
context.quadraticCurveTo(0, -projectedRadiusY * (eyeStyle.upperLidArchRatio - interaction.gazeY * 0.16 + interaction.intensity * 0.08), projectedRadiusX * 0.88, -projectedRadiusY * eyeStyle.upperLidInsetRatio);
|
|
24207
|
-
context.strokeStyle = `${palette.shadow}73`;
|
|
24208
|
-
context.lineWidth = projectedRadiusX * 0.14;
|
|
24209
|
-
context.lineCap = 'round';
|
|
24210
|
-
context.stroke();
|
|
24211
|
-
if (eyeStyle.lowerLidOpacity > 0) {
|
|
24212
|
-
context.beginPath();
|
|
24213
|
-
context.moveTo(-projectedRadiusX * 0.74, projectedRadiusY * 0.2);
|
|
24214
|
-
context.quadraticCurveTo(0, projectedRadiusY * 0.38, projectedRadiusX * 0.74, projectedRadiusY * 0.2);
|
|
24215
|
-
context.strokeStyle = `${palette.highlight}${formatAlphaHex(eyeStyle.lowerLidOpacity)}`;
|
|
24216
|
-
context.lineWidth = projectedRadiusX * 0.08;
|
|
24217
|
-
context.lineCap = 'round';
|
|
24218
|
-
context.stroke();
|
|
24219
|
-
}
|
|
24220
24498
|
context.restore();
|
|
24221
24499
|
}
|
|
24222
24500
|
/**
|
|
24223
|
-
*
|
|
24501
|
+
* Resolves all visible projected patches for the single blobby octopus mesh.
|
|
24224
24502
|
*
|
|
24225
|
-
* @private helper of `
|
|
24503
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
24226
24504
|
*/
|
|
24227
|
-
function
|
|
24228
|
-
const
|
|
24229
|
-
|
|
24230
|
-
|
|
24505
|
+
function resolveVisibleBlobbyOctopusPatches(options) {
|
|
24506
|
+
const { center, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, morphologyProfile, animationPhase, timeMs, } = options;
|
|
24507
|
+
const latitudePatchCount = 12;
|
|
24508
|
+
const longitudePatchCount = 24;
|
|
24509
|
+
const surfacePatches = [];
|
|
24510
|
+
for (let latitudeIndex = 0; latitudeIndex < latitudePatchCount; latitudeIndex++) {
|
|
24511
|
+
const startLatitude = -Math.PI / 2 + (latitudeIndex / latitudePatchCount) * Math.PI;
|
|
24512
|
+
const endLatitude = -Math.PI / 2 + ((latitudeIndex + 1) / latitudePatchCount) * Math.PI;
|
|
24513
|
+
const centerLatitude = (startLatitude + endLatitude) / 2;
|
|
24514
|
+
const verticalProgress = (Math.sin(centerLatitude) + 1) / 2;
|
|
24515
|
+
for (let longitudeIndex = 0; longitudeIndex < longitudePatchCount; longitudeIndex++) {
|
|
24516
|
+
const startLongitude = -Math.PI + (longitudeIndex / longitudePatchCount) * Math.PI * 2;
|
|
24517
|
+
const endLongitude = -Math.PI + ((longitudeIndex + 1) / longitudePatchCount) * Math.PI * 2;
|
|
24518
|
+
const centerLongitude = (startLongitude + endLongitude) / 2;
|
|
24519
|
+
const localCorners = [
|
|
24520
|
+
sampleBlobbyOctopusSurfacePoint(options, startLatitude, startLongitude),
|
|
24521
|
+
sampleBlobbyOctopusSurfacePoint(options, startLatitude, endLongitude),
|
|
24522
|
+
sampleBlobbyOctopusSurfacePoint(options, endLatitude, endLongitude),
|
|
24523
|
+
sampleBlobbyOctopusSurfacePoint(options, endLatitude, startLongitude),
|
|
24524
|
+
];
|
|
24525
|
+
const transformedCorners = localCorners.map((localCorner) => transformScenePoint(localCorner, center, rotationX, rotationY));
|
|
24526
|
+
const surfaceNormal = normalizeVector3(crossProduct3D(subtractPoint3D(transformedCorners[1], transformedCorners[0]), subtractPoint3D(transformedCorners[2], transformedCorners[0])));
|
|
24527
|
+
if (surfaceNormal.z <= 0.01) {
|
|
24528
|
+
continue;
|
|
24529
|
+
}
|
|
24530
|
+
const projectedCorners = transformedCorners.map((transformedCorner) => projectScenePoint(transformedCorner, size, sceneCenterX, sceneCenterY));
|
|
24531
|
+
surfacePatches.push({
|
|
24532
|
+
corners: projectedCorners,
|
|
24533
|
+
averageDepth: transformedCorners.reduce((depthSum, transformedCorner) => depthSum + transformedCorner.z, 0) /
|
|
24534
|
+
transformedCorners.length,
|
|
24535
|
+
lightIntensity: clampNumber$1(dotProduct3D(surfaceNormal, LIGHT_DIRECTION), -1, 1),
|
|
24536
|
+
fillStyle: resolveBlobbySurfacePatchFillStyle(palette, verticalProgress, Math.max(0, Math.cos(centerLongitude)), resolveLowerLobeWave(centerLongitude, morphologyProfile, animationPhase, timeMs)),
|
|
24537
|
+
outlineColor: verticalProgress < 0.58 ? `${palette.highlight}73` : `${palette.shadow}8a`,
|
|
24538
|
+
});
|
|
24539
|
+
}
|
|
24231
24540
|
}
|
|
24232
|
-
|
|
24233
|
-
context.beginPath();
|
|
24234
|
-
context.moveTo(projectedPoints[0].x, projectedPoints[0].y);
|
|
24235
|
-
context.quadraticCurveTo(projectedPoints[1].x, projectedPoints[1].y, projectedPoints[2].x, projectedPoints[2].y);
|
|
24236
|
-
context.strokeStyle = `${palette.ink}b8`;
|
|
24237
|
-
context.lineWidth = Math.max(1.1, size * 0.009);
|
|
24238
|
-
context.lineCap = 'round';
|
|
24239
|
-
context.stroke();
|
|
24541
|
+
return surfacePatches;
|
|
24240
24542
|
}
|
|
24241
24543
|
/**
|
|
24242
|
-
*
|
|
24544
|
+
* Samples one point on the continuous Octopus 3D 2 surface.
|
|
24545
|
+
*
|
|
24546
|
+
* The lower hemisphere widens and falls into soft lobe waves so the octopus stays one connected mesh
|
|
24547
|
+
* instead of switching to separately rendered tentacles.
|
|
24548
|
+
*
|
|
24549
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
24550
|
+
*/
|
|
24551
|
+
function sampleBlobbyOctopusSurfacePoint(options, latitude, longitude) {
|
|
24552
|
+
const { radiusX, radiusY, radiusZ, morphologyProfile, timeMs, animationPhase } = options;
|
|
24553
|
+
const cosineLatitude = Math.max(0, Math.cos(latitude));
|
|
24554
|
+
const verticalProgress = (Math.sin(latitude) + 1) / 2;
|
|
24555
|
+
const upperBlend = Math.pow(1 - verticalProgress, 1.2);
|
|
24556
|
+
const lowerBlend = Math.pow(verticalProgress, 1.42);
|
|
24557
|
+
const lowerLobeWave = resolveLowerLobeWave(longitude, morphologyProfile, animationPhase, timeMs);
|
|
24558
|
+
const skirtEnvelope = Math.pow(cosineLatitude, 0.5) * lowerBlend;
|
|
24559
|
+
const horizontalScale = 1.02 +
|
|
24560
|
+
skirtEnvelope * (0.34 + (morphologyProfile.tentacles.rootSpreadScale - 1) * 0.22 + lowerLobeWave * 0.22) -
|
|
24561
|
+
upperBlend * 0.08;
|
|
24562
|
+
const depthScale = 1.04 +
|
|
24563
|
+
upperBlend * 0.16 +
|
|
24564
|
+
Math.max(0, Math.cos(longitude)) * 0.1 +
|
|
24565
|
+
skirtEnvelope * (0.08 + lowerLobeWave * 0.06) -
|
|
24566
|
+
Math.max(0, -Math.cos(longitude)) * 0.04;
|
|
24567
|
+
const lowerDrop = skirtEnvelope *
|
|
24568
|
+
radiusY *
|
|
24569
|
+
(0.28 + lowerLobeWave * 0.14 + (morphologyProfile.tentacles.flowLengthScale - 1) * 0.12);
|
|
24570
|
+
const swayX = Math.sin(timeMs / 1250 + longitude * 1.8 + animationPhase) * skirtEnvelope * radiusX * 0.05;
|
|
24571
|
+
const swayZ = Math.cos(timeMs / 1480 + longitude * 1.2 - animationPhase * 0.7) * skirtEnvelope * radiusZ * 0.03;
|
|
24572
|
+
return {
|
|
24573
|
+
x: Math.sin(longitude) * cosineLatitude * radiusX * horizontalScale + swayX,
|
|
24574
|
+
y: Math.sin(latitude) * radiusY * (1 + upperBlend * 0.14) -
|
|
24575
|
+
upperBlend * radiusY * 0.1 +
|
|
24576
|
+
lowerDrop +
|
|
24577
|
+
Math.sin(timeMs / 1780 + animationPhase + latitude * 1.4) * skirtEnvelope * radiusY * 0.02,
|
|
24578
|
+
z: Math.cos(longitude) * cosineLatitude * radiusZ * depthScale + swayZ,
|
|
24579
|
+
};
|
|
24580
|
+
}
|
|
24581
|
+
/**
|
|
24582
|
+
* Resolves the soft lower-lobe wave that makes the silhouette read more like a real octopus.
|
|
24243
24583
|
*
|
|
24244
|
-
* @private helper of `
|
|
24584
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
24245
24585
|
*/
|
|
24246
|
-
function
|
|
24247
|
-
|
|
24248
|
-
|
|
24249
|
-
context.lineTo(corners[1].x, corners[1].y);
|
|
24250
|
-
context.lineTo(corners[2].x, corners[2].y);
|
|
24251
|
-
context.lineTo(corners[3].x, corners[3].y);
|
|
24252
|
-
context.closePath();
|
|
24253
|
-
context.fillStyle = fillStyle;
|
|
24254
|
-
context.fill();
|
|
24586
|
+
function resolveLowerLobeWave(longitude, morphologyProfile, animationPhase, timeMs) {
|
|
24587
|
+
const lobeCount = Math.max(4, Math.round((morphologyProfile.body.lobeCount + morphologyProfile.tentacles.count) / 2));
|
|
24588
|
+
return (Math.cos(longitude * lobeCount + animationPhase + timeMs / 1040) + 1) / 2;
|
|
24255
24589
|
}
|
|
24256
24590
|
/**
|
|
24257
|
-
*
|
|
24591
|
+
* Resolves one base fill tone for a surface patch on the single octopus mesh.
|
|
24258
24592
|
*
|
|
24259
|
-
* @private helper of `
|
|
24593
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
24260
24594
|
*/
|
|
24261
|
-
function
|
|
24262
|
-
|
|
24263
|
-
|
|
24264
|
-
.
|
|
24595
|
+
function resolveBlobbySurfacePatchFillStyle(palette, verticalProgress, forwardness, lowerLobeWave) {
|
|
24596
|
+
const tonalProgress = clampNumber$1(verticalProgress + lowerLobeWave * 0.12 - forwardness * 0.07, 0, 1);
|
|
24597
|
+
if (tonalProgress < 0.16) {
|
|
24598
|
+
return palette.highlight;
|
|
24599
|
+
}
|
|
24600
|
+
if (tonalProgress < 0.34) {
|
|
24601
|
+
return palette.secondary;
|
|
24602
|
+
}
|
|
24603
|
+
if (tonalProgress < 0.72) {
|
|
24604
|
+
return forwardness > 0.58 ? palette.secondary : palette.primary;
|
|
24605
|
+
}
|
|
24606
|
+
return `${palette.shadow}f2`;
|
|
24607
|
+
}
|
|
24608
|
+
/**
|
|
24609
|
+
* Draws one projected patch with soft octopus shading.
|
|
24610
|
+
*
|
|
24611
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
24612
|
+
*/
|
|
24613
|
+
function drawBlobbySurfacePatch(context, surfacePatch) {
|
|
24614
|
+
drawProjectedQuad(context, surfacePatch.corners, surfacePatch.fillStyle);
|
|
24615
|
+
if (surfacePatch.lightIntensity > 0) {
|
|
24616
|
+
drawProjectedQuad(context, surfacePatch.corners, `rgba(255, 255, 255, ${0.16 * surfacePatch.lightIntensity})`);
|
|
24617
|
+
}
|
|
24618
|
+
else if (surfacePatch.lightIntensity < 0) {
|
|
24619
|
+
drawProjectedQuad(context, surfacePatch.corners, `rgba(0, 0, 0, ${0.24 * Math.abs(surfacePatch.lightIntensity)})`);
|
|
24620
|
+
}
|
|
24621
|
+
context.save();
|
|
24622
|
+
context.beginPath();
|
|
24623
|
+
context.moveTo(surfacePatch.corners[0].x, surfacePatch.corners[0].y);
|
|
24624
|
+
for (let cornerIndex = 1; cornerIndex < surfacePatch.corners.length; cornerIndex++) {
|
|
24625
|
+
context.lineTo(surfacePatch.corners[cornerIndex].x, surfacePatch.corners[cornerIndex].y);
|
|
24626
|
+
}
|
|
24627
|
+
context.closePath();
|
|
24628
|
+
context.strokeStyle = surfacePatch.outlineColor;
|
|
24629
|
+
context.lineWidth = Math.max(1, getProjectedQuadPerimeter(surfacePatch.corners) * 0.0042);
|
|
24630
|
+
context.lineJoin = 'round';
|
|
24631
|
+
context.stroke();
|
|
24632
|
+
context.restore();
|
|
24265
24633
|
}
|
|
24266
24634
|
|
|
24267
24635
|
/* eslint-disable no-magic-numbers */
|
|
@@ -25033,6 +25401,7 @@
|
|
|
25033
25401
|
octopus2AvatarVisual,
|
|
25034
25402
|
octopus3AvatarVisual,
|
|
25035
25403
|
octopus3dAvatarVisual,
|
|
25404
|
+
octopus3d2AvatarVisual,
|
|
25036
25405
|
asciiOctopusAvatarVisual,
|
|
25037
25406
|
minecraftAvatarVisual,
|
|
25038
25407
|
minecraft2AvatarVisual,
|
|
@@ -30445,11 +30814,11 @@
|
|
|
30445
30814
|
});
|
|
30446
30815
|
}
|
|
30447
30816
|
/**
|
|
30448
|
-
*
|
|
30817
|
+
* Prepares one attachment for best-effort text decoding.
|
|
30449
30818
|
*
|
|
30450
|
-
* @private
|
|
30819
|
+
* @private function of decodeAttachmentAsText
|
|
30451
30820
|
*/
|
|
30452
|
-
function
|
|
30821
|
+
function createDecodeAttachmentPreparation(input, options) {
|
|
30453
30822
|
var _a;
|
|
30454
30823
|
const maxBytes = Math.max(1, Math.floor((_a = options.maxBytes) !== null && _a !== void 0 ? _a : DEFAULT_ATTACHMENT_TEXT_DECODE_BYTES));
|
|
30455
30824
|
const forceText = options.forceText === true;
|
|
@@ -30463,54 +30832,102 @@
|
|
|
30463
30832
|
const inspection = inspectBytes(truncatedBytes);
|
|
30464
30833
|
const trustedTextMime = isTrustedTextMimeType(mimeType);
|
|
30465
30834
|
const trustedBinaryMime = isTrustedBinaryMimeType(mimeType);
|
|
30835
|
+
const shouldTreatAsBinary = (trustedBinaryMime || inspection.looksBinary) && !trustedTextMime;
|
|
30466
30836
|
if (isTruncated) {
|
|
30467
30837
|
warnings.push(`Decoded only the first ${maxBytes} bytes of \`${input.filename}\` because the attachment exceeded the text preview limit.`);
|
|
30468
30838
|
}
|
|
30469
|
-
|
|
30470
|
-
|
|
30471
|
-
|
|
30472
|
-
|
|
30473
|
-
|
|
30474
|
-
|
|
30475
|
-
|
|
30476
|
-
|
|
30477
|
-
|
|
30478
|
-
|
|
30479
|
-
|
|
30839
|
+
return {
|
|
30840
|
+
warnings,
|
|
30841
|
+
charset,
|
|
30842
|
+
bom,
|
|
30843
|
+
inspection,
|
|
30844
|
+
truncatedBytes,
|
|
30845
|
+
isTruncated,
|
|
30846
|
+
forceText,
|
|
30847
|
+
shouldTreatAsBinary,
|
|
30848
|
+
};
|
|
30849
|
+
}
|
|
30850
|
+
/**
|
|
30851
|
+
* Returns an early result when the attachment should stay classified as binary.
|
|
30852
|
+
*
|
|
30853
|
+
* @private function of decodeAttachmentAsText
|
|
30854
|
+
*/
|
|
30855
|
+
function createBinaryDecodeResult(preparation) {
|
|
30856
|
+
if (!preparation.shouldTreatAsBinary) {
|
|
30857
|
+
return null;
|
|
30480
30858
|
}
|
|
30481
|
-
if (
|
|
30482
|
-
warnings.push('File content looks binary, but text decoding was forced with `forceText`.');
|
|
30859
|
+
if (preparation.forceText) {
|
|
30860
|
+
preparation.warnings.push('File content looks binary, but text decoding was forced with `forceText`.');
|
|
30861
|
+
return null;
|
|
30483
30862
|
}
|
|
30484
|
-
|
|
30485
|
-
|
|
30863
|
+
preparation.warnings.push('File content looks binary, so text decoding was skipped.');
|
|
30864
|
+
return {
|
|
30865
|
+
text: '',
|
|
30866
|
+
encodingUsed: 'binary',
|
|
30867
|
+
confidence: 1,
|
|
30868
|
+
warnings: preparation.warnings,
|
|
30869
|
+
wasBinary: true,
|
|
30870
|
+
isTruncated: preparation.isTruncated,
|
|
30871
|
+
};
|
|
30872
|
+
}
|
|
30873
|
+
/**
|
|
30874
|
+
* Warns when the declared charset cannot be used by the runtime decoder.
|
|
30875
|
+
*
|
|
30876
|
+
* @private function of decodeAttachmentAsText
|
|
30877
|
+
*/
|
|
30878
|
+
function addUnsupportedCharsetWarning(preparation) {
|
|
30879
|
+
if (preparation.charset && !isSupportedEncoding(preparation.charset)) {
|
|
30880
|
+
preparation.warnings.push(`Ignored unsupported declared charset \`${preparation.charset}\` and used best-effort detection instead.`);
|
|
30486
30881
|
}
|
|
30487
|
-
|
|
30488
|
-
|
|
30489
|
-
|
|
30490
|
-
|
|
30491
|
-
|
|
30492
|
-
|
|
30493
|
-
|
|
30494
|
-
|
|
30882
|
+
}
|
|
30883
|
+
/**
|
|
30884
|
+
* Returns the byte slice that should actually be decoded as text.
|
|
30885
|
+
*
|
|
30886
|
+
* @private function of decodeAttachmentAsText
|
|
30887
|
+
*/
|
|
30888
|
+
function getBytesToDecode(preparation) {
|
|
30889
|
+
return preparation.bom ? preparation.truncatedBytes.subarray(preparation.bom.offset) : preparation.truncatedBytes;
|
|
30890
|
+
}
|
|
30891
|
+
/**
|
|
30892
|
+
* Decodes all candidate encodings and sorts the successful results by score.
|
|
30893
|
+
*
|
|
30894
|
+
* @private function of decodeAttachmentAsText
|
|
30895
|
+
*/
|
|
30896
|
+
function decodeAttachmentCandidates(preparation) {
|
|
30897
|
+
return buildCandidateEncodings({
|
|
30898
|
+
charset: preparation.charset && isSupportedEncoding(preparation.charset) ? preparation.charset : null,
|
|
30899
|
+
bom: preparation.bom,
|
|
30900
|
+
inspection: preparation.inspection,
|
|
30901
|
+
})
|
|
30495
30902
|
.map(({ encoding, source }) => {
|
|
30496
|
-
const decoded = decodeWithEncoding(
|
|
30903
|
+
const decoded = decodeWithEncoding(getBytesToDecode(preparation), encoding);
|
|
30497
30904
|
return decoded ? { ...decoded, source } : null;
|
|
30498
30905
|
})
|
|
30499
30906
|
.filter((candidate) => candidate !== null)
|
|
30500
30907
|
.sort((left, right) => left.score - right.score);
|
|
30501
|
-
|
|
30502
|
-
|
|
30503
|
-
|
|
30504
|
-
|
|
30505
|
-
|
|
30506
|
-
|
|
30507
|
-
|
|
30508
|
-
|
|
30509
|
-
|
|
30510
|
-
|
|
30511
|
-
|
|
30512
|
-
|
|
30513
|
-
|
|
30908
|
+
}
|
|
30909
|
+
/**
|
|
30910
|
+
* Returns the fallback result used when no text decoder could be applied.
|
|
30911
|
+
*
|
|
30912
|
+
* @private function of decodeAttachmentAsText
|
|
30913
|
+
*/
|
|
30914
|
+
function createNoDecoderAvailableResult(preparation) {
|
|
30915
|
+
preparation.warnings.push('No supported text decoder was available.');
|
|
30916
|
+
return {
|
|
30917
|
+
text: '',
|
|
30918
|
+
encodingUsed: 'binary',
|
|
30919
|
+
confidence: 0,
|
|
30920
|
+
warnings: preparation.warnings,
|
|
30921
|
+
wasBinary: true,
|
|
30922
|
+
isTruncated: preparation.isTruncated,
|
|
30923
|
+
};
|
|
30924
|
+
}
|
|
30925
|
+
/**
|
|
30926
|
+
* Estimates confidence for the winning decoded text candidate.
|
|
30927
|
+
*
|
|
30928
|
+
* @private function of decodeAttachmentAsText
|
|
30929
|
+
*/
|
|
30930
|
+
function computeDecodeConfidence(bestCandidate, secondBestCandidate, preparation) {
|
|
30514
30931
|
const baseConfidence = bestCandidate.source === 'bom'
|
|
30515
30932
|
? 1
|
|
30516
30933
|
: bestCandidate.source === 'charset'
|
|
@@ -30523,27 +30940,62 @@
|
|
|
30523
30940
|
? 0.82
|
|
30524
30941
|
: 0.62;
|
|
30525
30942
|
const scoreMargin = secondBestCandidate ? Math.max(0, secondBestCandidate.score - bestCandidate.score) : 0.2;
|
|
30526
|
-
|
|
30943
|
+
return Math.max(0.2, Math.min(preparation.shouldTreatAsBinary && preparation.forceText ? 0.45 : 1, baseConfidence + Math.min(0.18, scoreMargin / 2)));
|
|
30944
|
+
}
|
|
30945
|
+
/**
|
|
30946
|
+
* Appends user-facing warnings derived from the chosen decoded text candidate.
|
|
30947
|
+
*
|
|
30948
|
+
* @private function of decodeAttachmentAsText
|
|
30949
|
+
*/
|
|
30950
|
+
function addDecodeWarnings(bestCandidate, confidence, preparation) {
|
|
30527
30951
|
if (bestCandidate.source === 'heuristic' && bestCandidate.encoding !== 'utf-8') {
|
|
30528
|
-
warnings.push(`Encoding was guessed as \`${bestCandidate.encoding}\`.`);
|
|
30952
|
+
preparation.warnings.push(`Encoding was guessed as \`${bestCandidate.encoding}\`.`);
|
|
30529
30953
|
}
|
|
30530
30954
|
if (bestCandidate.source === 'heuristic' &&
|
|
30531
30955
|
bestCandidate.encoding === 'utf-8' &&
|
|
30532
30956
|
bestCandidate.replacementCount > 0) {
|
|
30533
|
-
warnings.push('UTF-8 decoding produced replacement characters, so the extracted text may contain errors.');
|
|
30957
|
+
preparation.warnings.push('UTF-8 decoding produced replacement characters, so the extracted text may contain errors.');
|
|
30534
30958
|
}
|
|
30535
30959
|
if (confidence < 0.6) {
|
|
30536
|
-
warnings.push('Decoding confidence is low, so the extracted text may contain errors.');
|
|
30960
|
+
preparation.warnings.push('Decoding confidence is low, so the extracted text may contain errors.');
|
|
30537
30961
|
}
|
|
30962
|
+
}
|
|
30963
|
+
/**
|
|
30964
|
+
* Creates the final decoded-text result from the chosen candidate and accumulated metadata.
|
|
30965
|
+
*
|
|
30966
|
+
* @private function of decodeAttachmentAsText
|
|
30967
|
+
*/
|
|
30968
|
+
function createDecodedTextResult(bestCandidate, confidence, preparation) {
|
|
30538
30969
|
return {
|
|
30539
|
-
text: isTruncated ? appendTruncatedMarker(bestCandidate.text) : bestCandidate.text,
|
|
30970
|
+
text: preparation.isTruncated ? appendTruncatedMarker(bestCandidate.text) : bestCandidate.text,
|
|
30540
30971
|
encodingUsed: bestCandidate.encoding,
|
|
30541
30972
|
confidence,
|
|
30542
|
-
warnings,
|
|
30973
|
+
warnings: preparation.warnings,
|
|
30543
30974
|
wasBinary: false,
|
|
30544
|
-
isTruncated,
|
|
30975
|
+
isTruncated: preparation.isTruncated,
|
|
30545
30976
|
};
|
|
30546
30977
|
}
|
|
30978
|
+
/**
|
|
30979
|
+
* Best-effort decoder for uploaded or remote file bytes whose extension or encoding may be unknown.
|
|
30980
|
+
*
|
|
30981
|
+
* @private internal utility for shared text decoding
|
|
30982
|
+
*/
|
|
30983
|
+
function decodeAttachmentAsText(input, options = {}) {
|
|
30984
|
+
const preparation = createDecodeAttachmentPreparation(input, options);
|
|
30985
|
+
const binaryResult = createBinaryDecodeResult(preparation);
|
|
30986
|
+
if (binaryResult) {
|
|
30987
|
+
return binaryResult;
|
|
30988
|
+
}
|
|
30989
|
+
addUnsupportedCharsetWarning(preparation);
|
|
30990
|
+
const decodedCandidates = decodeAttachmentCandidates(preparation);
|
|
30991
|
+
const bestCandidate = decodedCandidates[0];
|
|
30992
|
+
if (!bestCandidate) {
|
|
30993
|
+
return createNoDecoderAvailableResult(preparation);
|
|
30994
|
+
}
|
|
30995
|
+
const confidence = computeDecodeConfidence(bestCandidate, decodedCandidates[1], preparation);
|
|
30996
|
+
addDecodeWarnings(bestCandidate, confidence, preparation);
|
|
30997
|
+
return createDecodedTextResult(bestCandidate, confidence, preparation);
|
|
30998
|
+
}
|
|
30547
30999
|
|
|
30548
31000
|
/**
|
|
30549
31001
|
* Base GitHub API URL.
|
|
@@ -39251,10 +39703,7 @@
|
|
|
39251
39703
|
* @private internal function of `$registeredLlmToolsMessage`
|
|
39252
39704
|
*/
|
|
39253
39705
|
function createProviderStatusMessages(llmToolStatus, env) {
|
|
39254
|
-
return [
|
|
39255
|
-
createInstallationStatusMessage(llmToolStatus),
|
|
39256
|
-
createConfigurationStatusMessage(llmToolStatus, env),
|
|
39257
|
-
];
|
|
39706
|
+
return [createInstallationStatusMessage(llmToolStatus), createConfigurationStatusMessage(llmToolStatus, env)];
|
|
39258
39707
|
}
|
|
39259
39708
|
/**
|
|
39260
39709
|
* Creates the installation-status sentence for one provider.
|