@promptbook/node 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/umd/index.umd.js
CHANGED
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
* @generated
|
|
49
49
|
* @see https://github.com/webgptorg/promptbook
|
|
50
50
|
*/
|
|
51
|
-
const PROMPTBOOK_ENGINE_VERSION = '0.112.0-
|
|
51
|
+
const PROMPTBOOK_ENGINE_VERSION = '0.112.0-80';
|
|
52
52
|
/**
|
|
53
53
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
|
54
54
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -298,6 +298,111 @@
|
|
|
298
298
|
}
|
|
299
299
|
}
|
|
300
300
|
|
|
301
|
+
/**
|
|
302
|
+
* Shared immutable channel storage and serialization helpers for `Color`.
|
|
303
|
+
*
|
|
304
|
+
* @private base class of Color
|
|
305
|
+
*/
|
|
306
|
+
class ColorValue {
|
|
307
|
+
constructor(red, green, blue, alpha = 255) {
|
|
308
|
+
this.red = red;
|
|
309
|
+
this.green = green;
|
|
310
|
+
this.blue = blue;
|
|
311
|
+
this.alpha = alpha;
|
|
312
|
+
checkChannelValue('Red', red);
|
|
313
|
+
checkChannelValue('Green', green);
|
|
314
|
+
checkChannelValue('Blue', blue);
|
|
315
|
+
checkChannelValue('Alpha', alpha);
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Shortcut for `red` property
|
|
319
|
+
* Number from 0 to 255
|
|
320
|
+
* @alias red
|
|
321
|
+
*/
|
|
322
|
+
get r() {
|
|
323
|
+
return this.red;
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Shortcut for `green` property
|
|
327
|
+
* Number from 0 to 255
|
|
328
|
+
* @alias green
|
|
329
|
+
*/
|
|
330
|
+
get g() {
|
|
331
|
+
return this.green;
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Shortcut for `blue` property
|
|
335
|
+
* Number from 0 to 255
|
|
336
|
+
* @alias blue
|
|
337
|
+
*/
|
|
338
|
+
get b() {
|
|
339
|
+
return this.blue;
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* Shortcut for `alpha` property
|
|
343
|
+
* Number from 0 (transparent) to 255 (opaque)
|
|
344
|
+
* @alias alpha
|
|
345
|
+
*/
|
|
346
|
+
get a() {
|
|
347
|
+
return this.alpha;
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Shortcut for `alpha` property
|
|
351
|
+
* Number from 0 (transparent) to 255 (opaque)
|
|
352
|
+
* @alias alpha
|
|
353
|
+
*/
|
|
354
|
+
get opacity() {
|
|
355
|
+
return this.alpha;
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* Shortcut for 1-`alpha` property
|
|
359
|
+
*/
|
|
360
|
+
get transparency() {
|
|
361
|
+
return 255 - this.alpha;
|
|
362
|
+
}
|
|
363
|
+
clone() {
|
|
364
|
+
return take(this.createColor(this.red, this.green, this.blue, this.alpha));
|
|
365
|
+
}
|
|
366
|
+
toString() {
|
|
367
|
+
return this.toHex();
|
|
368
|
+
}
|
|
369
|
+
toHex() {
|
|
370
|
+
if (this.alpha === 255) {
|
|
371
|
+
return `#${this.red.toString(16).padStart(2, '0')}${this.green.toString(16).padStart(2, '0')}${this.blue
|
|
372
|
+
.toString(16)
|
|
373
|
+
.padStart(2, '0')}`;
|
|
374
|
+
}
|
|
375
|
+
else {
|
|
376
|
+
return `#${this.red.toString(16).padStart(2, '0')}${this.green.toString(16).padStart(2, '0')}${this.blue
|
|
377
|
+
.toString(16)
|
|
378
|
+
.padStart(2, '0')}${this.alpha.toString(16).padStart(2, '0')}`;
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
toRgb() {
|
|
382
|
+
if (this.alpha === 255) {
|
|
383
|
+
return `rgb(${this.red}, ${this.green}, ${this.blue})`;
|
|
384
|
+
}
|
|
385
|
+
else {
|
|
386
|
+
return `rgba(${this.red}, ${this.green}, ${this.blue}, ${Math.round((this.alpha / 255) * 100)}%)`;
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
toHsl() {
|
|
390
|
+
throw new Error(`Getting HSL is not implemented`);
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* Checks if the given value is a valid hex color string
|
|
396
|
+
*
|
|
397
|
+
* @param value - value to check
|
|
398
|
+
* @returns true if the value is a valid hex color string (e.g., `#009edd`, `#fff`, etc.)
|
|
399
|
+
*
|
|
400
|
+
* @private function of Color
|
|
401
|
+
*/
|
|
402
|
+
function isHexColorString(value) {
|
|
403
|
+
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));
|
|
404
|
+
}
|
|
405
|
+
|
|
301
406
|
/**
|
|
302
407
|
* Constant for short hex lengths.
|
|
303
408
|
*/
|
|
@@ -509,16 +614,53 @@
|
|
|
509
614
|
|
|
510
615
|
/**
|
|
511
616
|
* Pattern matching hsl regex.
|
|
617
|
+
*
|
|
618
|
+
* @private function of Color
|
|
512
619
|
*/
|
|
513
620
|
const HSL_REGEX_PATTERN = /^hsl\(\s*([0-9.]+)\s*,\s*([0-9.]+)%\s*,\s*([0-9.]+)%\s*\)$/;
|
|
514
621
|
/**
|
|
515
622
|
* Pattern matching RGB regex.
|
|
623
|
+
*
|
|
624
|
+
* @private function of Color
|
|
516
625
|
*/
|
|
517
626
|
const RGB_REGEX_PATTERN = /^rgb\(\s*([0-9.%-]+)\s*,\s*([0-9.%-]+)\s*,\s*([0-9.%-]+)\s*\)$/;
|
|
518
627
|
/**
|
|
519
628
|
* Pattern matching rgba regex.
|
|
629
|
+
*
|
|
630
|
+
* @private function of Color
|
|
520
631
|
*/
|
|
521
632
|
const RGBA_REGEX_PATTERN = /^rgba\(\s*([0-9.%-]+)\s*,\s*([0-9.%-]+)\s*,\s*([0-9.%-]+)\s*,\s*([0-9.%-]+)\s*\)$/;
|
|
633
|
+
/**
|
|
634
|
+
* Parses a supported color string into RGBA channels.
|
|
635
|
+
*
|
|
636
|
+
* @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`,...
|
|
637
|
+
* @returns RGBA channel values.
|
|
638
|
+
*
|
|
639
|
+
* @private function of Color
|
|
640
|
+
*/
|
|
641
|
+
function parseColorString(color) {
|
|
642
|
+
const trimmed = color.trim();
|
|
643
|
+
const cssColor = CSS_COLORS[trimmed];
|
|
644
|
+
if (cssColor) {
|
|
645
|
+
return parseColorString(cssColor);
|
|
646
|
+
}
|
|
647
|
+
else if (isHexColorString(trimmed)) {
|
|
648
|
+
return parseHexColor(trimmed);
|
|
649
|
+
}
|
|
650
|
+
if (HSL_REGEX_PATTERN.test(trimmed)) {
|
|
651
|
+
return parseHslColor(trimmed);
|
|
652
|
+
}
|
|
653
|
+
else if (RGB_REGEX_PATTERN.test(trimmed)) {
|
|
654
|
+
return parseRgbColor(trimmed);
|
|
655
|
+
}
|
|
656
|
+
else if (RGBA_REGEX_PATTERN.test(trimmed)) {
|
|
657
|
+
return parseRgbaColor(trimmed);
|
|
658
|
+
}
|
|
659
|
+
else {
|
|
660
|
+
throw new Error(`Can not create a new Color instance from string "${trimmed}".`);
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
|
|
522
664
|
/**
|
|
523
665
|
* Color object represents an RGB color with alpha channel
|
|
524
666
|
*
|
|
@@ -526,7 +668,7 @@
|
|
|
526
668
|
*
|
|
527
669
|
* @public exported from `@promptbook/color`
|
|
528
670
|
*/
|
|
529
|
-
class Color {
|
|
671
|
+
class Color extends ColorValue {
|
|
530
672
|
/**
|
|
531
673
|
* Creates a new Color instance from miscellaneous formats
|
|
532
674
|
* - It can receive Color instance and just return the same instance
|
|
@@ -599,25 +741,7 @@
|
|
|
599
741
|
* @returns Color object
|
|
600
742
|
*/
|
|
601
743
|
static fromString(color) {
|
|
602
|
-
|
|
603
|
-
if (CSS_COLORS[trimmed]) {
|
|
604
|
-
return Color.fromString(CSS_COLORS[trimmed]);
|
|
605
|
-
}
|
|
606
|
-
else if (Color.isHexColorString(trimmed)) {
|
|
607
|
-
return Color.fromHex(trimmed);
|
|
608
|
-
}
|
|
609
|
-
if (HSL_REGEX_PATTERN.test(trimmed)) {
|
|
610
|
-
return Color.fromHsl(trimmed);
|
|
611
|
-
}
|
|
612
|
-
else if (RGB_REGEX_PATTERN.test(trimmed)) {
|
|
613
|
-
return Color.fromRgbString(trimmed);
|
|
614
|
-
}
|
|
615
|
-
else if (RGBA_REGEX_PATTERN.test(trimmed)) {
|
|
616
|
-
return Color.fromRgbaString(trimmed);
|
|
617
|
-
}
|
|
618
|
-
else {
|
|
619
|
-
throw new Error(`Can not create a new Color instance from string "${trimmed}".`);
|
|
620
|
-
}
|
|
744
|
+
return Color.fromColorChannels(parseColorString(color));
|
|
621
745
|
}
|
|
622
746
|
/**
|
|
623
747
|
* Gets common color
|
|
@@ -647,8 +771,7 @@
|
|
|
647
771
|
* @returns Color object
|
|
648
772
|
*/
|
|
649
773
|
static fromHex(hex) {
|
|
650
|
-
|
|
651
|
-
return take(new Color(red, green, blue, alpha));
|
|
774
|
+
return Color.fromColorChannels(parseHexColor(hex));
|
|
652
775
|
}
|
|
653
776
|
/**
|
|
654
777
|
* Creates a new Color instance from color in hsl format
|
|
@@ -657,8 +780,7 @@
|
|
|
657
780
|
* @returns Color object
|
|
658
781
|
*/
|
|
659
782
|
static fromHsl(hsl) {
|
|
660
|
-
|
|
661
|
-
return take(new Color(red, green, blue, alpha));
|
|
783
|
+
return Color.fromColorChannels(parseHslColor(hsl));
|
|
662
784
|
}
|
|
663
785
|
/**
|
|
664
786
|
* Creates a new Color instance from color in rgb format
|
|
@@ -667,8 +789,7 @@
|
|
|
667
789
|
* @returns Color object
|
|
668
790
|
*/
|
|
669
791
|
static fromRgbString(rgb) {
|
|
670
|
-
|
|
671
|
-
return take(new Color(red, green, blue, alpha));
|
|
792
|
+
return Color.fromColorChannels(parseRgbColor(rgb));
|
|
672
793
|
}
|
|
673
794
|
/**
|
|
674
795
|
* Creates a new Color instance from color in rbga format
|
|
@@ -677,8 +798,7 @@
|
|
|
677
798
|
* @returns Color object
|
|
678
799
|
*/
|
|
679
800
|
static fromRgbaString(rgba) {
|
|
680
|
-
|
|
681
|
-
return take(new Color(red, green, blue, alpha));
|
|
801
|
+
return Color.fromColorChannels(parseRgbaColor(rgba));
|
|
682
802
|
}
|
|
683
803
|
/**
|
|
684
804
|
* Creates a new Color for color channels values
|
|
@@ -690,7 +810,7 @@
|
|
|
690
810
|
* @returns Color object
|
|
691
811
|
*/
|
|
692
812
|
static fromValues(red, green, blue, alpha = 255) {
|
|
693
|
-
return
|
|
813
|
+
return Color.fromColorChannels({ red, green, blue, alpha });
|
|
694
814
|
}
|
|
695
815
|
/**
|
|
696
816
|
* Checks if the given value is a valid Color object.
|
|
@@ -723,8 +843,7 @@
|
|
|
723
843
|
* @returns true if the value is a valid hex color string (e.g., `#009edd`, `#fff`, etc.)
|
|
724
844
|
*/
|
|
725
845
|
static isHexColorString(value) {
|
|
726
|
-
return (
|
|
727
|
-
/^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/.test(value));
|
|
846
|
+
return isHexColorString(value);
|
|
728
847
|
}
|
|
729
848
|
/**
|
|
730
849
|
* Creates new Color object
|
|
@@ -737,89 +856,13 @@
|
|
|
737
856
|
* @param alpha number from 0 (transparent) to 255 (opaque)
|
|
738
857
|
*/
|
|
739
858
|
constructor(red, green, blue, alpha = 255) {
|
|
740
|
-
|
|
741
|
-
this.green = green;
|
|
742
|
-
this.blue = blue;
|
|
743
|
-
this.alpha = alpha;
|
|
744
|
-
checkChannelValue('Red', red);
|
|
745
|
-
checkChannelValue('Green', green);
|
|
746
|
-
checkChannelValue('Blue', blue);
|
|
747
|
-
checkChannelValue('Alpha', alpha);
|
|
748
|
-
}
|
|
749
|
-
/**
|
|
750
|
-
* Shortcut for `red` property
|
|
751
|
-
* Number from 0 to 255
|
|
752
|
-
* @alias red
|
|
753
|
-
*/
|
|
754
|
-
get r() {
|
|
755
|
-
return this.red;
|
|
756
|
-
}
|
|
757
|
-
/**
|
|
758
|
-
* Shortcut for `green` property
|
|
759
|
-
* Number from 0 to 255
|
|
760
|
-
* @alias green
|
|
761
|
-
*/
|
|
762
|
-
get g() {
|
|
763
|
-
return this.green;
|
|
764
|
-
}
|
|
765
|
-
/**
|
|
766
|
-
* Shortcut for `blue` property
|
|
767
|
-
* Number from 0 to 255
|
|
768
|
-
* @alias blue
|
|
769
|
-
*/
|
|
770
|
-
get b() {
|
|
771
|
-
return this.blue;
|
|
772
|
-
}
|
|
773
|
-
/**
|
|
774
|
-
* Shortcut for `alpha` property
|
|
775
|
-
* Number from 0 (transparent) to 255 (opaque)
|
|
776
|
-
* @alias alpha
|
|
777
|
-
*/
|
|
778
|
-
get a() {
|
|
779
|
-
return this.alpha;
|
|
780
|
-
}
|
|
781
|
-
/**
|
|
782
|
-
* Shortcut for `alpha` property
|
|
783
|
-
* Number from 0 (transparent) to 255 (opaque)
|
|
784
|
-
* @alias alpha
|
|
785
|
-
*/
|
|
786
|
-
get opacity() {
|
|
787
|
-
return this.alpha;
|
|
788
|
-
}
|
|
789
|
-
/**
|
|
790
|
-
* Shortcut for 1-`alpha` property
|
|
791
|
-
*/
|
|
792
|
-
get transparency() {
|
|
793
|
-
return 255 - this.alpha;
|
|
794
|
-
}
|
|
795
|
-
clone() {
|
|
796
|
-
return take(new Color(this.red, this.green, this.blue, this.alpha));
|
|
797
|
-
}
|
|
798
|
-
toString() {
|
|
799
|
-
return this.toHex();
|
|
800
|
-
}
|
|
801
|
-
toHex() {
|
|
802
|
-
if (this.alpha === 255) {
|
|
803
|
-
return `#${this.red.toString(16).padStart(2, '0')}${this.green.toString(16).padStart(2, '0')}${this.blue
|
|
804
|
-
.toString(16)
|
|
805
|
-
.padStart(2, '0')}`;
|
|
806
|
-
}
|
|
807
|
-
else {
|
|
808
|
-
return `#${this.red.toString(16).padStart(2, '0')}${this.green.toString(16).padStart(2, '0')}${this.blue
|
|
809
|
-
.toString(16)
|
|
810
|
-
.padStart(2, '0')}${this.alpha.toString(16).padStart(2, '0')}`;
|
|
811
|
-
}
|
|
859
|
+
super(red, green, blue, alpha);
|
|
812
860
|
}
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
return `rgb(${this.red}, ${this.green}, ${this.blue})`;
|
|
816
|
-
}
|
|
817
|
-
else {
|
|
818
|
-
return `rgba(${this.red}, ${this.green}, ${this.blue}, ${Math.round((this.alpha / 255) * 100)}%)`;
|
|
819
|
-
}
|
|
861
|
+
createColor(red, green, blue, alpha) {
|
|
862
|
+
return new Color(red, green, blue, alpha);
|
|
820
863
|
}
|
|
821
|
-
|
|
822
|
-
|
|
864
|
+
static fromColorChannels({ red, green, blue, alpha }) {
|
|
865
|
+
return take(new Color(red, green, blue, alpha));
|
|
823
866
|
}
|
|
824
867
|
}
|
|
825
868
|
|
|
@@ -1504,120 +1547,183 @@
|
|
|
1504
1547
|
* @public exported from `@promptbook/utils`
|
|
1505
1548
|
*/
|
|
1506
1549
|
function checkSerializableAsJson(options) {
|
|
1507
|
-
|
|
1550
|
+
checkSerializableValue(options);
|
|
1551
|
+
}
|
|
1552
|
+
// TODO: Can be return type more type-safe? like `asserts options.value is JsonValue`
|
|
1553
|
+
// TODO: [🧠][main] !!3 In-memory cache of same values to prevent multiple checks
|
|
1554
|
+
// Note: [🐠] This is how `checkSerializableAsJson` + `isSerializableAsJson` together can just retun true/false or rich error message
|
|
1555
|
+
/**
|
|
1556
|
+
* Checks one value and dispatches to the appropriate specialized validator.
|
|
1557
|
+
*
|
|
1558
|
+
* @private function of `checkSerializableAsJson`
|
|
1559
|
+
*/
|
|
1560
|
+
function checkSerializableValue(options) {
|
|
1561
|
+
const { value } = options;
|
|
1562
|
+
if (isSerializablePrimitive(value)) {
|
|
1563
|
+
return;
|
|
1564
|
+
}
|
|
1508
1565
|
if (value === undefined) {
|
|
1509
|
-
throw new UnexpectedError(`${name} is undefined`);
|
|
1566
|
+
throw new UnexpectedError(`${options.name} is undefined`);
|
|
1510
1567
|
}
|
|
1511
|
-
|
|
1512
|
-
|
|
1568
|
+
if (typeof value === 'symbol') {
|
|
1569
|
+
throw new UnexpectedError(`${options.name} is symbol`);
|
|
1513
1570
|
}
|
|
1514
|
-
|
|
1515
|
-
|
|
1571
|
+
if (typeof value === 'function') {
|
|
1572
|
+
throw new UnexpectedError(`${options.name} is function`);
|
|
1516
1573
|
}
|
|
1517
|
-
|
|
1574
|
+
if (Array.isArray(value)) {
|
|
1575
|
+
checkSerializableArray(options, value);
|
|
1518
1576
|
return;
|
|
1519
1577
|
}
|
|
1520
|
-
|
|
1578
|
+
if (value !== null && typeof value === 'object') {
|
|
1579
|
+
checkSerializableObject(options, value);
|
|
1521
1580
|
return;
|
|
1522
1581
|
}
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1582
|
+
throwUnknownTypeError(options);
|
|
1583
|
+
}
|
|
1584
|
+
/**
|
|
1585
|
+
* Checks the primitive values that are directly JSON serializable.
|
|
1586
|
+
*
|
|
1587
|
+
* @private function of `checkSerializableAsJson`
|
|
1588
|
+
*/
|
|
1589
|
+
function isSerializablePrimitive(value) {
|
|
1590
|
+
return (value === null ||
|
|
1591
|
+
typeof value === 'boolean' ||
|
|
1592
|
+
(typeof value === 'number' && !isNaN(value)) ||
|
|
1593
|
+
typeof value === 'string');
|
|
1594
|
+
}
|
|
1595
|
+
/**
|
|
1596
|
+
* Recursively checks JSON array items.
|
|
1597
|
+
*
|
|
1598
|
+
* @private function of `checkSerializableAsJson`
|
|
1599
|
+
*/
|
|
1600
|
+
function checkSerializableArray(context, arrayValue) {
|
|
1601
|
+
for (let index = 0; index < arrayValue.length; index++) {
|
|
1602
|
+
checkSerializableAsJson({
|
|
1603
|
+
...context,
|
|
1604
|
+
name: `${context.name}[${index}]`,
|
|
1605
|
+
value: arrayValue[index],
|
|
1606
|
+
});
|
|
1533
1607
|
}
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1608
|
+
}
|
|
1609
|
+
/**
|
|
1610
|
+
* Checks object-like values and dispatches special unsupported built-ins.
|
|
1611
|
+
*
|
|
1612
|
+
* @private function of `checkSerializableAsJson`
|
|
1613
|
+
*/
|
|
1614
|
+
function checkSerializableObject(context, objectValue) {
|
|
1615
|
+
checkUnsupportedObjectType(context, objectValue);
|
|
1616
|
+
checkSerializableObjectEntries(context, objectValue);
|
|
1617
|
+
assertJsonStringificationSucceeds(context, objectValue);
|
|
1618
|
+
}
|
|
1619
|
+
/**
|
|
1620
|
+
* Rejects built-in objects that must be converted before JSON serialization.
|
|
1621
|
+
*
|
|
1622
|
+
* @private function of `checkSerializableAsJson`
|
|
1623
|
+
*/
|
|
1624
|
+
function checkUnsupportedObjectType(context, objectValue) {
|
|
1625
|
+
if (objectValue instanceof Date) {
|
|
1626
|
+
throw new UnexpectedError(_spaceTrim.spaceTrim((block) => `
|
|
1627
|
+
\`${context.name}\` is Date
|
|
1538
1628
|
|
|
1539
|
-
|
|
1629
|
+
Use \`string_date_iso8601\` instead
|
|
1540
1630
|
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1631
|
+
Additional message for \`${context.name}\`:
|
|
1632
|
+
${block(context.message || '(nothing)')}
|
|
1633
|
+
`));
|
|
1634
|
+
}
|
|
1635
|
+
if (objectValue instanceof Map) {
|
|
1636
|
+
throw new UnexpectedError(`${context.name} is Map`);
|
|
1637
|
+
}
|
|
1638
|
+
if (objectValue instanceof Set) {
|
|
1639
|
+
throw new UnexpectedError(`${context.name} is Set`);
|
|
1640
|
+
}
|
|
1641
|
+
if (objectValue instanceof RegExp) {
|
|
1642
|
+
throw new UnexpectedError(`${context.name} is RegExp`);
|
|
1643
|
+
}
|
|
1644
|
+
if (objectValue instanceof Error) {
|
|
1645
|
+
throw new UnexpectedError(_spaceTrim.spaceTrim((block) => `
|
|
1646
|
+
\`${context.name}\` is unserialized Error
|
|
1557
1647
|
|
|
1558
|
-
|
|
1648
|
+
Use function \`serializeError\`
|
|
1559
1649
|
|
|
1560
|
-
|
|
1561
|
-
|
|
1650
|
+
Additional message for \`${context.name}\`:
|
|
1651
|
+
${block(context.message || '(nothing)')}
|
|
1562
1652
|
|
|
1563
|
-
|
|
1653
|
+
`));
|
|
1654
|
+
}
|
|
1655
|
+
}
|
|
1656
|
+
/**
|
|
1657
|
+
* Recursively checks object properties while preserving omitted `undefined` keys.
|
|
1658
|
+
*
|
|
1659
|
+
* @private function of `checkSerializableAsJson`
|
|
1660
|
+
*/
|
|
1661
|
+
function checkSerializableObjectEntries(context, objectValue) {
|
|
1662
|
+
for (const [subName, subValue] of Object.entries(objectValue)) {
|
|
1663
|
+
if (subValue === undefined) {
|
|
1664
|
+
// Note: undefined in object is serializable - it is just omitted
|
|
1665
|
+
continue;
|
|
1564
1666
|
}
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1667
|
+
checkSerializableAsJson({
|
|
1668
|
+
...context,
|
|
1669
|
+
name: `${context.name}.${subName}`,
|
|
1670
|
+
value: subValue,
|
|
1671
|
+
});
|
|
1672
|
+
}
|
|
1673
|
+
}
|
|
1674
|
+
/**
|
|
1675
|
+
* Uses `JSON.stringify` as the final guard for cases like circular references.
|
|
1676
|
+
*
|
|
1677
|
+
* @private function of `checkSerializableAsJson`
|
|
1678
|
+
*/
|
|
1679
|
+
function assertJsonStringificationSucceeds(context, objectValue) {
|
|
1680
|
+
try {
|
|
1681
|
+
JSON.stringify(objectValue); // <- TODO: [0]
|
|
1682
|
+
}
|
|
1683
|
+
catch (error) {
|
|
1684
|
+
assertsError(error);
|
|
1685
|
+
throw new UnexpectedError(_spaceTrim.spaceTrim((block) => `
|
|
1686
|
+
\`${context.name}\` is not serializable
|
|
1580
1687
|
|
|
1581
|
-
|
|
1688
|
+
${block(error.stack || error.message)}
|
|
1582
1689
|
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1690
|
+
Additional message for \`${context.name}\`:
|
|
1691
|
+
${block(context.message || '(nothing)')}
|
|
1692
|
+
`));
|
|
1693
|
+
}
|
|
1694
|
+
/*
|
|
1695
|
+
TODO: [0] Is there some more elegant way to check circular references?
|
|
1696
|
+
const seen = new Set();
|
|
1697
|
+
const stack = [{ value }];
|
|
1698
|
+
while (stack.length > 0) {
|
|
1699
|
+
const { value } = stack.pop()!;
|
|
1700
|
+
if (typeof value === 'object' && value !== null) {
|
|
1701
|
+
if (seen.has(value)) {
|
|
1702
|
+
throw new UnexpectedError(`${name} has circular reference`);
|
|
1586
1703
|
}
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
const { value } = stack.pop()!;
|
|
1593
|
-
if (typeof value === 'object' && value !== null) {
|
|
1594
|
-
if (seen.has(value)) {
|
|
1595
|
-
throw new UnexpectedError(`${name} has circular reference`);
|
|
1596
|
-
}
|
|
1597
|
-
seen.add(value);
|
|
1598
|
-
if (Array.isArray(value)) {
|
|
1599
|
-
stack.push(...value.map((value) => ({ value })));
|
|
1600
|
-
} else {
|
|
1601
|
-
stack.push(...Object.values(value).map((value) => ({ value })));
|
|
1602
|
-
}
|
|
1603
|
-
}
|
|
1704
|
+
seen.add(value);
|
|
1705
|
+
if (Array.isArray(value)) {
|
|
1706
|
+
stack.push(...value.map((value) => ({ value })));
|
|
1707
|
+
} else {
|
|
1708
|
+
stack.push(...Object.values(value).map((value) => ({ value })));
|
|
1604
1709
|
}
|
|
1605
|
-
*/
|
|
1606
|
-
return;
|
|
1607
1710
|
}
|
|
1608
1711
|
}
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1712
|
+
*/
|
|
1713
|
+
}
|
|
1714
|
+
/**
|
|
1715
|
+
* Throws the fallback error for unsupported value types like `bigint` and `NaN`.
|
|
1716
|
+
*
|
|
1717
|
+
* @private function of `checkSerializableAsJson`
|
|
1718
|
+
*/
|
|
1719
|
+
function throwUnknownTypeError(context) {
|
|
1720
|
+
throw new UnexpectedError(_spaceTrim.spaceTrim((block) => `
|
|
1721
|
+
\`${context.name}\` is unknown type
|
|
1612
1722
|
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
}
|
|
1723
|
+
Additional message for \`${context.name}\`:
|
|
1724
|
+
${block(context.message || '(nothing)')}
|
|
1725
|
+
`));
|
|
1617
1726
|
}
|
|
1618
|
-
// TODO: Can be return type more type-safe? like `asserts options.value is JsonValue`
|
|
1619
|
-
// TODO: [🧠][main] !!3 In-memory cache of same values to prevent multiple checks
|
|
1620
|
-
// Note: [🐠] This is how `checkSerializableAsJson` + `isSerializableAsJson` together can just retun true/false or rich error message
|
|
1621
1727
|
|
|
1622
1728
|
/**
|
|
1623
1729
|
* Creates a deep clone of the given object
|
|
@@ -2277,8 +2383,7 @@
|
|
|
2277
2383
|
* @private internal utility of `validatePipeline`
|
|
2278
2384
|
*/
|
|
2279
2385
|
function validateTaskSupportsJokers(task, pipelineIdentification) {
|
|
2280
|
-
if (task.format ||
|
|
2281
|
-
task.expectations /* <- TODO: Require at least 1 -> min <- expectation to use jokers */) {
|
|
2386
|
+
if (task.format || task.expectations /* <- TODO: Require at least 1 -> min <- expectation to use jokers */) {
|
|
2282
2387
|
return;
|
|
2283
2388
|
}
|
|
2284
2389
|
throw new PipelineLogicError(_spaceTrim.spaceTrim((block) => `
|
|
@@ -2843,7 +2948,7 @@
|
|
|
2843
2948
|
*/
|
|
2844
2949
|
function createPostprocessingCommands(task) {
|
|
2845
2950
|
var _a;
|
|
2846
|
-
return ((_a = task.postprocessingFunctionNames) === null || _a === void 0 ? void 0 : _a.map((postprocessingFunctionName) => `POSTPROCESSING \`${postprocessingFunctionName}\``)) || [];
|
|
2951
|
+
return (((_a = task.postprocessingFunctionNames) === null || _a === void 0 ? void 0 : _a.map((postprocessingFunctionName) => `POSTPROCESSING \`${postprocessingFunctionName}\``)) || []);
|
|
2847
2952
|
}
|
|
2848
2953
|
/**
|
|
2849
2954
|
* Collects expectation commands.
|
|
@@ -5959,9 +6064,7 @@
|
|
|
5959
6064
|
${block(quoteMultilineText(((_b = failure.error) === null || _b === void 0 ? void 0 : _b.message) || ''))}
|
|
5960
6065
|
|
|
5961
6066
|
Result:
|
|
5962
|
-
${block(failure.result === null
|
|
5963
|
-
? 'null'
|
|
5964
|
-
: quoteMultilineText(_spaceTrim.spaceTrim(failure.result)))}
|
|
6067
|
+
${block(failure.result === null ? 'null' : quoteMultilineText(_spaceTrim.spaceTrim(failure.result)))}
|
|
5965
6068
|
`;
|
|
5966
6069
|
}))
|
|
5967
6070
|
.join('\n\n---\n\n');
|
|
@@ -17468,7 +17571,7 @@
|
|
|
17468
17571
|
*
|
|
17469
17572
|
* @private helper of `minecraft2AvatarVisual`
|
|
17470
17573
|
*/
|
|
17471
|
-
const LIGHT_DIRECTION$
|
|
17574
|
+
const LIGHT_DIRECTION$2 = normalizeVector3({
|
|
17472
17575
|
x: 0.4,
|
|
17473
17576
|
y: -0.65,
|
|
17474
17577
|
z: 0.92,
|
|
@@ -17680,7 +17783,7 @@
|
|
|
17680
17783
|
corners: projectedCorners,
|
|
17681
17784
|
texture: faceDefinition.texture,
|
|
17682
17785
|
averageDepth: transformedCorners.reduce((depthSum, corner) => depthSum + corner.z, 0) / transformedCorners.length,
|
|
17683
|
-
lightIntensity: clampNumber$1(dotProduct3D(faceNormal, LIGHT_DIRECTION$
|
|
17786
|
+
lightIntensity: clampNumber$1(dotProduct3D(faceNormal, LIGHT_DIRECTION$2), -1, 1),
|
|
17684
17787
|
outlineColor: cuboid.outlineColor,
|
|
17685
17788
|
};
|
|
17686
17789
|
});
|
|
@@ -18740,13 +18843,138 @@
|
|
|
18740
18843
|
context.restore();
|
|
18741
18844
|
}
|
|
18742
18845
|
|
|
18846
|
+
/* eslint-disable no-magic-numbers */
|
|
18847
|
+
/**
|
|
18848
|
+
* Draws one projected eye on a rotated octopus surface.
|
|
18849
|
+
*
|
|
18850
|
+
* @private helper of the 3D octopus avatar visuals
|
|
18851
|
+
*/
|
|
18852
|
+
function drawProjectedOrganicEye(context, localCenter, radiusX, radiusY, center, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, phase, interaction, eyeStyle) {
|
|
18853
|
+
const centerScenePoint = transformScenePoint(localCenter, center, rotationX, rotationY);
|
|
18854
|
+
if (centerScenePoint.z <= center.z) {
|
|
18855
|
+
return;
|
|
18856
|
+
}
|
|
18857
|
+
const horizontalScenePoint = transformScenePoint({ x: localCenter.x + radiusX, y: localCenter.y, z: localCenter.z }, center, rotationX, rotationY);
|
|
18858
|
+
const verticalScenePoint = transformScenePoint({ x: localCenter.x, y: localCenter.y + radiusY, z: localCenter.z }, center, rotationX, rotationY);
|
|
18859
|
+
const projectedCenterPoint = projectScenePoint(centerScenePoint, size, sceneCenterX, sceneCenterY);
|
|
18860
|
+
const projectedHorizontalPoint = projectScenePoint(horizontalScenePoint, size, sceneCenterX, sceneCenterY);
|
|
18861
|
+
const projectedVerticalPoint = projectScenePoint(verticalScenePoint, size, sceneCenterX, sceneCenterY);
|
|
18862
|
+
const projectedRadiusX = Math.hypot(projectedHorizontalPoint.x - projectedCenterPoint.x, projectedHorizontalPoint.y - projectedCenterPoint.y);
|
|
18863
|
+
const projectedRadiusY = Math.hypot(projectedVerticalPoint.x - projectedCenterPoint.x, projectedVerticalPoint.y - projectedCenterPoint.y);
|
|
18864
|
+
if (projectedRadiusX < size * 0.008 || projectedRadiusY < size * 0.008) {
|
|
18865
|
+
return;
|
|
18866
|
+
}
|
|
18867
|
+
const { pupilOffsetX, pupilOffsetY } = resolveOrganicEyeMotion({
|
|
18868
|
+
radiusX: projectedRadiusX,
|
|
18869
|
+
radiusY: projectedRadiusY,
|
|
18870
|
+
timeMs,
|
|
18871
|
+
phase,
|
|
18872
|
+
interaction,
|
|
18873
|
+
});
|
|
18874
|
+
const rotation = Math.atan2(projectedHorizontalPoint.y - projectedCenterPoint.y, projectedHorizontalPoint.x - projectedCenterPoint.x);
|
|
18875
|
+
context.save();
|
|
18876
|
+
context.translate(projectedCenterPoint.x, projectedCenterPoint.y);
|
|
18877
|
+
context.rotate(rotation);
|
|
18878
|
+
context.beginPath();
|
|
18879
|
+
context.ellipse(0, 0, projectedRadiusX, projectedRadiusY, 0, 0, Math.PI * 2);
|
|
18880
|
+
context.fillStyle = '#f8fbff';
|
|
18881
|
+
context.fill();
|
|
18882
|
+
context.clip();
|
|
18883
|
+
const irisGradient = context.createRadialGradient(-projectedRadiusX * 0.2, -projectedRadiusY * 0.26, projectedRadiusX * 0.05, 0, 0, projectedRadiusX * 0.92);
|
|
18884
|
+
irisGradient.addColorStop(0, palette.highlight);
|
|
18885
|
+
irisGradient.addColorStop(0.56, palette.secondary);
|
|
18886
|
+
irisGradient.addColorStop(1, palette.shadow);
|
|
18887
|
+
context.beginPath();
|
|
18888
|
+
context.ellipse(pupilOffsetX, pupilOffsetY, projectedRadiusX * 0.62 * eyeStyle.irisScale, projectedRadiusY * 0.72 * eyeStyle.irisScale, 0, 0, Math.PI * 2);
|
|
18889
|
+
context.fillStyle = irisGradient;
|
|
18890
|
+
context.fill();
|
|
18891
|
+
context.beginPath();
|
|
18892
|
+
context.ellipse(pupilOffsetX, pupilOffsetY, projectedRadiusX * 0.15 * eyeStyle.pupilWidthScale, projectedRadiusY * 0.48 * eyeStyle.pupilHeightScale, 0, 0, Math.PI * 2);
|
|
18893
|
+
context.fillStyle = palette.ink;
|
|
18894
|
+
context.fill();
|
|
18895
|
+
context.beginPath();
|
|
18896
|
+
context.ellipse(pupilOffsetX - projectedRadiusX * 0.22, pupilOffsetY - projectedRadiusY * 0.24, projectedRadiusX * 0.12, projectedRadiusY * 0.14, 0, 0, Math.PI * 2);
|
|
18897
|
+
context.fillStyle = '#ffffff';
|
|
18898
|
+
context.fill();
|
|
18899
|
+
context.restore();
|
|
18900
|
+
context.save();
|
|
18901
|
+
context.translate(projectedCenterPoint.x, projectedCenterPoint.y);
|
|
18902
|
+
context.rotate(rotation);
|
|
18903
|
+
context.beginPath();
|
|
18904
|
+
context.ellipse(0, 0, projectedRadiusX, projectedRadiusY, 0, 0, Math.PI * 2);
|
|
18905
|
+
context.strokeStyle = `${palette.shadow}cc`;
|
|
18906
|
+
context.lineWidth = projectedRadiusX * 0.16;
|
|
18907
|
+
context.stroke();
|
|
18908
|
+
context.beginPath();
|
|
18909
|
+
context.moveTo(-projectedRadiusX * 0.88, -projectedRadiusY * eyeStyle.upperLidInsetRatio);
|
|
18910
|
+
context.quadraticCurveTo(0, -projectedRadiusY * (eyeStyle.upperLidArchRatio - interaction.gazeY * 0.16 + interaction.intensity * 0.08), projectedRadiusX * 0.88, -projectedRadiusY * eyeStyle.upperLidInsetRatio);
|
|
18911
|
+
context.strokeStyle = `${palette.shadow}73`;
|
|
18912
|
+
context.lineWidth = projectedRadiusX * 0.14;
|
|
18913
|
+
context.lineCap = 'round';
|
|
18914
|
+
context.stroke();
|
|
18915
|
+
if (eyeStyle.lowerLidOpacity > 0) {
|
|
18916
|
+
context.beginPath();
|
|
18917
|
+
context.moveTo(-projectedRadiusX * 0.74, projectedRadiusY * 0.2);
|
|
18918
|
+
context.quadraticCurveTo(0, projectedRadiusY * 0.38, projectedRadiusX * 0.74, projectedRadiusY * 0.2);
|
|
18919
|
+
context.strokeStyle = `${palette.highlight}${formatAlphaHex(eyeStyle.lowerLidOpacity)}`;
|
|
18920
|
+
context.lineWidth = projectedRadiusX * 0.08;
|
|
18921
|
+
context.lineCap = 'round';
|
|
18922
|
+
context.stroke();
|
|
18923
|
+
}
|
|
18924
|
+
context.restore();
|
|
18925
|
+
}
|
|
18926
|
+
/**
|
|
18927
|
+
* Draws a subtle projected mouth arc across the front of a rotated octopus surface.
|
|
18928
|
+
*
|
|
18929
|
+
* @private helper of the 3D octopus avatar visuals
|
|
18930
|
+
*/
|
|
18931
|
+
function drawProjectedOrganicMouth(context, localPoints, center, rotationX, rotationY, sceneCenterX, sceneCenterY, palette, size) {
|
|
18932
|
+
const scenePoints = localPoints.map((localPoint) => transformScenePoint(localPoint, center, rotationX, rotationY));
|
|
18933
|
+
if (scenePoints.some((scenePoint) => scenePoint.z <= center.z)) {
|
|
18934
|
+
return;
|
|
18935
|
+
}
|
|
18936
|
+
const projectedPoints = scenePoints.map((scenePoint) => projectScenePoint(scenePoint, size, sceneCenterX, sceneCenterY));
|
|
18937
|
+
context.beginPath();
|
|
18938
|
+
context.moveTo(projectedPoints[0].x, projectedPoints[0].y);
|
|
18939
|
+
context.quadraticCurveTo(projectedPoints[1].x, projectedPoints[1].y, projectedPoints[2].x, projectedPoints[2].y);
|
|
18940
|
+
context.strokeStyle = `${palette.ink}b8`;
|
|
18941
|
+
context.lineWidth = Math.max(1.1, size * 0.009);
|
|
18942
|
+
context.lineCap = 'round';
|
|
18943
|
+
context.stroke();
|
|
18944
|
+
}
|
|
18945
|
+
/**
|
|
18946
|
+
* Draws one filled projected quad.
|
|
18947
|
+
*
|
|
18948
|
+
* @private helper of the 3D octopus avatar visuals
|
|
18949
|
+
*/
|
|
18950
|
+
function drawProjectedQuad(context, corners, fillStyle) {
|
|
18951
|
+
context.beginPath();
|
|
18952
|
+
context.moveTo(corners[0].x, corners[0].y);
|
|
18953
|
+
context.lineTo(corners[1].x, corners[1].y);
|
|
18954
|
+
context.lineTo(corners[2].x, corners[2].y);
|
|
18955
|
+
context.lineTo(corners[3].x, corners[3].y);
|
|
18956
|
+
context.closePath();
|
|
18957
|
+
context.fillStyle = fillStyle;
|
|
18958
|
+
context.fill();
|
|
18959
|
+
}
|
|
18960
|
+
/**
|
|
18961
|
+
* Converts an opacity ratio into a two-digit hexadecimal alpha suffix.
|
|
18962
|
+
*
|
|
18963
|
+
* @private helper of the 3D octopus avatar visuals
|
|
18964
|
+
*/
|
|
18965
|
+
function formatAlphaHex(opacity) {
|
|
18966
|
+
return Math.round(clampNumber$1(opacity, 0, 1) * 255)
|
|
18967
|
+
.toString(16)
|
|
18968
|
+
.padStart(2, '0');
|
|
18969
|
+
}
|
|
18970
|
+
|
|
18743
18971
|
/* eslint-disable no-magic-numbers */
|
|
18744
18972
|
/**
|
|
18745
18973
|
* Light direction used by the organic 3D octopus shading.
|
|
18746
18974
|
*
|
|
18747
18975
|
* @private helper of `octopus3dAvatarVisual`
|
|
18748
18976
|
*/
|
|
18749
|
-
const LIGHT_DIRECTION = normalizeVector3({
|
|
18977
|
+
const LIGHT_DIRECTION$1 = normalizeVector3({
|
|
18750
18978
|
x: 0.48,
|
|
18751
18979
|
y: -0.62,
|
|
18752
18980
|
z: 0.94,
|
|
@@ -18859,17 +19087,17 @@
|
|
|
18859
19087
|
for (const tentacleStroke of tentacleStrokes.filter((candidateTentacleStroke) => candidateTentacleStroke.isFrontFacing)) {
|
|
18860
19088
|
drawTentacleStroke(context, tentacleStroke, palette);
|
|
18861
19089
|
}
|
|
18862
|
-
|
|
19090
|
+
drawProjectedOrganicEye(context, {
|
|
18863
19091
|
x: -faceEyeSpacing,
|
|
18864
19092
|
y: faceEyeYOffset,
|
|
18865
19093
|
z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, -faceEyeSpacing, faceEyeYOffset),
|
|
18866
19094
|
}, faceEyeRadiusX, faceEyeRadiusY, mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + eyeRandom() * 0.6, interaction, morphologyProfile.face.eyeStyle);
|
|
18867
|
-
|
|
19095
|
+
drawProjectedOrganicEye(context, {
|
|
18868
19096
|
x: faceEyeSpacing,
|
|
18869
19097
|
y: faceEyeYOffset,
|
|
18870
19098
|
z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, faceEyeSpacing, faceEyeYOffset),
|
|
18871
19099
|
}, faceEyeRadiusX, faceEyeRadiusY, mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + 0.7 + eyeRandom() * 0.6, interaction, morphologyProfile.face.eyeStyle);
|
|
18872
|
-
|
|
19100
|
+
drawProjectedOrganicMouth(context, [
|
|
18873
19101
|
{
|
|
18874
19102
|
x: -mouthHalfWidth,
|
|
18875
19103
|
y: mouthY,
|
|
@@ -18956,7 +19184,7 @@
|
|
|
18956
19184
|
corners: projectedCorners,
|
|
18957
19185
|
averageDepth: transformedCorners.reduce((depthSum, transformedCorner) => depthSum + transformedCorner.z, 0) /
|
|
18958
19186
|
transformedCorners.length,
|
|
18959
|
-
lightIntensity: clampNumber$1(dotProduct3D(surfaceNormal, LIGHT_DIRECTION), -1, 1),
|
|
19187
|
+
lightIntensity: clampNumber$1(dotProduct3D(surfaceNormal, LIGHT_DIRECTION$1), -1, 1),
|
|
18960
19188
|
fillStyle: resolveSurfacePatchFillStyle(palette, verticalProgress + verticalColorBias),
|
|
18961
19189
|
outlineColor,
|
|
18962
19190
|
});
|
|
@@ -19138,128 +19366,260 @@
|
|
|
19138
19366
|
const remainingDepthRatio = Math.max(0, 1 - normalizedX * normalizedX - normalizedY * normalizedY);
|
|
19139
19367
|
return Math.sqrt(remainingDepthRatio) * radiusZ;
|
|
19140
19368
|
}
|
|
19369
|
+
|
|
19370
|
+
/* eslint-disable no-magic-numbers */
|
|
19141
19371
|
/**
|
|
19142
|
-
*
|
|
19372
|
+
* Light direction used by the single-mesh octopus shading.
|
|
19143
19373
|
*
|
|
19144
|
-
* @private helper of `
|
|
19374
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
19145
19375
|
*/
|
|
19146
|
-
|
|
19147
|
-
|
|
19148
|
-
|
|
19149
|
-
|
|
19150
|
-
|
|
19151
|
-
|
|
19152
|
-
|
|
19153
|
-
|
|
19154
|
-
|
|
19155
|
-
|
|
19156
|
-
|
|
19157
|
-
|
|
19158
|
-
|
|
19159
|
-
|
|
19160
|
-
|
|
19161
|
-
|
|
19162
|
-
|
|
19163
|
-
|
|
19164
|
-
|
|
19165
|
-
|
|
19166
|
-
|
|
19167
|
-
|
|
19168
|
-
|
|
19376
|
+
const LIGHT_DIRECTION = normalizeVector3({
|
|
19377
|
+
x: 0.38,
|
|
19378
|
+
y: -0.6,
|
|
19379
|
+
z: 0.98,
|
|
19380
|
+
});
|
|
19381
|
+
/**
|
|
19382
|
+
* Octopus 3D 2 avatar visual.
|
|
19383
|
+
*
|
|
19384
|
+
* @private built-in avatar visual
|
|
19385
|
+
*/
|
|
19386
|
+
const octopus3d2AvatarVisual = {
|
|
19387
|
+
id: 'octopus3d2',
|
|
19388
|
+
title: 'Octopus 3D 2',
|
|
19389
|
+
description: 'Continuous blobby 3D octopus portrait with one soft mesh, turning silhouette, and cursor-aware eyes.',
|
|
19390
|
+
isAnimated: true,
|
|
19391
|
+
supportsPointerTracking: true,
|
|
19392
|
+
render({ context, size, palette, createRandom, timeMs, interaction }) {
|
|
19393
|
+
const morphologyProfile = createOctopus3MorphologyProfile(createRandom);
|
|
19394
|
+
const animationRandom = createRandom('octopus3d2-animation-profile');
|
|
19395
|
+
const eyeRandom = createRandom('octopus3d2-eye-profile');
|
|
19396
|
+
const animationPhase = animationRandom() * Math.PI * 2;
|
|
19397
|
+
const sceneCenterX = size * 0.5;
|
|
19398
|
+
const sceneCenterY = size * 0.575;
|
|
19399
|
+
const bob = Math.sin(timeMs / 940 + animationPhase) * size * 0.013;
|
|
19400
|
+
const meshCenter = {
|
|
19401
|
+
x: interaction.bodyOffsetX * size * 0.044 + size * morphologyProfile.body.centerXJitterRatio * 0.5,
|
|
19402
|
+
y: -size * 0.03 + interaction.bodyOffsetY * size * 0.026 + bob,
|
|
19403
|
+
z: interaction.intensity * size * 0.018,
|
|
19404
|
+
};
|
|
19405
|
+
const rotationY = -0.14 +
|
|
19406
|
+
Math.sin(timeMs / 2600 + animationPhase) * 0.04 +
|
|
19407
|
+
interaction.bodyOffsetX * 0.2 +
|
|
19408
|
+
interaction.gazeX * 0.78;
|
|
19409
|
+
const rotationX = -0.06 +
|
|
19410
|
+
Math.cos(timeMs / 3000 + animationPhase * 0.7) * 0.02 -
|
|
19411
|
+
interaction.bodyOffsetY * 0.08 -
|
|
19412
|
+
interaction.gazeY * 0.34;
|
|
19413
|
+
const surfaceOptions = {
|
|
19414
|
+
radiusX: size * morphologyProfile.body.bodyRadiusRatio * morphologyProfile.body.horizontalStretch * 1.02,
|
|
19415
|
+
radiusY: size * morphologyProfile.body.bodyRadiusRatio * morphologyProfile.body.verticalStretch * 1.22,
|
|
19416
|
+
radiusZ: size *
|
|
19417
|
+
morphologyProfile.body.bodyRadiusRatio *
|
|
19418
|
+
(0.98 + (morphologyProfile.body.horizontalStretch - 1) * 0.2),
|
|
19419
|
+
morphologyProfile,
|
|
19420
|
+
timeMs,
|
|
19421
|
+
animationPhase,
|
|
19422
|
+
};
|
|
19423
|
+
const surfacePatches = resolveVisibleBlobbyOctopusPatches({
|
|
19424
|
+
...surfaceOptions,
|
|
19425
|
+
center: meshCenter,
|
|
19426
|
+
rotationX,
|
|
19427
|
+
rotationY,
|
|
19428
|
+
sceneCenterX,
|
|
19429
|
+
sceneCenterY,
|
|
19430
|
+
size,
|
|
19431
|
+
palette,
|
|
19432
|
+
});
|
|
19433
|
+
const eyeLatitude = clampNumber$1(morphologyProfile.face.eyeCenterYOffsetRatio * 4.4, -0.16, 0.11);
|
|
19434
|
+
const eyeLongitude = clampNumber$1(morphologyProfile.face.eyeSpacingRatio * 3.25, 0.2, 0.34);
|
|
19435
|
+
const mouthLatitude = clampNumber$1(eyeLatitude + 0.19 + morphologyProfile.face.mouthYOffsetRatio * 1.08, 0.08, 0.34);
|
|
19436
|
+
const mouthCenterLongitude = clampNumber$1(morphologyProfile.face.mouthCenterOffsetRatio * 5.8, -0.08, 0.08);
|
|
19437
|
+
const mouthHalfLongitude = clampNumber$1(eyeLongitude * 0.82, 0.16, 0.29);
|
|
19438
|
+
const mouthCurveLatitude = clampNumber$1(mouthLatitude + morphologyProfile.face.mouthCurveDepthRatio * 0.85, mouthLatitude + 0.03, 0.42);
|
|
19439
|
+
drawAvatarFrame(context, size, palette);
|
|
19440
|
+
drawBlobbyOctopusAtmosphere(context, size, palette, sceneCenterX, sceneCenterY, interaction, timeMs);
|
|
19441
|
+
drawBlobbyOctopusShadow(context, size, palette, interaction, timeMs, morphologyProfile);
|
|
19442
|
+
for (const surfacePatch of surfacePatches.sort((firstSurfacePatch, secondSurfacePatch) => firstSurfacePatch.averageDepth - secondSurfacePatch.averageDepth)) {
|
|
19443
|
+
drawBlobbySurfacePatch(context, surfacePatch);
|
|
19444
|
+
}
|
|
19445
|
+
const leftEyeLocalCenter = sampleBlobbyOctopusSurfacePoint(surfaceOptions, eyeLatitude, -eyeLongitude);
|
|
19446
|
+
const rightEyeLocalCenter = sampleBlobbyOctopusSurfacePoint(surfaceOptions, eyeLatitude, eyeLongitude);
|
|
19447
|
+
const eyeRadiusX = size * morphologyProfile.face.eyeRadiusXRatio * 0.78;
|
|
19448
|
+
const eyeRadiusY = eyeRadiusX * morphologyProfile.face.eyeHeightRatio * 0.92;
|
|
19449
|
+
drawProjectedOrganicEye(context, leftEyeLocalCenter, eyeRadiusX, eyeRadiusY, meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + eyeRandom() * 0.7, interaction, morphologyProfile.face.eyeStyle);
|
|
19450
|
+
drawProjectedOrganicEye(context, rightEyeLocalCenter, eyeRadiusX, eyeRadiusY, meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + 0.9 + eyeRandom() * 0.7, interaction, morphologyProfile.face.eyeStyle);
|
|
19451
|
+
drawProjectedOrganicMouth(context, [
|
|
19452
|
+
sampleBlobbyOctopusSurfacePoint(surfaceOptions, mouthLatitude, mouthCenterLongitude - mouthHalfLongitude),
|
|
19453
|
+
sampleBlobbyOctopusSurfacePoint(surfaceOptions, mouthCurveLatitude, mouthCenterLongitude),
|
|
19454
|
+
sampleBlobbyOctopusSurfacePoint(surfaceOptions, mouthLatitude, mouthCenterLongitude + mouthHalfLongitude),
|
|
19455
|
+
], meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, palette, size);
|
|
19456
|
+
},
|
|
19457
|
+
};
|
|
19458
|
+
/**
|
|
19459
|
+
* Draws the deep-water glow behind the continuous octopus mesh.
|
|
19460
|
+
*
|
|
19461
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
19462
|
+
*/
|
|
19463
|
+
function drawBlobbyOctopusAtmosphere(context, size, palette, sceneCenterX, sceneCenterY, interaction, timeMs) {
|
|
19464
|
+
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);
|
|
19465
|
+
glowGradient.addColorStop(0, `${palette.highlight}5e`);
|
|
19466
|
+
glowGradient.addColorStop(0.38, `${palette.accent}26`);
|
|
19467
|
+
glowGradient.addColorStop(1, `${palette.highlight}00`);
|
|
19468
|
+
context.fillStyle = glowGradient;
|
|
19469
|
+
context.fillRect(0, 0, size, size);
|
|
19470
|
+
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);
|
|
19471
|
+
lowerGradient.addColorStop(0, `${palette.secondary}22`);
|
|
19472
|
+
lowerGradient.addColorStop(1, `${palette.secondary}00`);
|
|
19473
|
+
context.fillStyle = lowerGradient;
|
|
19474
|
+
context.fillRect(0, 0, size, size);
|
|
19475
|
+
}
|
|
19476
|
+
/**
|
|
19477
|
+
* Draws the soft floor shadow that anchors the single mesh in the frame.
|
|
19478
|
+
*
|
|
19479
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
19480
|
+
*/
|
|
19481
|
+
function drawBlobbyOctopusShadow(context, size, palette, interaction, timeMs, morphologyProfile) {
|
|
19169
19482
|
context.save();
|
|
19170
|
-
context.
|
|
19171
|
-
context.
|
|
19172
|
-
context.beginPath();
|
|
19173
|
-
context.ellipse(0, 0, projectedRadiusX, projectedRadiusY, 0, 0, Math.PI * 2);
|
|
19174
|
-
context.fillStyle = '#f8fbff';
|
|
19175
|
-
context.fill();
|
|
19176
|
-
context.clip();
|
|
19177
|
-
const irisGradient = context.createRadialGradient(-projectedRadiusX * 0.2, -projectedRadiusY * 0.26, projectedRadiusX * 0.05, 0, 0, projectedRadiusX * 0.92);
|
|
19178
|
-
irisGradient.addColorStop(0, palette.highlight);
|
|
19179
|
-
irisGradient.addColorStop(0.56, palette.secondary);
|
|
19180
|
-
irisGradient.addColorStop(1, palette.shadow);
|
|
19181
|
-
context.beginPath();
|
|
19182
|
-
context.ellipse(pupilOffsetX, pupilOffsetY, projectedRadiusX * 0.62 * eyeStyle.irisScale, projectedRadiusY * 0.72 * eyeStyle.irisScale, 0, 0, Math.PI * 2);
|
|
19183
|
-
context.fillStyle = irisGradient;
|
|
19184
|
-
context.fill();
|
|
19185
|
-
context.beginPath();
|
|
19186
|
-
context.ellipse(pupilOffsetX, pupilOffsetY, projectedRadiusX * 0.15 * eyeStyle.pupilWidthScale, projectedRadiusY * 0.48 * eyeStyle.pupilHeightScale, 0, 0, Math.PI * 2);
|
|
19187
|
-
context.fillStyle = palette.ink;
|
|
19188
|
-
context.fill();
|
|
19483
|
+
context.fillStyle = `${palette.shadow}66`;
|
|
19484
|
+
context.filter = `blur(${size * 0.024}px)`;
|
|
19189
19485
|
context.beginPath();
|
|
19190
|
-
context.ellipse(
|
|
19191
|
-
context.fillStyle = '#ffffff';
|
|
19486
|
+
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);
|
|
19192
19487
|
context.fill();
|
|
19193
19488
|
context.restore();
|
|
19194
|
-
context.save();
|
|
19195
|
-
context.translate(projectedCenterPoint.x, projectedCenterPoint.y);
|
|
19196
|
-
context.rotate(rotation);
|
|
19197
|
-
context.beginPath();
|
|
19198
|
-
context.ellipse(0, 0, projectedRadiusX, projectedRadiusY, 0, 0, Math.PI * 2);
|
|
19199
|
-
context.strokeStyle = `${palette.shadow}cc`;
|
|
19200
|
-
context.lineWidth = projectedRadiusX * 0.16;
|
|
19201
|
-
context.stroke();
|
|
19202
|
-
context.beginPath();
|
|
19203
|
-
context.moveTo(-projectedRadiusX * 0.88, -projectedRadiusY * eyeStyle.upperLidInsetRatio);
|
|
19204
|
-
context.quadraticCurveTo(0, -projectedRadiusY * (eyeStyle.upperLidArchRatio - interaction.gazeY * 0.16 + interaction.intensity * 0.08), projectedRadiusX * 0.88, -projectedRadiusY * eyeStyle.upperLidInsetRatio);
|
|
19205
|
-
context.strokeStyle = `${palette.shadow}73`;
|
|
19206
|
-
context.lineWidth = projectedRadiusX * 0.14;
|
|
19207
|
-
context.lineCap = 'round';
|
|
19208
|
-
context.stroke();
|
|
19209
|
-
if (eyeStyle.lowerLidOpacity > 0) {
|
|
19210
|
-
context.beginPath();
|
|
19211
|
-
context.moveTo(-projectedRadiusX * 0.74, projectedRadiusY * 0.2);
|
|
19212
|
-
context.quadraticCurveTo(0, projectedRadiusY * 0.38, projectedRadiusX * 0.74, projectedRadiusY * 0.2);
|
|
19213
|
-
context.strokeStyle = `${palette.highlight}${formatAlphaHex(eyeStyle.lowerLidOpacity)}`;
|
|
19214
|
-
context.lineWidth = projectedRadiusX * 0.08;
|
|
19215
|
-
context.lineCap = 'round';
|
|
19216
|
-
context.stroke();
|
|
19217
|
-
}
|
|
19218
|
-
context.restore();
|
|
19219
19489
|
}
|
|
19220
19490
|
/**
|
|
19221
|
-
*
|
|
19491
|
+
* Resolves all visible projected patches for the single blobby octopus mesh.
|
|
19222
19492
|
*
|
|
19223
|
-
* @private helper of `
|
|
19493
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
19224
19494
|
*/
|
|
19225
|
-
function
|
|
19226
|
-
const
|
|
19227
|
-
|
|
19228
|
-
|
|
19495
|
+
function resolveVisibleBlobbyOctopusPatches(options) {
|
|
19496
|
+
const { center, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, morphologyProfile, animationPhase, timeMs, } = options;
|
|
19497
|
+
const latitudePatchCount = 12;
|
|
19498
|
+
const longitudePatchCount = 24;
|
|
19499
|
+
const surfacePatches = [];
|
|
19500
|
+
for (let latitudeIndex = 0; latitudeIndex < latitudePatchCount; latitudeIndex++) {
|
|
19501
|
+
const startLatitude = -Math.PI / 2 + (latitudeIndex / latitudePatchCount) * Math.PI;
|
|
19502
|
+
const endLatitude = -Math.PI / 2 + ((latitudeIndex + 1) / latitudePatchCount) * Math.PI;
|
|
19503
|
+
const centerLatitude = (startLatitude + endLatitude) / 2;
|
|
19504
|
+
const verticalProgress = (Math.sin(centerLatitude) + 1) / 2;
|
|
19505
|
+
for (let longitudeIndex = 0; longitudeIndex < longitudePatchCount; longitudeIndex++) {
|
|
19506
|
+
const startLongitude = -Math.PI + (longitudeIndex / longitudePatchCount) * Math.PI * 2;
|
|
19507
|
+
const endLongitude = -Math.PI + ((longitudeIndex + 1) / longitudePatchCount) * Math.PI * 2;
|
|
19508
|
+
const centerLongitude = (startLongitude + endLongitude) / 2;
|
|
19509
|
+
const localCorners = [
|
|
19510
|
+
sampleBlobbyOctopusSurfacePoint(options, startLatitude, startLongitude),
|
|
19511
|
+
sampleBlobbyOctopusSurfacePoint(options, startLatitude, endLongitude),
|
|
19512
|
+
sampleBlobbyOctopusSurfacePoint(options, endLatitude, endLongitude),
|
|
19513
|
+
sampleBlobbyOctopusSurfacePoint(options, endLatitude, startLongitude),
|
|
19514
|
+
];
|
|
19515
|
+
const transformedCorners = localCorners.map((localCorner) => transformScenePoint(localCorner, center, rotationX, rotationY));
|
|
19516
|
+
const surfaceNormal = normalizeVector3(crossProduct3D(subtractPoint3D(transformedCorners[1], transformedCorners[0]), subtractPoint3D(transformedCorners[2], transformedCorners[0])));
|
|
19517
|
+
if (surfaceNormal.z <= 0.01) {
|
|
19518
|
+
continue;
|
|
19519
|
+
}
|
|
19520
|
+
const projectedCorners = transformedCorners.map((transformedCorner) => projectScenePoint(transformedCorner, size, sceneCenterX, sceneCenterY));
|
|
19521
|
+
surfacePatches.push({
|
|
19522
|
+
corners: projectedCorners,
|
|
19523
|
+
averageDepth: transformedCorners.reduce((depthSum, transformedCorner) => depthSum + transformedCorner.z, 0) /
|
|
19524
|
+
transformedCorners.length,
|
|
19525
|
+
lightIntensity: clampNumber$1(dotProduct3D(surfaceNormal, LIGHT_DIRECTION), -1, 1),
|
|
19526
|
+
fillStyle: resolveBlobbySurfacePatchFillStyle(palette, verticalProgress, Math.max(0, Math.cos(centerLongitude)), resolveLowerLobeWave(centerLongitude, morphologyProfile, animationPhase, timeMs)),
|
|
19527
|
+
outlineColor: verticalProgress < 0.58 ? `${palette.highlight}73` : `${palette.shadow}8a`,
|
|
19528
|
+
});
|
|
19529
|
+
}
|
|
19229
19530
|
}
|
|
19230
|
-
|
|
19231
|
-
context.beginPath();
|
|
19232
|
-
context.moveTo(projectedPoints[0].x, projectedPoints[0].y);
|
|
19233
|
-
context.quadraticCurveTo(projectedPoints[1].x, projectedPoints[1].y, projectedPoints[2].x, projectedPoints[2].y);
|
|
19234
|
-
context.strokeStyle = `${palette.ink}b8`;
|
|
19235
|
-
context.lineWidth = Math.max(1.1, size * 0.009);
|
|
19236
|
-
context.lineCap = 'round';
|
|
19237
|
-
context.stroke();
|
|
19531
|
+
return surfacePatches;
|
|
19238
19532
|
}
|
|
19239
19533
|
/**
|
|
19240
|
-
*
|
|
19534
|
+
* Samples one point on the continuous Octopus 3D 2 surface.
|
|
19535
|
+
*
|
|
19536
|
+
* The lower hemisphere widens and falls into soft lobe waves so the octopus stays one connected mesh
|
|
19537
|
+
* instead of switching to separately rendered tentacles.
|
|
19538
|
+
*
|
|
19539
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
19540
|
+
*/
|
|
19541
|
+
function sampleBlobbyOctopusSurfacePoint(options, latitude, longitude) {
|
|
19542
|
+
const { radiusX, radiusY, radiusZ, morphologyProfile, timeMs, animationPhase } = options;
|
|
19543
|
+
const cosineLatitude = Math.max(0, Math.cos(latitude));
|
|
19544
|
+
const verticalProgress = (Math.sin(latitude) + 1) / 2;
|
|
19545
|
+
const upperBlend = Math.pow(1 - verticalProgress, 1.2);
|
|
19546
|
+
const lowerBlend = Math.pow(verticalProgress, 1.42);
|
|
19547
|
+
const lowerLobeWave = resolveLowerLobeWave(longitude, morphologyProfile, animationPhase, timeMs);
|
|
19548
|
+
const skirtEnvelope = Math.pow(cosineLatitude, 0.5) * lowerBlend;
|
|
19549
|
+
const horizontalScale = 1.02 +
|
|
19550
|
+
skirtEnvelope * (0.34 + (morphologyProfile.tentacles.rootSpreadScale - 1) * 0.22 + lowerLobeWave * 0.22) -
|
|
19551
|
+
upperBlend * 0.08;
|
|
19552
|
+
const depthScale = 1.04 +
|
|
19553
|
+
upperBlend * 0.16 +
|
|
19554
|
+
Math.max(0, Math.cos(longitude)) * 0.1 +
|
|
19555
|
+
skirtEnvelope * (0.08 + lowerLobeWave * 0.06) -
|
|
19556
|
+
Math.max(0, -Math.cos(longitude)) * 0.04;
|
|
19557
|
+
const lowerDrop = skirtEnvelope *
|
|
19558
|
+
radiusY *
|
|
19559
|
+
(0.28 + lowerLobeWave * 0.14 + (morphologyProfile.tentacles.flowLengthScale - 1) * 0.12);
|
|
19560
|
+
const swayX = Math.sin(timeMs / 1250 + longitude * 1.8 + animationPhase) * skirtEnvelope * radiusX * 0.05;
|
|
19561
|
+
const swayZ = Math.cos(timeMs / 1480 + longitude * 1.2 - animationPhase * 0.7) * skirtEnvelope * radiusZ * 0.03;
|
|
19562
|
+
return {
|
|
19563
|
+
x: Math.sin(longitude) * cosineLatitude * radiusX * horizontalScale + swayX,
|
|
19564
|
+
y: Math.sin(latitude) * radiusY * (1 + upperBlend * 0.14) -
|
|
19565
|
+
upperBlend * radiusY * 0.1 +
|
|
19566
|
+
lowerDrop +
|
|
19567
|
+
Math.sin(timeMs / 1780 + animationPhase + latitude * 1.4) * skirtEnvelope * radiusY * 0.02,
|
|
19568
|
+
z: Math.cos(longitude) * cosineLatitude * radiusZ * depthScale + swayZ,
|
|
19569
|
+
};
|
|
19570
|
+
}
|
|
19571
|
+
/**
|
|
19572
|
+
* Resolves the soft lower-lobe wave that makes the silhouette read more like a real octopus.
|
|
19241
19573
|
*
|
|
19242
|
-
* @private helper of `
|
|
19574
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
19243
19575
|
*/
|
|
19244
|
-
function
|
|
19245
|
-
|
|
19246
|
-
|
|
19247
|
-
context.lineTo(corners[1].x, corners[1].y);
|
|
19248
|
-
context.lineTo(corners[2].x, corners[2].y);
|
|
19249
|
-
context.lineTo(corners[3].x, corners[3].y);
|
|
19250
|
-
context.closePath();
|
|
19251
|
-
context.fillStyle = fillStyle;
|
|
19252
|
-
context.fill();
|
|
19576
|
+
function resolveLowerLobeWave(longitude, morphologyProfile, animationPhase, timeMs) {
|
|
19577
|
+
const lobeCount = Math.max(4, Math.round((morphologyProfile.body.lobeCount + morphologyProfile.tentacles.count) / 2));
|
|
19578
|
+
return (Math.cos(longitude * lobeCount + animationPhase + timeMs / 1040) + 1) / 2;
|
|
19253
19579
|
}
|
|
19254
19580
|
/**
|
|
19255
|
-
*
|
|
19581
|
+
* Resolves one base fill tone for a surface patch on the single octopus mesh.
|
|
19256
19582
|
*
|
|
19257
|
-
* @private helper of `
|
|
19583
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
19258
19584
|
*/
|
|
19259
|
-
function
|
|
19260
|
-
|
|
19261
|
-
|
|
19262
|
-
.
|
|
19585
|
+
function resolveBlobbySurfacePatchFillStyle(palette, verticalProgress, forwardness, lowerLobeWave) {
|
|
19586
|
+
const tonalProgress = clampNumber$1(verticalProgress + lowerLobeWave * 0.12 - forwardness * 0.07, 0, 1);
|
|
19587
|
+
if (tonalProgress < 0.16) {
|
|
19588
|
+
return palette.highlight;
|
|
19589
|
+
}
|
|
19590
|
+
if (tonalProgress < 0.34) {
|
|
19591
|
+
return palette.secondary;
|
|
19592
|
+
}
|
|
19593
|
+
if (tonalProgress < 0.72) {
|
|
19594
|
+
return forwardness > 0.58 ? palette.secondary : palette.primary;
|
|
19595
|
+
}
|
|
19596
|
+
return `${palette.shadow}f2`;
|
|
19597
|
+
}
|
|
19598
|
+
/**
|
|
19599
|
+
* Draws one projected patch with soft octopus shading.
|
|
19600
|
+
*
|
|
19601
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
19602
|
+
*/
|
|
19603
|
+
function drawBlobbySurfacePatch(context, surfacePatch) {
|
|
19604
|
+
drawProjectedQuad(context, surfacePatch.corners, surfacePatch.fillStyle);
|
|
19605
|
+
if (surfacePatch.lightIntensity > 0) {
|
|
19606
|
+
drawProjectedQuad(context, surfacePatch.corners, `rgba(255, 255, 255, ${0.16 * surfacePatch.lightIntensity})`);
|
|
19607
|
+
}
|
|
19608
|
+
else if (surfacePatch.lightIntensity < 0) {
|
|
19609
|
+
drawProjectedQuad(context, surfacePatch.corners, `rgba(0, 0, 0, ${0.24 * Math.abs(surfacePatch.lightIntensity)})`);
|
|
19610
|
+
}
|
|
19611
|
+
context.save();
|
|
19612
|
+
context.beginPath();
|
|
19613
|
+
context.moveTo(surfacePatch.corners[0].x, surfacePatch.corners[0].y);
|
|
19614
|
+
for (let cornerIndex = 1; cornerIndex < surfacePatch.corners.length; cornerIndex++) {
|
|
19615
|
+
context.lineTo(surfacePatch.corners[cornerIndex].x, surfacePatch.corners[cornerIndex].y);
|
|
19616
|
+
}
|
|
19617
|
+
context.closePath();
|
|
19618
|
+
context.strokeStyle = surfacePatch.outlineColor;
|
|
19619
|
+
context.lineWidth = Math.max(1, getProjectedQuadPerimeter(surfacePatch.corners) * 0.0042);
|
|
19620
|
+
context.lineJoin = 'round';
|
|
19621
|
+
context.stroke();
|
|
19622
|
+
context.restore();
|
|
19263
19623
|
}
|
|
19264
19624
|
|
|
19265
19625
|
/* eslint-disable no-magic-numbers */
|
|
@@ -20031,6 +20391,7 @@
|
|
|
20031
20391
|
octopus2AvatarVisual,
|
|
20032
20392
|
octopus3AvatarVisual,
|
|
20033
20393
|
octopus3dAvatarVisual,
|
|
20394
|
+
octopus3d2AvatarVisual,
|
|
20034
20395
|
asciiOctopusAvatarVisual,
|
|
20035
20396
|
minecraftAvatarVisual,
|
|
20036
20397
|
minecraft2AvatarVisual,
|
|
@@ -25606,11 +25967,11 @@
|
|
|
25606
25967
|
});
|
|
25607
25968
|
}
|
|
25608
25969
|
/**
|
|
25609
|
-
*
|
|
25970
|
+
* Prepares one attachment for best-effort text decoding.
|
|
25610
25971
|
*
|
|
25611
|
-
* @private
|
|
25972
|
+
* @private function of decodeAttachmentAsText
|
|
25612
25973
|
*/
|
|
25613
|
-
function
|
|
25974
|
+
function createDecodeAttachmentPreparation(input, options) {
|
|
25614
25975
|
var _a;
|
|
25615
25976
|
const maxBytes = Math.max(1, Math.floor((_a = options.maxBytes) !== null && _a !== void 0 ? _a : DEFAULT_ATTACHMENT_TEXT_DECODE_BYTES));
|
|
25616
25977
|
const forceText = options.forceText === true;
|
|
@@ -25624,54 +25985,102 @@
|
|
|
25624
25985
|
const inspection = inspectBytes(truncatedBytes);
|
|
25625
25986
|
const trustedTextMime = isTrustedTextMimeType(mimeType);
|
|
25626
25987
|
const trustedBinaryMime = isTrustedBinaryMimeType(mimeType);
|
|
25988
|
+
const shouldTreatAsBinary = (trustedBinaryMime || inspection.looksBinary) && !trustedTextMime;
|
|
25627
25989
|
if (isTruncated) {
|
|
25628
25990
|
warnings.push(`Decoded only the first ${maxBytes} bytes of \`${input.filename}\` because the attachment exceeded the text preview limit.`);
|
|
25629
25991
|
}
|
|
25630
|
-
|
|
25631
|
-
|
|
25632
|
-
|
|
25633
|
-
|
|
25634
|
-
|
|
25635
|
-
|
|
25636
|
-
|
|
25637
|
-
|
|
25638
|
-
|
|
25639
|
-
|
|
25640
|
-
|
|
25992
|
+
return {
|
|
25993
|
+
warnings,
|
|
25994
|
+
charset,
|
|
25995
|
+
bom,
|
|
25996
|
+
inspection,
|
|
25997
|
+
truncatedBytes,
|
|
25998
|
+
isTruncated,
|
|
25999
|
+
forceText,
|
|
26000
|
+
shouldTreatAsBinary,
|
|
26001
|
+
};
|
|
26002
|
+
}
|
|
26003
|
+
/**
|
|
26004
|
+
* Returns an early result when the attachment should stay classified as binary.
|
|
26005
|
+
*
|
|
26006
|
+
* @private function of decodeAttachmentAsText
|
|
26007
|
+
*/
|
|
26008
|
+
function createBinaryDecodeResult(preparation) {
|
|
26009
|
+
if (!preparation.shouldTreatAsBinary) {
|
|
26010
|
+
return null;
|
|
25641
26011
|
}
|
|
25642
|
-
if (
|
|
25643
|
-
warnings.push('File content looks binary, but text decoding was forced with `forceText`.');
|
|
26012
|
+
if (preparation.forceText) {
|
|
26013
|
+
preparation.warnings.push('File content looks binary, but text decoding was forced with `forceText`.');
|
|
26014
|
+
return null;
|
|
25644
26015
|
}
|
|
25645
|
-
|
|
25646
|
-
|
|
26016
|
+
preparation.warnings.push('File content looks binary, so text decoding was skipped.');
|
|
26017
|
+
return {
|
|
26018
|
+
text: '',
|
|
26019
|
+
encodingUsed: 'binary',
|
|
26020
|
+
confidence: 1,
|
|
26021
|
+
warnings: preparation.warnings,
|
|
26022
|
+
wasBinary: true,
|
|
26023
|
+
isTruncated: preparation.isTruncated,
|
|
26024
|
+
};
|
|
26025
|
+
}
|
|
26026
|
+
/**
|
|
26027
|
+
* Warns when the declared charset cannot be used by the runtime decoder.
|
|
26028
|
+
*
|
|
26029
|
+
* @private function of decodeAttachmentAsText
|
|
26030
|
+
*/
|
|
26031
|
+
function addUnsupportedCharsetWarning(preparation) {
|
|
26032
|
+
if (preparation.charset && !isSupportedEncoding(preparation.charset)) {
|
|
26033
|
+
preparation.warnings.push(`Ignored unsupported declared charset \`${preparation.charset}\` and used best-effort detection instead.`);
|
|
25647
26034
|
}
|
|
25648
|
-
|
|
25649
|
-
|
|
25650
|
-
|
|
25651
|
-
|
|
25652
|
-
|
|
25653
|
-
|
|
25654
|
-
|
|
25655
|
-
|
|
26035
|
+
}
|
|
26036
|
+
/**
|
|
26037
|
+
* Returns the byte slice that should actually be decoded as text.
|
|
26038
|
+
*
|
|
26039
|
+
* @private function of decodeAttachmentAsText
|
|
26040
|
+
*/
|
|
26041
|
+
function getBytesToDecode(preparation) {
|
|
26042
|
+
return preparation.bom ? preparation.truncatedBytes.subarray(preparation.bom.offset) : preparation.truncatedBytes;
|
|
26043
|
+
}
|
|
26044
|
+
/**
|
|
26045
|
+
* Decodes all candidate encodings and sorts the successful results by score.
|
|
26046
|
+
*
|
|
26047
|
+
* @private function of decodeAttachmentAsText
|
|
26048
|
+
*/
|
|
26049
|
+
function decodeAttachmentCandidates(preparation) {
|
|
26050
|
+
return buildCandidateEncodings({
|
|
26051
|
+
charset: preparation.charset && isSupportedEncoding(preparation.charset) ? preparation.charset : null,
|
|
26052
|
+
bom: preparation.bom,
|
|
26053
|
+
inspection: preparation.inspection,
|
|
26054
|
+
})
|
|
25656
26055
|
.map(({ encoding, source }) => {
|
|
25657
|
-
const decoded = decodeWithEncoding(
|
|
26056
|
+
const decoded = decodeWithEncoding(getBytesToDecode(preparation), encoding);
|
|
25658
26057
|
return decoded ? { ...decoded, source } : null;
|
|
25659
26058
|
})
|
|
25660
26059
|
.filter((candidate) => candidate !== null)
|
|
25661
26060
|
.sort((left, right) => left.score - right.score);
|
|
25662
|
-
|
|
25663
|
-
|
|
25664
|
-
|
|
25665
|
-
|
|
25666
|
-
|
|
25667
|
-
|
|
25668
|
-
|
|
25669
|
-
|
|
25670
|
-
|
|
25671
|
-
|
|
25672
|
-
|
|
25673
|
-
|
|
25674
|
-
|
|
26061
|
+
}
|
|
26062
|
+
/**
|
|
26063
|
+
* Returns the fallback result used when no text decoder could be applied.
|
|
26064
|
+
*
|
|
26065
|
+
* @private function of decodeAttachmentAsText
|
|
26066
|
+
*/
|
|
26067
|
+
function createNoDecoderAvailableResult(preparation) {
|
|
26068
|
+
preparation.warnings.push('No supported text decoder was available.');
|
|
26069
|
+
return {
|
|
26070
|
+
text: '',
|
|
26071
|
+
encodingUsed: 'binary',
|
|
26072
|
+
confidence: 0,
|
|
26073
|
+
warnings: preparation.warnings,
|
|
26074
|
+
wasBinary: true,
|
|
26075
|
+
isTruncated: preparation.isTruncated,
|
|
26076
|
+
};
|
|
26077
|
+
}
|
|
26078
|
+
/**
|
|
26079
|
+
* Estimates confidence for the winning decoded text candidate.
|
|
26080
|
+
*
|
|
26081
|
+
* @private function of decodeAttachmentAsText
|
|
26082
|
+
*/
|
|
26083
|
+
function computeDecodeConfidence(bestCandidate, secondBestCandidate, preparation) {
|
|
25675
26084
|
const baseConfidence = bestCandidate.source === 'bom'
|
|
25676
26085
|
? 1
|
|
25677
26086
|
: bestCandidate.source === 'charset'
|
|
@@ -25684,27 +26093,62 @@
|
|
|
25684
26093
|
? 0.82
|
|
25685
26094
|
: 0.62;
|
|
25686
26095
|
const scoreMargin = secondBestCandidate ? Math.max(0, secondBestCandidate.score - bestCandidate.score) : 0.2;
|
|
25687
|
-
|
|
26096
|
+
return Math.max(0.2, Math.min(preparation.shouldTreatAsBinary && preparation.forceText ? 0.45 : 1, baseConfidence + Math.min(0.18, scoreMargin / 2)));
|
|
26097
|
+
}
|
|
26098
|
+
/**
|
|
26099
|
+
* Appends user-facing warnings derived from the chosen decoded text candidate.
|
|
26100
|
+
*
|
|
26101
|
+
* @private function of decodeAttachmentAsText
|
|
26102
|
+
*/
|
|
26103
|
+
function addDecodeWarnings(bestCandidate, confidence, preparation) {
|
|
25688
26104
|
if (bestCandidate.source === 'heuristic' && bestCandidate.encoding !== 'utf-8') {
|
|
25689
|
-
warnings.push(`Encoding was guessed as \`${bestCandidate.encoding}\`.`);
|
|
26105
|
+
preparation.warnings.push(`Encoding was guessed as \`${bestCandidate.encoding}\`.`);
|
|
25690
26106
|
}
|
|
25691
26107
|
if (bestCandidate.source === 'heuristic' &&
|
|
25692
26108
|
bestCandidate.encoding === 'utf-8' &&
|
|
25693
26109
|
bestCandidate.replacementCount > 0) {
|
|
25694
|
-
warnings.push('UTF-8 decoding produced replacement characters, so the extracted text may contain errors.');
|
|
26110
|
+
preparation.warnings.push('UTF-8 decoding produced replacement characters, so the extracted text may contain errors.');
|
|
25695
26111
|
}
|
|
25696
26112
|
if (confidence < 0.6) {
|
|
25697
|
-
warnings.push('Decoding confidence is low, so the extracted text may contain errors.');
|
|
26113
|
+
preparation.warnings.push('Decoding confidence is low, so the extracted text may contain errors.');
|
|
25698
26114
|
}
|
|
26115
|
+
}
|
|
26116
|
+
/**
|
|
26117
|
+
* Creates the final decoded-text result from the chosen candidate and accumulated metadata.
|
|
26118
|
+
*
|
|
26119
|
+
* @private function of decodeAttachmentAsText
|
|
26120
|
+
*/
|
|
26121
|
+
function createDecodedTextResult(bestCandidate, confidence, preparation) {
|
|
25699
26122
|
return {
|
|
25700
|
-
text: isTruncated ? appendTruncatedMarker(bestCandidate.text) : bestCandidate.text,
|
|
26123
|
+
text: preparation.isTruncated ? appendTruncatedMarker(bestCandidate.text) : bestCandidate.text,
|
|
25701
26124
|
encodingUsed: bestCandidate.encoding,
|
|
25702
26125
|
confidence,
|
|
25703
|
-
warnings,
|
|
26126
|
+
warnings: preparation.warnings,
|
|
25704
26127
|
wasBinary: false,
|
|
25705
|
-
isTruncated,
|
|
26128
|
+
isTruncated: preparation.isTruncated,
|
|
25706
26129
|
};
|
|
25707
26130
|
}
|
|
26131
|
+
/**
|
|
26132
|
+
* Best-effort decoder for uploaded or remote file bytes whose extension or encoding may be unknown.
|
|
26133
|
+
*
|
|
26134
|
+
* @private internal utility for shared text decoding
|
|
26135
|
+
*/
|
|
26136
|
+
function decodeAttachmentAsText(input, options = {}) {
|
|
26137
|
+
const preparation = createDecodeAttachmentPreparation(input, options);
|
|
26138
|
+
const binaryResult = createBinaryDecodeResult(preparation);
|
|
26139
|
+
if (binaryResult) {
|
|
26140
|
+
return binaryResult;
|
|
26141
|
+
}
|
|
26142
|
+
addUnsupportedCharsetWarning(preparation);
|
|
26143
|
+
const decodedCandidates = decodeAttachmentCandidates(preparation);
|
|
26144
|
+
const bestCandidate = decodedCandidates[0];
|
|
26145
|
+
if (!bestCandidate) {
|
|
26146
|
+
return createNoDecoderAvailableResult(preparation);
|
|
26147
|
+
}
|
|
26148
|
+
const confidence = computeDecodeConfidence(bestCandidate, decodedCandidates[1], preparation);
|
|
26149
|
+
addDecodeWarnings(bestCandidate, confidence, preparation);
|
|
26150
|
+
return createDecodedTextResult(bestCandidate, confidence, preparation);
|
|
26151
|
+
}
|
|
25708
26152
|
|
|
25709
26153
|
/**
|
|
25710
26154
|
* Base GitHub API URL.
|
|
@@ -30250,10 +30694,7 @@
|
|
|
30250
30694
|
* @private internal function of `$registeredLlmToolsMessage`
|
|
30251
30695
|
*/
|
|
30252
30696
|
function createProviderStatusMessages(llmToolStatus, env) {
|
|
30253
|
-
return [
|
|
30254
|
-
createInstallationStatusMessage(llmToolStatus),
|
|
30255
|
-
createConfigurationStatusMessage(llmToolStatus, env),
|
|
30256
|
-
];
|
|
30697
|
+
return [createInstallationStatusMessage(llmToolStatus), createConfigurationStatusMessage(llmToolStatus, env)];
|
|
30257
30698
|
}
|
|
30258
30699
|
/**
|
|
30259
30700
|
* Creates the installation-status sentence for one provider.
|
|
@@ -37769,7 +38210,10 @@
|
|
|
37769
38210
|
Cannot find model in ${this.options.getTitle()} models with name "${defaultModelName}" which should be used as default.
|
|
37770
38211
|
|
|
37771
38212
|
Available models:
|
|
37772
|
-
${block(this.options
|
|
38213
|
+
${block(this.options
|
|
38214
|
+
.getHardcodedModels()
|
|
38215
|
+
.map(({ modelName }) => `- "${modelName}"`)
|
|
38216
|
+
.join('\n'))}
|
|
37773
38217
|
|
|
37774
38218
|
Model "${defaultModelName}" is probably not available anymore, not installed, inaccessible or misconfigured.
|
|
37775
38219
|
|
|
@@ -38123,7 +38567,8 @@
|
|
|
38123
38567
|
};
|
|
38124
38568
|
let rawPromptContent = templateParameters(content, { ...parameters, modelName });
|
|
38125
38569
|
if ('attachments' in prompt && Array.isArray(prompt.attachments) && prompt.attachments.length > 0) {
|
|
38126
|
-
rawPromptContent +=
|
|
38570
|
+
rawPromptContent +=
|
|
38571
|
+
'\n\n' + prompt.attachments.map((attachment) => `Image attachment: ${attachment.url}`).join('\n');
|
|
38127
38572
|
}
|
|
38128
38573
|
const rawRequest = {
|
|
38129
38574
|
...modelSettings,
|
|
@@ -38228,7 +38673,9 @@
|
|
|
38228
38673
|
* Schedules one request through the shared limiter and retry policy.
|
|
38229
38674
|
*/
|
|
38230
38675
|
async executeRateLimitedRequest(requestFn) {
|
|
38231
|
-
return this.limiter
|
|
38676
|
+
return this.limiter
|
|
38677
|
+
.schedule(() => this.makeRequestWithNetworkRetry(requestFn))
|
|
38678
|
+
.catch((error) => {
|
|
38232
38679
|
assertsError(error);
|
|
38233
38680
|
if (this.options.isVerbose) {
|
|
38234
38681
|
console.info(colors__default["default"].bgRed('error'), error);
|
|
@@ -39435,7 +39882,9 @@
|
|
|
39435
39882
|
pollingState.lastProgressAtMs = nowMs;
|
|
39436
39883
|
pollingState.lastProgressKey = progressKey;
|
|
39437
39884
|
}
|
|
39438
|
-
if (this.options.isVerbose &&
|
|
39885
|
+
if (this.options.isVerbose &&
|
|
39886
|
+
(statusCountsKey !== pollingState.lastCountsKey ||
|
|
39887
|
+
nowMs - pollingState.lastLogAtMs >= progressLogIntervalMs)) {
|
|
39439
39888
|
console.info('[🤰]', 'Vector store file batch status', {
|
|
39440
39889
|
vectorStoreId,
|
|
39441
39890
|
batchId,
|