@promptbook/remote-server 0.112.0-73 → 0.112.0-80
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/esm/index.es.js
CHANGED
|
@@ -40,7 +40,7 @@ const BOOK_LANGUAGE_VERSION = '2.0.0';
|
|
|
40
40
|
* @generated
|
|
41
41
|
* @see https://github.com/webgptorg/promptbook
|
|
42
42
|
*/
|
|
43
|
-
const PROMPTBOOK_ENGINE_VERSION = '0.112.0-
|
|
43
|
+
const PROMPTBOOK_ENGINE_VERSION = '0.112.0-80';
|
|
44
44
|
/**
|
|
45
45
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
|
46
46
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -290,6 +290,111 @@ function checkChannelValue(channelName, value) {
|
|
|
290
290
|
}
|
|
291
291
|
}
|
|
292
292
|
|
|
293
|
+
/**
|
|
294
|
+
* Shared immutable channel storage and serialization helpers for `Color`.
|
|
295
|
+
*
|
|
296
|
+
* @private base class of Color
|
|
297
|
+
*/
|
|
298
|
+
class ColorValue {
|
|
299
|
+
constructor(red, green, blue, alpha = 255) {
|
|
300
|
+
this.red = red;
|
|
301
|
+
this.green = green;
|
|
302
|
+
this.blue = blue;
|
|
303
|
+
this.alpha = alpha;
|
|
304
|
+
checkChannelValue('Red', red);
|
|
305
|
+
checkChannelValue('Green', green);
|
|
306
|
+
checkChannelValue('Blue', blue);
|
|
307
|
+
checkChannelValue('Alpha', alpha);
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Shortcut for `red` property
|
|
311
|
+
* Number from 0 to 255
|
|
312
|
+
* @alias red
|
|
313
|
+
*/
|
|
314
|
+
get r() {
|
|
315
|
+
return this.red;
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Shortcut for `green` property
|
|
319
|
+
* Number from 0 to 255
|
|
320
|
+
* @alias green
|
|
321
|
+
*/
|
|
322
|
+
get g() {
|
|
323
|
+
return this.green;
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Shortcut for `blue` property
|
|
327
|
+
* Number from 0 to 255
|
|
328
|
+
* @alias blue
|
|
329
|
+
*/
|
|
330
|
+
get b() {
|
|
331
|
+
return this.blue;
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Shortcut for `alpha` property
|
|
335
|
+
* Number from 0 (transparent) to 255 (opaque)
|
|
336
|
+
* @alias alpha
|
|
337
|
+
*/
|
|
338
|
+
get a() {
|
|
339
|
+
return this.alpha;
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* Shortcut for `alpha` property
|
|
343
|
+
* Number from 0 (transparent) to 255 (opaque)
|
|
344
|
+
* @alias alpha
|
|
345
|
+
*/
|
|
346
|
+
get opacity() {
|
|
347
|
+
return this.alpha;
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Shortcut for 1-`alpha` property
|
|
351
|
+
*/
|
|
352
|
+
get transparency() {
|
|
353
|
+
return 255 - this.alpha;
|
|
354
|
+
}
|
|
355
|
+
clone() {
|
|
356
|
+
return take(this.createColor(this.red, this.green, this.blue, this.alpha));
|
|
357
|
+
}
|
|
358
|
+
toString() {
|
|
359
|
+
return this.toHex();
|
|
360
|
+
}
|
|
361
|
+
toHex() {
|
|
362
|
+
if (this.alpha === 255) {
|
|
363
|
+
return `#${this.red.toString(16).padStart(2, '0')}${this.green.toString(16).padStart(2, '0')}${this.blue
|
|
364
|
+
.toString(16)
|
|
365
|
+
.padStart(2, '0')}`;
|
|
366
|
+
}
|
|
367
|
+
else {
|
|
368
|
+
return `#${this.red.toString(16).padStart(2, '0')}${this.green.toString(16).padStart(2, '0')}${this.blue
|
|
369
|
+
.toString(16)
|
|
370
|
+
.padStart(2, '0')}${this.alpha.toString(16).padStart(2, '0')}`;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
toRgb() {
|
|
374
|
+
if (this.alpha === 255) {
|
|
375
|
+
return `rgb(${this.red}, ${this.green}, ${this.blue})`;
|
|
376
|
+
}
|
|
377
|
+
else {
|
|
378
|
+
return `rgba(${this.red}, ${this.green}, ${this.blue}, ${Math.round((this.alpha / 255) * 100)}%)`;
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
toHsl() {
|
|
382
|
+
throw new Error(`Getting HSL is not implemented`);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* Checks if the given value is a valid hex color string
|
|
388
|
+
*
|
|
389
|
+
* @param value - value to check
|
|
390
|
+
* @returns true if the value is a valid hex color string (e.g., `#009edd`, `#fff`, etc.)
|
|
391
|
+
*
|
|
392
|
+
* @private function of Color
|
|
393
|
+
*/
|
|
394
|
+
function isHexColorString(value) {
|
|
395
|
+
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));
|
|
396
|
+
}
|
|
397
|
+
|
|
293
398
|
/**
|
|
294
399
|
* Constant for short hex lengths.
|
|
295
400
|
*/
|
|
@@ -501,16 +606,53 @@ function parseAlphaValue(value) {
|
|
|
501
606
|
|
|
502
607
|
/**
|
|
503
608
|
* Pattern matching hsl regex.
|
|
609
|
+
*
|
|
610
|
+
* @private function of Color
|
|
504
611
|
*/
|
|
505
612
|
const HSL_REGEX_PATTERN = /^hsl\(\s*([0-9.]+)\s*,\s*([0-9.]+)%\s*,\s*([0-9.]+)%\s*\)$/;
|
|
506
613
|
/**
|
|
507
614
|
* Pattern matching RGB regex.
|
|
615
|
+
*
|
|
616
|
+
* @private function of Color
|
|
508
617
|
*/
|
|
509
618
|
const RGB_REGEX_PATTERN = /^rgb\(\s*([0-9.%-]+)\s*,\s*([0-9.%-]+)\s*,\s*([0-9.%-]+)\s*\)$/;
|
|
510
619
|
/**
|
|
511
620
|
* Pattern matching rgba regex.
|
|
621
|
+
*
|
|
622
|
+
* @private function of Color
|
|
512
623
|
*/
|
|
513
624
|
const RGBA_REGEX_PATTERN = /^rgba\(\s*([0-9.%-]+)\s*,\s*([0-9.%-]+)\s*,\s*([0-9.%-]+)\s*,\s*([0-9.%-]+)\s*\)$/;
|
|
625
|
+
/**
|
|
626
|
+
* Parses a supported color string into RGBA channels.
|
|
627
|
+
*
|
|
628
|
+
* @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`,...
|
|
629
|
+
* @returns RGBA channel values.
|
|
630
|
+
*
|
|
631
|
+
* @private function of Color
|
|
632
|
+
*/
|
|
633
|
+
function parseColorString(color) {
|
|
634
|
+
const trimmed = color.trim();
|
|
635
|
+
const cssColor = CSS_COLORS[trimmed];
|
|
636
|
+
if (cssColor) {
|
|
637
|
+
return parseColorString(cssColor);
|
|
638
|
+
}
|
|
639
|
+
else if (isHexColorString(trimmed)) {
|
|
640
|
+
return parseHexColor(trimmed);
|
|
641
|
+
}
|
|
642
|
+
if (HSL_REGEX_PATTERN.test(trimmed)) {
|
|
643
|
+
return parseHslColor(trimmed);
|
|
644
|
+
}
|
|
645
|
+
else if (RGB_REGEX_PATTERN.test(trimmed)) {
|
|
646
|
+
return parseRgbColor(trimmed);
|
|
647
|
+
}
|
|
648
|
+
else if (RGBA_REGEX_PATTERN.test(trimmed)) {
|
|
649
|
+
return parseRgbaColor(trimmed);
|
|
650
|
+
}
|
|
651
|
+
else {
|
|
652
|
+
throw new Error(`Can not create a new Color instance from string "${trimmed}".`);
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
|
|
514
656
|
/**
|
|
515
657
|
* Color object represents an RGB color with alpha channel
|
|
516
658
|
*
|
|
@@ -518,7 +660,7 @@ const RGBA_REGEX_PATTERN = /^rgba\(\s*([0-9.%-]+)\s*,\s*([0-9.%-]+)\s*,\s*([0-9.
|
|
|
518
660
|
*
|
|
519
661
|
* @public exported from `@promptbook/color`
|
|
520
662
|
*/
|
|
521
|
-
class Color {
|
|
663
|
+
class Color extends ColorValue {
|
|
522
664
|
/**
|
|
523
665
|
* Creates a new Color instance from miscellaneous formats
|
|
524
666
|
* - It can receive Color instance and just return the same instance
|
|
@@ -591,25 +733,7 @@ class Color {
|
|
|
591
733
|
* @returns Color object
|
|
592
734
|
*/
|
|
593
735
|
static fromString(color) {
|
|
594
|
-
|
|
595
|
-
if (CSS_COLORS[trimmed]) {
|
|
596
|
-
return Color.fromString(CSS_COLORS[trimmed]);
|
|
597
|
-
}
|
|
598
|
-
else if (Color.isHexColorString(trimmed)) {
|
|
599
|
-
return Color.fromHex(trimmed);
|
|
600
|
-
}
|
|
601
|
-
if (HSL_REGEX_PATTERN.test(trimmed)) {
|
|
602
|
-
return Color.fromHsl(trimmed);
|
|
603
|
-
}
|
|
604
|
-
else if (RGB_REGEX_PATTERN.test(trimmed)) {
|
|
605
|
-
return Color.fromRgbString(trimmed);
|
|
606
|
-
}
|
|
607
|
-
else if (RGBA_REGEX_PATTERN.test(trimmed)) {
|
|
608
|
-
return Color.fromRgbaString(trimmed);
|
|
609
|
-
}
|
|
610
|
-
else {
|
|
611
|
-
throw new Error(`Can not create a new Color instance from string "${trimmed}".`);
|
|
612
|
-
}
|
|
736
|
+
return Color.fromColorChannels(parseColorString(color));
|
|
613
737
|
}
|
|
614
738
|
/**
|
|
615
739
|
* Gets common color
|
|
@@ -639,8 +763,7 @@ class Color {
|
|
|
639
763
|
* @returns Color object
|
|
640
764
|
*/
|
|
641
765
|
static fromHex(hex) {
|
|
642
|
-
|
|
643
|
-
return take(new Color(red, green, blue, alpha));
|
|
766
|
+
return Color.fromColorChannels(parseHexColor(hex));
|
|
644
767
|
}
|
|
645
768
|
/**
|
|
646
769
|
* Creates a new Color instance from color in hsl format
|
|
@@ -649,8 +772,7 @@ class Color {
|
|
|
649
772
|
* @returns Color object
|
|
650
773
|
*/
|
|
651
774
|
static fromHsl(hsl) {
|
|
652
|
-
|
|
653
|
-
return take(new Color(red, green, blue, alpha));
|
|
775
|
+
return Color.fromColorChannels(parseHslColor(hsl));
|
|
654
776
|
}
|
|
655
777
|
/**
|
|
656
778
|
* Creates a new Color instance from color in rgb format
|
|
@@ -659,8 +781,7 @@ class Color {
|
|
|
659
781
|
* @returns Color object
|
|
660
782
|
*/
|
|
661
783
|
static fromRgbString(rgb) {
|
|
662
|
-
|
|
663
|
-
return take(new Color(red, green, blue, alpha));
|
|
784
|
+
return Color.fromColorChannels(parseRgbColor(rgb));
|
|
664
785
|
}
|
|
665
786
|
/**
|
|
666
787
|
* Creates a new Color instance from color in rbga format
|
|
@@ -669,8 +790,7 @@ class Color {
|
|
|
669
790
|
* @returns Color object
|
|
670
791
|
*/
|
|
671
792
|
static fromRgbaString(rgba) {
|
|
672
|
-
|
|
673
|
-
return take(new Color(red, green, blue, alpha));
|
|
793
|
+
return Color.fromColorChannels(parseRgbaColor(rgba));
|
|
674
794
|
}
|
|
675
795
|
/**
|
|
676
796
|
* Creates a new Color for color channels values
|
|
@@ -682,7 +802,7 @@ class Color {
|
|
|
682
802
|
* @returns Color object
|
|
683
803
|
*/
|
|
684
804
|
static fromValues(red, green, blue, alpha = 255) {
|
|
685
|
-
return
|
|
805
|
+
return Color.fromColorChannels({ red, green, blue, alpha });
|
|
686
806
|
}
|
|
687
807
|
/**
|
|
688
808
|
* Checks if the given value is a valid Color object.
|
|
@@ -715,8 +835,7 @@ class Color {
|
|
|
715
835
|
* @returns true if the value is a valid hex color string (e.g., `#009edd`, `#fff`, etc.)
|
|
716
836
|
*/
|
|
717
837
|
static isHexColorString(value) {
|
|
718
|
-
return (
|
|
719
|
-
/^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/.test(value));
|
|
838
|
+
return isHexColorString(value);
|
|
720
839
|
}
|
|
721
840
|
/**
|
|
722
841
|
* Creates new Color object
|
|
@@ -729,89 +848,13 @@ class Color {
|
|
|
729
848
|
* @param alpha number from 0 (transparent) to 255 (opaque)
|
|
730
849
|
*/
|
|
731
850
|
constructor(red, green, blue, alpha = 255) {
|
|
732
|
-
|
|
733
|
-
this.green = green;
|
|
734
|
-
this.blue = blue;
|
|
735
|
-
this.alpha = alpha;
|
|
736
|
-
checkChannelValue('Red', red);
|
|
737
|
-
checkChannelValue('Green', green);
|
|
738
|
-
checkChannelValue('Blue', blue);
|
|
739
|
-
checkChannelValue('Alpha', alpha);
|
|
740
|
-
}
|
|
741
|
-
/**
|
|
742
|
-
* Shortcut for `red` property
|
|
743
|
-
* Number from 0 to 255
|
|
744
|
-
* @alias red
|
|
745
|
-
*/
|
|
746
|
-
get r() {
|
|
747
|
-
return this.red;
|
|
748
|
-
}
|
|
749
|
-
/**
|
|
750
|
-
* Shortcut for `green` property
|
|
751
|
-
* Number from 0 to 255
|
|
752
|
-
* @alias green
|
|
753
|
-
*/
|
|
754
|
-
get g() {
|
|
755
|
-
return this.green;
|
|
756
|
-
}
|
|
757
|
-
/**
|
|
758
|
-
* Shortcut for `blue` property
|
|
759
|
-
* Number from 0 to 255
|
|
760
|
-
* @alias blue
|
|
761
|
-
*/
|
|
762
|
-
get b() {
|
|
763
|
-
return this.blue;
|
|
764
|
-
}
|
|
765
|
-
/**
|
|
766
|
-
* Shortcut for `alpha` property
|
|
767
|
-
* Number from 0 (transparent) to 255 (opaque)
|
|
768
|
-
* @alias alpha
|
|
769
|
-
*/
|
|
770
|
-
get a() {
|
|
771
|
-
return this.alpha;
|
|
772
|
-
}
|
|
773
|
-
/**
|
|
774
|
-
* Shortcut for `alpha` property
|
|
775
|
-
* Number from 0 (transparent) to 255 (opaque)
|
|
776
|
-
* @alias alpha
|
|
777
|
-
*/
|
|
778
|
-
get opacity() {
|
|
779
|
-
return this.alpha;
|
|
780
|
-
}
|
|
781
|
-
/**
|
|
782
|
-
* Shortcut for 1-`alpha` property
|
|
783
|
-
*/
|
|
784
|
-
get transparency() {
|
|
785
|
-
return 255 - this.alpha;
|
|
786
|
-
}
|
|
787
|
-
clone() {
|
|
788
|
-
return take(new Color(this.red, this.green, this.blue, this.alpha));
|
|
789
|
-
}
|
|
790
|
-
toString() {
|
|
791
|
-
return this.toHex();
|
|
792
|
-
}
|
|
793
|
-
toHex() {
|
|
794
|
-
if (this.alpha === 255) {
|
|
795
|
-
return `#${this.red.toString(16).padStart(2, '0')}${this.green.toString(16).padStart(2, '0')}${this.blue
|
|
796
|
-
.toString(16)
|
|
797
|
-
.padStart(2, '0')}`;
|
|
798
|
-
}
|
|
799
|
-
else {
|
|
800
|
-
return `#${this.red.toString(16).padStart(2, '0')}${this.green.toString(16).padStart(2, '0')}${this.blue
|
|
801
|
-
.toString(16)
|
|
802
|
-
.padStart(2, '0')}${this.alpha.toString(16).padStart(2, '0')}`;
|
|
803
|
-
}
|
|
851
|
+
super(red, green, blue, alpha);
|
|
804
852
|
}
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
return `rgb(${this.red}, ${this.green}, ${this.blue})`;
|
|
808
|
-
}
|
|
809
|
-
else {
|
|
810
|
-
return `rgba(${this.red}, ${this.green}, ${this.blue}, ${Math.round((this.alpha / 255) * 100)}%)`;
|
|
811
|
-
}
|
|
853
|
+
createColor(red, green, blue, alpha) {
|
|
854
|
+
return new Color(red, green, blue, alpha);
|
|
812
855
|
}
|
|
813
|
-
|
|
814
|
-
|
|
856
|
+
static fromColorChannels({ red, green, blue, alpha }) {
|
|
857
|
+
return take(new Color(red, green, blue, alpha));
|
|
815
858
|
}
|
|
816
859
|
}
|
|
817
860
|
|
|
@@ -2171,120 +2214,183 @@ function $deepFreeze(objectValue) {
|
|
|
2171
2214
|
* @public exported from `@promptbook/utils`
|
|
2172
2215
|
*/
|
|
2173
2216
|
function checkSerializableAsJson(options) {
|
|
2174
|
-
|
|
2217
|
+
checkSerializableValue(options);
|
|
2218
|
+
}
|
|
2219
|
+
// TODO: Can be return type more type-safe? like `asserts options.value is JsonValue`
|
|
2220
|
+
// TODO: [🧠][main] !!3 In-memory cache of same values to prevent multiple checks
|
|
2221
|
+
// Note: [🐠] This is how `checkSerializableAsJson` + `isSerializableAsJson` together can just retun true/false or rich error message
|
|
2222
|
+
/**
|
|
2223
|
+
* Checks one value and dispatches to the appropriate specialized validator.
|
|
2224
|
+
*
|
|
2225
|
+
* @private function of `checkSerializableAsJson`
|
|
2226
|
+
*/
|
|
2227
|
+
function checkSerializableValue(options) {
|
|
2228
|
+
const { value } = options;
|
|
2229
|
+
if (isSerializablePrimitive(value)) {
|
|
2230
|
+
return;
|
|
2231
|
+
}
|
|
2175
2232
|
if (value === undefined) {
|
|
2176
|
-
throw new UnexpectedError(`${name} is undefined`);
|
|
2233
|
+
throw new UnexpectedError(`${options.name} is undefined`);
|
|
2177
2234
|
}
|
|
2178
|
-
|
|
2179
|
-
|
|
2235
|
+
if (typeof value === 'symbol') {
|
|
2236
|
+
throw new UnexpectedError(`${options.name} is symbol`);
|
|
2180
2237
|
}
|
|
2181
|
-
|
|
2182
|
-
|
|
2238
|
+
if (typeof value === 'function') {
|
|
2239
|
+
throw new UnexpectedError(`${options.name} is function`);
|
|
2183
2240
|
}
|
|
2184
|
-
|
|
2241
|
+
if (Array.isArray(value)) {
|
|
2242
|
+
checkSerializableArray(options, value);
|
|
2185
2243
|
return;
|
|
2186
2244
|
}
|
|
2187
|
-
|
|
2245
|
+
if (value !== null && typeof value === 'object') {
|
|
2246
|
+
checkSerializableObject(options, value);
|
|
2188
2247
|
return;
|
|
2189
2248
|
}
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2249
|
+
throwUnknownTypeError(options);
|
|
2250
|
+
}
|
|
2251
|
+
/**
|
|
2252
|
+
* Checks the primitive values that are directly JSON serializable.
|
|
2253
|
+
*
|
|
2254
|
+
* @private function of `checkSerializableAsJson`
|
|
2255
|
+
*/
|
|
2256
|
+
function isSerializablePrimitive(value) {
|
|
2257
|
+
return (value === null ||
|
|
2258
|
+
typeof value === 'boolean' ||
|
|
2259
|
+
(typeof value === 'number' && !isNaN(value)) ||
|
|
2260
|
+
typeof value === 'string');
|
|
2261
|
+
}
|
|
2262
|
+
/**
|
|
2263
|
+
* Recursively checks JSON array items.
|
|
2264
|
+
*
|
|
2265
|
+
* @private function of `checkSerializableAsJson`
|
|
2266
|
+
*/
|
|
2267
|
+
function checkSerializableArray(context, arrayValue) {
|
|
2268
|
+
for (let index = 0; index < arrayValue.length; index++) {
|
|
2269
|
+
checkSerializableAsJson({
|
|
2270
|
+
...context,
|
|
2271
|
+
name: `${context.name}[${index}]`,
|
|
2272
|
+
value: arrayValue[index],
|
|
2273
|
+
});
|
|
2200
2274
|
}
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2275
|
+
}
|
|
2276
|
+
/**
|
|
2277
|
+
* Checks object-like values and dispatches special unsupported built-ins.
|
|
2278
|
+
*
|
|
2279
|
+
* @private function of `checkSerializableAsJson`
|
|
2280
|
+
*/
|
|
2281
|
+
function checkSerializableObject(context, objectValue) {
|
|
2282
|
+
checkUnsupportedObjectType(context, objectValue);
|
|
2283
|
+
checkSerializableObjectEntries(context, objectValue);
|
|
2284
|
+
assertJsonStringificationSucceeds(context, objectValue);
|
|
2285
|
+
}
|
|
2286
|
+
/**
|
|
2287
|
+
* Rejects built-in objects that must be converted before JSON serialization.
|
|
2288
|
+
*
|
|
2289
|
+
* @private function of `checkSerializableAsJson`
|
|
2290
|
+
*/
|
|
2291
|
+
function checkUnsupportedObjectType(context, objectValue) {
|
|
2292
|
+
if (objectValue instanceof Date) {
|
|
2293
|
+
throw new UnexpectedError(spaceTrim$1((block) => `
|
|
2294
|
+
\`${context.name}\` is Date
|
|
2205
2295
|
|
|
2206
|
-
|
|
2296
|
+
Use \`string_date_iso8601\` instead
|
|
2207
2297
|
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2298
|
+
Additional message for \`${context.name}\`:
|
|
2299
|
+
${block(context.message || '(nothing)')}
|
|
2300
|
+
`));
|
|
2301
|
+
}
|
|
2302
|
+
if (objectValue instanceof Map) {
|
|
2303
|
+
throw new UnexpectedError(`${context.name} is Map`);
|
|
2304
|
+
}
|
|
2305
|
+
if (objectValue instanceof Set) {
|
|
2306
|
+
throw new UnexpectedError(`${context.name} is Set`);
|
|
2307
|
+
}
|
|
2308
|
+
if (objectValue instanceof RegExp) {
|
|
2309
|
+
throw new UnexpectedError(`${context.name} is RegExp`);
|
|
2310
|
+
}
|
|
2311
|
+
if (objectValue instanceof Error) {
|
|
2312
|
+
throw new UnexpectedError(spaceTrim$1((block) => `
|
|
2313
|
+
\`${context.name}\` is unserialized Error
|
|
2224
2314
|
|
|
2225
|
-
|
|
2315
|
+
Use function \`serializeError\`
|
|
2226
2316
|
|
|
2227
|
-
|
|
2228
|
-
|
|
2317
|
+
Additional message for \`${context.name}\`:
|
|
2318
|
+
${block(context.message || '(nothing)')}
|
|
2229
2319
|
|
|
2230
|
-
|
|
2320
|
+
`));
|
|
2321
|
+
}
|
|
2322
|
+
}
|
|
2323
|
+
/**
|
|
2324
|
+
* Recursively checks object properties while preserving omitted `undefined` keys.
|
|
2325
|
+
*
|
|
2326
|
+
* @private function of `checkSerializableAsJson`
|
|
2327
|
+
*/
|
|
2328
|
+
function checkSerializableObjectEntries(context, objectValue) {
|
|
2329
|
+
for (const [subName, subValue] of Object.entries(objectValue)) {
|
|
2330
|
+
if (subValue === undefined) {
|
|
2331
|
+
// Note: undefined in object is serializable - it is just omitted
|
|
2332
|
+
continue;
|
|
2231
2333
|
}
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2334
|
+
checkSerializableAsJson({
|
|
2335
|
+
...context,
|
|
2336
|
+
name: `${context.name}.${subName}`,
|
|
2337
|
+
value: subValue,
|
|
2338
|
+
});
|
|
2339
|
+
}
|
|
2340
|
+
}
|
|
2341
|
+
/**
|
|
2342
|
+
* Uses `JSON.stringify` as the final guard for cases like circular references.
|
|
2343
|
+
*
|
|
2344
|
+
* @private function of `checkSerializableAsJson`
|
|
2345
|
+
*/
|
|
2346
|
+
function assertJsonStringificationSucceeds(context, objectValue) {
|
|
2347
|
+
try {
|
|
2348
|
+
JSON.stringify(objectValue); // <- TODO: [0]
|
|
2349
|
+
}
|
|
2350
|
+
catch (error) {
|
|
2351
|
+
assertsError(error);
|
|
2352
|
+
throw new UnexpectedError(spaceTrim$1((block) => `
|
|
2353
|
+
\`${context.name}\` is not serializable
|
|
2247
2354
|
|
|
2248
|
-
|
|
2355
|
+
${block(error.stack || error.message)}
|
|
2249
2356
|
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2357
|
+
Additional message for \`${context.name}\`:
|
|
2358
|
+
${block(context.message || '(nothing)')}
|
|
2359
|
+
`));
|
|
2360
|
+
}
|
|
2361
|
+
/*
|
|
2362
|
+
TODO: [0] Is there some more elegant way to check circular references?
|
|
2363
|
+
const seen = new Set();
|
|
2364
|
+
const stack = [{ value }];
|
|
2365
|
+
while (stack.length > 0) {
|
|
2366
|
+
const { value } = stack.pop()!;
|
|
2367
|
+
if (typeof value === 'object' && value !== null) {
|
|
2368
|
+
if (seen.has(value)) {
|
|
2369
|
+
throw new UnexpectedError(`${name} has circular reference`);
|
|
2253
2370
|
}
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
const { value } = stack.pop()!;
|
|
2260
|
-
if (typeof value === 'object' && value !== null) {
|
|
2261
|
-
if (seen.has(value)) {
|
|
2262
|
-
throw new UnexpectedError(`${name} has circular reference`);
|
|
2263
|
-
}
|
|
2264
|
-
seen.add(value);
|
|
2265
|
-
if (Array.isArray(value)) {
|
|
2266
|
-
stack.push(...value.map((value) => ({ value })));
|
|
2267
|
-
} else {
|
|
2268
|
-
stack.push(...Object.values(value).map((value) => ({ value })));
|
|
2269
|
-
}
|
|
2270
|
-
}
|
|
2371
|
+
seen.add(value);
|
|
2372
|
+
if (Array.isArray(value)) {
|
|
2373
|
+
stack.push(...value.map((value) => ({ value })));
|
|
2374
|
+
} else {
|
|
2375
|
+
stack.push(...Object.values(value).map((value) => ({ value })));
|
|
2271
2376
|
}
|
|
2272
|
-
*/
|
|
2273
|
-
return;
|
|
2274
2377
|
}
|
|
2275
2378
|
}
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2379
|
+
*/
|
|
2380
|
+
}
|
|
2381
|
+
/**
|
|
2382
|
+
* Throws the fallback error for unsupported value types like `bigint` and `NaN`.
|
|
2383
|
+
*
|
|
2384
|
+
* @private function of `checkSerializableAsJson`
|
|
2385
|
+
*/
|
|
2386
|
+
function throwUnknownTypeError(context) {
|
|
2387
|
+
throw new UnexpectedError(spaceTrim$1((block) => `
|
|
2388
|
+
\`${context.name}\` is unknown type
|
|
2279
2389
|
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
}
|
|
2390
|
+
Additional message for \`${context.name}\`:
|
|
2391
|
+
${block(context.message || '(nothing)')}
|
|
2392
|
+
`));
|
|
2284
2393
|
}
|
|
2285
|
-
// TODO: Can be return type more type-safe? like `asserts options.value is JsonValue`
|
|
2286
|
-
// TODO: [🧠][main] !!3 In-memory cache of same values to prevent multiple checks
|
|
2287
|
-
// Note: [🐠] This is how `checkSerializableAsJson` + `isSerializableAsJson` together can just retun true/false or rich error message
|
|
2288
2394
|
|
|
2289
2395
|
/**
|
|
2290
2396
|
* Creates a deep clone of the given object
|
|
@@ -2917,8 +3023,7 @@ function hasTaskJokers(task) {
|
|
|
2917
3023
|
* @private internal utility of `validatePipeline`
|
|
2918
3024
|
*/
|
|
2919
3025
|
function validateTaskSupportsJokers(task, pipelineIdentification) {
|
|
2920
|
-
if (task.format ||
|
|
2921
|
-
task.expectations /* <- TODO: Require at least 1 -> min <- expectation to use jokers */) {
|
|
3026
|
+
if (task.format || task.expectations /* <- TODO: Require at least 1 -> min <- expectation to use jokers */) {
|
|
2922
3027
|
return;
|
|
2923
3028
|
}
|
|
2924
3029
|
throw new PipelineLogicError(spaceTrim$1((block) => `
|
|
@@ -4035,7 +4140,7 @@ function createJokerCommands(task) {
|
|
|
4035
4140
|
*/
|
|
4036
4141
|
function createPostprocessingCommands(task) {
|
|
4037
4142
|
var _a;
|
|
4038
|
-
return ((_a = task.postprocessingFunctionNames) === null || _a === void 0 ? void 0 : _a.map((postprocessingFunctionName) => `POSTPROCESSING \`${postprocessingFunctionName}\``)) || [];
|
|
4143
|
+
return (((_a = task.postprocessingFunctionNames) === null || _a === void 0 ? void 0 : _a.map((postprocessingFunctionName) => `POSTPROCESSING \`${postprocessingFunctionName}\``)) || []);
|
|
4039
4144
|
}
|
|
4040
4145
|
/**
|
|
4041
4146
|
* Collects expectation commands.
|
|
@@ -7466,9 +7571,7 @@ function createFailuresSummary($failedResults) {
|
|
|
7466
7571
|
${block(quoteMultilineText(((_b = failure.error) === null || _b === void 0 ? void 0 : _b.message) || ''))}
|
|
7467
7572
|
|
|
7468
7573
|
Result:
|
|
7469
|
-
${block(failure.result === null
|
|
7470
|
-
? 'null'
|
|
7471
|
-
: quoteMultilineText(spaceTrim$1(failure.result)))}
|
|
7574
|
+
${block(failure.result === null ? 'null' : quoteMultilineText(spaceTrim$1(failure.result)))}
|
|
7472
7575
|
`;
|
|
7473
7576
|
}))
|
|
7474
7577
|
.join('\n\n---\n\n');
|
|
@@ -9050,10 +9153,7 @@ function createAvailableProviderMessage(llmToolStatus, index, env) {
|
|
|
9050
9153
|
* @private internal function of `$registeredLlmToolsMessage`
|
|
9051
9154
|
*/
|
|
9052
9155
|
function createProviderStatusMessages(llmToolStatus, env) {
|
|
9053
|
-
return [
|
|
9054
|
-
createInstallationStatusMessage(llmToolStatus),
|
|
9055
|
-
createConfigurationStatusMessage(llmToolStatus, env),
|
|
9056
|
-
];
|
|
9156
|
+
return [createInstallationStatusMessage(llmToolStatus), createConfigurationStatusMessage(llmToolStatus, env)];
|
|
9057
9157
|
}
|
|
9058
9158
|
/**
|
|
9059
9159
|
* Creates the installation-status sentence for one provider.
|
|
@@ -14616,7 +14716,7 @@ function fillTextureRect(texture, x, y, width, height, color) {
|
|
|
14616
14716
|
*
|
|
14617
14717
|
* @private helper of `minecraft2AvatarVisual`
|
|
14618
14718
|
*/
|
|
14619
|
-
const LIGHT_DIRECTION$
|
|
14719
|
+
const LIGHT_DIRECTION$2 = normalizeVector3({
|
|
14620
14720
|
x: 0.4,
|
|
14621
14721
|
y: -0.65,
|
|
14622
14722
|
z: 0.92,
|
|
@@ -14828,7 +14928,7 @@ function resolveVisibleCuboidFaces(cuboid, size, sceneCenterX, sceneCenterY) {
|
|
|
14828
14928
|
corners: projectedCorners,
|
|
14829
14929
|
texture: faceDefinition.texture,
|
|
14830
14930
|
averageDepth: transformedCorners.reduce((depthSum, corner) => depthSum + corner.z, 0) / transformedCorners.length,
|
|
14831
|
-
lightIntensity: clampNumber$1(dotProduct3D(faceNormal, LIGHT_DIRECTION$
|
|
14931
|
+
lightIntensity: clampNumber$1(dotProduct3D(faceNormal, LIGHT_DIRECTION$2), -1, 1),
|
|
14832
14932
|
outlineColor: cuboid.outlineColor,
|
|
14833
14933
|
};
|
|
14834
14934
|
});
|
|
@@ -15888,13 +15988,138 @@ function drawSeededEye(context, centerX, centerY, radiusX, radiusY, rotation, pa
|
|
|
15888
15988
|
context.restore();
|
|
15889
15989
|
}
|
|
15890
15990
|
|
|
15991
|
+
/* eslint-disable no-magic-numbers */
|
|
15992
|
+
/**
|
|
15993
|
+
* Draws one projected eye on a rotated octopus surface.
|
|
15994
|
+
*
|
|
15995
|
+
* @private helper of the 3D octopus avatar visuals
|
|
15996
|
+
*/
|
|
15997
|
+
function drawProjectedOrganicEye(context, localCenter, radiusX, radiusY, center, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, phase, interaction, eyeStyle) {
|
|
15998
|
+
const centerScenePoint = transformScenePoint(localCenter, center, rotationX, rotationY);
|
|
15999
|
+
if (centerScenePoint.z <= center.z) {
|
|
16000
|
+
return;
|
|
16001
|
+
}
|
|
16002
|
+
const horizontalScenePoint = transformScenePoint({ x: localCenter.x + radiusX, y: localCenter.y, z: localCenter.z }, center, rotationX, rotationY);
|
|
16003
|
+
const verticalScenePoint = transformScenePoint({ x: localCenter.x, y: localCenter.y + radiusY, z: localCenter.z }, center, rotationX, rotationY);
|
|
16004
|
+
const projectedCenterPoint = projectScenePoint(centerScenePoint, size, sceneCenterX, sceneCenterY);
|
|
16005
|
+
const projectedHorizontalPoint = projectScenePoint(horizontalScenePoint, size, sceneCenterX, sceneCenterY);
|
|
16006
|
+
const projectedVerticalPoint = projectScenePoint(verticalScenePoint, size, sceneCenterX, sceneCenterY);
|
|
16007
|
+
const projectedRadiusX = Math.hypot(projectedHorizontalPoint.x - projectedCenterPoint.x, projectedHorizontalPoint.y - projectedCenterPoint.y);
|
|
16008
|
+
const projectedRadiusY = Math.hypot(projectedVerticalPoint.x - projectedCenterPoint.x, projectedVerticalPoint.y - projectedCenterPoint.y);
|
|
16009
|
+
if (projectedRadiusX < size * 0.008 || projectedRadiusY < size * 0.008) {
|
|
16010
|
+
return;
|
|
16011
|
+
}
|
|
16012
|
+
const { pupilOffsetX, pupilOffsetY } = resolveOrganicEyeMotion({
|
|
16013
|
+
radiusX: projectedRadiusX,
|
|
16014
|
+
radiusY: projectedRadiusY,
|
|
16015
|
+
timeMs,
|
|
16016
|
+
phase,
|
|
16017
|
+
interaction,
|
|
16018
|
+
});
|
|
16019
|
+
const rotation = Math.atan2(projectedHorizontalPoint.y - projectedCenterPoint.y, projectedHorizontalPoint.x - projectedCenterPoint.x);
|
|
16020
|
+
context.save();
|
|
16021
|
+
context.translate(projectedCenterPoint.x, projectedCenterPoint.y);
|
|
16022
|
+
context.rotate(rotation);
|
|
16023
|
+
context.beginPath();
|
|
16024
|
+
context.ellipse(0, 0, projectedRadiusX, projectedRadiusY, 0, 0, Math.PI * 2);
|
|
16025
|
+
context.fillStyle = '#f8fbff';
|
|
16026
|
+
context.fill();
|
|
16027
|
+
context.clip();
|
|
16028
|
+
const irisGradient = context.createRadialGradient(-projectedRadiusX * 0.2, -projectedRadiusY * 0.26, projectedRadiusX * 0.05, 0, 0, projectedRadiusX * 0.92);
|
|
16029
|
+
irisGradient.addColorStop(0, palette.highlight);
|
|
16030
|
+
irisGradient.addColorStop(0.56, palette.secondary);
|
|
16031
|
+
irisGradient.addColorStop(1, palette.shadow);
|
|
16032
|
+
context.beginPath();
|
|
16033
|
+
context.ellipse(pupilOffsetX, pupilOffsetY, projectedRadiusX * 0.62 * eyeStyle.irisScale, projectedRadiusY * 0.72 * eyeStyle.irisScale, 0, 0, Math.PI * 2);
|
|
16034
|
+
context.fillStyle = irisGradient;
|
|
16035
|
+
context.fill();
|
|
16036
|
+
context.beginPath();
|
|
16037
|
+
context.ellipse(pupilOffsetX, pupilOffsetY, projectedRadiusX * 0.15 * eyeStyle.pupilWidthScale, projectedRadiusY * 0.48 * eyeStyle.pupilHeightScale, 0, 0, Math.PI * 2);
|
|
16038
|
+
context.fillStyle = palette.ink;
|
|
16039
|
+
context.fill();
|
|
16040
|
+
context.beginPath();
|
|
16041
|
+
context.ellipse(pupilOffsetX - projectedRadiusX * 0.22, pupilOffsetY - projectedRadiusY * 0.24, projectedRadiusX * 0.12, projectedRadiusY * 0.14, 0, 0, Math.PI * 2);
|
|
16042
|
+
context.fillStyle = '#ffffff';
|
|
16043
|
+
context.fill();
|
|
16044
|
+
context.restore();
|
|
16045
|
+
context.save();
|
|
16046
|
+
context.translate(projectedCenterPoint.x, projectedCenterPoint.y);
|
|
16047
|
+
context.rotate(rotation);
|
|
16048
|
+
context.beginPath();
|
|
16049
|
+
context.ellipse(0, 0, projectedRadiusX, projectedRadiusY, 0, 0, Math.PI * 2);
|
|
16050
|
+
context.strokeStyle = `${palette.shadow}cc`;
|
|
16051
|
+
context.lineWidth = projectedRadiusX * 0.16;
|
|
16052
|
+
context.stroke();
|
|
16053
|
+
context.beginPath();
|
|
16054
|
+
context.moveTo(-projectedRadiusX * 0.88, -projectedRadiusY * eyeStyle.upperLidInsetRatio);
|
|
16055
|
+
context.quadraticCurveTo(0, -projectedRadiusY * (eyeStyle.upperLidArchRatio - interaction.gazeY * 0.16 + interaction.intensity * 0.08), projectedRadiusX * 0.88, -projectedRadiusY * eyeStyle.upperLidInsetRatio);
|
|
16056
|
+
context.strokeStyle = `${palette.shadow}73`;
|
|
16057
|
+
context.lineWidth = projectedRadiusX * 0.14;
|
|
16058
|
+
context.lineCap = 'round';
|
|
16059
|
+
context.stroke();
|
|
16060
|
+
if (eyeStyle.lowerLidOpacity > 0) {
|
|
16061
|
+
context.beginPath();
|
|
16062
|
+
context.moveTo(-projectedRadiusX * 0.74, projectedRadiusY * 0.2);
|
|
16063
|
+
context.quadraticCurveTo(0, projectedRadiusY * 0.38, projectedRadiusX * 0.74, projectedRadiusY * 0.2);
|
|
16064
|
+
context.strokeStyle = `${palette.highlight}${formatAlphaHex(eyeStyle.lowerLidOpacity)}`;
|
|
16065
|
+
context.lineWidth = projectedRadiusX * 0.08;
|
|
16066
|
+
context.lineCap = 'round';
|
|
16067
|
+
context.stroke();
|
|
16068
|
+
}
|
|
16069
|
+
context.restore();
|
|
16070
|
+
}
|
|
16071
|
+
/**
|
|
16072
|
+
* Draws a subtle projected mouth arc across the front of a rotated octopus surface.
|
|
16073
|
+
*
|
|
16074
|
+
* @private helper of the 3D octopus avatar visuals
|
|
16075
|
+
*/
|
|
16076
|
+
function drawProjectedOrganicMouth(context, localPoints, center, rotationX, rotationY, sceneCenterX, sceneCenterY, palette, size) {
|
|
16077
|
+
const scenePoints = localPoints.map((localPoint) => transformScenePoint(localPoint, center, rotationX, rotationY));
|
|
16078
|
+
if (scenePoints.some((scenePoint) => scenePoint.z <= center.z)) {
|
|
16079
|
+
return;
|
|
16080
|
+
}
|
|
16081
|
+
const projectedPoints = scenePoints.map((scenePoint) => projectScenePoint(scenePoint, size, sceneCenterX, sceneCenterY));
|
|
16082
|
+
context.beginPath();
|
|
16083
|
+
context.moveTo(projectedPoints[0].x, projectedPoints[0].y);
|
|
16084
|
+
context.quadraticCurveTo(projectedPoints[1].x, projectedPoints[1].y, projectedPoints[2].x, projectedPoints[2].y);
|
|
16085
|
+
context.strokeStyle = `${palette.ink}b8`;
|
|
16086
|
+
context.lineWidth = Math.max(1.1, size * 0.009);
|
|
16087
|
+
context.lineCap = 'round';
|
|
16088
|
+
context.stroke();
|
|
16089
|
+
}
|
|
16090
|
+
/**
|
|
16091
|
+
* Draws one filled projected quad.
|
|
16092
|
+
*
|
|
16093
|
+
* @private helper of the 3D octopus avatar visuals
|
|
16094
|
+
*/
|
|
16095
|
+
function drawProjectedQuad(context, corners, fillStyle) {
|
|
16096
|
+
context.beginPath();
|
|
16097
|
+
context.moveTo(corners[0].x, corners[0].y);
|
|
16098
|
+
context.lineTo(corners[1].x, corners[1].y);
|
|
16099
|
+
context.lineTo(corners[2].x, corners[2].y);
|
|
16100
|
+
context.lineTo(corners[3].x, corners[3].y);
|
|
16101
|
+
context.closePath();
|
|
16102
|
+
context.fillStyle = fillStyle;
|
|
16103
|
+
context.fill();
|
|
16104
|
+
}
|
|
16105
|
+
/**
|
|
16106
|
+
* Converts an opacity ratio into a two-digit hexadecimal alpha suffix.
|
|
16107
|
+
*
|
|
16108
|
+
* @private helper of the 3D octopus avatar visuals
|
|
16109
|
+
*/
|
|
16110
|
+
function formatAlphaHex(opacity) {
|
|
16111
|
+
return Math.round(clampNumber$1(opacity, 0, 1) * 255)
|
|
16112
|
+
.toString(16)
|
|
16113
|
+
.padStart(2, '0');
|
|
16114
|
+
}
|
|
16115
|
+
|
|
15891
16116
|
/* eslint-disable no-magic-numbers */
|
|
15892
16117
|
/**
|
|
15893
16118
|
* Light direction used by the organic 3D octopus shading.
|
|
15894
16119
|
*
|
|
15895
16120
|
* @private helper of `octopus3dAvatarVisual`
|
|
15896
16121
|
*/
|
|
15897
|
-
const LIGHT_DIRECTION = normalizeVector3({
|
|
16122
|
+
const LIGHT_DIRECTION$1 = normalizeVector3({
|
|
15898
16123
|
x: 0.48,
|
|
15899
16124
|
y: -0.62,
|
|
15900
16125
|
z: 0.94,
|
|
@@ -16007,17 +16232,17 @@ const octopus3dAvatarVisual = {
|
|
|
16007
16232
|
for (const tentacleStroke of tentacleStrokes.filter((candidateTentacleStroke) => candidateTentacleStroke.isFrontFacing)) {
|
|
16008
16233
|
drawTentacleStroke(context, tentacleStroke, palette);
|
|
16009
16234
|
}
|
|
16010
|
-
|
|
16235
|
+
drawProjectedOrganicEye(context, {
|
|
16011
16236
|
x: -faceEyeSpacing,
|
|
16012
16237
|
y: faceEyeYOffset,
|
|
16013
16238
|
z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, -faceEyeSpacing, faceEyeYOffset),
|
|
16014
16239
|
}, faceEyeRadiusX, faceEyeRadiusY, mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + eyeRandom() * 0.6, interaction, morphologyProfile.face.eyeStyle);
|
|
16015
|
-
|
|
16240
|
+
drawProjectedOrganicEye(context, {
|
|
16016
16241
|
x: faceEyeSpacing,
|
|
16017
16242
|
y: faceEyeYOffset,
|
|
16018
16243
|
z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, faceEyeSpacing, faceEyeYOffset),
|
|
16019
16244
|
}, faceEyeRadiusX, faceEyeRadiusY, mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + 0.7 + eyeRandom() * 0.6, interaction, morphologyProfile.face.eyeStyle);
|
|
16020
|
-
|
|
16245
|
+
drawProjectedOrganicMouth(context, [
|
|
16021
16246
|
{
|
|
16022
16247
|
x: -mouthHalfWidth,
|
|
16023
16248
|
y: mouthY,
|
|
@@ -16104,7 +16329,7 @@ function resolveVisibleEllipsoidPatches(options) {
|
|
|
16104
16329
|
corners: projectedCorners,
|
|
16105
16330
|
averageDepth: transformedCorners.reduce((depthSum, transformedCorner) => depthSum + transformedCorner.z, 0) /
|
|
16106
16331
|
transformedCorners.length,
|
|
16107
|
-
lightIntensity: clampNumber$1(dotProduct3D(surfaceNormal, LIGHT_DIRECTION), -1, 1),
|
|
16332
|
+
lightIntensity: clampNumber$1(dotProduct3D(surfaceNormal, LIGHT_DIRECTION$1), -1, 1),
|
|
16108
16333
|
fillStyle: resolveSurfacePatchFillStyle(palette, verticalProgress + verticalColorBias),
|
|
16109
16334
|
outlineColor,
|
|
16110
16335
|
});
|
|
@@ -16286,128 +16511,260 @@ function resolveEllipsoidSurfaceDepth(radiusX, radiusY, radiusZ, x, y) {
|
|
|
16286
16511
|
const remainingDepthRatio = Math.max(0, 1 - normalizedX * normalizedX - normalizedY * normalizedY);
|
|
16287
16512
|
return Math.sqrt(remainingDepthRatio) * radiusZ;
|
|
16288
16513
|
}
|
|
16514
|
+
|
|
16515
|
+
/* eslint-disable no-magic-numbers */
|
|
16289
16516
|
/**
|
|
16290
|
-
*
|
|
16517
|
+
* Light direction used by the single-mesh octopus shading.
|
|
16291
16518
|
*
|
|
16292
|
-
* @private helper of `
|
|
16519
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
16293
16520
|
*/
|
|
16294
|
-
|
|
16295
|
-
|
|
16296
|
-
|
|
16297
|
-
|
|
16298
|
-
|
|
16299
|
-
|
|
16300
|
-
|
|
16301
|
-
|
|
16302
|
-
|
|
16303
|
-
|
|
16304
|
-
|
|
16305
|
-
|
|
16306
|
-
|
|
16307
|
-
|
|
16308
|
-
|
|
16309
|
-
|
|
16310
|
-
|
|
16311
|
-
|
|
16312
|
-
|
|
16313
|
-
|
|
16314
|
-
|
|
16315
|
-
|
|
16316
|
-
|
|
16521
|
+
const LIGHT_DIRECTION = normalizeVector3({
|
|
16522
|
+
x: 0.38,
|
|
16523
|
+
y: -0.6,
|
|
16524
|
+
z: 0.98,
|
|
16525
|
+
});
|
|
16526
|
+
/**
|
|
16527
|
+
* Octopus 3D 2 avatar visual.
|
|
16528
|
+
*
|
|
16529
|
+
* @private built-in avatar visual
|
|
16530
|
+
*/
|
|
16531
|
+
const octopus3d2AvatarVisual = {
|
|
16532
|
+
id: 'octopus3d2',
|
|
16533
|
+
title: 'Octopus 3D 2',
|
|
16534
|
+
description: 'Continuous blobby 3D octopus portrait with one soft mesh, turning silhouette, and cursor-aware eyes.',
|
|
16535
|
+
isAnimated: true,
|
|
16536
|
+
supportsPointerTracking: true,
|
|
16537
|
+
render({ context, size, palette, createRandom, timeMs, interaction }) {
|
|
16538
|
+
const morphologyProfile = createOctopus3MorphologyProfile(createRandom);
|
|
16539
|
+
const animationRandom = createRandom('octopus3d2-animation-profile');
|
|
16540
|
+
const eyeRandom = createRandom('octopus3d2-eye-profile');
|
|
16541
|
+
const animationPhase = animationRandom() * Math.PI * 2;
|
|
16542
|
+
const sceneCenterX = size * 0.5;
|
|
16543
|
+
const sceneCenterY = size * 0.575;
|
|
16544
|
+
const bob = Math.sin(timeMs / 940 + animationPhase) * size * 0.013;
|
|
16545
|
+
const meshCenter = {
|
|
16546
|
+
x: interaction.bodyOffsetX * size * 0.044 + size * morphologyProfile.body.centerXJitterRatio * 0.5,
|
|
16547
|
+
y: -size * 0.03 + interaction.bodyOffsetY * size * 0.026 + bob,
|
|
16548
|
+
z: interaction.intensity * size * 0.018,
|
|
16549
|
+
};
|
|
16550
|
+
const rotationY = -0.14 +
|
|
16551
|
+
Math.sin(timeMs / 2600 + animationPhase) * 0.04 +
|
|
16552
|
+
interaction.bodyOffsetX * 0.2 +
|
|
16553
|
+
interaction.gazeX * 0.78;
|
|
16554
|
+
const rotationX = -0.06 +
|
|
16555
|
+
Math.cos(timeMs / 3000 + animationPhase * 0.7) * 0.02 -
|
|
16556
|
+
interaction.bodyOffsetY * 0.08 -
|
|
16557
|
+
interaction.gazeY * 0.34;
|
|
16558
|
+
const surfaceOptions = {
|
|
16559
|
+
radiusX: size * morphologyProfile.body.bodyRadiusRatio * morphologyProfile.body.horizontalStretch * 1.02,
|
|
16560
|
+
radiusY: size * morphologyProfile.body.bodyRadiusRatio * morphologyProfile.body.verticalStretch * 1.22,
|
|
16561
|
+
radiusZ: size *
|
|
16562
|
+
morphologyProfile.body.bodyRadiusRatio *
|
|
16563
|
+
(0.98 + (morphologyProfile.body.horizontalStretch - 1) * 0.2),
|
|
16564
|
+
morphologyProfile,
|
|
16565
|
+
timeMs,
|
|
16566
|
+
animationPhase,
|
|
16567
|
+
};
|
|
16568
|
+
const surfacePatches = resolveVisibleBlobbyOctopusPatches({
|
|
16569
|
+
...surfaceOptions,
|
|
16570
|
+
center: meshCenter,
|
|
16571
|
+
rotationX,
|
|
16572
|
+
rotationY,
|
|
16573
|
+
sceneCenterX,
|
|
16574
|
+
sceneCenterY,
|
|
16575
|
+
size,
|
|
16576
|
+
palette,
|
|
16577
|
+
});
|
|
16578
|
+
const eyeLatitude = clampNumber$1(morphologyProfile.face.eyeCenterYOffsetRatio * 4.4, -0.16, 0.11);
|
|
16579
|
+
const eyeLongitude = clampNumber$1(morphologyProfile.face.eyeSpacingRatio * 3.25, 0.2, 0.34);
|
|
16580
|
+
const mouthLatitude = clampNumber$1(eyeLatitude + 0.19 + morphologyProfile.face.mouthYOffsetRatio * 1.08, 0.08, 0.34);
|
|
16581
|
+
const mouthCenterLongitude = clampNumber$1(morphologyProfile.face.mouthCenterOffsetRatio * 5.8, -0.08, 0.08);
|
|
16582
|
+
const mouthHalfLongitude = clampNumber$1(eyeLongitude * 0.82, 0.16, 0.29);
|
|
16583
|
+
const mouthCurveLatitude = clampNumber$1(mouthLatitude + morphologyProfile.face.mouthCurveDepthRatio * 0.85, mouthLatitude + 0.03, 0.42);
|
|
16584
|
+
drawAvatarFrame(context, size, palette);
|
|
16585
|
+
drawBlobbyOctopusAtmosphere(context, size, palette, sceneCenterX, sceneCenterY, interaction, timeMs);
|
|
16586
|
+
drawBlobbyOctopusShadow(context, size, palette, interaction, timeMs, morphologyProfile);
|
|
16587
|
+
for (const surfacePatch of surfacePatches.sort((firstSurfacePatch, secondSurfacePatch) => firstSurfacePatch.averageDepth - secondSurfacePatch.averageDepth)) {
|
|
16588
|
+
drawBlobbySurfacePatch(context, surfacePatch);
|
|
16589
|
+
}
|
|
16590
|
+
const leftEyeLocalCenter = sampleBlobbyOctopusSurfacePoint(surfaceOptions, eyeLatitude, -eyeLongitude);
|
|
16591
|
+
const rightEyeLocalCenter = sampleBlobbyOctopusSurfacePoint(surfaceOptions, eyeLatitude, eyeLongitude);
|
|
16592
|
+
const eyeRadiusX = size * morphologyProfile.face.eyeRadiusXRatio * 0.78;
|
|
16593
|
+
const eyeRadiusY = eyeRadiusX * morphologyProfile.face.eyeHeightRatio * 0.92;
|
|
16594
|
+
drawProjectedOrganicEye(context, leftEyeLocalCenter, eyeRadiusX, eyeRadiusY, meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + eyeRandom() * 0.7, interaction, morphologyProfile.face.eyeStyle);
|
|
16595
|
+
drawProjectedOrganicEye(context, rightEyeLocalCenter, eyeRadiusX, eyeRadiusY, meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + 0.9 + eyeRandom() * 0.7, interaction, morphologyProfile.face.eyeStyle);
|
|
16596
|
+
drawProjectedOrganicMouth(context, [
|
|
16597
|
+
sampleBlobbyOctopusSurfacePoint(surfaceOptions, mouthLatitude, mouthCenterLongitude - mouthHalfLongitude),
|
|
16598
|
+
sampleBlobbyOctopusSurfacePoint(surfaceOptions, mouthCurveLatitude, mouthCenterLongitude),
|
|
16599
|
+
sampleBlobbyOctopusSurfacePoint(surfaceOptions, mouthLatitude, mouthCenterLongitude + mouthHalfLongitude),
|
|
16600
|
+
], meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, palette, size);
|
|
16601
|
+
},
|
|
16602
|
+
};
|
|
16603
|
+
/**
|
|
16604
|
+
* Draws the deep-water glow behind the continuous octopus mesh.
|
|
16605
|
+
*
|
|
16606
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
16607
|
+
*/
|
|
16608
|
+
function drawBlobbyOctopusAtmosphere(context, size, palette, sceneCenterX, sceneCenterY, interaction, timeMs) {
|
|
16609
|
+
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);
|
|
16610
|
+
glowGradient.addColorStop(0, `${palette.highlight}5e`);
|
|
16611
|
+
glowGradient.addColorStop(0.38, `${palette.accent}26`);
|
|
16612
|
+
glowGradient.addColorStop(1, `${palette.highlight}00`);
|
|
16613
|
+
context.fillStyle = glowGradient;
|
|
16614
|
+
context.fillRect(0, 0, size, size);
|
|
16615
|
+
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);
|
|
16616
|
+
lowerGradient.addColorStop(0, `${palette.secondary}22`);
|
|
16617
|
+
lowerGradient.addColorStop(1, `${palette.secondary}00`);
|
|
16618
|
+
context.fillStyle = lowerGradient;
|
|
16619
|
+
context.fillRect(0, 0, size, size);
|
|
16620
|
+
}
|
|
16621
|
+
/**
|
|
16622
|
+
* Draws the soft floor shadow that anchors the single mesh in the frame.
|
|
16623
|
+
*
|
|
16624
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
16625
|
+
*/
|
|
16626
|
+
function drawBlobbyOctopusShadow(context, size, palette, interaction, timeMs, morphologyProfile) {
|
|
16317
16627
|
context.save();
|
|
16318
|
-
context.
|
|
16319
|
-
context.
|
|
16320
|
-
context.beginPath();
|
|
16321
|
-
context.ellipse(0, 0, projectedRadiusX, projectedRadiusY, 0, 0, Math.PI * 2);
|
|
16322
|
-
context.fillStyle = '#f8fbff';
|
|
16323
|
-
context.fill();
|
|
16324
|
-
context.clip();
|
|
16325
|
-
const irisGradient = context.createRadialGradient(-projectedRadiusX * 0.2, -projectedRadiusY * 0.26, projectedRadiusX * 0.05, 0, 0, projectedRadiusX * 0.92);
|
|
16326
|
-
irisGradient.addColorStop(0, palette.highlight);
|
|
16327
|
-
irisGradient.addColorStop(0.56, palette.secondary);
|
|
16328
|
-
irisGradient.addColorStop(1, palette.shadow);
|
|
16329
|
-
context.beginPath();
|
|
16330
|
-
context.ellipse(pupilOffsetX, pupilOffsetY, projectedRadiusX * 0.62 * eyeStyle.irisScale, projectedRadiusY * 0.72 * eyeStyle.irisScale, 0, 0, Math.PI * 2);
|
|
16331
|
-
context.fillStyle = irisGradient;
|
|
16332
|
-
context.fill();
|
|
16628
|
+
context.fillStyle = `${palette.shadow}66`;
|
|
16629
|
+
context.filter = `blur(${size * 0.024}px)`;
|
|
16333
16630
|
context.beginPath();
|
|
16334
|
-
context.ellipse(
|
|
16335
|
-
context.fillStyle = palette.ink;
|
|
16336
|
-
context.fill();
|
|
16337
|
-
context.beginPath();
|
|
16338
|
-
context.ellipse(pupilOffsetX - projectedRadiusX * 0.22, pupilOffsetY - projectedRadiusY * 0.24, projectedRadiusX * 0.12, projectedRadiusY * 0.14, 0, 0, Math.PI * 2);
|
|
16339
|
-
context.fillStyle = '#ffffff';
|
|
16631
|
+
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);
|
|
16340
16632
|
context.fill();
|
|
16341
16633
|
context.restore();
|
|
16342
|
-
context.save();
|
|
16343
|
-
context.translate(projectedCenterPoint.x, projectedCenterPoint.y);
|
|
16344
|
-
context.rotate(rotation);
|
|
16345
|
-
context.beginPath();
|
|
16346
|
-
context.ellipse(0, 0, projectedRadiusX, projectedRadiusY, 0, 0, Math.PI * 2);
|
|
16347
|
-
context.strokeStyle = `${palette.shadow}cc`;
|
|
16348
|
-
context.lineWidth = projectedRadiusX * 0.16;
|
|
16349
|
-
context.stroke();
|
|
16350
|
-
context.beginPath();
|
|
16351
|
-
context.moveTo(-projectedRadiusX * 0.88, -projectedRadiusY * eyeStyle.upperLidInsetRatio);
|
|
16352
|
-
context.quadraticCurveTo(0, -projectedRadiusY * (eyeStyle.upperLidArchRatio - interaction.gazeY * 0.16 + interaction.intensity * 0.08), projectedRadiusX * 0.88, -projectedRadiusY * eyeStyle.upperLidInsetRatio);
|
|
16353
|
-
context.strokeStyle = `${palette.shadow}73`;
|
|
16354
|
-
context.lineWidth = projectedRadiusX * 0.14;
|
|
16355
|
-
context.lineCap = 'round';
|
|
16356
|
-
context.stroke();
|
|
16357
|
-
if (eyeStyle.lowerLidOpacity > 0) {
|
|
16358
|
-
context.beginPath();
|
|
16359
|
-
context.moveTo(-projectedRadiusX * 0.74, projectedRadiusY * 0.2);
|
|
16360
|
-
context.quadraticCurveTo(0, projectedRadiusY * 0.38, projectedRadiusX * 0.74, projectedRadiusY * 0.2);
|
|
16361
|
-
context.strokeStyle = `${palette.highlight}${formatAlphaHex(eyeStyle.lowerLidOpacity)}`;
|
|
16362
|
-
context.lineWidth = projectedRadiusX * 0.08;
|
|
16363
|
-
context.lineCap = 'round';
|
|
16364
|
-
context.stroke();
|
|
16365
|
-
}
|
|
16366
|
-
context.restore();
|
|
16367
16634
|
}
|
|
16368
16635
|
/**
|
|
16369
|
-
*
|
|
16636
|
+
* Resolves all visible projected patches for the single blobby octopus mesh.
|
|
16370
16637
|
*
|
|
16371
|
-
* @private helper of `
|
|
16638
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
16372
16639
|
*/
|
|
16373
|
-
function
|
|
16374
|
-
const
|
|
16375
|
-
|
|
16376
|
-
|
|
16640
|
+
function resolveVisibleBlobbyOctopusPatches(options) {
|
|
16641
|
+
const { center, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, morphologyProfile, animationPhase, timeMs, } = options;
|
|
16642
|
+
const latitudePatchCount = 12;
|
|
16643
|
+
const longitudePatchCount = 24;
|
|
16644
|
+
const surfacePatches = [];
|
|
16645
|
+
for (let latitudeIndex = 0; latitudeIndex < latitudePatchCount; latitudeIndex++) {
|
|
16646
|
+
const startLatitude = -Math.PI / 2 + (latitudeIndex / latitudePatchCount) * Math.PI;
|
|
16647
|
+
const endLatitude = -Math.PI / 2 + ((latitudeIndex + 1) / latitudePatchCount) * Math.PI;
|
|
16648
|
+
const centerLatitude = (startLatitude + endLatitude) / 2;
|
|
16649
|
+
const verticalProgress = (Math.sin(centerLatitude) + 1) / 2;
|
|
16650
|
+
for (let longitudeIndex = 0; longitudeIndex < longitudePatchCount; longitudeIndex++) {
|
|
16651
|
+
const startLongitude = -Math.PI + (longitudeIndex / longitudePatchCount) * Math.PI * 2;
|
|
16652
|
+
const endLongitude = -Math.PI + ((longitudeIndex + 1) / longitudePatchCount) * Math.PI * 2;
|
|
16653
|
+
const centerLongitude = (startLongitude + endLongitude) / 2;
|
|
16654
|
+
const localCorners = [
|
|
16655
|
+
sampleBlobbyOctopusSurfacePoint(options, startLatitude, startLongitude),
|
|
16656
|
+
sampleBlobbyOctopusSurfacePoint(options, startLatitude, endLongitude),
|
|
16657
|
+
sampleBlobbyOctopusSurfacePoint(options, endLatitude, endLongitude),
|
|
16658
|
+
sampleBlobbyOctopusSurfacePoint(options, endLatitude, startLongitude),
|
|
16659
|
+
];
|
|
16660
|
+
const transformedCorners = localCorners.map((localCorner) => transformScenePoint(localCorner, center, rotationX, rotationY));
|
|
16661
|
+
const surfaceNormal = normalizeVector3(crossProduct3D(subtractPoint3D(transformedCorners[1], transformedCorners[0]), subtractPoint3D(transformedCorners[2], transformedCorners[0])));
|
|
16662
|
+
if (surfaceNormal.z <= 0.01) {
|
|
16663
|
+
continue;
|
|
16664
|
+
}
|
|
16665
|
+
const projectedCorners = transformedCorners.map((transformedCorner) => projectScenePoint(transformedCorner, size, sceneCenterX, sceneCenterY));
|
|
16666
|
+
surfacePatches.push({
|
|
16667
|
+
corners: projectedCorners,
|
|
16668
|
+
averageDepth: transformedCorners.reduce((depthSum, transformedCorner) => depthSum + transformedCorner.z, 0) /
|
|
16669
|
+
transformedCorners.length,
|
|
16670
|
+
lightIntensity: clampNumber$1(dotProduct3D(surfaceNormal, LIGHT_DIRECTION), -1, 1),
|
|
16671
|
+
fillStyle: resolveBlobbySurfacePatchFillStyle(palette, verticalProgress, Math.max(0, Math.cos(centerLongitude)), resolveLowerLobeWave(centerLongitude, morphologyProfile, animationPhase, timeMs)),
|
|
16672
|
+
outlineColor: verticalProgress < 0.58 ? `${palette.highlight}73` : `${palette.shadow}8a`,
|
|
16673
|
+
});
|
|
16674
|
+
}
|
|
16377
16675
|
}
|
|
16378
|
-
|
|
16379
|
-
context.beginPath();
|
|
16380
|
-
context.moveTo(projectedPoints[0].x, projectedPoints[0].y);
|
|
16381
|
-
context.quadraticCurveTo(projectedPoints[1].x, projectedPoints[1].y, projectedPoints[2].x, projectedPoints[2].y);
|
|
16382
|
-
context.strokeStyle = `${palette.ink}b8`;
|
|
16383
|
-
context.lineWidth = Math.max(1.1, size * 0.009);
|
|
16384
|
-
context.lineCap = 'round';
|
|
16385
|
-
context.stroke();
|
|
16676
|
+
return surfacePatches;
|
|
16386
16677
|
}
|
|
16387
16678
|
/**
|
|
16388
|
-
*
|
|
16679
|
+
* Samples one point on the continuous Octopus 3D 2 surface.
|
|
16680
|
+
*
|
|
16681
|
+
* The lower hemisphere widens and falls into soft lobe waves so the octopus stays one connected mesh
|
|
16682
|
+
* instead of switching to separately rendered tentacles.
|
|
16683
|
+
*
|
|
16684
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
16685
|
+
*/
|
|
16686
|
+
function sampleBlobbyOctopusSurfacePoint(options, latitude, longitude) {
|
|
16687
|
+
const { radiusX, radiusY, radiusZ, morphologyProfile, timeMs, animationPhase } = options;
|
|
16688
|
+
const cosineLatitude = Math.max(0, Math.cos(latitude));
|
|
16689
|
+
const verticalProgress = (Math.sin(latitude) + 1) / 2;
|
|
16690
|
+
const upperBlend = Math.pow(1 - verticalProgress, 1.2);
|
|
16691
|
+
const lowerBlend = Math.pow(verticalProgress, 1.42);
|
|
16692
|
+
const lowerLobeWave = resolveLowerLobeWave(longitude, morphologyProfile, animationPhase, timeMs);
|
|
16693
|
+
const skirtEnvelope = Math.pow(cosineLatitude, 0.5) * lowerBlend;
|
|
16694
|
+
const horizontalScale = 1.02 +
|
|
16695
|
+
skirtEnvelope * (0.34 + (morphologyProfile.tentacles.rootSpreadScale - 1) * 0.22 + lowerLobeWave * 0.22) -
|
|
16696
|
+
upperBlend * 0.08;
|
|
16697
|
+
const depthScale = 1.04 +
|
|
16698
|
+
upperBlend * 0.16 +
|
|
16699
|
+
Math.max(0, Math.cos(longitude)) * 0.1 +
|
|
16700
|
+
skirtEnvelope * (0.08 + lowerLobeWave * 0.06) -
|
|
16701
|
+
Math.max(0, -Math.cos(longitude)) * 0.04;
|
|
16702
|
+
const lowerDrop = skirtEnvelope *
|
|
16703
|
+
radiusY *
|
|
16704
|
+
(0.28 + lowerLobeWave * 0.14 + (morphologyProfile.tentacles.flowLengthScale - 1) * 0.12);
|
|
16705
|
+
const swayX = Math.sin(timeMs / 1250 + longitude * 1.8 + animationPhase) * skirtEnvelope * radiusX * 0.05;
|
|
16706
|
+
const swayZ = Math.cos(timeMs / 1480 + longitude * 1.2 - animationPhase * 0.7) * skirtEnvelope * radiusZ * 0.03;
|
|
16707
|
+
return {
|
|
16708
|
+
x: Math.sin(longitude) * cosineLatitude * radiusX * horizontalScale + swayX,
|
|
16709
|
+
y: Math.sin(latitude) * radiusY * (1 + upperBlend * 0.14) -
|
|
16710
|
+
upperBlend * radiusY * 0.1 +
|
|
16711
|
+
lowerDrop +
|
|
16712
|
+
Math.sin(timeMs / 1780 + animationPhase + latitude * 1.4) * skirtEnvelope * radiusY * 0.02,
|
|
16713
|
+
z: Math.cos(longitude) * cosineLatitude * radiusZ * depthScale + swayZ,
|
|
16714
|
+
};
|
|
16715
|
+
}
|
|
16716
|
+
/**
|
|
16717
|
+
* Resolves the soft lower-lobe wave that makes the silhouette read more like a real octopus.
|
|
16389
16718
|
*
|
|
16390
|
-
* @private helper of `
|
|
16719
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
16391
16720
|
*/
|
|
16392
|
-
function
|
|
16393
|
-
|
|
16394
|
-
|
|
16395
|
-
context.lineTo(corners[1].x, corners[1].y);
|
|
16396
|
-
context.lineTo(corners[2].x, corners[2].y);
|
|
16397
|
-
context.lineTo(corners[3].x, corners[3].y);
|
|
16398
|
-
context.closePath();
|
|
16399
|
-
context.fillStyle = fillStyle;
|
|
16400
|
-
context.fill();
|
|
16721
|
+
function resolveLowerLobeWave(longitude, morphologyProfile, animationPhase, timeMs) {
|
|
16722
|
+
const lobeCount = Math.max(4, Math.round((morphologyProfile.body.lobeCount + morphologyProfile.tentacles.count) / 2));
|
|
16723
|
+
return (Math.cos(longitude * lobeCount + animationPhase + timeMs / 1040) + 1) / 2;
|
|
16401
16724
|
}
|
|
16402
16725
|
/**
|
|
16403
|
-
*
|
|
16726
|
+
* Resolves one base fill tone for a surface patch on the single octopus mesh.
|
|
16404
16727
|
*
|
|
16405
|
-
* @private helper of `
|
|
16728
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
16406
16729
|
*/
|
|
16407
|
-
function
|
|
16408
|
-
|
|
16409
|
-
|
|
16410
|
-
.
|
|
16730
|
+
function resolveBlobbySurfacePatchFillStyle(palette, verticalProgress, forwardness, lowerLobeWave) {
|
|
16731
|
+
const tonalProgress = clampNumber$1(verticalProgress + lowerLobeWave * 0.12 - forwardness * 0.07, 0, 1);
|
|
16732
|
+
if (tonalProgress < 0.16) {
|
|
16733
|
+
return palette.highlight;
|
|
16734
|
+
}
|
|
16735
|
+
if (tonalProgress < 0.34) {
|
|
16736
|
+
return palette.secondary;
|
|
16737
|
+
}
|
|
16738
|
+
if (tonalProgress < 0.72) {
|
|
16739
|
+
return forwardness > 0.58 ? palette.secondary : palette.primary;
|
|
16740
|
+
}
|
|
16741
|
+
return `${palette.shadow}f2`;
|
|
16742
|
+
}
|
|
16743
|
+
/**
|
|
16744
|
+
* Draws one projected patch with soft octopus shading.
|
|
16745
|
+
*
|
|
16746
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
16747
|
+
*/
|
|
16748
|
+
function drawBlobbySurfacePatch(context, surfacePatch) {
|
|
16749
|
+
drawProjectedQuad(context, surfacePatch.corners, surfacePatch.fillStyle);
|
|
16750
|
+
if (surfacePatch.lightIntensity > 0) {
|
|
16751
|
+
drawProjectedQuad(context, surfacePatch.corners, `rgba(255, 255, 255, ${0.16 * surfacePatch.lightIntensity})`);
|
|
16752
|
+
}
|
|
16753
|
+
else if (surfacePatch.lightIntensity < 0) {
|
|
16754
|
+
drawProjectedQuad(context, surfacePatch.corners, `rgba(0, 0, 0, ${0.24 * Math.abs(surfacePatch.lightIntensity)})`);
|
|
16755
|
+
}
|
|
16756
|
+
context.save();
|
|
16757
|
+
context.beginPath();
|
|
16758
|
+
context.moveTo(surfacePatch.corners[0].x, surfacePatch.corners[0].y);
|
|
16759
|
+
for (let cornerIndex = 1; cornerIndex < surfacePatch.corners.length; cornerIndex++) {
|
|
16760
|
+
context.lineTo(surfacePatch.corners[cornerIndex].x, surfacePatch.corners[cornerIndex].y);
|
|
16761
|
+
}
|
|
16762
|
+
context.closePath();
|
|
16763
|
+
context.strokeStyle = surfacePatch.outlineColor;
|
|
16764
|
+
context.lineWidth = Math.max(1, getProjectedQuadPerimeter(surfacePatch.corners) * 0.0042);
|
|
16765
|
+
context.lineJoin = 'round';
|
|
16766
|
+
context.stroke();
|
|
16767
|
+
context.restore();
|
|
16411
16768
|
}
|
|
16412
16769
|
|
|
16413
16770
|
/* eslint-disable no-magic-numbers */
|
|
@@ -17179,6 +17536,7 @@ const AVATAR_VISUALS = [
|
|
|
17179
17536
|
octopus2AvatarVisual,
|
|
17180
17537
|
octopus3AvatarVisual,
|
|
17181
17538
|
octopus3dAvatarVisual,
|
|
17539
|
+
octopus3d2AvatarVisual,
|
|
17182
17540
|
asciiOctopusAvatarVisual,
|
|
17183
17541
|
minecraftAvatarVisual,
|
|
17184
17542
|
minecraft2AvatarVisual,
|
|
@@ -22754,11 +23112,11 @@ function buildCandidateEncodings(options) {
|
|
|
22754
23112
|
});
|
|
22755
23113
|
}
|
|
22756
23114
|
/**
|
|
22757
|
-
*
|
|
23115
|
+
* Prepares one attachment for best-effort text decoding.
|
|
22758
23116
|
*
|
|
22759
|
-
* @private
|
|
23117
|
+
* @private function of decodeAttachmentAsText
|
|
22760
23118
|
*/
|
|
22761
|
-
function
|
|
23119
|
+
function createDecodeAttachmentPreparation(input, options) {
|
|
22762
23120
|
var _a;
|
|
22763
23121
|
const maxBytes = Math.max(1, Math.floor((_a = options.maxBytes) !== null && _a !== void 0 ? _a : DEFAULT_ATTACHMENT_TEXT_DECODE_BYTES));
|
|
22764
23122
|
const forceText = options.forceText === true;
|
|
@@ -22772,54 +23130,102 @@ function decodeAttachmentAsText(input, options = {}) {
|
|
|
22772
23130
|
const inspection = inspectBytes(truncatedBytes);
|
|
22773
23131
|
const trustedTextMime = isTrustedTextMimeType(mimeType);
|
|
22774
23132
|
const trustedBinaryMime = isTrustedBinaryMimeType(mimeType);
|
|
23133
|
+
const shouldTreatAsBinary = (trustedBinaryMime || inspection.looksBinary) && !trustedTextMime;
|
|
22775
23134
|
if (isTruncated) {
|
|
22776
23135
|
warnings.push(`Decoded only the first ${maxBytes} bytes of \`${input.filename}\` because the attachment exceeded the text preview limit.`);
|
|
22777
23136
|
}
|
|
22778
|
-
|
|
22779
|
-
|
|
22780
|
-
|
|
22781
|
-
|
|
22782
|
-
|
|
22783
|
-
|
|
22784
|
-
|
|
22785
|
-
|
|
22786
|
-
|
|
22787
|
-
|
|
22788
|
-
|
|
23137
|
+
return {
|
|
23138
|
+
warnings,
|
|
23139
|
+
charset,
|
|
23140
|
+
bom,
|
|
23141
|
+
inspection,
|
|
23142
|
+
truncatedBytes,
|
|
23143
|
+
isTruncated,
|
|
23144
|
+
forceText,
|
|
23145
|
+
shouldTreatAsBinary,
|
|
23146
|
+
};
|
|
23147
|
+
}
|
|
23148
|
+
/**
|
|
23149
|
+
* Returns an early result when the attachment should stay classified as binary.
|
|
23150
|
+
*
|
|
23151
|
+
* @private function of decodeAttachmentAsText
|
|
23152
|
+
*/
|
|
23153
|
+
function createBinaryDecodeResult(preparation) {
|
|
23154
|
+
if (!preparation.shouldTreatAsBinary) {
|
|
23155
|
+
return null;
|
|
22789
23156
|
}
|
|
22790
|
-
if (
|
|
22791
|
-
warnings.push('File content looks binary, but text decoding was forced with `forceText`.');
|
|
23157
|
+
if (preparation.forceText) {
|
|
23158
|
+
preparation.warnings.push('File content looks binary, but text decoding was forced with `forceText`.');
|
|
23159
|
+
return null;
|
|
22792
23160
|
}
|
|
22793
|
-
|
|
22794
|
-
|
|
23161
|
+
preparation.warnings.push('File content looks binary, so text decoding was skipped.');
|
|
23162
|
+
return {
|
|
23163
|
+
text: '',
|
|
23164
|
+
encodingUsed: 'binary',
|
|
23165
|
+
confidence: 1,
|
|
23166
|
+
warnings: preparation.warnings,
|
|
23167
|
+
wasBinary: true,
|
|
23168
|
+
isTruncated: preparation.isTruncated,
|
|
23169
|
+
};
|
|
23170
|
+
}
|
|
23171
|
+
/**
|
|
23172
|
+
* Warns when the declared charset cannot be used by the runtime decoder.
|
|
23173
|
+
*
|
|
23174
|
+
* @private function of decodeAttachmentAsText
|
|
23175
|
+
*/
|
|
23176
|
+
function addUnsupportedCharsetWarning(preparation) {
|
|
23177
|
+
if (preparation.charset && !isSupportedEncoding(preparation.charset)) {
|
|
23178
|
+
preparation.warnings.push(`Ignored unsupported declared charset \`${preparation.charset}\` and used best-effort detection instead.`);
|
|
22795
23179
|
}
|
|
22796
|
-
|
|
22797
|
-
|
|
22798
|
-
|
|
22799
|
-
|
|
22800
|
-
|
|
22801
|
-
|
|
22802
|
-
|
|
22803
|
-
|
|
23180
|
+
}
|
|
23181
|
+
/**
|
|
23182
|
+
* Returns the byte slice that should actually be decoded as text.
|
|
23183
|
+
*
|
|
23184
|
+
* @private function of decodeAttachmentAsText
|
|
23185
|
+
*/
|
|
23186
|
+
function getBytesToDecode(preparation) {
|
|
23187
|
+
return preparation.bom ? preparation.truncatedBytes.subarray(preparation.bom.offset) : preparation.truncatedBytes;
|
|
23188
|
+
}
|
|
23189
|
+
/**
|
|
23190
|
+
* Decodes all candidate encodings and sorts the successful results by score.
|
|
23191
|
+
*
|
|
23192
|
+
* @private function of decodeAttachmentAsText
|
|
23193
|
+
*/
|
|
23194
|
+
function decodeAttachmentCandidates(preparation) {
|
|
23195
|
+
return buildCandidateEncodings({
|
|
23196
|
+
charset: preparation.charset && isSupportedEncoding(preparation.charset) ? preparation.charset : null,
|
|
23197
|
+
bom: preparation.bom,
|
|
23198
|
+
inspection: preparation.inspection,
|
|
23199
|
+
})
|
|
22804
23200
|
.map(({ encoding, source }) => {
|
|
22805
|
-
const decoded = decodeWithEncoding(
|
|
23201
|
+
const decoded = decodeWithEncoding(getBytesToDecode(preparation), encoding);
|
|
22806
23202
|
return decoded ? { ...decoded, source } : null;
|
|
22807
23203
|
})
|
|
22808
23204
|
.filter((candidate) => candidate !== null)
|
|
22809
23205
|
.sort((left, right) => left.score - right.score);
|
|
22810
|
-
|
|
22811
|
-
|
|
22812
|
-
|
|
22813
|
-
|
|
22814
|
-
|
|
22815
|
-
|
|
22816
|
-
|
|
22817
|
-
|
|
22818
|
-
|
|
22819
|
-
|
|
22820
|
-
|
|
22821
|
-
|
|
22822
|
-
|
|
23206
|
+
}
|
|
23207
|
+
/**
|
|
23208
|
+
* Returns the fallback result used when no text decoder could be applied.
|
|
23209
|
+
*
|
|
23210
|
+
* @private function of decodeAttachmentAsText
|
|
23211
|
+
*/
|
|
23212
|
+
function createNoDecoderAvailableResult(preparation) {
|
|
23213
|
+
preparation.warnings.push('No supported text decoder was available.');
|
|
23214
|
+
return {
|
|
23215
|
+
text: '',
|
|
23216
|
+
encodingUsed: 'binary',
|
|
23217
|
+
confidence: 0,
|
|
23218
|
+
warnings: preparation.warnings,
|
|
23219
|
+
wasBinary: true,
|
|
23220
|
+
isTruncated: preparation.isTruncated,
|
|
23221
|
+
};
|
|
23222
|
+
}
|
|
23223
|
+
/**
|
|
23224
|
+
* Estimates confidence for the winning decoded text candidate.
|
|
23225
|
+
*
|
|
23226
|
+
* @private function of decodeAttachmentAsText
|
|
23227
|
+
*/
|
|
23228
|
+
function computeDecodeConfidence(bestCandidate, secondBestCandidate, preparation) {
|
|
22823
23229
|
const baseConfidence = bestCandidate.source === 'bom'
|
|
22824
23230
|
? 1
|
|
22825
23231
|
: bestCandidate.source === 'charset'
|
|
@@ -22832,27 +23238,62 @@ function decodeAttachmentAsText(input, options = {}) {
|
|
|
22832
23238
|
? 0.82
|
|
22833
23239
|
: 0.62;
|
|
22834
23240
|
const scoreMargin = secondBestCandidate ? Math.max(0, secondBestCandidate.score - bestCandidate.score) : 0.2;
|
|
22835
|
-
|
|
23241
|
+
return Math.max(0.2, Math.min(preparation.shouldTreatAsBinary && preparation.forceText ? 0.45 : 1, baseConfidence + Math.min(0.18, scoreMargin / 2)));
|
|
23242
|
+
}
|
|
23243
|
+
/**
|
|
23244
|
+
* Appends user-facing warnings derived from the chosen decoded text candidate.
|
|
23245
|
+
*
|
|
23246
|
+
* @private function of decodeAttachmentAsText
|
|
23247
|
+
*/
|
|
23248
|
+
function addDecodeWarnings(bestCandidate, confidence, preparation) {
|
|
22836
23249
|
if (bestCandidate.source === 'heuristic' && bestCandidate.encoding !== 'utf-8') {
|
|
22837
|
-
warnings.push(`Encoding was guessed as \`${bestCandidate.encoding}\`.`);
|
|
23250
|
+
preparation.warnings.push(`Encoding was guessed as \`${bestCandidate.encoding}\`.`);
|
|
22838
23251
|
}
|
|
22839
23252
|
if (bestCandidate.source === 'heuristic' &&
|
|
22840
23253
|
bestCandidate.encoding === 'utf-8' &&
|
|
22841
23254
|
bestCandidate.replacementCount > 0) {
|
|
22842
|
-
warnings.push('UTF-8 decoding produced replacement characters, so the extracted text may contain errors.');
|
|
23255
|
+
preparation.warnings.push('UTF-8 decoding produced replacement characters, so the extracted text may contain errors.');
|
|
22843
23256
|
}
|
|
22844
23257
|
if (confidence < 0.6) {
|
|
22845
|
-
warnings.push('Decoding confidence is low, so the extracted text may contain errors.');
|
|
23258
|
+
preparation.warnings.push('Decoding confidence is low, so the extracted text may contain errors.');
|
|
22846
23259
|
}
|
|
23260
|
+
}
|
|
23261
|
+
/**
|
|
23262
|
+
* Creates the final decoded-text result from the chosen candidate and accumulated metadata.
|
|
23263
|
+
*
|
|
23264
|
+
* @private function of decodeAttachmentAsText
|
|
23265
|
+
*/
|
|
23266
|
+
function createDecodedTextResult(bestCandidate, confidence, preparation) {
|
|
22847
23267
|
return {
|
|
22848
|
-
text: isTruncated ? appendTruncatedMarker(bestCandidate.text) : bestCandidate.text,
|
|
23268
|
+
text: preparation.isTruncated ? appendTruncatedMarker(bestCandidate.text) : bestCandidate.text,
|
|
22849
23269
|
encodingUsed: bestCandidate.encoding,
|
|
22850
23270
|
confidence,
|
|
22851
|
-
warnings,
|
|
23271
|
+
warnings: preparation.warnings,
|
|
22852
23272
|
wasBinary: false,
|
|
22853
|
-
isTruncated,
|
|
23273
|
+
isTruncated: preparation.isTruncated,
|
|
22854
23274
|
};
|
|
22855
23275
|
}
|
|
23276
|
+
/**
|
|
23277
|
+
* Best-effort decoder for uploaded or remote file bytes whose extension or encoding may be unknown.
|
|
23278
|
+
*
|
|
23279
|
+
* @private internal utility for shared text decoding
|
|
23280
|
+
*/
|
|
23281
|
+
function decodeAttachmentAsText(input, options = {}) {
|
|
23282
|
+
const preparation = createDecodeAttachmentPreparation(input, options);
|
|
23283
|
+
const binaryResult = createBinaryDecodeResult(preparation);
|
|
23284
|
+
if (binaryResult) {
|
|
23285
|
+
return binaryResult;
|
|
23286
|
+
}
|
|
23287
|
+
addUnsupportedCharsetWarning(preparation);
|
|
23288
|
+
const decodedCandidates = decodeAttachmentCandidates(preparation);
|
|
23289
|
+
const bestCandidate = decodedCandidates[0];
|
|
23290
|
+
if (!bestCandidate) {
|
|
23291
|
+
return createNoDecoderAvailableResult(preparation);
|
|
23292
|
+
}
|
|
23293
|
+
const confidence = computeDecodeConfidence(bestCandidate, decodedCandidates[1], preparation);
|
|
23294
|
+
addDecodeWarnings(bestCandidate, confidence, preparation);
|
|
23295
|
+
return createDecodedTextResult(bestCandidate, confidence, preparation);
|
|
23296
|
+
}
|
|
22856
23297
|
|
|
22857
23298
|
/**
|
|
22858
23299
|
* Base GitHub API URL.
|
|
@@ -34751,7 +35192,10 @@ class OpenAiCompatibleModelCatalog {
|
|
|
34751
35192
|
Cannot find model in ${this.options.getTitle()} models with name "${defaultModelName}" which should be used as default.
|
|
34752
35193
|
|
|
34753
35194
|
Available models:
|
|
34754
|
-
${block(this.options
|
|
35195
|
+
${block(this.options
|
|
35196
|
+
.getHardcodedModels()
|
|
35197
|
+
.map(({ modelName }) => `- "${modelName}"`)
|
|
35198
|
+
.join('\n'))}
|
|
34755
35199
|
|
|
34756
35200
|
Model "${defaultModelName}" is probably not available anymore, not installed, inaccessible or misconfigured.
|
|
34757
35201
|
|
|
@@ -35105,7 +35549,8 @@ class OpenAiCompatibleNonChatPromptCaller {
|
|
|
35105
35549
|
};
|
|
35106
35550
|
let rawPromptContent = templateParameters(content, { ...parameters, modelName });
|
|
35107
35551
|
if ('attachments' in prompt && Array.isArray(prompt.attachments) && prompt.attachments.length > 0) {
|
|
35108
|
-
rawPromptContent +=
|
|
35552
|
+
rawPromptContent +=
|
|
35553
|
+
'\n\n' + prompt.attachments.map((attachment) => `Image attachment: ${attachment.url}`).join('\n');
|
|
35109
35554
|
}
|
|
35110
35555
|
const rawRequest = {
|
|
35111
35556
|
...modelSettings,
|
|
@@ -35210,7 +35655,9 @@ class OpenAiCompatibleRequestManager {
|
|
|
35210
35655
|
* Schedules one request through the shared limiter and retry policy.
|
|
35211
35656
|
*/
|
|
35212
35657
|
async executeRateLimitedRequest(requestFn) {
|
|
35213
|
-
return this.limiter
|
|
35658
|
+
return this.limiter
|
|
35659
|
+
.schedule(() => this.makeRequestWithNetworkRetry(requestFn))
|
|
35660
|
+
.catch((error) => {
|
|
35214
35661
|
assertsError(error);
|
|
35215
35662
|
if (this.options.isVerbose) {
|
|
35216
35663
|
console.info(colors.bgRed('error'), error);
|
|
@@ -36417,7 +36864,9 @@ class OpenAiVectorStoreFileBatchPoller {
|
|
|
36417
36864
|
pollingState.lastProgressAtMs = nowMs;
|
|
36418
36865
|
pollingState.lastProgressKey = progressKey;
|
|
36419
36866
|
}
|
|
36420
|
-
if (this.options.isVerbose &&
|
|
36867
|
+
if (this.options.isVerbose &&
|
|
36868
|
+
(statusCountsKey !== pollingState.lastCountsKey ||
|
|
36869
|
+
nowMs - pollingState.lastLogAtMs >= progressLogIntervalMs)) {
|
|
36421
36870
|
console.info('[🤰]', 'Vector store file batch status', {
|
|
36422
36871
|
vectorStoreId,
|
|
36423
36872
|
batchId,
|