@promptbook/node 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/esm/index.es.js
CHANGED
|
@@ -35,7 +35,7 @@ const BOOK_LANGUAGE_VERSION = '2.0.0';
|
|
|
35
35
|
* @generated
|
|
36
36
|
* @see https://github.com/webgptorg/promptbook
|
|
37
37
|
*/
|
|
38
|
-
const PROMPTBOOK_ENGINE_VERSION = '0.112.0-
|
|
38
|
+
const PROMPTBOOK_ENGINE_VERSION = '0.112.0-79';
|
|
39
39
|
/**
|
|
40
40
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
|
41
41
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -285,6 +285,111 @@ function checkChannelValue(channelName, value) {
|
|
|
285
285
|
}
|
|
286
286
|
}
|
|
287
287
|
|
|
288
|
+
/**
|
|
289
|
+
* Shared immutable channel storage and serialization helpers for `Color`.
|
|
290
|
+
*
|
|
291
|
+
* @private base class of Color
|
|
292
|
+
*/
|
|
293
|
+
class ColorValue {
|
|
294
|
+
constructor(red, green, blue, alpha = 255) {
|
|
295
|
+
this.red = red;
|
|
296
|
+
this.green = green;
|
|
297
|
+
this.blue = blue;
|
|
298
|
+
this.alpha = alpha;
|
|
299
|
+
checkChannelValue('Red', red);
|
|
300
|
+
checkChannelValue('Green', green);
|
|
301
|
+
checkChannelValue('Blue', blue);
|
|
302
|
+
checkChannelValue('Alpha', alpha);
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Shortcut for `red` property
|
|
306
|
+
* Number from 0 to 255
|
|
307
|
+
* @alias red
|
|
308
|
+
*/
|
|
309
|
+
get r() {
|
|
310
|
+
return this.red;
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* Shortcut for `green` property
|
|
314
|
+
* Number from 0 to 255
|
|
315
|
+
* @alias green
|
|
316
|
+
*/
|
|
317
|
+
get g() {
|
|
318
|
+
return this.green;
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Shortcut for `blue` property
|
|
322
|
+
* Number from 0 to 255
|
|
323
|
+
* @alias blue
|
|
324
|
+
*/
|
|
325
|
+
get b() {
|
|
326
|
+
return this.blue;
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Shortcut for `alpha` property
|
|
330
|
+
* Number from 0 (transparent) to 255 (opaque)
|
|
331
|
+
* @alias alpha
|
|
332
|
+
*/
|
|
333
|
+
get a() {
|
|
334
|
+
return this.alpha;
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Shortcut for `alpha` property
|
|
338
|
+
* Number from 0 (transparent) to 255 (opaque)
|
|
339
|
+
* @alias alpha
|
|
340
|
+
*/
|
|
341
|
+
get opacity() {
|
|
342
|
+
return this.alpha;
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* Shortcut for 1-`alpha` property
|
|
346
|
+
*/
|
|
347
|
+
get transparency() {
|
|
348
|
+
return 255 - this.alpha;
|
|
349
|
+
}
|
|
350
|
+
clone() {
|
|
351
|
+
return take(this.createColor(this.red, this.green, this.blue, this.alpha));
|
|
352
|
+
}
|
|
353
|
+
toString() {
|
|
354
|
+
return this.toHex();
|
|
355
|
+
}
|
|
356
|
+
toHex() {
|
|
357
|
+
if (this.alpha === 255) {
|
|
358
|
+
return `#${this.red.toString(16).padStart(2, '0')}${this.green.toString(16).padStart(2, '0')}${this.blue
|
|
359
|
+
.toString(16)
|
|
360
|
+
.padStart(2, '0')}`;
|
|
361
|
+
}
|
|
362
|
+
else {
|
|
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')}${this.alpha.toString(16).padStart(2, '0')}`;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
toRgb() {
|
|
369
|
+
if (this.alpha === 255) {
|
|
370
|
+
return `rgb(${this.red}, ${this.green}, ${this.blue})`;
|
|
371
|
+
}
|
|
372
|
+
else {
|
|
373
|
+
return `rgba(${this.red}, ${this.green}, ${this.blue}, ${Math.round((this.alpha / 255) * 100)}%)`;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
toHsl() {
|
|
377
|
+
throw new Error(`Getting HSL is not implemented`);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* Checks if the given value is a valid hex color string
|
|
383
|
+
*
|
|
384
|
+
* @param value - value to check
|
|
385
|
+
* @returns true if the value is a valid hex color string (e.g., `#009edd`, `#fff`, etc.)
|
|
386
|
+
*
|
|
387
|
+
* @private function of Color
|
|
388
|
+
*/
|
|
389
|
+
function isHexColorString(value) {
|
|
390
|
+
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));
|
|
391
|
+
}
|
|
392
|
+
|
|
288
393
|
/**
|
|
289
394
|
* Constant for short hex lengths.
|
|
290
395
|
*/
|
|
@@ -496,16 +601,53 @@ function parseAlphaValue(value) {
|
|
|
496
601
|
|
|
497
602
|
/**
|
|
498
603
|
* Pattern matching hsl regex.
|
|
604
|
+
*
|
|
605
|
+
* @private function of Color
|
|
499
606
|
*/
|
|
500
607
|
const HSL_REGEX_PATTERN = /^hsl\(\s*([0-9.]+)\s*,\s*([0-9.]+)%\s*,\s*([0-9.]+)%\s*\)$/;
|
|
501
608
|
/**
|
|
502
609
|
* Pattern matching RGB regex.
|
|
610
|
+
*
|
|
611
|
+
* @private function of Color
|
|
503
612
|
*/
|
|
504
613
|
const RGB_REGEX_PATTERN = /^rgb\(\s*([0-9.%-]+)\s*,\s*([0-9.%-]+)\s*,\s*([0-9.%-]+)\s*\)$/;
|
|
505
614
|
/**
|
|
506
615
|
* Pattern matching rgba regex.
|
|
616
|
+
*
|
|
617
|
+
* @private function of Color
|
|
507
618
|
*/
|
|
508
619
|
const RGBA_REGEX_PATTERN = /^rgba\(\s*([0-9.%-]+)\s*,\s*([0-9.%-]+)\s*,\s*([0-9.%-]+)\s*,\s*([0-9.%-]+)\s*\)$/;
|
|
620
|
+
/**
|
|
621
|
+
* Parses a supported color string into RGBA channels.
|
|
622
|
+
*
|
|
623
|
+
* @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`,...
|
|
624
|
+
* @returns RGBA channel values.
|
|
625
|
+
*
|
|
626
|
+
* @private function of Color
|
|
627
|
+
*/
|
|
628
|
+
function parseColorString(color) {
|
|
629
|
+
const trimmed = color.trim();
|
|
630
|
+
const cssColor = CSS_COLORS[trimmed];
|
|
631
|
+
if (cssColor) {
|
|
632
|
+
return parseColorString(cssColor);
|
|
633
|
+
}
|
|
634
|
+
else if (isHexColorString(trimmed)) {
|
|
635
|
+
return parseHexColor(trimmed);
|
|
636
|
+
}
|
|
637
|
+
if (HSL_REGEX_PATTERN.test(trimmed)) {
|
|
638
|
+
return parseHslColor(trimmed);
|
|
639
|
+
}
|
|
640
|
+
else if (RGB_REGEX_PATTERN.test(trimmed)) {
|
|
641
|
+
return parseRgbColor(trimmed);
|
|
642
|
+
}
|
|
643
|
+
else if (RGBA_REGEX_PATTERN.test(trimmed)) {
|
|
644
|
+
return parseRgbaColor(trimmed);
|
|
645
|
+
}
|
|
646
|
+
else {
|
|
647
|
+
throw new Error(`Can not create a new Color instance from string "${trimmed}".`);
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
|
|
509
651
|
/**
|
|
510
652
|
* Color object represents an RGB color with alpha channel
|
|
511
653
|
*
|
|
@@ -513,7 +655,7 @@ const RGBA_REGEX_PATTERN = /^rgba\(\s*([0-9.%-]+)\s*,\s*([0-9.%-]+)\s*,\s*([0-9.
|
|
|
513
655
|
*
|
|
514
656
|
* @public exported from `@promptbook/color`
|
|
515
657
|
*/
|
|
516
|
-
class Color {
|
|
658
|
+
class Color extends ColorValue {
|
|
517
659
|
/**
|
|
518
660
|
* Creates a new Color instance from miscellaneous formats
|
|
519
661
|
* - It can receive Color instance and just return the same instance
|
|
@@ -586,25 +728,7 @@ class Color {
|
|
|
586
728
|
* @returns Color object
|
|
587
729
|
*/
|
|
588
730
|
static fromString(color) {
|
|
589
|
-
|
|
590
|
-
if (CSS_COLORS[trimmed]) {
|
|
591
|
-
return Color.fromString(CSS_COLORS[trimmed]);
|
|
592
|
-
}
|
|
593
|
-
else if (Color.isHexColorString(trimmed)) {
|
|
594
|
-
return Color.fromHex(trimmed);
|
|
595
|
-
}
|
|
596
|
-
if (HSL_REGEX_PATTERN.test(trimmed)) {
|
|
597
|
-
return Color.fromHsl(trimmed);
|
|
598
|
-
}
|
|
599
|
-
else if (RGB_REGEX_PATTERN.test(trimmed)) {
|
|
600
|
-
return Color.fromRgbString(trimmed);
|
|
601
|
-
}
|
|
602
|
-
else if (RGBA_REGEX_PATTERN.test(trimmed)) {
|
|
603
|
-
return Color.fromRgbaString(trimmed);
|
|
604
|
-
}
|
|
605
|
-
else {
|
|
606
|
-
throw new Error(`Can not create a new Color instance from string "${trimmed}".`);
|
|
607
|
-
}
|
|
731
|
+
return Color.fromColorChannels(parseColorString(color));
|
|
608
732
|
}
|
|
609
733
|
/**
|
|
610
734
|
* Gets common color
|
|
@@ -634,8 +758,7 @@ class Color {
|
|
|
634
758
|
* @returns Color object
|
|
635
759
|
*/
|
|
636
760
|
static fromHex(hex) {
|
|
637
|
-
|
|
638
|
-
return take(new Color(red, green, blue, alpha));
|
|
761
|
+
return Color.fromColorChannels(parseHexColor(hex));
|
|
639
762
|
}
|
|
640
763
|
/**
|
|
641
764
|
* Creates a new Color instance from color in hsl format
|
|
@@ -644,8 +767,7 @@ class Color {
|
|
|
644
767
|
* @returns Color object
|
|
645
768
|
*/
|
|
646
769
|
static fromHsl(hsl) {
|
|
647
|
-
|
|
648
|
-
return take(new Color(red, green, blue, alpha));
|
|
770
|
+
return Color.fromColorChannels(parseHslColor(hsl));
|
|
649
771
|
}
|
|
650
772
|
/**
|
|
651
773
|
* Creates a new Color instance from color in rgb format
|
|
@@ -654,8 +776,7 @@ class Color {
|
|
|
654
776
|
* @returns Color object
|
|
655
777
|
*/
|
|
656
778
|
static fromRgbString(rgb) {
|
|
657
|
-
|
|
658
|
-
return take(new Color(red, green, blue, alpha));
|
|
779
|
+
return Color.fromColorChannels(parseRgbColor(rgb));
|
|
659
780
|
}
|
|
660
781
|
/**
|
|
661
782
|
* Creates a new Color instance from color in rbga format
|
|
@@ -664,8 +785,7 @@ class Color {
|
|
|
664
785
|
* @returns Color object
|
|
665
786
|
*/
|
|
666
787
|
static fromRgbaString(rgba) {
|
|
667
|
-
|
|
668
|
-
return take(new Color(red, green, blue, alpha));
|
|
788
|
+
return Color.fromColorChannels(parseRgbaColor(rgba));
|
|
669
789
|
}
|
|
670
790
|
/**
|
|
671
791
|
* Creates a new Color for color channels values
|
|
@@ -677,7 +797,7 @@ class Color {
|
|
|
677
797
|
* @returns Color object
|
|
678
798
|
*/
|
|
679
799
|
static fromValues(red, green, blue, alpha = 255) {
|
|
680
|
-
return
|
|
800
|
+
return Color.fromColorChannels({ red, green, blue, alpha });
|
|
681
801
|
}
|
|
682
802
|
/**
|
|
683
803
|
* Checks if the given value is a valid Color object.
|
|
@@ -710,8 +830,7 @@ class Color {
|
|
|
710
830
|
* @returns true if the value is a valid hex color string (e.g., `#009edd`, `#fff`, etc.)
|
|
711
831
|
*/
|
|
712
832
|
static isHexColorString(value) {
|
|
713
|
-
return (
|
|
714
|
-
/^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/.test(value));
|
|
833
|
+
return isHexColorString(value);
|
|
715
834
|
}
|
|
716
835
|
/**
|
|
717
836
|
* Creates new Color object
|
|
@@ -724,89 +843,13 @@ class Color {
|
|
|
724
843
|
* @param alpha number from 0 (transparent) to 255 (opaque)
|
|
725
844
|
*/
|
|
726
845
|
constructor(red, green, blue, alpha = 255) {
|
|
727
|
-
|
|
728
|
-
this.green = green;
|
|
729
|
-
this.blue = blue;
|
|
730
|
-
this.alpha = alpha;
|
|
731
|
-
checkChannelValue('Red', red);
|
|
732
|
-
checkChannelValue('Green', green);
|
|
733
|
-
checkChannelValue('Blue', blue);
|
|
734
|
-
checkChannelValue('Alpha', alpha);
|
|
735
|
-
}
|
|
736
|
-
/**
|
|
737
|
-
* Shortcut for `red` property
|
|
738
|
-
* Number from 0 to 255
|
|
739
|
-
* @alias red
|
|
740
|
-
*/
|
|
741
|
-
get r() {
|
|
742
|
-
return this.red;
|
|
743
|
-
}
|
|
744
|
-
/**
|
|
745
|
-
* Shortcut for `green` property
|
|
746
|
-
* Number from 0 to 255
|
|
747
|
-
* @alias green
|
|
748
|
-
*/
|
|
749
|
-
get g() {
|
|
750
|
-
return this.green;
|
|
751
|
-
}
|
|
752
|
-
/**
|
|
753
|
-
* Shortcut for `blue` property
|
|
754
|
-
* Number from 0 to 255
|
|
755
|
-
* @alias blue
|
|
756
|
-
*/
|
|
757
|
-
get b() {
|
|
758
|
-
return this.blue;
|
|
759
|
-
}
|
|
760
|
-
/**
|
|
761
|
-
* Shortcut for `alpha` property
|
|
762
|
-
* Number from 0 (transparent) to 255 (opaque)
|
|
763
|
-
* @alias alpha
|
|
764
|
-
*/
|
|
765
|
-
get a() {
|
|
766
|
-
return this.alpha;
|
|
767
|
-
}
|
|
768
|
-
/**
|
|
769
|
-
* Shortcut for `alpha` property
|
|
770
|
-
* Number from 0 (transparent) to 255 (opaque)
|
|
771
|
-
* @alias alpha
|
|
772
|
-
*/
|
|
773
|
-
get opacity() {
|
|
774
|
-
return this.alpha;
|
|
775
|
-
}
|
|
776
|
-
/**
|
|
777
|
-
* Shortcut for 1-`alpha` property
|
|
778
|
-
*/
|
|
779
|
-
get transparency() {
|
|
780
|
-
return 255 - this.alpha;
|
|
781
|
-
}
|
|
782
|
-
clone() {
|
|
783
|
-
return take(new Color(this.red, this.green, this.blue, this.alpha));
|
|
784
|
-
}
|
|
785
|
-
toString() {
|
|
786
|
-
return this.toHex();
|
|
787
|
-
}
|
|
788
|
-
toHex() {
|
|
789
|
-
if (this.alpha === 255) {
|
|
790
|
-
return `#${this.red.toString(16).padStart(2, '0')}${this.green.toString(16).padStart(2, '0')}${this.blue
|
|
791
|
-
.toString(16)
|
|
792
|
-
.padStart(2, '0')}`;
|
|
793
|
-
}
|
|
794
|
-
else {
|
|
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')}${this.alpha.toString(16).padStart(2, '0')}`;
|
|
798
|
-
}
|
|
846
|
+
super(red, green, blue, alpha);
|
|
799
847
|
}
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
return `rgb(${this.red}, ${this.green}, ${this.blue})`;
|
|
803
|
-
}
|
|
804
|
-
else {
|
|
805
|
-
return `rgba(${this.red}, ${this.green}, ${this.blue}, ${Math.round((this.alpha / 255) * 100)}%)`;
|
|
806
|
-
}
|
|
848
|
+
createColor(red, green, blue, alpha) {
|
|
849
|
+
return new Color(red, green, blue, alpha);
|
|
807
850
|
}
|
|
808
|
-
|
|
809
|
-
|
|
851
|
+
static fromColorChannels({ red, green, blue, alpha }) {
|
|
852
|
+
return take(new Color(red, green, blue, alpha));
|
|
810
853
|
}
|
|
811
854
|
}
|
|
812
855
|
|
|
@@ -1491,120 +1534,183 @@ function assertsError(whatWasThrown) {
|
|
|
1491
1534
|
* @public exported from `@promptbook/utils`
|
|
1492
1535
|
*/
|
|
1493
1536
|
function checkSerializableAsJson(options) {
|
|
1494
|
-
|
|
1537
|
+
checkSerializableValue(options);
|
|
1538
|
+
}
|
|
1539
|
+
// TODO: Can be return type more type-safe? like `asserts options.value is JsonValue`
|
|
1540
|
+
// TODO: [🧠][main] !!3 In-memory cache of same values to prevent multiple checks
|
|
1541
|
+
// Note: [🐠] This is how `checkSerializableAsJson` + `isSerializableAsJson` together can just retun true/false or rich error message
|
|
1542
|
+
/**
|
|
1543
|
+
* Checks one value and dispatches to the appropriate specialized validator.
|
|
1544
|
+
*
|
|
1545
|
+
* @private function of `checkSerializableAsJson`
|
|
1546
|
+
*/
|
|
1547
|
+
function checkSerializableValue(options) {
|
|
1548
|
+
const { value } = options;
|
|
1549
|
+
if (isSerializablePrimitive(value)) {
|
|
1550
|
+
return;
|
|
1551
|
+
}
|
|
1495
1552
|
if (value === undefined) {
|
|
1496
|
-
throw new UnexpectedError(`${name} is undefined`);
|
|
1553
|
+
throw new UnexpectedError(`${options.name} is undefined`);
|
|
1497
1554
|
}
|
|
1498
|
-
|
|
1499
|
-
|
|
1555
|
+
if (typeof value === 'symbol') {
|
|
1556
|
+
throw new UnexpectedError(`${options.name} is symbol`);
|
|
1500
1557
|
}
|
|
1501
|
-
|
|
1502
|
-
|
|
1558
|
+
if (typeof value === 'function') {
|
|
1559
|
+
throw new UnexpectedError(`${options.name} is function`);
|
|
1503
1560
|
}
|
|
1504
|
-
|
|
1561
|
+
if (Array.isArray(value)) {
|
|
1562
|
+
checkSerializableArray(options, value);
|
|
1505
1563
|
return;
|
|
1506
1564
|
}
|
|
1507
|
-
|
|
1565
|
+
if (value !== null && typeof value === 'object') {
|
|
1566
|
+
checkSerializableObject(options, value);
|
|
1508
1567
|
return;
|
|
1509
1568
|
}
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1569
|
+
throwUnknownTypeError(options);
|
|
1570
|
+
}
|
|
1571
|
+
/**
|
|
1572
|
+
* Checks the primitive values that are directly JSON serializable.
|
|
1573
|
+
*
|
|
1574
|
+
* @private function of `checkSerializableAsJson`
|
|
1575
|
+
*/
|
|
1576
|
+
function isSerializablePrimitive(value) {
|
|
1577
|
+
return (value === null ||
|
|
1578
|
+
typeof value === 'boolean' ||
|
|
1579
|
+
(typeof value === 'number' && !isNaN(value)) ||
|
|
1580
|
+
typeof value === 'string');
|
|
1581
|
+
}
|
|
1582
|
+
/**
|
|
1583
|
+
* Recursively checks JSON array items.
|
|
1584
|
+
*
|
|
1585
|
+
* @private function of `checkSerializableAsJson`
|
|
1586
|
+
*/
|
|
1587
|
+
function checkSerializableArray(context, arrayValue) {
|
|
1588
|
+
for (let index = 0; index < arrayValue.length; index++) {
|
|
1589
|
+
checkSerializableAsJson({
|
|
1590
|
+
...context,
|
|
1591
|
+
name: `${context.name}[${index}]`,
|
|
1592
|
+
value: arrayValue[index],
|
|
1593
|
+
});
|
|
1520
1594
|
}
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1595
|
+
}
|
|
1596
|
+
/**
|
|
1597
|
+
* Checks object-like values and dispatches special unsupported built-ins.
|
|
1598
|
+
*
|
|
1599
|
+
* @private function of `checkSerializableAsJson`
|
|
1600
|
+
*/
|
|
1601
|
+
function checkSerializableObject(context, objectValue) {
|
|
1602
|
+
checkUnsupportedObjectType(context, objectValue);
|
|
1603
|
+
checkSerializableObjectEntries(context, objectValue);
|
|
1604
|
+
assertJsonStringificationSucceeds(context, objectValue);
|
|
1605
|
+
}
|
|
1606
|
+
/**
|
|
1607
|
+
* Rejects built-in objects that must be converted before JSON serialization.
|
|
1608
|
+
*
|
|
1609
|
+
* @private function of `checkSerializableAsJson`
|
|
1610
|
+
*/
|
|
1611
|
+
function checkUnsupportedObjectType(context, objectValue) {
|
|
1612
|
+
if (objectValue instanceof Date) {
|
|
1613
|
+
throw new UnexpectedError(spaceTrim$1((block) => `
|
|
1614
|
+
\`${context.name}\` is Date
|
|
1525
1615
|
|
|
1526
|
-
|
|
1616
|
+
Use \`string_date_iso8601\` instead
|
|
1527
1617
|
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1618
|
+
Additional message for \`${context.name}\`:
|
|
1619
|
+
${block(context.message || '(nothing)')}
|
|
1620
|
+
`));
|
|
1621
|
+
}
|
|
1622
|
+
if (objectValue instanceof Map) {
|
|
1623
|
+
throw new UnexpectedError(`${context.name} is Map`);
|
|
1624
|
+
}
|
|
1625
|
+
if (objectValue instanceof Set) {
|
|
1626
|
+
throw new UnexpectedError(`${context.name} is Set`);
|
|
1627
|
+
}
|
|
1628
|
+
if (objectValue instanceof RegExp) {
|
|
1629
|
+
throw new UnexpectedError(`${context.name} is RegExp`);
|
|
1630
|
+
}
|
|
1631
|
+
if (objectValue instanceof Error) {
|
|
1632
|
+
throw new UnexpectedError(spaceTrim$1((block) => `
|
|
1633
|
+
\`${context.name}\` is unserialized Error
|
|
1544
1634
|
|
|
1545
|
-
|
|
1635
|
+
Use function \`serializeError\`
|
|
1546
1636
|
|
|
1547
|
-
|
|
1548
|
-
|
|
1637
|
+
Additional message for \`${context.name}\`:
|
|
1638
|
+
${block(context.message || '(nothing)')}
|
|
1549
1639
|
|
|
1550
|
-
|
|
1640
|
+
`));
|
|
1641
|
+
}
|
|
1642
|
+
}
|
|
1643
|
+
/**
|
|
1644
|
+
* Recursively checks object properties while preserving omitted `undefined` keys.
|
|
1645
|
+
*
|
|
1646
|
+
* @private function of `checkSerializableAsJson`
|
|
1647
|
+
*/
|
|
1648
|
+
function checkSerializableObjectEntries(context, objectValue) {
|
|
1649
|
+
for (const [subName, subValue] of Object.entries(objectValue)) {
|
|
1650
|
+
if (subValue === undefined) {
|
|
1651
|
+
// Note: undefined in object is serializable - it is just omitted
|
|
1652
|
+
continue;
|
|
1551
1653
|
}
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1654
|
+
checkSerializableAsJson({
|
|
1655
|
+
...context,
|
|
1656
|
+
name: `${context.name}.${subName}`,
|
|
1657
|
+
value: subValue,
|
|
1658
|
+
});
|
|
1659
|
+
}
|
|
1660
|
+
}
|
|
1661
|
+
/**
|
|
1662
|
+
* Uses `JSON.stringify` as the final guard for cases like circular references.
|
|
1663
|
+
*
|
|
1664
|
+
* @private function of `checkSerializableAsJson`
|
|
1665
|
+
*/
|
|
1666
|
+
function assertJsonStringificationSucceeds(context, objectValue) {
|
|
1667
|
+
try {
|
|
1668
|
+
JSON.stringify(objectValue); // <- TODO: [0]
|
|
1669
|
+
}
|
|
1670
|
+
catch (error) {
|
|
1671
|
+
assertsError(error);
|
|
1672
|
+
throw new UnexpectedError(spaceTrim$1((block) => `
|
|
1673
|
+
\`${context.name}\` is not serializable
|
|
1567
1674
|
|
|
1568
|
-
|
|
1675
|
+
${block(error.stack || error.message)}
|
|
1569
1676
|
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1677
|
+
Additional message for \`${context.name}\`:
|
|
1678
|
+
${block(context.message || '(nothing)')}
|
|
1679
|
+
`));
|
|
1680
|
+
}
|
|
1681
|
+
/*
|
|
1682
|
+
TODO: [0] Is there some more elegant way to check circular references?
|
|
1683
|
+
const seen = new Set();
|
|
1684
|
+
const stack = [{ value }];
|
|
1685
|
+
while (stack.length > 0) {
|
|
1686
|
+
const { value } = stack.pop()!;
|
|
1687
|
+
if (typeof value === 'object' && value !== null) {
|
|
1688
|
+
if (seen.has(value)) {
|
|
1689
|
+
throw new UnexpectedError(`${name} has circular reference`);
|
|
1573
1690
|
}
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
const { value } = stack.pop()!;
|
|
1580
|
-
if (typeof value === 'object' && value !== null) {
|
|
1581
|
-
if (seen.has(value)) {
|
|
1582
|
-
throw new UnexpectedError(`${name} has circular reference`);
|
|
1583
|
-
}
|
|
1584
|
-
seen.add(value);
|
|
1585
|
-
if (Array.isArray(value)) {
|
|
1586
|
-
stack.push(...value.map((value) => ({ value })));
|
|
1587
|
-
} else {
|
|
1588
|
-
stack.push(...Object.values(value).map((value) => ({ value })));
|
|
1589
|
-
}
|
|
1590
|
-
}
|
|
1691
|
+
seen.add(value);
|
|
1692
|
+
if (Array.isArray(value)) {
|
|
1693
|
+
stack.push(...value.map((value) => ({ value })));
|
|
1694
|
+
} else {
|
|
1695
|
+
stack.push(...Object.values(value).map((value) => ({ value })));
|
|
1591
1696
|
}
|
|
1592
|
-
*/
|
|
1593
|
-
return;
|
|
1594
1697
|
}
|
|
1595
1698
|
}
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1699
|
+
*/
|
|
1700
|
+
}
|
|
1701
|
+
/**
|
|
1702
|
+
* Throws the fallback error for unsupported value types like `bigint` and `NaN`.
|
|
1703
|
+
*
|
|
1704
|
+
* @private function of `checkSerializableAsJson`
|
|
1705
|
+
*/
|
|
1706
|
+
function throwUnknownTypeError(context) {
|
|
1707
|
+
throw new UnexpectedError(spaceTrim$1((block) => `
|
|
1708
|
+
\`${context.name}\` is unknown type
|
|
1599
1709
|
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
}
|
|
1710
|
+
Additional message for \`${context.name}\`:
|
|
1711
|
+
${block(context.message || '(nothing)')}
|
|
1712
|
+
`));
|
|
1604
1713
|
}
|
|
1605
|
-
// TODO: Can be return type more type-safe? like `asserts options.value is JsonValue`
|
|
1606
|
-
// TODO: [🧠][main] !!3 In-memory cache of same values to prevent multiple checks
|
|
1607
|
-
// Note: [🐠] This is how `checkSerializableAsJson` + `isSerializableAsJson` together can just retun true/false or rich error message
|
|
1608
1714
|
|
|
1609
1715
|
/**
|
|
1610
1716
|
* Creates a deep clone of the given object
|
|
@@ -2264,8 +2370,7 @@ function hasTaskJokers(task) {
|
|
|
2264
2370
|
* @private internal utility of `validatePipeline`
|
|
2265
2371
|
*/
|
|
2266
2372
|
function validateTaskSupportsJokers(task, pipelineIdentification) {
|
|
2267
|
-
if (task.format ||
|
|
2268
|
-
task.expectations /* <- TODO: Require at least 1 -> min <- expectation to use jokers */) {
|
|
2373
|
+
if (task.format || task.expectations /* <- TODO: Require at least 1 -> min <- expectation to use jokers */) {
|
|
2269
2374
|
return;
|
|
2270
2375
|
}
|
|
2271
2376
|
throw new PipelineLogicError(spaceTrim$1((block) => `
|
|
@@ -2830,7 +2935,7 @@ function createJokerCommands(task) {
|
|
|
2830
2935
|
*/
|
|
2831
2936
|
function createPostprocessingCommands(task) {
|
|
2832
2937
|
var _a;
|
|
2833
|
-
return ((_a = task.postprocessingFunctionNames) === null || _a === void 0 ? void 0 : _a.map((postprocessingFunctionName) => `POSTPROCESSING \`${postprocessingFunctionName}\``)) || [];
|
|
2938
|
+
return (((_a = task.postprocessingFunctionNames) === null || _a === void 0 ? void 0 : _a.map((postprocessingFunctionName) => `POSTPROCESSING \`${postprocessingFunctionName}\``)) || []);
|
|
2834
2939
|
}
|
|
2835
2940
|
/**
|
|
2836
2941
|
* Collects expectation commands.
|
|
@@ -5946,9 +6051,7 @@ function createFailuresSummary($failedResults) {
|
|
|
5946
6051
|
${block(quoteMultilineText(((_b = failure.error) === null || _b === void 0 ? void 0 : _b.message) || ''))}
|
|
5947
6052
|
|
|
5948
6053
|
Result:
|
|
5949
|
-
${block(failure.result === null
|
|
5950
|
-
? 'null'
|
|
5951
|
-
: quoteMultilineText(spaceTrim$1(failure.result)))}
|
|
6054
|
+
${block(failure.result === null ? 'null' : quoteMultilineText(spaceTrim$1(failure.result)))}
|
|
5952
6055
|
`;
|
|
5953
6056
|
}))
|
|
5954
6057
|
.join('\n\n---\n\n');
|
|
@@ -17455,7 +17558,7 @@ function fillTextureRect(texture, x, y, width, height, color) {
|
|
|
17455
17558
|
*
|
|
17456
17559
|
* @private helper of `minecraft2AvatarVisual`
|
|
17457
17560
|
*/
|
|
17458
|
-
const LIGHT_DIRECTION$
|
|
17561
|
+
const LIGHT_DIRECTION$2 = normalizeVector3({
|
|
17459
17562
|
x: 0.4,
|
|
17460
17563
|
y: -0.65,
|
|
17461
17564
|
z: 0.92,
|
|
@@ -17667,7 +17770,7 @@ function resolveVisibleCuboidFaces(cuboid, size, sceneCenterX, sceneCenterY) {
|
|
|
17667
17770
|
corners: projectedCorners,
|
|
17668
17771
|
texture: faceDefinition.texture,
|
|
17669
17772
|
averageDepth: transformedCorners.reduce((depthSum, corner) => depthSum + corner.z, 0) / transformedCorners.length,
|
|
17670
|
-
lightIntensity: clampNumber$1(dotProduct3D(faceNormal, LIGHT_DIRECTION$
|
|
17773
|
+
lightIntensity: clampNumber$1(dotProduct3D(faceNormal, LIGHT_DIRECTION$2), -1, 1),
|
|
17671
17774
|
outlineColor: cuboid.outlineColor,
|
|
17672
17775
|
};
|
|
17673
17776
|
});
|
|
@@ -18727,13 +18830,138 @@ function drawSeededEye(context, centerX, centerY, radiusX, radiusY, rotation, pa
|
|
|
18727
18830
|
context.restore();
|
|
18728
18831
|
}
|
|
18729
18832
|
|
|
18833
|
+
/* eslint-disable no-magic-numbers */
|
|
18834
|
+
/**
|
|
18835
|
+
* Draws one projected eye on a rotated octopus surface.
|
|
18836
|
+
*
|
|
18837
|
+
* @private helper of the 3D octopus avatar visuals
|
|
18838
|
+
*/
|
|
18839
|
+
function drawProjectedOrganicEye(context, localCenter, radiusX, radiusY, center, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, phase, interaction, eyeStyle) {
|
|
18840
|
+
const centerScenePoint = transformScenePoint(localCenter, center, rotationX, rotationY);
|
|
18841
|
+
if (centerScenePoint.z <= center.z) {
|
|
18842
|
+
return;
|
|
18843
|
+
}
|
|
18844
|
+
const horizontalScenePoint = transformScenePoint({ x: localCenter.x + radiusX, y: localCenter.y, z: localCenter.z }, center, rotationX, rotationY);
|
|
18845
|
+
const verticalScenePoint = transformScenePoint({ x: localCenter.x, y: localCenter.y + radiusY, z: localCenter.z }, center, rotationX, rotationY);
|
|
18846
|
+
const projectedCenterPoint = projectScenePoint(centerScenePoint, size, sceneCenterX, sceneCenterY);
|
|
18847
|
+
const projectedHorizontalPoint = projectScenePoint(horizontalScenePoint, size, sceneCenterX, sceneCenterY);
|
|
18848
|
+
const projectedVerticalPoint = projectScenePoint(verticalScenePoint, size, sceneCenterX, sceneCenterY);
|
|
18849
|
+
const projectedRadiusX = Math.hypot(projectedHorizontalPoint.x - projectedCenterPoint.x, projectedHorizontalPoint.y - projectedCenterPoint.y);
|
|
18850
|
+
const projectedRadiusY = Math.hypot(projectedVerticalPoint.x - projectedCenterPoint.x, projectedVerticalPoint.y - projectedCenterPoint.y);
|
|
18851
|
+
if (projectedRadiusX < size * 0.008 || projectedRadiusY < size * 0.008) {
|
|
18852
|
+
return;
|
|
18853
|
+
}
|
|
18854
|
+
const { pupilOffsetX, pupilOffsetY } = resolveOrganicEyeMotion({
|
|
18855
|
+
radiusX: projectedRadiusX,
|
|
18856
|
+
radiusY: projectedRadiusY,
|
|
18857
|
+
timeMs,
|
|
18858
|
+
phase,
|
|
18859
|
+
interaction,
|
|
18860
|
+
});
|
|
18861
|
+
const rotation = Math.atan2(projectedHorizontalPoint.y - projectedCenterPoint.y, projectedHorizontalPoint.x - projectedCenterPoint.x);
|
|
18862
|
+
context.save();
|
|
18863
|
+
context.translate(projectedCenterPoint.x, projectedCenterPoint.y);
|
|
18864
|
+
context.rotate(rotation);
|
|
18865
|
+
context.beginPath();
|
|
18866
|
+
context.ellipse(0, 0, projectedRadiusX, projectedRadiusY, 0, 0, Math.PI * 2);
|
|
18867
|
+
context.fillStyle = '#f8fbff';
|
|
18868
|
+
context.fill();
|
|
18869
|
+
context.clip();
|
|
18870
|
+
const irisGradient = context.createRadialGradient(-projectedRadiusX * 0.2, -projectedRadiusY * 0.26, projectedRadiusX * 0.05, 0, 0, projectedRadiusX * 0.92);
|
|
18871
|
+
irisGradient.addColorStop(0, palette.highlight);
|
|
18872
|
+
irisGradient.addColorStop(0.56, palette.secondary);
|
|
18873
|
+
irisGradient.addColorStop(1, palette.shadow);
|
|
18874
|
+
context.beginPath();
|
|
18875
|
+
context.ellipse(pupilOffsetX, pupilOffsetY, projectedRadiusX * 0.62 * eyeStyle.irisScale, projectedRadiusY * 0.72 * eyeStyle.irisScale, 0, 0, Math.PI * 2);
|
|
18876
|
+
context.fillStyle = irisGradient;
|
|
18877
|
+
context.fill();
|
|
18878
|
+
context.beginPath();
|
|
18879
|
+
context.ellipse(pupilOffsetX, pupilOffsetY, projectedRadiusX * 0.15 * eyeStyle.pupilWidthScale, projectedRadiusY * 0.48 * eyeStyle.pupilHeightScale, 0, 0, Math.PI * 2);
|
|
18880
|
+
context.fillStyle = palette.ink;
|
|
18881
|
+
context.fill();
|
|
18882
|
+
context.beginPath();
|
|
18883
|
+
context.ellipse(pupilOffsetX - projectedRadiusX * 0.22, pupilOffsetY - projectedRadiusY * 0.24, projectedRadiusX * 0.12, projectedRadiusY * 0.14, 0, 0, Math.PI * 2);
|
|
18884
|
+
context.fillStyle = '#ffffff';
|
|
18885
|
+
context.fill();
|
|
18886
|
+
context.restore();
|
|
18887
|
+
context.save();
|
|
18888
|
+
context.translate(projectedCenterPoint.x, projectedCenterPoint.y);
|
|
18889
|
+
context.rotate(rotation);
|
|
18890
|
+
context.beginPath();
|
|
18891
|
+
context.ellipse(0, 0, projectedRadiusX, projectedRadiusY, 0, 0, Math.PI * 2);
|
|
18892
|
+
context.strokeStyle = `${palette.shadow}cc`;
|
|
18893
|
+
context.lineWidth = projectedRadiusX * 0.16;
|
|
18894
|
+
context.stroke();
|
|
18895
|
+
context.beginPath();
|
|
18896
|
+
context.moveTo(-projectedRadiusX * 0.88, -projectedRadiusY * eyeStyle.upperLidInsetRatio);
|
|
18897
|
+
context.quadraticCurveTo(0, -projectedRadiusY * (eyeStyle.upperLidArchRatio - interaction.gazeY * 0.16 + interaction.intensity * 0.08), projectedRadiusX * 0.88, -projectedRadiusY * eyeStyle.upperLidInsetRatio);
|
|
18898
|
+
context.strokeStyle = `${palette.shadow}73`;
|
|
18899
|
+
context.lineWidth = projectedRadiusX * 0.14;
|
|
18900
|
+
context.lineCap = 'round';
|
|
18901
|
+
context.stroke();
|
|
18902
|
+
if (eyeStyle.lowerLidOpacity > 0) {
|
|
18903
|
+
context.beginPath();
|
|
18904
|
+
context.moveTo(-projectedRadiusX * 0.74, projectedRadiusY * 0.2);
|
|
18905
|
+
context.quadraticCurveTo(0, projectedRadiusY * 0.38, projectedRadiusX * 0.74, projectedRadiusY * 0.2);
|
|
18906
|
+
context.strokeStyle = `${palette.highlight}${formatAlphaHex(eyeStyle.lowerLidOpacity)}`;
|
|
18907
|
+
context.lineWidth = projectedRadiusX * 0.08;
|
|
18908
|
+
context.lineCap = 'round';
|
|
18909
|
+
context.stroke();
|
|
18910
|
+
}
|
|
18911
|
+
context.restore();
|
|
18912
|
+
}
|
|
18913
|
+
/**
|
|
18914
|
+
* Draws a subtle projected mouth arc across the front of a rotated octopus surface.
|
|
18915
|
+
*
|
|
18916
|
+
* @private helper of the 3D octopus avatar visuals
|
|
18917
|
+
*/
|
|
18918
|
+
function drawProjectedOrganicMouth(context, localPoints, center, rotationX, rotationY, sceneCenterX, sceneCenterY, palette, size) {
|
|
18919
|
+
const scenePoints = localPoints.map((localPoint) => transformScenePoint(localPoint, center, rotationX, rotationY));
|
|
18920
|
+
if (scenePoints.some((scenePoint) => scenePoint.z <= center.z)) {
|
|
18921
|
+
return;
|
|
18922
|
+
}
|
|
18923
|
+
const projectedPoints = scenePoints.map((scenePoint) => projectScenePoint(scenePoint, size, sceneCenterX, sceneCenterY));
|
|
18924
|
+
context.beginPath();
|
|
18925
|
+
context.moveTo(projectedPoints[0].x, projectedPoints[0].y);
|
|
18926
|
+
context.quadraticCurveTo(projectedPoints[1].x, projectedPoints[1].y, projectedPoints[2].x, projectedPoints[2].y);
|
|
18927
|
+
context.strokeStyle = `${palette.ink}b8`;
|
|
18928
|
+
context.lineWidth = Math.max(1.1, size * 0.009);
|
|
18929
|
+
context.lineCap = 'round';
|
|
18930
|
+
context.stroke();
|
|
18931
|
+
}
|
|
18932
|
+
/**
|
|
18933
|
+
* Draws one filled projected quad.
|
|
18934
|
+
*
|
|
18935
|
+
* @private helper of the 3D octopus avatar visuals
|
|
18936
|
+
*/
|
|
18937
|
+
function drawProjectedQuad(context, corners, fillStyle) {
|
|
18938
|
+
context.beginPath();
|
|
18939
|
+
context.moveTo(corners[0].x, corners[0].y);
|
|
18940
|
+
context.lineTo(corners[1].x, corners[1].y);
|
|
18941
|
+
context.lineTo(corners[2].x, corners[2].y);
|
|
18942
|
+
context.lineTo(corners[3].x, corners[3].y);
|
|
18943
|
+
context.closePath();
|
|
18944
|
+
context.fillStyle = fillStyle;
|
|
18945
|
+
context.fill();
|
|
18946
|
+
}
|
|
18947
|
+
/**
|
|
18948
|
+
* Converts an opacity ratio into a two-digit hexadecimal alpha suffix.
|
|
18949
|
+
*
|
|
18950
|
+
* @private helper of the 3D octopus avatar visuals
|
|
18951
|
+
*/
|
|
18952
|
+
function formatAlphaHex(opacity) {
|
|
18953
|
+
return Math.round(clampNumber$1(opacity, 0, 1) * 255)
|
|
18954
|
+
.toString(16)
|
|
18955
|
+
.padStart(2, '0');
|
|
18956
|
+
}
|
|
18957
|
+
|
|
18730
18958
|
/* eslint-disable no-magic-numbers */
|
|
18731
18959
|
/**
|
|
18732
18960
|
* Light direction used by the organic 3D octopus shading.
|
|
18733
18961
|
*
|
|
18734
18962
|
* @private helper of `octopus3dAvatarVisual`
|
|
18735
18963
|
*/
|
|
18736
|
-
const LIGHT_DIRECTION = normalizeVector3({
|
|
18964
|
+
const LIGHT_DIRECTION$1 = normalizeVector3({
|
|
18737
18965
|
x: 0.48,
|
|
18738
18966
|
y: -0.62,
|
|
18739
18967
|
z: 0.94,
|
|
@@ -18846,17 +19074,17 @@ const octopus3dAvatarVisual = {
|
|
|
18846
19074
|
for (const tentacleStroke of tentacleStrokes.filter((candidateTentacleStroke) => candidateTentacleStroke.isFrontFacing)) {
|
|
18847
19075
|
drawTentacleStroke(context, tentacleStroke, palette);
|
|
18848
19076
|
}
|
|
18849
|
-
|
|
19077
|
+
drawProjectedOrganicEye(context, {
|
|
18850
19078
|
x: -faceEyeSpacing,
|
|
18851
19079
|
y: faceEyeYOffset,
|
|
18852
19080
|
z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, -faceEyeSpacing, faceEyeYOffset),
|
|
18853
19081
|
}, faceEyeRadiusX, faceEyeRadiusY, mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + eyeRandom() * 0.6, interaction, morphologyProfile.face.eyeStyle);
|
|
18854
|
-
|
|
19082
|
+
drawProjectedOrganicEye(context, {
|
|
18855
19083
|
x: faceEyeSpacing,
|
|
18856
19084
|
y: faceEyeYOffset,
|
|
18857
19085
|
z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, faceEyeSpacing, faceEyeYOffset),
|
|
18858
19086
|
}, faceEyeRadiusX, faceEyeRadiusY, mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + 0.7 + eyeRandom() * 0.6, interaction, morphologyProfile.face.eyeStyle);
|
|
18859
|
-
|
|
19087
|
+
drawProjectedOrganicMouth(context, [
|
|
18860
19088
|
{
|
|
18861
19089
|
x: -mouthHalfWidth,
|
|
18862
19090
|
y: mouthY,
|
|
@@ -18943,7 +19171,7 @@ function resolveVisibleEllipsoidPatches(options) {
|
|
|
18943
19171
|
corners: projectedCorners,
|
|
18944
19172
|
averageDepth: transformedCorners.reduce((depthSum, transformedCorner) => depthSum + transformedCorner.z, 0) /
|
|
18945
19173
|
transformedCorners.length,
|
|
18946
|
-
lightIntensity: clampNumber$1(dotProduct3D(surfaceNormal, LIGHT_DIRECTION), -1, 1),
|
|
19174
|
+
lightIntensity: clampNumber$1(dotProduct3D(surfaceNormal, LIGHT_DIRECTION$1), -1, 1),
|
|
18947
19175
|
fillStyle: resolveSurfacePatchFillStyle(palette, verticalProgress + verticalColorBias),
|
|
18948
19176
|
outlineColor,
|
|
18949
19177
|
});
|
|
@@ -19125,128 +19353,260 @@ function resolveEllipsoidSurfaceDepth(radiusX, radiusY, radiusZ, x, y) {
|
|
|
19125
19353
|
const remainingDepthRatio = Math.max(0, 1 - normalizedX * normalizedX - normalizedY * normalizedY);
|
|
19126
19354
|
return Math.sqrt(remainingDepthRatio) * radiusZ;
|
|
19127
19355
|
}
|
|
19356
|
+
|
|
19357
|
+
/* eslint-disable no-magic-numbers */
|
|
19128
19358
|
/**
|
|
19129
|
-
*
|
|
19359
|
+
* Light direction used by the single-mesh octopus shading.
|
|
19130
19360
|
*
|
|
19131
|
-
* @private helper of `
|
|
19361
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
19132
19362
|
*/
|
|
19133
|
-
|
|
19134
|
-
|
|
19135
|
-
|
|
19136
|
-
|
|
19137
|
-
|
|
19138
|
-
|
|
19139
|
-
|
|
19140
|
-
|
|
19141
|
-
|
|
19142
|
-
|
|
19143
|
-
|
|
19144
|
-
|
|
19145
|
-
|
|
19146
|
-
|
|
19147
|
-
|
|
19148
|
-
|
|
19149
|
-
|
|
19150
|
-
|
|
19151
|
-
|
|
19152
|
-
|
|
19153
|
-
|
|
19154
|
-
|
|
19155
|
-
|
|
19363
|
+
const LIGHT_DIRECTION = normalizeVector3({
|
|
19364
|
+
x: 0.38,
|
|
19365
|
+
y: -0.6,
|
|
19366
|
+
z: 0.98,
|
|
19367
|
+
});
|
|
19368
|
+
/**
|
|
19369
|
+
* Octopus 3D 2 avatar visual.
|
|
19370
|
+
*
|
|
19371
|
+
* @private built-in avatar visual
|
|
19372
|
+
*/
|
|
19373
|
+
const octopus3d2AvatarVisual = {
|
|
19374
|
+
id: 'octopus3d2',
|
|
19375
|
+
title: 'Octopus 3D 2',
|
|
19376
|
+
description: 'Continuous blobby 3D octopus portrait with one soft mesh, turning silhouette, and cursor-aware eyes.',
|
|
19377
|
+
isAnimated: true,
|
|
19378
|
+
supportsPointerTracking: true,
|
|
19379
|
+
render({ context, size, palette, createRandom, timeMs, interaction }) {
|
|
19380
|
+
const morphologyProfile = createOctopus3MorphologyProfile(createRandom);
|
|
19381
|
+
const animationRandom = createRandom('octopus3d2-animation-profile');
|
|
19382
|
+
const eyeRandom = createRandom('octopus3d2-eye-profile');
|
|
19383
|
+
const animationPhase = animationRandom() * Math.PI * 2;
|
|
19384
|
+
const sceneCenterX = size * 0.5;
|
|
19385
|
+
const sceneCenterY = size * 0.575;
|
|
19386
|
+
const bob = Math.sin(timeMs / 940 + animationPhase) * size * 0.013;
|
|
19387
|
+
const meshCenter = {
|
|
19388
|
+
x: interaction.bodyOffsetX * size * 0.044 + size * morphologyProfile.body.centerXJitterRatio * 0.5,
|
|
19389
|
+
y: -size * 0.03 + interaction.bodyOffsetY * size * 0.026 + bob,
|
|
19390
|
+
z: interaction.intensity * size * 0.018,
|
|
19391
|
+
};
|
|
19392
|
+
const rotationY = -0.14 +
|
|
19393
|
+
Math.sin(timeMs / 2600 + animationPhase) * 0.04 +
|
|
19394
|
+
interaction.bodyOffsetX * 0.2 +
|
|
19395
|
+
interaction.gazeX * 0.78;
|
|
19396
|
+
const rotationX = -0.06 +
|
|
19397
|
+
Math.cos(timeMs / 3000 + animationPhase * 0.7) * 0.02 -
|
|
19398
|
+
interaction.bodyOffsetY * 0.08 -
|
|
19399
|
+
interaction.gazeY * 0.34;
|
|
19400
|
+
const surfaceOptions = {
|
|
19401
|
+
radiusX: size * morphologyProfile.body.bodyRadiusRatio * morphologyProfile.body.horizontalStretch * 1.02,
|
|
19402
|
+
radiusY: size * morphologyProfile.body.bodyRadiusRatio * morphologyProfile.body.verticalStretch * 1.22,
|
|
19403
|
+
radiusZ: size *
|
|
19404
|
+
morphologyProfile.body.bodyRadiusRatio *
|
|
19405
|
+
(0.98 + (morphologyProfile.body.horizontalStretch - 1) * 0.2),
|
|
19406
|
+
morphologyProfile,
|
|
19407
|
+
timeMs,
|
|
19408
|
+
animationPhase,
|
|
19409
|
+
};
|
|
19410
|
+
const surfacePatches = resolveVisibleBlobbyOctopusPatches({
|
|
19411
|
+
...surfaceOptions,
|
|
19412
|
+
center: meshCenter,
|
|
19413
|
+
rotationX,
|
|
19414
|
+
rotationY,
|
|
19415
|
+
sceneCenterX,
|
|
19416
|
+
sceneCenterY,
|
|
19417
|
+
size,
|
|
19418
|
+
palette,
|
|
19419
|
+
});
|
|
19420
|
+
const eyeLatitude = clampNumber$1(morphologyProfile.face.eyeCenterYOffsetRatio * 4.4, -0.16, 0.11);
|
|
19421
|
+
const eyeLongitude = clampNumber$1(morphologyProfile.face.eyeSpacingRatio * 3.25, 0.2, 0.34);
|
|
19422
|
+
const mouthLatitude = clampNumber$1(eyeLatitude + 0.19 + morphologyProfile.face.mouthYOffsetRatio * 1.08, 0.08, 0.34);
|
|
19423
|
+
const mouthCenterLongitude = clampNumber$1(morphologyProfile.face.mouthCenterOffsetRatio * 5.8, -0.08, 0.08);
|
|
19424
|
+
const mouthHalfLongitude = clampNumber$1(eyeLongitude * 0.82, 0.16, 0.29);
|
|
19425
|
+
const mouthCurveLatitude = clampNumber$1(mouthLatitude + morphologyProfile.face.mouthCurveDepthRatio * 0.85, mouthLatitude + 0.03, 0.42);
|
|
19426
|
+
drawAvatarFrame(context, size, palette);
|
|
19427
|
+
drawBlobbyOctopusAtmosphere(context, size, palette, sceneCenterX, sceneCenterY, interaction, timeMs);
|
|
19428
|
+
drawBlobbyOctopusShadow(context, size, palette, interaction, timeMs, morphologyProfile);
|
|
19429
|
+
for (const surfacePatch of surfacePatches.sort((firstSurfacePatch, secondSurfacePatch) => firstSurfacePatch.averageDepth - secondSurfacePatch.averageDepth)) {
|
|
19430
|
+
drawBlobbySurfacePatch(context, surfacePatch);
|
|
19431
|
+
}
|
|
19432
|
+
const leftEyeLocalCenter = sampleBlobbyOctopusSurfacePoint(surfaceOptions, eyeLatitude, -eyeLongitude);
|
|
19433
|
+
const rightEyeLocalCenter = sampleBlobbyOctopusSurfacePoint(surfaceOptions, eyeLatitude, eyeLongitude);
|
|
19434
|
+
const eyeRadiusX = size * morphologyProfile.face.eyeRadiusXRatio * 0.78;
|
|
19435
|
+
const eyeRadiusY = eyeRadiusX * morphologyProfile.face.eyeHeightRatio * 0.92;
|
|
19436
|
+
drawProjectedOrganicEye(context, leftEyeLocalCenter, eyeRadiusX, eyeRadiusY, meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + eyeRandom() * 0.7, interaction, morphologyProfile.face.eyeStyle);
|
|
19437
|
+
drawProjectedOrganicEye(context, rightEyeLocalCenter, eyeRadiusX, eyeRadiusY, meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + 0.9 + eyeRandom() * 0.7, interaction, morphologyProfile.face.eyeStyle);
|
|
19438
|
+
drawProjectedOrganicMouth(context, [
|
|
19439
|
+
sampleBlobbyOctopusSurfacePoint(surfaceOptions, mouthLatitude, mouthCenterLongitude - mouthHalfLongitude),
|
|
19440
|
+
sampleBlobbyOctopusSurfacePoint(surfaceOptions, mouthCurveLatitude, mouthCenterLongitude),
|
|
19441
|
+
sampleBlobbyOctopusSurfacePoint(surfaceOptions, mouthLatitude, mouthCenterLongitude + mouthHalfLongitude),
|
|
19442
|
+
], meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, palette, size);
|
|
19443
|
+
},
|
|
19444
|
+
};
|
|
19445
|
+
/**
|
|
19446
|
+
* Draws the deep-water glow behind the continuous octopus mesh.
|
|
19447
|
+
*
|
|
19448
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
19449
|
+
*/
|
|
19450
|
+
function drawBlobbyOctopusAtmosphere(context, size, palette, sceneCenterX, sceneCenterY, interaction, timeMs) {
|
|
19451
|
+
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);
|
|
19452
|
+
glowGradient.addColorStop(0, `${palette.highlight}5e`);
|
|
19453
|
+
glowGradient.addColorStop(0.38, `${palette.accent}26`);
|
|
19454
|
+
glowGradient.addColorStop(1, `${palette.highlight}00`);
|
|
19455
|
+
context.fillStyle = glowGradient;
|
|
19456
|
+
context.fillRect(0, 0, size, size);
|
|
19457
|
+
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);
|
|
19458
|
+
lowerGradient.addColorStop(0, `${palette.secondary}22`);
|
|
19459
|
+
lowerGradient.addColorStop(1, `${palette.secondary}00`);
|
|
19460
|
+
context.fillStyle = lowerGradient;
|
|
19461
|
+
context.fillRect(0, 0, size, size);
|
|
19462
|
+
}
|
|
19463
|
+
/**
|
|
19464
|
+
* Draws the soft floor shadow that anchors the single mesh in the frame.
|
|
19465
|
+
*
|
|
19466
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
19467
|
+
*/
|
|
19468
|
+
function drawBlobbyOctopusShadow(context, size, palette, interaction, timeMs, morphologyProfile) {
|
|
19156
19469
|
context.save();
|
|
19157
|
-
context.
|
|
19158
|
-
context.
|
|
19159
|
-
context.beginPath();
|
|
19160
|
-
context.ellipse(0, 0, projectedRadiusX, projectedRadiusY, 0, 0, Math.PI * 2);
|
|
19161
|
-
context.fillStyle = '#f8fbff';
|
|
19162
|
-
context.fill();
|
|
19163
|
-
context.clip();
|
|
19164
|
-
const irisGradient = context.createRadialGradient(-projectedRadiusX * 0.2, -projectedRadiusY * 0.26, projectedRadiusX * 0.05, 0, 0, projectedRadiusX * 0.92);
|
|
19165
|
-
irisGradient.addColorStop(0, palette.highlight);
|
|
19166
|
-
irisGradient.addColorStop(0.56, palette.secondary);
|
|
19167
|
-
irisGradient.addColorStop(1, palette.shadow);
|
|
19168
|
-
context.beginPath();
|
|
19169
|
-
context.ellipse(pupilOffsetX, pupilOffsetY, projectedRadiusX * 0.62 * eyeStyle.irisScale, projectedRadiusY * 0.72 * eyeStyle.irisScale, 0, 0, Math.PI * 2);
|
|
19170
|
-
context.fillStyle = irisGradient;
|
|
19171
|
-
context.fill();
|
|
19470
|
+
context.fillStyle = `${palette.shadow}66`;
|
|
19471
|
+
context.filter = `blur(${size * 0.024}px)`;
|
|
19172
19472
|
context.beginPath();
|
|
19173
|
-
context.ellipse(
|
|
19174
|
-
context.fillStyle = palette.ink;
|
|
19473
|
+
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);
|
|
19175
19474
|
context.fill();
|
|
19176
|
-
context.beginPath();
|
|
19177
|
-
context.ellipse(pupilOffsetX - projectedRadiusX * 0.22, pupilOffsetY - projectedRadiusY * 0.24, projectedRadiusX * 0.12, projectedRadiusY * 0.14, 0, 0, Math.PI * 2);
|
|
19178
|
-
context.fillStyle = '#ffffff';
|
|
19179
|
-
context.fill();
|
|
19180
|
-
context.restore();
|
|
19181
|
-
context.save();
|
|
19182
|
-
context.translate(projectedCenterPoint.x, projectedCenterPoint.y);
|
|
19183
|
-
context.rotate(rotation);
|
|
19184
|
-
context.beginPath();
|
|
19185
|
-
context.ellipse(0, 0, projectedRadiusX, projectedRadiusY, 0, 0, Math.PI * 2);
|
|
19186
|
-
context.strokeStyle = `${palette.shadow}cc`;
|
|
19187
|
-
context.lineWidth = projectedRadiusX * 0.16;
|
|
19188
|
-
context.stroke();
|
|
19189
|
-
context.beginPath();
|
|
19190
|
-
context.moveTo(-projectedRadiusX * 0.88, -projectedRadiusY * eyeStyle.upperLidInsetRatio);
|
|
19191
|
-
context.quadraticCurveTo(0, -projectedRadiusY * (eyeStyle.upperLidArchRatio - interaction.gazeY * 0.16 + interaction.intensity * 0.08), projectedRadiusX * 0.88, -projectedRadiusY * eyeStyle.upperLidInsetRatio);
|
|
19192
|
-
context.strokeStyle = `${palette.shadow}73`;
|
|
19193
|
-
context.lineWidth = projectedRadiusX * 0.14;
|
|
19194
|
-
context.lineCap = 'round';
|
|
19195
|
-
context.stroke();
|
|
19196
|
-
if (eyeStyle.lowerLidOpacity > 0) {
|
|
19197
|
-
context.beginPath();
|
|
19198
|
-
context.moveTo(-projectedRadiusX * 0.74, projectedRadiusY * 0.2);
|
|
19199
|
-
context.quadraticCurveTo(0, projectedRadiusY * 0.38, projectedRadiusX * 0.74, projectedRadiusY * 0.2);
|
|
19200
|
-
context.strokeStyle = `${palette.highlight}${formatAlphaHex(eyeStyle.lowerLidOpacity)}`;
|
|
19201
|
-
context.lineWidth = projectedRadiusX * 0.08;
|
|
19202
|
-
context.lineCap = 'round';
|
|
19203
|
-
context.stroke();
|
|
19204
|
-
}
|
|
19205
19475
|
context.restore();
|
|
19206
19476
|
}
|
|
19207
19477
|
/**
|
|
19208
|
-
*
|
|
19478
|
+
* Resolves all visible projected patches for the single blobby octopus mesh.
|
|
19209
19479
|
*
|
|
19210
|
-
* @private helper of `
|
|
19480
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
19211
19481
|
*/
|
|
19212
|
-
function
|
|
19213
|
-
const
|
|
19214
|
-
|
|
19215
|
-
|
|
19482
|
+
function resolveVisibleBlobbyOctopusPatches(options) {
|
|
19483
|
+
const { center, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, morphologyProfile, animationPhase, timeMs, } = options;
|
|
19484
|
+
const latitudePatchCount = 12;
|
|
19485
|
+
const longitudePatchCount = 24;
|
|
19486
|
+
const surfacePatches = [];
|
|
19487
|
+
for (let latitudeIndex = 0; latitudeIndex < latitudePatchCount; latitudeIndex++) {
|
|
19488
|
+
const startLatitude = -Math.PI / 2 + (latitudeIndex / latitudePatchCount) * Math.PI;
|
|
19489
|
+
const endLatitude = -Math.PI / 2 + ((latitudeIndex + 1) / latitudePatchCount) * Math.PI;
|
|
19490
|
+
const centerLatitude = (startLatitude + endLatitude) / 2;
|
|
19491
|
+
const verticalProgress = (Math.sin(centerLatitude) + 1) / 2;
|
|
19492
|
+
for (let longitudeIndex = 0; longitudeIndex < longitudePatchCount; longitudeIndex++) {
|
|
19493
|
+
const startLongitude = -Math.PI + (longitudeIndex / longitudePatchCount) * Math.PI * 2;
|
|
19494
|
+
const endLongitude = -Math.PI + ((longitudeIndex + 1) / longitudePatchCount) * Math.PI * 2;
|
|
19495
|
+
const centerLongitude = (startLongitude + endLongitude) / 2;
|
|
19496
|
+
const localCorners = [
|
|
19497
|
+
sampleBlobbyOctopusSurfacePoint(options, startLatitude, startLongitude),
|
|
19498
|
+
sampleBlobbyOctopusSurfacePoint(options, startLatitude, endLongitude),
|
|
19499
|
+
sampleBlobbyOctopusSurfacePoint(options, endLatitude, endLongitude),
|
|
19500
|
+
sampleBlobbyOctopusSurfacePoint(options, endLatitude, startLongitude),
|
|
19501
|
+
];
|
|
19502
|
+
const transformedCorners = localCorners.map((localCorner) => transformScenePoint(localCorner, center, rotationX, rotationY));
|
|
19503
|
+
const surfaceNormal = normalizeVector3(crossProduct3D(subtractPoint3D(transformedCorners[1], transformedCorners[0]), subtractPoint3D(transformedCorners[2], transformedCorners[0])));
|
|
19504
|
+
if (surfaceNormal.z <= 0.01) {
|
|
19505
|
+
continue;
|
|
19506
|
+
}
|
|
19507
|
+
const projectedCorners = transformedCorners.map((transformedCorner) => projectScenePoint(transformedCorner, size, sceneCenterX, sceneCenterY));
|
|
19508
|
+
surfacePatches.push({
|
|
19509
|
+
corners: projectedCorners,
|
|
19510
|
+
averageDepth: transformedCorners.reduce((depthSum, transformedCorner) => depthSum + transformedCorner.z, 0) /
|
|
19511
|
+
transformedCorners.length,
|
|
19512
|
+
lightIntensity: clampNumber$1(dotProduct3D(surfaceNormal, LIGHT_DIRECTION), -1, 1),
|
|
19513
|
+
fillStyle: resolveBlobbySurfacePatchFillStyle(palette, verticalProgress, Math.max(0, Math.cos(centerLongitude)), resolveLowerLobeWave(centerLongitude, morphologyProfile, animationPhase, timeMs)),
|
|
19514
|
+
outlineColor: verticalProgress < 0.58 ? `${palette.highlight}73` : `${palette.shadow}8a`,
|
|
19515
|
+
});
|
|
19516
|
+
}
|
|
19216
19517
|
}
|
|
19217
|
-
|
|
19218
|
-
context.beginPath();
|
|
19219
|
-
context.moveTo(projectedPoints[0].x, projectedPoints[0].y);
|
|
19220
|
-
context.quadraticCurveTo(projectedPoints[1].x, projectedPoints[1].y, projectedPoints[2].x, projectedPoints[2].y);
|
|
19221
|
-
context.strokeStyle = `${palette.ink}b8`;
|
|
19222
|
-
context.lineWidth = Math.max(1.1, size * 0.009);
|
|
19223
|
-
context.lineCap = 'round';
|
|
19224
|
-
context.stroke();
|
|
19518
|
+
return surfacePatches;
|
|
19225
19519
|
}
|
|
19226
19520
|
/**
|
|
19227
|
-
*
|
|
19521
|
+
* Samples one point on the continuous Octopus 3D 2 surface.
|
|
19522
|
+
*
|
|
19523
|
+
* The lower hemisphere widens and falls into soft lobe waves so the octopus stays one connected mesh
|
|
19524
|
+
* instead of switching to separately rendered tentacles.
|
|
19525
|
+
*
|
|
19526
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
19527
|
+
*/
|
|
19528
|
+
function sampleBlobbyOctopusSurfacePoint(options, latitude, longitude) {
|
|
19529
|
+
const { radiusX, radiusY, radiusZ, morphologyProfile, timeMs, animationPhase } = options;
|
|
19530
|
+
const cosineLatitude = Math.max(0, Math.cos(latitude));
|
|
19531
|
+
const verticalProgress = (Math.sin(latitude) + 1) / 2;
|
|
19532
|
+
const upperBlend = Math.pow(1 - verticalProgress, 1.2);
|
|
19533
|
+
const lowerBlend = Math.pow(verticalProgress, 1.42);
|
|
19534
|
+
const lowerLobeWave = resolveLowerLobeWave(longitude, morphologyProfile, animationPhase, timeMs);
|
|
19535
|
+
const skirtEnvelope = Math.pow(cosineLatitude, 0.5) * lowerBlend;
|
|
19536
|
+
const horizontalScale = 1.02 +
|
|
19537
|
+
skirtEnvelope * (0.34 + (morphologyProfile.tentacles.rootSpreadScale - 1) * 0.22 + lowerLobeWave * 0.22) -
|
|
19538
|
+
upperBlend * 0.08;
|
|
19539
|
+
const depthScale = 1.04 +
|
|
19540
|
+
upperBlend * 0.16 +
|
|
19541
|
+
Math.max(0, Math.cos(longitude)) * 0.1 +
|
|
19542
|
+
skirtEnvelope * (0.08 + lowerLobeWave * 0.06) -
|
|
19543
|
+
Math.max(0, -Math.cos(longitude)) * 0.04;
|
|
19544
|
+
const lowerDrop = skirtEnvelope *
|
|
19545
|
+
radiusY *
|
|
19546
|
+
(0.28 + lowerLobeWave * 0.14 + (morphologyProfile.tentacles.flowLengthScale - 1) * 0.12);
|
|
19547
|
+
const swayX = Math.sin(timeMs / 1250 + longitude * 1.8 + animationPhase) * skirtEnvelope * radiusX * 0.05;
|
|
19548
|
+
const swayZ = Math.cos(timeMs / 1480 + longitude * 1.2 - animationPhase * 0.7) * skirtEnvelope * radiusZ * 0.03;
|
|
19549
|
+
return {
|
|
19550
|
+
x: Math.sin(longitude) * cosineLatitude * radiusX * horizontalScale + swayX,
|
|
19551
|
+
y: Math.sin(latitude) * radiusY * (1 + upperBlend * 0.14) -
|
|
19552
|
+
upperBlend * radiusY * 0.1 +
|
|
19553
|
+
lowerDrop +
|
|
19554
|
+
Math.sin(timeMs / 1780 + animationPhase + latitude * 1.4) * skirtEnvelope * radiusY * 0.02,
|
|
19555
|
+
z: Math.cos(longitude) * cosineLatitude * radiusZ * depthScale + swayZ,
|
|
19556
|
+
};
|
|
19557
|
+
}
|
|
19558
|
+
/**
|
|
19559
|
+
* Resolves the soft lower-lobe wave that makes the silhouette read more like a real octopus.
|
|
19228
19560
|
*
|
|
19229
|
-
* @private helper of `
|
|
19561
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
19230
19562
|
*/
|
|
19231
|
-
function
|
|
19232
|
-
|
|
19233
|
-
|
|
19234
|
-
context.lineTo(corners[1].x, corners[1].y);
|
|
19235
|
-
context.lineTo(corners[2].x, corners[2].y);
|
|
19236
|
-
context.lineTo(corners[3].x, corners[3].y);
|
|
19237
|
-
context.closePath();
|
|
19238
|
-
context.fillStyle = fillStyle;
|
|
19239
|
-
context.fill();
|
|
19563
|
+
function resolveLowerLobeWave(longitude, morphologyProfile, animationPhase, timeMs) {
|
|
19564
|
+
const lobeCount = Math.max(4, Math.round((morphologyProfile.body.lobeCount + morphologyProfile.tentacles.count) / 2));
|
|
19565
|
+
return (Math.cos(longitude * lobeCount + animationPhase + timeMs / 1040) + 1) / 2;
|
|
19240
19566
|
}
|
|
19241
19567
|
/**
|
|
19242
|
-
*
|
|
19568
|
+
* Resolves one base fill tone for a surface patch on the single octopus mesh.
|
|
19243
19569
|
*
|
|
19244
|
-
* @private helper of `
|
|
19570
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
19245
19571
|
*/
|
|
19246
|
-
function
|
|
19247
|
-
|
|
19248
|
-
|
|
19249
|
-
.
|
|
19572
|
+
function resolveBlobbySurfacePatchFillStyle(palette, verticalProgress, forwardness, lowerLobeWave) {
|
|
19573
|
+
const tonalProgress = clampNumber$1(verticalProgress + lowerLobeWave * 0.12 - forwardness * 0.07, 0, 1);
|
|
19574
|
+
if (tonalProgress < 0.16) {
|
|
19575
|
+
return palette.highlight;
|
|
19576
|
+
}
|
|
19577
|
+
if (tonalProgress < 0.34) {
|
|
19578
|
+
return palette.secondary;
|
|
19579
|
+
}
|
|
19580
|
+
if (tonalProgress < 0.72) {
|
|
19581
|
+
return forwardness > 0.58 ? palette.secondary : palette.primary;
|
|
19582
|
+
}
|
|
19583
|
+
return `${palette.shadow}f2`;
|
|
19584
|
+
}
|
|
19585
|
+
/**
|
|
19586
|
+
* Draws one projected patch with soft octopus shading.
|
|
19587
|
+
*
|
|
19588
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
19589
|
+
*/
|
|
19590
|
+
function drawBlobbySurfacePatch(context, surfacePatch) {
|
|
19591
|
+
drawProjectedQuad(context, surfacePatch.corners, surfacePatch.fillStyle);
|
|
19592
|
+
if (surfacePatch.lightIntensity > 0) {
|
|
19593
|
+
drawProjectedQuad(context, surfacePatch.corners, `rgba(255, 255, 255, ${0.16 * surfacePatch.lightIntensity})`);
|
|
19594
|
+
}
|
|
19595
|
+
else if (surfacePatch.lightIntensity < 0) {
|
|
19596
|
+
drawProjectedQuad(context, surfacePatch.corners, `rgba(0, 0, 0, ${0.24 * Math.abs(surfacePatch.lightIntensity)})`);
|
|
19597
|
+
}
|
|
19598
|
+
context.save();
|
|
19599
|
+
context.beginPath();
|
|
19600
|
+
context.moveTo(surfacePatch.corners[0].x, surfacePatch.corners[0].y);
|
|
19601
|
+
for (let cornerIndex = 1; cornerIndex < surfacePatch.corners.length; cornerIndex++) {
|
|
19602
|
+
context.lineTo(surfacePatch.corners[cornerIndex].x, surfacePatch.corners[cornerIndex].y);
|
|
19603
|
+
}
|
|
19604
|
+
context.closePath();
|
|
19605
|
+
context.strokeStyle = surfacePatch.outlineColor;
|
|
19606
|
+
context.lineWidth = Math.max(1, getProjectedQuadPerimeter(surfacePatch.corners) * 0.0042);
|
|
19607
|
+
context.lineJoin = 'round';
|
|
19608
|
+
context.stroke();
|
|
19609
|
+
context.restore();
|
|
19250
19610
|
}
|
|
19251
19611
|
|
|
19252
19612
|
/* eslint-disable no-magic-numbers */
|
|
@@ -20018,6 +20378,7 @@ const AVATAR_VISUALS = [
|
|
|
20018
20378
|
octopus2AvatarVisual,
|
|
20019
20379
|
octopus3AvatarVisual,
|
|
20020
20380
|
octopus3dAvatarVisual,
|
|
20381
|
+
octopus3d2AvatarVisual,
|
|
20021
20382
|
asciiOctopusAvatarVisual,
|
|
20022
20383
|
minecraftAvatarVisual,
|
|
20023
20384
|
minecraft2AvatarVisual,
|
|
@@ -25593,11 +25954,11 @@ function buildCandidateEncodings(options) {
|
|
|
25593
25954
|
});
|
|
25594
25955
|
}
|
|
25595
25956
|
/**
|
|
25596
|
-
*
|
|
25957
|
+
* Prepares one attachment for best-effort text decoding.
|
|
25597
25958
|
*
|
|
25598
|
-
* @private
|
|
25959
|
+
* @private function of decodeAttachmentAsText
|
|
25599
25960
|
*/
|
|
25600
|
-
function
|
|
25961
|
+
function createDecodeAttachmentPreparation(input, options) {
|
|
25601
25962
|
var _a;
|
|
25602
25963
|
const maxBytes = Math.max(1, Math.floor((_a = options.maxBytes) !== null && _a !== void 0 ? _a : DEFAULT_ATTACHMENT_TEXT_DECODE_BYTES));
|
|
25603
25964
|
const forceText = options.forceText === true;
|
|
@@ -25611,54 +25972,102 @@ function decodeAttachmentAsText(input, options = {}) {
|
|
|
25611
25972
|
const inspection = inspectBytes(truncatedBytes);
|
|
25612
25973
|
const trustedTextMime = isTrustedTextMimeType(mimeType);
|
|
25613
25974
|
const trustedBinaryMime = isTrustedBinaryMimeType(mimeType);
|
|
25975
|
+
const shouldTreatAsBinary = (trustedBinaryMime || inspection.looksBinary) && !trustedTextMime;
|
|
25614
25976
|
if (isTruncated) {
|
|
25615
25977
|
warnings.push(`Decoded only the first ${maxBytes} bytes of \`${input.filename}\` because the attachment exceeded the text preview limit.`);
|
|
25616
25978
|
}
|
|
25617
|
-
|
|
25618
|
-
|
|
25619
|
-
|
|
25620
|
-
|
|
25621
|
-
|
|
25622
|
-
|
|
25623
|
-
|
|
25624
|
-
|
|
25625
|
-
|
|
25626
|
-
|
|
25627
|
-
|
|
25979
|
+
return {
|
|
25980
|
+
warnings,
|
|
25981
|
+
charset,
|
|
25982
|
+
bom,
|
|
25983
|
+
inspection,
|
|
25984
|
+
truncatedBytes,
|
|
25985
|
+
isTruncated,
|
|
25986
|
+
forceText,
|
|
25987
|
+
shouldTreatAsBinary,
|
|
25988
|
+
};
|
|
25989
|
+
}
|
|
25990
|
+
/**
|
|
25991
|
+
* Returns an early result when the attachment should stay classified as binary.
|
|
25992
|
+
*
|
|
25993
|
+
* @private function of decodeAttachmentAsText
|
|
25994
|
+
*/
|
|
25995
|
+
function createBinaryDecodeResult(preparation) {
|
|
25996
|
+
if (!preparation.shouldTreatAsBinary) {
|
|
25997
|
+
return null;
|
|
25628
25998
|
}
|
|
25629
|
-
if (
|
|
25630
|
-
warnings.push('File content looks binary, but text decoding was forced with `forceText`.');
|
|
25999
|
+
if (preparation.forceText) {
|
|
26000
|
+
preparation.warnings.push('File content looks binary, but text decoding was forced with `forceText`.');
|
|
26001
|
+
return null;
|
|
25631
26002
|
}
|
|
25632
|
-
|
|
25633
|
-
|
|
26003
|
+
preparation.warnings.push('File content looks binary, so text decoding was skipped.');
|
|
26004
|
+
return {
|
|
26005
|
+
text: '',
|
|
26006
|
+
encodingUsed: 'binary',
|
|
26007
|
+
confidence: 1,
|
|
26008
|
+
warnings: preparation.warnings,
|
|
26009
|
+
wasBinary: true,
|
|
26010
|
+
isTruncated: preparation.isTruncated,
|
|
26011
|
+
};
|
|
26012
|
+
}
|
|
26013
|
+
/**
|
|
26014
|
+
* Warns when the declared charset cannot be used by the runtime decoder.
|
|
26015
|
+
*
|
|
26016
|
+
* @private function of decodeAttachmentAsText
|
|
26017
|
+
*/
|
|
26018
|
+
function addUnsupportedCharsetWarning(preparation) {
|
|
26019
|
+
if (preparation.charset && !isSupportedEncoding(preparation.charset)) {
|
|
26020
|
+
preparation.warnings.push(`Ignored unsupported declared charset \`${preparation.charset}\` and used best-effort detection instead.`);
|
|
25634
26021
|
}
|
|
25635
|
-
|
|
25636
|
-
|
|
25637
|
-
|
|
25638
|
-
|
|
25639
|
-
|
|
25640
|
-
|
|
25641
|
-
|
|
25642
|
-
|
|
26022
|
+
}
|
|
26023
|
+
/**
|
|
26024
|
+
* Returns the byte slice that should actually be decoded as text.
|
|
26025
|
+
*
|
|
26026
|
+
* @private function of decodeAttachmentAsText
|
|
26027
|
+
*/
|
|
26028
|
+
function getBytesToDecode(preparation) {
|
|
26029
|
+
return preparation.bom ? preparation.truncatedBytes.subarray(preparation.bom.offset) : preparation.truncatedBytes;
|
|
26030
|
+
}
|
|
26031
|
+
/**
|
|
26032
|
+
* Decodes all candidate encodings and sorts the successful results by score.
|
|
26033
|
+
*
|
|
26034
|
+
* @private function of decodeAttachmentAsText
|
|
26035
|
+
*/
|
|
26036
|
+
function decodeAttachmentCandidates(preparation) {
|
|
26037
|
+
return buildCandidateEncodings({
|
|
26038
|
+
charset: preparation.charset && isSupportedEncoding(preparation.charset) ? preparation.charset : null,
|
|
26039
|
+
bom: preparation.bom,
|
|
26040
|
+
inspection: preparation.inspection,
|
|
26041
|
+
})
|
|
25643
26042
|
.map(({ encoding, source }) => {
|
|
25644
|
-
const decoded = decodeWithEncoding(
|
|
26043
|
+
const decoded = decodeWithEncoding(getBytesToDecode(preparation), encoding);
|
|
25645
26044
|
return decoded ? { ...decoded, source } : null;
|
|
25646
26045
|
})
|
|
25647
26046
|
.filter((candidate) => candidate !== null)
|
|
25648
26047
|
.sort((left, right) => left.score - right.score);
|
|
25649
|
-
|
|
25650
|
-
|
|
25651
|
-
|
|
25652
|
-
|
|
25653
|
-
|
|
25654
|
-
|
|
25655
|
-
|
|
25656
|
-
|
|
25657
|
-
|
|
25658
|
-
|
|
25659
|
-
|
|
25660
|
-
|
|
25661
|
-
|
|
26048
|
+
}
|
|
26049
|
+
/**
|
|
26050
|
+
* Returns the fallback result used when no text decoder could be applied.
|
|
26051
|
+
*
|
|
26052
|
+
* @private function of decodeAttachmentAsText
|
|
26053
|
+
*/
|
|
26054
|
+
function createNoDecoderAvailableResult(preparation) {
|
|
26055
|
+
preparation.warnings.push('No supported text decoder was available.');
|
|
26056
|
+
return {
|
|
26057
|
+
text: '',
|
|
26058
|
+
encodingUsed: 'binary',
|
|
26059
|
+
confidence: 0,
|
|
26060
|
+
warnings: preparation.warnings,
|
|
26061
|
+
wasBinary: true,
|
|
26062
|
+
isTruncated: preparation.isTruncated,
|
|
26063
|
+
};
|
|
26064
|
+
}
|
|
26065
|
+
/**
|
|
26066
|
+
* Estimates confidence for the winning decoded text candidate.
|
|
26067
|
+
*
|
|
26068
|
+
* @private function of decodeAttachmentAsText
|
|
26069
|
+
*/
|
|
26070
|
+
function computeDecodeConfidence(bestCandidate, secondBestCandidate, preparation) {
|
|
25662
26071
|
const baseConfidence = bestCandidate.source === 'bom'
|
|
25663
26072
|
? 1
|
|
25664
26073
|
: bestCandidate.source === 'charset'
|
|
@@ -25671,27 +26080,62 @@ function decodeAttachmentAsText(input, options = {}) {
|
|
|
25671
26080
|
? 0.82
|
|
25672
26081
|
: 0.62;
|
|
25673
26082
|
const scoreMargin = secondBestCandidate ? Math.max(0, secondBestCandidate.score - bestCandidate.score) : 0.2;
|
|
25674
|
-
|
|
26083
|
+
return Math.max(0.2, Math.min(preparation.shouldTreatAsBinary && preparation.forceText ? 0.45 : 1, baseConfidence + Math.min(0.18, scoreMargin / 2)));
|
|
26084
|
+
}
|
|
26085
|
+
/**
|
|
26086
|
+
* Appends user-facing warnings derived from the chosen decoded text candidate.
|
|
26087
|
+
*
|
|
26088
|
+
* @private function of decodeAttachmentAsText
|
|
26089
|
+
*/
|
|
26090
|
+
function addDecodeWarnings(bestCandidate, confidence, preparation) {
|
|
25675
26091
|
if (bestCandidate.source === 'heuristic' && bestCandidate.encoding !== 'utf-8') {
|
|
25676
|
-
warnings.push(`Encoding was guessed as \`${bestCandidate.encoding}\`.`);
|
|
26092
|
+
preparation.warnings.push(`Encoding was guessed as \`${bestCandidate.encoding}\`.`);
|
|
25677
26093
|
}
|
|
25678
26094
|
if (bestCandidate.source === 'heuristic' &&
|
|
25679
26095
|
bestCandidate.encoding === 'utf-8' &&
|
|
25680
26096
|
bestCandidate.replacementCount > 0) {
|
|
25681
|
-
warnings.push('UTF-8 decoding produced replacement characters, so the extracted text may contain errors.');
|
|
26097
|
+
preparation.warnings.push('UTF-8 decoding produced replacement characters, so the extracted text may contain errors.');
|
|
25682
26098
|
}
|
|
25683
26099
|
if (confidence < 0.6) {
|
|
25684
|
-
warnings.push('Decoding confidence is low, so the extracted text may contain errors.');
|
|
26100
|
+
preparation.warnings.push('Decoding confidence is low, so the extracted text may contain errors.');
|
|
25685
26101
|
}
|
|
26102
|
+
}
|
|
26103
|
+
/**
|
|
26104
|
+
* Creates the final decoded-text result from the chosen candidate and accumulated metadata.
|
|
26105
|
+
*
|
|
26106
|
+
* @private function of decodeAttachmentAsText
|
|
26107
|
+
*/
|
|
26108
|
+
function createDecodedTextResult(bestCandidate, confidence, preparation) {
|
|
25686
26109
|
return {
|
|
25687
|
-
text: isTruncated ? appendTruncatedMarker(bestCandidate.text) : bestCandidate.text,
|
|
26110
|
+
text: preparation.isTruncated ? appendTruncatedMarker(bestCandidate.text) : bestCandidate.text,
|
|
25688
26111
|
encodingUsed: bestCandidate.encoding,
|
|
25689
26112
|
confidence,
|
|
25690
|
-
warnings,
|
|
26113
|
+
warnings: preparation.warnings,
|
|
25691
26114
|
wasBinary: false,
|
|
25692
|
-
isTruncated,
|
|
26115
|
+
isTruncated: preparation.isTruncated,
|
|
25693
26116
|
};
|
|
25694
26117
|
}
|
|
26118
|
+
/**
|
|
26119
|
+
* Best-effort decoder for uploaded or remote file bytes whose extension or encoding may be unknown.
|
|
26120
|
+
*
|
|
26121
|
+
* @private internal utility for shared text decoding
|
|
26122
|
+
*/
|
|
26123
|
+
function decodeAttachmentAsText(input, options = {}) {
|
|
26124
|
+
const preparation = createDecodeAttachmentPreparation(input, options);
|
|
26125
|
+
const binaryResult = createBinaryDecodeResult(preparation);
|
|
26126
|
+
if (binaryResult) {
|
|
26127
|
+
return binaryResult;
|
|
26128
|
+
}
|
|
26129
|
+
addUnsupportedCharsetWarning(preparation);
|
|
26130
|
+
const decodedCandidates = decodeAttachmentCandidates(preparation);
|
|
26131
|
+
const bestCandidate = decodedCandidates[0];
|
|
26132
|
+
if (!bestCandidate) {
|
|
26133
|
+
return createNoDecoderAvailableResult(preparation);
|
|
26134
|
+
}
|
|
26135
|
+
const confidence = computeDecodeConfidence(bestCandidate, decodedCandidates[1], preparation);
|
|
26136
|
+
addDecodeWarnings(bestCandidate, confidence, preparation);
|
|
26137
|
+
return createDecodedTextResult(bestCandidate, confidence, preparation);
|
|
26138
|
+
}
|
|
25695
26139
|
|
|
25696
26140
|
/**
|
|
25697
26141
|
* Base GitHub API URL.
|
|
@@ -30237,10 +30681,7 @@ function createAvailableProviderMessage(llmToolStatus, index, env) {
|
|
|
30237
30681
|
* @private internal function of `$registeredLlmToolsMessage`
|
|
30238
30682
|
*/
|
|
30239
30683
|
function createProviderStatusMessages(llmToolStatus, env) {
|
|
30240
|
-
return [
|
|
30241
|
-
createInstallationStatusMessage(llmToolStatus),
|
|
30242
|
-
createConfigurationStatusMessage(llmToolStatus, env),
|
|
30243
|
-
];
|
|
30684
|
+
return [createInstallationStatusMessage(llmToolStatus), createConfigurationStatusMessage(llmToolStatus, env)];
|
|
30244
30685
|
}
|
|
30245
30686
|
/**
|
|
30246
30687
|
* Creates the installation-status sentence for one provider.
|
|
@@ -37756,7 +38197,10 @@ class OpenAiCompatibleModelCatalog {
|
|
|
37756
38197
|
Cannot find model in ${this.options.getTitle()} models with name "${defaultModelName}" which should be used as default.
|
|
37757
38198
|
|
|
37758
38199
|
Available models:
|
|
37759
|
-
${block(this.options
|
|
38200
|
+
${block(this.options
|
|
38201
|
+
.getHardcodedModels()
|
|
38202
|
+
.map(({ modelName }) => `- "${modelName}"`)
|
|
38203
|
+
.join('\n'))}
|
|
37760
38204
|
|
|
37761
38205
|
Model "${defaultModelName}" is probably not available anymore, not installed, inaccessible or misconfigured.
|
|
37762
38206
|
|
|
@@ -38110,7 +38554,8 @@ class OpenAiCompatibleNonChatPromptCaller {
|
|
|
38110
38554
|
};
|
|
38111
38555
|
let rawPromptContent = templateParameters(content, { ...parameters, modelName });
|
|
38112
38556
|
if ('attachments' in prompt && Array.isArray(prompt.attachments) && prompt.attachments.length > 0) {
|
|
38113
|
-
rawPromptContent +=
|
|
38557
|
+
rawPromptContent +=
|
|
38558
|
+
'\n\n' + prompt.attachments.map((attachment) => `Image attachment: ${attachment.url}`).join('\n');
|
|
38114
38559
|
}
|
|
38115
38560
|
const rawRequest = {
|
|
38116
38561
|
...modelSettings,
|
|
@@ -38215,7 +38660,9 @@ class OpenAiCompatibleRequestManager {
|
|
|
38215
38660
|
* Schedules one request through the shared limiter and retry policy.
|
|
38216
38661
|
*/
|
|
38217
38662
|
async executeRateLimitedRequest(requestFn) {
|
|
38218
|
-
return this.limiter
|
|
38663
|
+
return this.limiter
|
|
38664
|
+
.schedule(() => this.makeRequestWithNetworkRetry(requestFn))
|
|
38665
|
+
.catch((error) => {
|
|
38219
38666
|
assertsError(error);
|
|
38220
38667
|
if (this.options.isVerbose) {
|
|
38221
38668
|
console.info(colors.bgRed('error'), error);
|
|
@@ -39422,7 +39869,9 @@ class OpenAiVectorStoreFileBatchPoller {
|
|
|
39422
39869
|
pollingState.lastProgressAtMs = nowMs;
|
|
39423
39870
|
pollingState.lastProgressKey = progressKey;
|
|
39424
39871
|
}
|
|
39425
|
-
if (this.options.isVerbose &&
|
|
39872
|
+
if (this.options.isVerbose &&
|
|
39873
|
+
(statusCountsKey !== pollingState.lastCountsKey ||
|
|
39874
|
+
nowMs - pollingState.lastLogAtMs >= progressLogIntervalMs)) {
|
|
39426
39875
|
console.info('[🤰]', 'Vector store file batch status', {
|
|
39427
39876
|
vectorStoreId,
|
|
39428
39877
|
batchId,
|