@promptbook/core 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 +1 -1
- 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
|
@@ -28,7 +28,7 @@ const BOOK_LANGUAGE_VERSION = '2.0.0';
|
|
|
28
28
|
* @generated
|
|
29
29
|
* @see https://github.com/webgptorg/promptbook
|
|
30
30
|
*/
|
|
31
|
-
const PROMPTBOOK_ENGINE_VERSION = '0.112.0-
|
|
31
|
+
const PROMPTBOOK_ENGINE_VERSION = '0.112.0-80';
|
|
32
32
|
/**
|
|
33
33
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
|
34
34
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -278,6 +278,111 @@ function checkChannelValue(channelName, value) {
|
|
|
278
278
|
}
|
|
279
279
|
}
|
|
280
280
|
|
|
281
|
+
/**
|
|
282
|
+
* Shared immutable channel storage and serialization helpers for `Color`.
|
|
283
|
+
*
|
|
284
|
+
* @private base class of Color
|
|
285
|
+
*/
|
|
286
|
+
class ColorValue {
|
|
287
|
+
constructor(red, green, blue, alpha = 255) {
|
|
288
|
+
this.red = red;
|
|
289
|
+
this.green = green;
|
|
290
|
+
this.blue = blue;
|
|
291
|
+
this.alpha = alpha;
|
|
292
|
+
checkChannelValue('Red', red);
|
|
293
|
+
checkChannelValue('Green', green);
|
|
294
|
+
checkChannelValue('Blue', blue);
|
|
295
|
+
checkChannelValue('Alpha', alpha);
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Shortcut for `red` property
|
|
299
|
+
* Number from 0 to 255
|
|
300
|
+
* @alias red
|
|
301
|
+
*/
|
|
302
|
+
get r() {
|
|
303
|
+
return this.red;
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Shortcut for `green` property
|
|
307
|
+
* Number from 0 to 255
|
|
308
|
+
* @alias green
|
|
309
|
+
*/
|
|
310
|
+
get g() {
|
|
311
|
+
return this.green;
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Shortcut for `blue` property
|
|
315
|
+
* Number from 0 to 255
|
|
316
|
+
* @alias blue
|
|
317
|
+
*/
|
|
318
|
+
get b() {
|
|
319
|
+
return this.blue;
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* Shortcut for `alpha` property
|
|
323
|
+
* Number from 0 (transparent) to 255 (opaque)
|
|
324
|
+
* @alias alpha
|
|
325
|
+
*/
|
|
326
|
+
get a() {
|
|
327
|
+
return this.alpha;
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Shortcut for `alpha` property
|
|
331
|
+
* Number from 0 (transparent) to 255 (opaque)
|
|
332
|
+
* @alias alpha
|
|
333
|
+
*/
|
|
334
|
+
get opacity() {
|
|
335
|
+
return this.alpha;
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Shortcut for 1-`alpha` property
|
|
339
|
+
*/
|
|
340
|
+
get transparency() {
|
|
341
|
+
return 255 - this.alpha;
|
|
342
|
+
}
|
|
343
|
+
clone() {
|
|
344
|
+
return take(this.createColor(this.red, this.green, this.blue, this.alpha));
|
|
345
|
+
}
|
|
346
|
+
toString() {
|
|
347
|
+
return this.toHex();
|
|
348
|
+
}
|
|
349
|
+
toHex() {
|
|
350
|
+
if (this.alpha === 255) {
|
|
351
|
+
return `#${this.red.toString(16).padStart(2, '0')}${this.green.toString(16).padStart(2, '0')}${this.blue
|
|
352
|
+
.toString(16)
|
|
353
|
+
.padStart(2, '0')}`;
|
|
354
|
+
}
|
|
355
|
+
else {
|
|
356
|
+
return `#${this.red.toString(16).padStart(2, '0')}${this.green.toString(16).padStart(2, '0')}${this.blue
|
|
357
|
+
.toString(16)
|
|
358
|
+
.padStart(2, '0')}${this.alpha.toString(16).padStart(2, '0')}`;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
toRgb() {
|
|
362
|
+
if (this.alpha === 255) {
|
|
363
|
+
return `rgb(${this.red}, ${this.green}, ${this.blue})`;
|
|
364
|
+
}
|
|
365
|
+
else {
|
|
366
|
+
return `rgba(${this.red}, ${this.green}, ${this.blue}, ${Math.round((this.alpha / 255) * 100)}%)`;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
toHsl() {
|
|
370
|
+
throw new Error(`Getting HSL is not implemented`);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* Checks if the given value is a valid hex color string
|
|
376
|
+
*
|
|
377
|
+
* @param value - value to check
|
|
378
|
+
* @returns true if the value is a valid hex color string (e.g., `#009edd`, `#fff`, etc.)
|
|
379
|
+
*
|
|
380
|
+
* @private function of Color
|
|
381
|
+
*/
|
|
382
|
+
function isHexColorString(value) {
|
|
383
|
+
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));
|
|
384
|
+
}
|
|
385
|
+
|
|
281
386
|
/**
|
|
282
387
|
* Constant for short hex lengths.
|
|
283
388
|
*/
|
|
@@ -489,16 +594,53 @@ function parseAlphaValue(value) {
|
|
|
489
594
|
|
|
490
595
|
/**
|
|
491
596
|
* Pattern matching hsl regex.
|
|
597
|
+
*
|
|
598
|
+
* @private function of Color
|
|
492
599
|
*/
|
|
493
600
|
const HSL_REGEX_PATTERN = /^hsl\(\s*([0-9.]+)\s*,\s*([0-9.]+)%\s*,\s*([0-9.]+)%\s*\)$/;
|
|
494
601
|
/**
|
|
495
602
|
* Pattern matching RGB regex.
|
|
603
|
+
*
|
|
604
|
+
* @private function of Color
|
|
496
605
|
*/
|
|
497
606
|
const RGB_REGEX_PATTERN = /^rgb\(\s*([0-9.%-]+)\s*,\s*([0-9.%-]+)\s*,\s*([0-9.%-]+)\s*\)$/;
|
|
498
607
|
/**
|
|
499
608
|
* Pattern matching rgba regex.
|
|
609
|
+
*
|
|
610
|
+
* @private function of Color
|
|
500
611
|
*/
|
|
501
612
|
const RGBA_REGEX_PATTERN = /^rgba\(\s*([0-9.%-]+)\s*,\s*([0-9.%-]+)\s*,\s*([0-9.%-]+)\s*,\s*([0-9.%-]+)\s*\)$/;
|
|
613
|
+
/**
|
|
614
|
+
* Parses a supported color string into RGBA channels.
|
|
615
|
+
*
|
|
616
|
+
* @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`,...
|
|
617
|
+
* @returns RGBA channel values.
|
|
618
|
+
*
|
|
619
|
+
* @private function of Color
|
|
620
|
+
*/
|
|
621
|
+
function parseColorString(color) {
|
|
622
|
+
const trimmed = color.trim();
|
|
623
|
+
const cssColor = CSS_COLORS[trimmed];
|
|
624
|
+
if (cssColor) {
|
|
625
|
+
return parseColorString(cssColor);
|
|
626
|
+
}
|
|
627
|
+
else if (isHexColorString(trimmed)) {
|
|
628
|
+
return parseHexColor(trimmed);
|
|
629
|
+
}
|
|
630
|
+
if (HSL_REGEX_PATTERN.test(trimmed)) {
|
|
631
|
+
return parseHslColor(trimmed);
|
|
632
|
+
}
|
|
633
|
+
else if (RGB_REGEX_PATTERN.test(trimmed)) {
|
|
634
|
+
return parseRgbColor(trimmed);
|
|
635
|
+
}
|
|
636
|
+
else if (RGBA_REGEX_PATTERN.test(trimmed)) {
|
|
637
|
+
return parseRgbaColor(trimmed);
|
|
638
|
+
}
|
|
639
|
+
else {
|
|
640
|
+
throw new Error(`Can not create a new Color instance from string "${trimmed}".`);
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
|
|
502
644
|
/**
|
|
503
645
|
* Color object represents an RGB color with alpha channel
|
|
504
646
|
*
|
|
@@ -506,7 +648,7 @@ const RGBA_REGEX_PATTERN = /^rgba\(\s*([0-9.%-]+)\s*,\s*([0-9.%-]+)\s*,\s*([0-9.
|
|
|
506
648
|
*
|
|
507
649
|
* @public exported from `@promptbook/color`
|
|
508
650
|
*/
|
|
509
|
-
class Color {
|
|
651
|
+
class Color extends ColorValue {
|
|
510
652
|
/**
|
|
511
653
|
* Creates a new Color instance from miscellaneous formats
|
|
512
654
|
* - It can receive Color instance and just return the same instance
|
|
@@ -579,25 +721,7 @@ class Color {
|
|
|
579
721
|
* @returns Color object
|
|
580
722
|
*/
|
|
581
723
|
static fromString(color) {
|
|
582
|
-
|
|
583
|
-
if (CSS_COLORS[trimmed]) {
|
|
584
|
-
return Color.fromString(CSS_COLORS[trimmed]);
|
|
585
|
-
}
|
|
586
|
-
else if (Color.isHexColorString(trimmed)) {
|
|
587
|
-
return Color.fromHex(trimmed);
|
|
588
|
-
}
|
|
589
|
-
if (HSL_REGEX_PATTERN.test(trimmed)) {
|
|
590
|
-
return Color.fromHsl(trimmed);
|
|
591
|
-
}
|
|
592
|
-
else if (RGB_REGEX_PATTERN.test(trimmed)) {
|
|
593
|
-
return Color.fromRgbString(trimmed);
|
|
594
|
-
}
|
|
595
|
-
else if (RGBA_REGEX_PATTERN.test(trimmed)) {
|
|
596
|
-
return Color.fromRgbaString(trimmed);
|
|
597
|
-
}
|
|
598
|
-
else {
|
|
599
|
-
throw new Error(`Can not create a new Color instance from string "${trimmed}".`);
|
|
600
|
-
}
|
|
724
|
+
return Color.fromColorChannels(parseColorString(color));
|
|
601
725
|
}
|
|
602
726
|
/**
|
|
603
727
|
* Gets common color
|
|
@@ -627,8 +751,7 @@ class Color {
|
|
|
627
751
|
* @returns Color object
|
|
628
752
|
*/
|
|
629
753
|
static fromHex(hex) {
|
|
630
|
-
|
|
631
|
-
return take(new Color(red, green, blue, alpha));
|
|
754
|
+
return Color.fromColorChannels(parseHexColor(hex));
|
|
632
755
|
}
|
|
633
756
|
/**
|
|
634
757
|
* Creates a new Color instance from color in hsl format
|
|
@@ -637,8 +760,7 @@ class Color {
|
|
|
637
760
|
* @returns Color object
|
|
638
761
|
*/
|
|
639
762
|
static fromHsl(hsl) {
|
|
640
|
-
|
|
641
|
-
return take(new Color(red, green, blue, alpha));
|
|
763
|
+
return Color.fromColorChannels(parseHslColor(hsl));
|
|
642
764
|
}
|
|
643
765
|
/**
|
|
644
766
|
* Creates a new Color instance from color in rgb format
|
|
@@ -647,8 +769,7 @@ class Color {
|
|
|
647
769
|
* @returns Color object
|
|
648
770
|
*/
|
|
649
771
|
static fromRgbString(rgb) {
|
|
650
|
-
|
|
651
|
-
return take(new Color(red, green, blue, alpha));
|
|
772
|
+
return Color.fromColorChannels(parseRgbColor(rgb));
|
|
652
773
|
}
|
|
653
774
|
/**
|
|
654
775
|
* Creates a new Color instance from color in rbga format
|
|
@@ -657,8 +778,7 @@ class Color {
|
|
|
657
778
|
* @returns Color object
|
|
658
779
|
*/
|
|
659
780
|
static fromRgbaString(rgba) {
|
|
660
|
-
|
|
661
|
-
return take(new Color(red, green, blue, alpha));
|
|
781
|
+
return Color.fromColorChannels(parseRgbaColor(rgba));
|
|
662
782
|
}
|
|
663
783
|
/**
|
|
664
784
|
* Creates a new Color for color channels values
|
|
@@ -670,7 +790,7 @@ class Color {
|
|
|
670
790
|
* @returns Color object
|
|
671
791
|
*/
|
|
672
792
|
static fromValues(red, green, blue, alpha = 255) {
|
|
673
|
-
return
|
|
793
|
+
return Color.fromColorChannels({ red, green, blue, alpha });
|
|
674
794
|
}
|
|
675
795
|
/**
|
|
676
796
|
* Checks if the given value is a valid Color object.
|
|
@@ -703,8 +823,7 @@ class Color {
|
|
|
703
823
|
* @returns true if the value is a valid hex color string (e.g., `#009edd`, `#fff`, etc.)
|
|
704
824
|
*/
|
|
705
825
|
static isHexColorString(value) {
|
|
706
|
-
return (
|
|
707
|
-
/^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/.test(value));
|
|
826
|
+
return isHexColorString(value);
|
|
708
827
|
}
|
|
709
828
|
/**
|
|
710
829
|
* Creates new Color object
|
|
@@ -717,89 +836,13 @@ class Color {
|
|
|
717
836
|
* @param alpha number from 0 (transparent) to 255 (opaque)
|
|
718
837
|
*/
|
|
719
838
|
constructor(red, green, blue, alpha = 255) {
|
|
720
|
-
|
|
721
|
-
this.green = green;
|
|
722
|
-
this.blue = blue;
|
|
723
|
-
this.alpha = alpha;
|
|
724
|
-
checkChannelValue('Red', red);
|
|
725
|
-
checkChannelValue('Green', green);
|
|
726
|
-
checkChannelValue('Blue', blue);
|
|
727
|
-
checkChannelValue('Alpha', alpha);
|
|
728
|
-
}
|
|
729
|
-
/**
|
|
730
|
-
* Shortcut for `red` property
|
|
731
|
-
* Number from 0 to 255
|
|
732
|
-
* @alias red
|
|
733
|
-
*/
|
|
734
|
-
get r() {
|
|
735
|
-
return this.red;
|
|
736
|
-
}
|
|
737
|
-
/**
|
|
738
|
-
* Shortcut for `green` property
|
|
739
|
-
* Number from 0 to 255
|
|
740
|
-
* @alias green
|
|
741
|
-
*/
|
|
742
|
-
get g() {
|
|
743
|
-
return this.green;
|
|
744
|
-
}
|
|
745
|
-
/**
|
|
746
|
-
* Shortcut for `blue` property
|
|
747
|
-
* Number from 0 to 255
|
|
748
|
-
* @alias blue
|
|
749
|
-
*/
|
|
750
|
-
get b() {
|
|
751
|
-
return this.blue;
|
|
752
|
-
}
|
|
753
|
-
/**
|
|
754
|
-
* Shortcut for `alpha` property
|
|
755
|
-
* Number from 0 (transparent) to 255 (opaque)
|
|
756
|
-
* @alias alpha
|
|
757
|
-
*/
|
|
758
|
-
get a() {
|
|
759
|
-
return this.alpha;
|
|
760
|
-
}
|
|
761
|
-
/**
|
|
762
|
-
* Shortcut for `alpha` property
|
|
763
|
-
* Number from 0 (transparent) to 255 (opaque)
|
|
764
|
-
* @alias alpha
|
|
765
|
-
*/
|
|
766
|
-
get opacity() {
|
|
767
|
-
return this.alpha;
|
|
768
|
-
}
|
|
769
|
-
/**
|
|
770
|
-
* Shortcut for 1-`alpha` property
|
|
771
|
-
*/
|
|
772
|
-
get transparency() {
|
|
773
|
-
return 255 - this.alpha;
|
|
774
|
-
}
|
|
775
|
-
clone() {
|
|
776
|
-
return take(new Color(this.red, this.green, this.blue, this.alpha));
|
|
777
|
-
}
|
|
778
|
-
toString() {
|
|
779
|
-
return this.toHex();
|
|
780
|
-
}
|
|
781
|
-
toHex() {
|
|
782
|
-
if (this.alpha === 255) {
|
|
783
|
-
return `#${this.red.toString(16).padStart(2, '0')}${this.green.toString(16).padStart(2, '0')}${this.blue
|
|
784
|
-
.toString(16)
|
|
785
|
-
.padStart(2, '0')}`;
|
|
786
|
-
}
|
|
787
|
-
else {
|
|
788
|
-
return `#${this.red.toString(16).padStart(2, '0')}${this.green.toString(16).padStart(2, '0')}${this.blue
|
|
789
|
-
.toString(16)
|
|
790
|
-
.padStart(2, '0')}${this.alpha.toString(16).padStart(2, '0')}`;
|
|
791
|
-
}
|
|
839
|
+
super(red, green, blue, alpha);
|
|
792
840
|
}
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
return `rgb(${this.red}, ${this.green}, ${this.blue})`;
|
|
796
|
-
}
|
|
797
|
-
else {
|
|
798
|
-
return `rgba(${this.red}, ${this.green}, ${this.blue}, ${Math.round((this.alpha / 255) * 100)}%)`;
|
|
799
|
-
}
|
|
841
|
+
createColor(red, green, blue, alpha) {
|
|
842
|
+
return new Color(red, green, blue, alpha);
|
|
800
843
|
}
|
|
801
|
-
|
|
802
|
-
|
|
844
|
+
static fromColorChannels({ red, green, blue, alpha }) {
|
|
845
|
+
return take(new Color(red, green, blue, alpha));
|
|
803
846
|
}
|
|
804
847
|
}
|
|
805
848
|
|
|
@@ -1982,7 +2025,7 @@ function createJokerCommands(task) {
|
|
|
1982
2025
|
*/
|
|
1983
2026
|
function createPostprocessingCommands(task) {
|
|
1984
2027
|
var _a;
|
|
1985
|
-
return ((_a = task.postprocessingFunctionNames) === null || _a === void 0 ? void 0 : _a.map((postprocessingFunctionName) => `POSTPROCESSING \`${postprocessingFunctionName}\``)) || [];
|
|
2028
|
+
return (((_a = task.postprocessingFunctionNames) === null || _a === void 0 ? void 0 : _a.map((postprocessingFunctionName) => `POSTPROCESSING \`${postprocessingFunctionName}\``)) || []);
|
|
1986
2029
|
}
|
|
1987
2030
|
/**
|
|
1988
2031
|
* Collects expectation commands.
|
|
@@ -2147,120 +2190,183 @@ function $deepFreeze(objectValue) {
|
|
|
2147
2190
|
* @public exported from `@promptbook/utils`
|
|
2148
2191
|
*/
|
|
2149
2192
|
function checkSerializableAsJson(options) {
|
|
2150
|
-
|
|
2193
|
+
checkSerializableValue(options);
|
|
2194
|
+
}
|
|
2195
|
+
// TODO: Can be return type more type-safe? like `asserts options.value is JsonValue`
|
|
2196
|
+
// TODO: [🧠][main] !!3 In-memory cache of same values to prevent multiple checks
|
|
2197
|
+
// Note: [🐠] This is how `checkSerializableAsJson` + `isSerializableAsJson` together can just retun true/false or rich error message
|
|
2198
|
+
/**
|
|
2199
|
+
* Checks one value and dispatches to the appropriate specialized validator.
|
|
2200
|
+
*
|
|
2201
|
+
* @private function of `checkSerializableAsJson`
|
|
2202
|
+
*/
|
|
2203
|
+
function checkSerializableValue(options) {
|
|
2204
|
+
const { value } = options;
|
|
2205
|
+
if (isSerializablePrimitive(value)) {
|
|
2206
|
+
return;
|
|
2207
|
+
}
|
|
2151
2208
|
if (value === undefined) {
|
|
2152
|
-
throw new UnexpectedError(`${name} is undefined`);
|
|
2209
|
+
throw new UnexpectedError(`${options.name} is undefined`);
|
|
2153
2210
|
}
|
|
2154
|
-
|
|
2155
|
-
|
|
2211
|
+
if (typeof value === 'symbol') {
|
|
2212
|
+
throw new UnexpectedError(`${options.name} is symbol`);
|
|
2156
2213
|
}
|
|
2157
|
-
|
|
2158
|
-
|
|
2214
|
+
if (typeof value === 'function') {
|
|
2215
|
+
throw new UnexpectedError(`${options.name} is function`);
|
|
2159
2216
|
}
|
|
2160
|
-
|
|
2217
|
+
if (Array.isArray(value)) {
|
|
2218
|
+
checkSerializableArray(options, value);
|
|
2161
2219
|
return;
|
|
2162
2220
|
}
|
|
2163
|
-
|
|
2221
|
+
if (value !== null && typeof value === 'object') {
|
|
2222
|
+
checkSerializableObject(options, value);
|
|
2164
2223
|
return;
|
|
2165
2224
|
}
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2225
|
+
throwUnknownTypeError(options);
|
|
2226
|
+
}
|
|
2227
|
+
/**
|
|
2228
|
+
* Checks the primitive values that are directly JSON serializable.
|
|
2229
|
+
*
|
|
2230
|
+
* @private function of `checkSerializableAsJson`
|
|
2231
|
+
*/
|
|
2232
|
+
function isSerializablePrimitive(value) {
|
|
2233
|
+
return (value === null ||
|
|
2234
|
+
typeof value === 'boolean' ||
|
|
2235
|
+
(typeof value === 'number' && !isNaN(value)) ||
|
|
2236
|
+
typeof value === 'string');
|
|
2237
|
+
}
|
|
2238
|
+
/**
|
|
2239
|
+
* Recursively checks JSON array items.
|
|
2240
|
+
*
|
|
2241
|
+
* @private function of `checkSerializableAsJson`
|
|
2242
|
+
*/
|
|
2243
|
+
function checkSerializableArray(context, arrayValue) {
|
|
2244
|
+
for (let index = 0; index < arrayValue.length; index++) {
|
|
2245
|
+
checkSerializableAsJson({
|
|
2246
|
+
...context,
|
|
2247
|
+
name: `${context.name}[${index}]`,
|
|
2248
|
+
value: arrayValue[index],
|
|
2249
|
+
});
|
|
2176
2250
|
}
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2251
|
+
}
|
|
2252
|
+
/**
|
|
2253
|
+
* Checks object-like values and dispatches special unsupported built-ins.
|
|
2254
|
+
*
|
|
2255
|
+
* @private function of `checkSerializableAsJson`
|
|
2256
|
+
*/
|
|
2257
|
+
function checkSerializableObject(context, objectValue) {
|
|
2258
|
+
checkUnsupportedObjectType(context, objectValue);
|
|
2259
|
+
checkSerializableObjectEntries(context, objectValue);
|
|
2260
|
+
assertJsonStringificationSucceeds(context, objectValue);
|
|
2261
|
+
}
|
|
2262
|
+
/**
|
|
2263
|
+
* Rejects built-in objects that must be converted before JSON serialization.
|
|
2264
|
+
*
|
|
2265
|
+
* @private function of `checkSerializableAsJson`
|
|
2266
|
+
*/
|
|
2267
|
+
function checkUnsupportedObjectType(context, objectValue) {
|
|
2268
|
+
if (objectValue instanceof Date) {
|
|
2269
|
+
throw new UnexpectedError(spaceTrim$1((block) => `
|
|
2270
|
+
\`${context.name}\` is Date
|
|
2181
2271
|
|
|
2182
|
-
|
|
2272
|
+
Use \`string_date_iso8601\` instead
|
|
2183
2273
|
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2274
|
+
Additional message for \`${context.name}\`:
|
|
2275
|
+
${block(context.message || '(nothing)')}
|
|
2276
|
+
`));
|
|
2277
|
+
}
|
|
2278
|
+
if (objectValue instanceof Map) {
|
|
2279
|
+
throw new UnexpectedError(`${context.name} is Map`);
|
|
2280
|
+
}
|
|
2281
|
+
if (objectValue instanceof Set) {
|
|
2282
|
+
throw new UnexpectedError(`${context.name} is Set`);
|
|
2283
|
+
}
|
|
2284
|
+
if (objectValue instanceof RegExp) {
|
|
2285
|
+
throw new UnexpectedError(`${context.name} is RegExp`);
|
|
2286
|
+
}
|
|
2287
|
+
if (objectValue instanceof Error) {
|
|
2288
|
+
throw new UnexpectedError(spaceTrim$1((block) => `
|
|
2289
|
+
\`${context.name}\` is unserialized Error
|
|
2200
2290
|
|
|
2201
|
-
|
|
2291
|
+
Use function \`serializeError\`
|
|
2202
2292
|
|
|
2203
|
-
|
|
2204
|
-
|
|
2293
|
+
Additional message for \`${context.name}\`:
|
|
2294
|
+
${block(context.message || '(nothing)')}
|
|
2205
2295
|
|
|
2206
|
-
|
|
2296
|
+
`));
|
|
2297
|
+
}
|
|
2298
|
+
}
|
|
2299
|
+
/**
|
|
2300
|
+
* Recursively checks object properties while preserving omitted `undefined` keys.
|
|
2301
|
+
*
|
|
2302
|
+
* @private function of `checkSerializableAsJson`
|
|
2303
|
+
*/
|
|
2304
|
+
function checkSerializableObjectEntries(context, objectValue) {
|
|
2305
|
+
for (const [subName, subValue] of Object.entries(objectValue)) {
|
|
2306
|
+
if (subValue === undefined) {
|
|
2307
|
+
// Note: undefined in object is serializable - it is just omitted
|
|
2308
|
+
continue;
|
|
2207
2309
|
}
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2310
|
+
checkSerializableAsJson({
|
|
2311
|
+
...context,
|
|
2312
|
+
name: `${context.name}.${subName}`,
|
|
2313
|
+
value: subValue,
|
|
2314
|
+
});
|
|
2315
|
+
}
|
|
2316
|
+
}
|
|
2317
|
+
/**
|
|
2318
|
+
* Uses `JSON.stringify` as the final guard for cases like circular references.
|
|
2319
|
+
*
|
|
2320
|
+
* @private function of `checkSerializableAsJson`
|
|
2321
|
+
*/
|
|
2322
|
+
function assertJsonStringificationSucceeds(context, objectValue) {
|
|
2323
|
+
try {
|
|
2324
|
+
JSON.stringify(objectValue); // <- TODO: [0]
|
|
2325
|
+
}
|
|
2326
|
+
catch (error) {
|
|
2327
|
+
assertsError(error);
|
|
2328
|
+
throw new UnexpectedError(spaceTrim$1((block) => `
|
|
2329
|
+
\`${context.name}\` is not serializable
|
|
2223
2330
|
|
|
2224
|
-
|
|
2331
|
+
${block(error.stack || error.message)}
|
|
2225
2332
|
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2333
|
+
Additional message for \`${context.name}\`:
|
|
2334
|
+
${block(context.message || '(nothing)')}
|
|
2335
|
+
`));
|
|
2336
|
+
}
|
|
2337
|
+
/*
|
|
2338
|
+
TODO: [0] Is there some more elegant way to check circular references?
|
|
2339
|
+
const seen = new Set();
|
|
2340
|
+
const stack = [{ value }];
|
|
2341
|
+
while (stack.length > 0) {
|
|
2342
|
+
const { value } = stack.pop()!;
|
|
2343
|
+
if (typeof value === 'object' && value !== null) {
|
|
2344
|
+
if (seen.has(value)) {
|
|
2345
|
+
throw new UnexpectedError(`${name} has circular reference`);
|
|
2229
2346
|
}
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
const { value } = stack.pop()!;
|
|
2236
|
-
if (typeof value === 'object' && value !== null) {
|
|
2237
|
-
if (seen.has(value)) {
|
|
2238
|
-
throw new UnexpectedError(`${name} has circular reference`);
|
|
2239
|
-
}
|
|
2240
|
-
seen.add(value);
|
|
2241
|
-
if (Array.isArray(value)) {
|
|
2242
|
-
stack.push(...value.map((value) => ({ value })));
|
|
2243
|
-
} else {
|
|
2244
|
-
stack.push(...Object.values(value).map((value) => ({ value })));
|
|
2245
|
-
}
|
|
2246
|
-
}
|
|
2347
|
+
seen.add(value);
|
|
2348
|
+
if (Array.isArray(value)) {
|
|
2349
|
+
stack.push(...value.map((value) => ({ value })));
|
|
2350
|
+
} else {
|
|
2351
|
+
stack.push(...Object.values(value).map((value) => ({ value })));
|
|
2247
2352
|
}
|
|
2248
|
-
*/
|
|
2249
|
-
return;
|
|
2250
2353
|
}
|
|
2251
2354
|
}
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2355
|
+
*/
|
|
2356
|
+
}
|
|
2357
|
+
/**
|
|
2358
|
+
* Throws the fallback error for unsupported value types like `bigint` and `NaN`.
|
|
2359
|
+
*
|
|
2360
|
+
* @private function of `checkSerializableAsJson`
|
|
2361
|
+
*/
|
|
2362
|
+
function throwUnknownTypeError(context) {
|
|
2363
|
+
throw new UnexpectedError(spaceTrim$1((block) => `
|
|
2364
|
+
\`${context.name}\` is unknown type
|
|
2255
2365
|
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
}
|
|
2366
|
+
Additional message for \`${context.name}\`:
|
|
2367
|
+
${block(context.message || '(nothing)')}
|
|
2368
|
+
`));
|
|
2260
2369
|
}
|
|
2261
|
-
// TODO: Can be return type more type-safe? like `asserts options.value is JsonValue`
|
|
2262
|
-
// TODO: [🧠][main] !!3 In-memory cache of same values to prevent multiple checks
|
|
2263
|
-
// Note: [🐠] This is how `checkSerializableAsJson` + `isSerializableAsJson` together can just retun true/false or rich error message
|
|
2264
2370
|
|
|
2265
2371
|
/**
|
|
2266
2372
|
* Creates a deep clone of the given object
|
|
@@ -3001,8 +3107,7 @@ function hasTaskJokers(task) {
|
|
|
3001
3107
|
* @private internal utility of `validatePipeline`
|
|
3002
3108
|
*/
|
|
3003
3109
|
function validateTaskSupportsJokers(task, pipelineIdentification) {
|
|
3004
|
-
if (task.format ||
|
|
3005
|
-
task.expectations /* <- TODO: Require at least 1 -> min <- expectation to use jokers */) {
|
|
3110
|
+
if (task.format || task.expectations /* <- TODO: Require at least 1 -> min <- expectation to use jokers */) {
|
|
3006
3111
|
return;
|
|
3007
3112
|
}
|
|
3008
3113
|
throw new PipelineLogicError(spaceTrim$1((block) => `
|
|
@@ -7391,9 +7496,7 @@ function createFailuresSummary($failedResults) {
|
|
|
7391
7496
|
${block(quoteMultilineText(((_b = failure.error) === null || _b === void 0 ? void 0 : _b.message) || ''))}
|
|
7392
7497
|
|
|
7393
7498
|
Result:
|
|
7394
|
-
${block(failure.result === null
|
|
7395
|
-
? 'null'
|
|
7396
|
-
: quoteMultilineText(spaceTrim$1(failure.result)))}
|
|
7499
|
+
${block(failure.result === null ? 'null' : quoteMultilineText(spaceTrim$1(failure.result)))}
|
|
7397
7500
|
`;
|
|
7398
7501
|
}))
|
|
7399
7502
|
.join('\n\n---\n\n');
|
|
@@ -13436,7 +13539,7 @@ function fillTextureRect(texture, x, y, width, height, color) {
|
|
|
13436
13539
|
*
|
|
13437
13540
|
* @private helper of `minecraft2AvatarVisual`
|
|
13438
13541
|
*/
|
|
13439
|
-
const LIGHT_DIRECTION$
|
|
13542
|
+
const LIGHT_DIRECTION$2 = normalizeVector3({
|
|
13440
13543
|
x: 0.4,
|
|
13441
13544
|
y: -0.65,
|
|
13442
13545
|
z: 0.92,
|
|
@@ -13648,7 +13751,7 @@ function resolveVisibleCuboidFaces(cuboid, size, sceneCenterX, sceneCenterY) {
|
|
|
13648
13751
|
corners: projectedCorners,
|
|
13649
13752
|
texture: faceDefinition.texture,
|
|
13650
13753
|
averageDepth: transformedCorners.reduce((depthSum, corner) => depthSum + corner.z, 0) / transformedCorners.length,
|
|
13651
|
-
lightIntensity: clampNumber$1(dotProduct3D(faceNormal, LIGHT_DIRECTION$
|
|
13754
|
+
lightIntensity: clampNumber$1(dotProduct3D(faceNormal, LIGHT_DIRECTION$2), -1, 1),
|
|
13652
13755
|
outlineColor: cuboid.outlineColor,
|
|
13653
13756
|
};
|
|
13654
13757
|
});
|
|
@@ -14708,13 +14811,138 @@ function drawSeededEye(context, centerX, centerY, radiusX, radiusY, rotation, pa
|
|
|
14708
14811
|
context.restore();
|
|
14709
14812
|
}
|
|
14710
14813
|
|
|
14814
|
+
/* eslint-disable no-magic-numbers */
|
|
14815
|
+
/**
|
|
14816
|
+
* Draws one projected eye on a rotated octopus surface.
|
|
14817
|
+
*
|
|
14818
|
+
* @private helper of the 3D octopus avatar visuals
|
|
14819
|
+
*/
|
|
14820
|
+
function drawProjectedOrganicEye(context, localCenter, radiusX, radiusY, center, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, phase, interaction, eyeStyle) {
|
|
14821
|
+
const centerScenePoint = transformScenePoint(localCenter, center, rotationX, rotationY);
|
|
14822
|
+
if (centerScenePoint.z <= center.z) {
|
|
14823
|
+
return;
|
|
14824
|
+
}
|
|
14825
|
+
const horizontalScenePoint = transformScenePoint({ x: localCenter.x + radiusX, y: localCenter.y, z: localCenter.z }, center, rotationX, rotationY);
|
|
14826
|
+
const verticalScenePoint = transformScenePoint({ x: localCenter.x, y: localCenter.y + radiusY, z: localCenter.z }, center, rotationX, rotationY);
|
|
14827
|
+
const projectedCenterPoint = projectScenePoint(centerScenePoint, size, sceneCenterX, sceneCenterY);
|
|
14828
|
+
const projectedHorizontalPoint = projectScenePoint(horizontalScenePoint, size, sceneCenterX, sceneCenterY);
|
|
14829
|
+
const projectedVerticalPoint = projectScenePoint(verticalScenePoint, size, sceneCenterX, sceneCenterY);
|
|
14830
|
+
const projectedRadiusX = Math.hypot(projectedHorizontalPoint.x - projectedCenterPoint.x, projectedHorizontalPoint.y - projectedCenterPoint.y);
|
|
14831
|
+
const projectedRadiusY = Math.hypot(projectedVerticalPoint.x - projectedCenterPoint.x, projectedVerticalPoint.y - projectedCenterPoint.y);
|
|
14832
|
+
if (projectedRadiusX < size * 0.008 || projectedRadiusY < size * 0.008) {
|
|
14833
|
+
return;
|
|
14834
|
+
}
|
|
14835
|
+
const { pupilOffsetX, pupilOffsetY } = resolveOrganicEyeMotion({
|
|
14836
|
+
radiusX: projectedRadiusX,
|
|
14837
|
+
radiusY: projectedRadiusY,
|
|
14838
|
+
timeMs,
|
|
14839
|
+
phase,
|
|
14840
|
+
interaction,
|
|
14841
|
+
});
|
|
14842
|
+
const rotation = Math.atan2(projectedHorizontalPoint.y - projectedCenterPoint.y, projectedHorizontalPoint.x - projectedCenterPoint.x);
|
|
14843
|
+
context.save();
|
|
14844
|
+
context.translate(projectedCenterPoint.x, projectedCenterPoint.y);
|
|
14845
|
+
context.rotate(rotation);
|
|
14846
|
+
context.beginPath();
|
|
14847
|
+
context.ellipse(0, 0, projectedRadiusX, projectedRadiusY, 0, 0, Math.PI * 2);
|
|
14848
|
+
context.fillStyle = '#f8fbff';
|
|
14849
|
+
context.fill();
|
|
14850
|
+
context.clip();
|
|
14851
|
+
const irisGradient = context.createRadialGradient(-projectedRadiusX * 0.2, -projectedRadiusY * 0.26, projectedRadiusX * 0.05, 0, 0, projectedRadiusX * 0.92);
|
|
14852
|
+
irisGradient.addColorStop(0, palette.highlight);
|
|
14853
|
+
irisGradient.addColorStop(0.56, palette.secondary);
|
|
14854
|
+
irisGradient.addColorStop(1, palette.shadow);
|
|
14855
|
+
context.beginPath();
|
|
14856
|
+
context.ellipse(pupilOffsetX, pupilOffsetY, projectedRadiusX * 0.62 * eyeStyle.irisScale, projectedRadiusY * 0.72 * eyeStyle.irisScale, 0, 0, Math.PI * 2);
|
|
14857
|
+
context.fillStyle = irisGradient;
|
|
14858
|
+
context.fill();
|
|
14859
|
+
context.beginPath();
|
|
14860
|
+
context.ellipse(pupilOffsetX, pupilOffsetY, projectedRadiusX * 0.15 * eyeStyle.pupilWidthScale, projectedRadiusY * 0.48 * eyeStyle.pupilHeightScale, 0, 0, Math.PI * 2);
|
|
14861
|
+
context.fillStyle = palette.ink;
|
|
14862
|
+
context.fill();
|
|
14863
|
+
context.beginPath();
|
|
14864
|
+
context.ellipse(pupilOffsetX - projectedRadiusX * 0.22, pupilOffsetY - projectedRadiusY * 0.24, projectedRadiusX * 0.12, projectedRadiusY * 0.14, 0, 0, Math.PI * 2);
|
|
14865
|
+
context.fillStyle = '#ffffff';
|
|
14866
|
+
context.fill();
|
|
14867
|
+
context.restore();
|
|
14868
|
+
context.save();
|
|
14869
|
+
context.translate(projectedCenterPoint.x, projectedCenterPoint.y);
|
|
14870
|
+
context.rotate(rotation);
|
|
14871
|
+
context.beginPath();
|
|
14872
|
+
context.ellipse(0, 0, projectedRadiusX, projectedRadiusY, 0, 0, Math.PI * 2);
|
|
14873
|
+
context.strokeStyle = `${palette.shadow}cc`;
|
|
14874
|
+
context.lineWidth = projectedRadiusX * 0.16;
|
|
14875
|
+
context.stroke();
|
|
14876
|
+
context.beginPath();
|
|
14877
|
+
context.moveTo(-projectedRadiusX * 0.88, -projectedRadiusY * eyeStyle.upperLidInsetRatio);
|
|
14878
|
+
context.quadraticCurveTo(0, -projectedRadiusY * (eyeStyle.upperLidArchRatio - interaction.gazeY * 0.16 + interaction.intensity * 0.08), projectedRadiusX * 0.88, -projectedRadiusY * eyeStyle.upperLidInsetRatio);
|
|
14879
|
+
context.strokeStyle = `${palette.shadow}73`;
|
|
14880
|
+
context.lineWidth = projectedRadiusX * 0.14;
|
|
14881
|
+
context.lineCap = 'round';
|
|
14882
|
+
context.stroke();
|
|
14883
|
+
if (eyeStyle.lowerLidOpacity > 0) {
|
|
14884
|
+
context.beginPath();
|
|
14885
|
+
context.moveTo(-projectedRadiusX * 0.74, projectedRadiusY * 0.2);
|
|
14886
|
+
context.quadraticCurveTo(0, projectedRadiusY * 0.38, projectedRadiusX * 0.74, projectedRadiusY * 0.2);
|
|
14887
|
+
context.strokeStyle = `${palette.highlight}${formatAlphaHex(eyeStyle.lowerLidOpacity)}`;
|
|
14888
|
+
context.lineWidth = projectedRadiusX * 0.08;
|
|
14889
|
+
context.lineCap = 'round';
|
|
14890
|
+
context.stroke();
|
|
14891
|
+
}
|
|
14892
|
+
context.restore();
|
|
14893
|
+
}
|
|
14894
|
+
/**
|
|
14895
|
+
* Draws a subtle projected mouth arc across the front of a rotated octopus surface.
|
|
14896
|
+
*
|
|
14897
|
+
* @private helper of the 3D octopus avatar visuals
|
|
14898
|
+
*/
|
|
14899
|
+
function drawProjectedOrganicMouth(context, localPoints, center, rotationX, rotationY, sceneCenterX, sceneCenterY, palette, size) {
|
|
14900
|
+
const scenePoints = localPoints.map((localPoint) => transformScenePoint(localPoint, center, rotationX, rotationY));
|
|
14901
|
+
if (scenePoints.some((scenePoint) => scenePoint.z <= center.z)) {
|
|
14902
|
+
return;
|
|
14903
|
+
}
|
|
14904
|
+
const projectedPoints = scenePoints.map((scenePoint) => projectScenePoint(scenePoint, size, sceneCenterX, sceneCenterY));
|
|
14905
|
+
context.beginPath();
|
|
14906
|
+
context.moveTo(projectedPoints[0].x, projectedPoints[0].y);
|
|
14907
|
+
context.quadraticCurveTo(projectedPoints[1].x, projectedPoints[1].y, projectedPoints[2].x, projectedPoints[2].y);
|
|
14908
|
+
context.strokeStyle = `${palette.ink}b8`;
|
|
14909
|
+
context.lineWidth = Math.max(1.1, size * 0.009);
|
|
14910
|
+
context.lineCap = 'round';
|
|
14911
|
+
context.stroke();
|
|
14912
|
+
}
|
|
14913
|
+
/**
|
|
14914
|
+
* Draws one filled projected quad.
|
|
14915
|
+
*
|
|
14916
|
+
* @private helper of the 3D octopus avatar visuals
|
|
14917
|
+
*/
|
|
14918
|
+
function drawProjectedQuad(context, corners, fillStyle) {
|
|
14919
|
+
context.beginPath();
|
|
14920
|
+
context.moveTo(corners[0].x, corners[0].y);
|
|
14921
|
+
context.lineTo(corners[1].x, corners[1].y);
|
|
14922
|
+
context.lineTo(corners[2].x, corners[2].y);
|
|
14923
|
+
context.lineTo(corners[3].x, corners[3].y);
|
|
14924
|
+
context.closePath();
|
|
14925
|
+
context.fillStyle = fillStyle;
|
|
14926
|
+
context.fill();
|
|
14927
|
+
}
|
|
14928
|
+
/**
|
|
14929
|
+
* Converts an opacity ratio into a two-digit hexadecimal alpha suffix.
|
|
14930
|
+
*
|
|
14931
|
+
* @private helper of the 3D octopus avatar visuals
|
|
14932
|
+
*/
|
|
14933
|
+
function formatAlphaHex(opacity) {
|
|
14934
|
+
return Math.round(clampNumber$1(opacity, 0, 1) * 255)
|
|
14935
|
+
.toString(16)
|
|
14936
|
+
.padStart(2, '0');
|
|
14937
|
+
}
|
|
14938
|
+
|
|
14711
14939
|
/* eslint-disable no-magic-numbers */
|
|
14712
14940
|
/**
|
|
14713
14941
|
* Light direction used by the organic 3D octopus shading.
|
|
14714
14942
|
*
|
|
14715
14943
|
* @private helper of `octopus3dAvatarVisual`
|
|
14716
14944
|
*/
|
|
14717
|
-
const LIGHT_DIRECTION = normalizeVector3({
|
|
14945
|
+
const LIGHT_DIRECTION$1 = normalizeVector3({
|
|
14718
14946
|
x: 0.48,
|
|
14719
14947
|
y: -0.62,
|
|
14720
14948
|
z: 0.94,
|
|
@@ -14827,17 +15055,17 @@ const octopus3dAvatarVisual = {
|
|
|
14827
15055
|
for (const tentacleStroke of tentacleStrokes.filter((candidateTentacleStroke) => candidateTentacleStroke.isFrontFacing)) {
|
|
14828
15056
|
drawTentacleStroke(context, tentacleStroke, palette);
|
|
14829
15057
|
}
|
|
14830
|
-
|
|
15058
|
+
drawProjectedOrganicEye(context, {
|
|
14831
15059
|
x: -faceEyeSpacing,
|
|
14832
15060
|
y: faceEyeYOffset,
|
|
14833
15061
|
z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, -faceEyeSpacing, faceEyeYOffset),
|
|
14834
15062
|
}, faceEyeRadiusX, faceEyeRadiusY, mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + eyeRandom() * 0.6, interaction, morphologyProfile.face.eyeStyle);
|
|
14835
|
-
|
|
15063
|
+
drawProjectedOrganicEye(context, {
|
|
14836
15064
|
x: faceEyeSpacing,
|
|
14837
15065
|
y: faceEyeYOffset,
|
|
14838
15066
|
z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, faceEyeSpacing, faceEyeYOffset),
|
|
14839
15067
|
}, faceEyeRadiusX, faceEyeRadiusY, mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + 0.7 + eyeRandom() * 0.6, interaction, morphologyProfile.face.eyeStyle);
|
|
14840
|
-
|
|
15068
|
+
drawProjectedOrganicMouth(context, [
|
|
14841
15069
|
{
|
|
14842
15070
|
x: -mouthHalfWidth,
|
|
14843
15071
|
y: mouthY,
|
|
@@ -14924,7 +15152,7 @@ function resolveVisibleEllipsoidPatches(options) {
|
|
|
14924
15152
|
corners: projectedCorners,
|
|
14925
15153
|
averageDepth: transformedCorners.reduce((depthSum, transformedCorner) => depthSum + transformedCorner.z, 0) /
|
|
14926
15154
|
transformedCorners.length,
|
|
14927
|
-
lightIntensity: clampNumber$1(dotProduct3D(surfaceNormal, LIGHT_DIRECTION), -1, 1),
|
|
15155
|
+
lightIntensity: clampNumber$1(dotProduct3D(surfaceNormal, LIGHT_DIRECTION$1), -1, 1),
|
|
14928
15156
|
fillStyle: resolveSurfacePatchFillStyle(palette, verticalProgress + verticalColorBias),
|
|
14929
15157
|
outlineColor,
|
|
14930
15158
|
});
|
|
@@ -15106,128 +15334,260 @@ function resolveEllipsoidSurfaceDepth(radiusX, radiusY, radiusZ, x, y) {
|
|
|
15106
15334
|
const remainingDepthRatio = Math.max(0, 1 - normalizedX * normalizedX - normalizedY * normalizedY);
|
|
15107
15335
|
return Math.sqrt(remainingDepthRatio) * radiusZ;
|
|
15108
15336
|
}
|
|
15337
|
+
|
|
15338
|
+
/* eslint-disable no-magic-numbers */
|
|
15109
15339
|
/**
|
|
15110
|
-
*
|
|
15340
|
+
* Light direction used by the single-mesh octopus shading.
|
|
15111
15341
|
*
|
|
15112
|
-
* @private helper of `
|
|
15342
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
15113
15343
|
*/
|
|
15114
|
-
|
|
15115
|
-
|
|
15116
|
-
|
|
15117
|
-
|
|
15118
|
-
|
|
15119
|
-
|
|
15120
|
-
|
|
15121
|
-
|
|
15122
|
-
|
|
15123
|
-
|
|
15124
|
-
|
|
15125
|
-
|
|
15126
|
-
|
|
15127
|
-
|
|
15128
|
-
|
|
15129
|
-
|
|
15130
|
-
|
|
15131
|
-
|
|
15132
|
-
|
|
15133
|
-
|
|
15134
|
-
|
|
15135
|
-
|
|
15136
|
-
|
|
15344
|
+
const LIGHT_DIRECTION = normalizeVector3({
|
|
15345
|
+
x: 0.38,
|
|
15346
|
+
y: -0.6,
|
|
15347
|
+
z: 0.98,
|
|
15348
|
+
});
|
|
15349
|
+
/**
|
|
15350
|
+
* Octopus 3D 2 avatar visual.
|
|
15351
|
+
*
|
|
15352
|
+
* @private built-in avatar visual
|
|
15353
|
+
*/
|
|
15354
|
+
const octopus3d2AvatarVisual = {
|
|
15355
|
+
id: 'octopus3d2',
|
|
15356
|
+
title: 'Octopus 3D 2',
|
|
15357
|
+
description: 'Continuous blobby 3D octopus portrait with one soft mesh, turning silhouette, and cursor-aware eyes.',
|
|
15358
|
+
isAnimated: true,
|
|
15359
|
+
supportsPointerTracking: true,
|
|
15360
|
+
render({ context, size, palette, createRandom, timeMs, interaction }) {
|
|
15361
|
+
const morphologyProfile = createOctopus3MorphologyProfile(createRandom);
|
|
15362
|
+
const animationRandom = createRandom('octopus3d2-animation-profile');
|
|
15363
|
+
const eyeRandom = createRandom('octopus3d2-eye-profile');
|
|
15364
|
+
const animationPhase = animationRandom() * Math.PI * 2;
|
|
15365
|
+
const sceneCenterX = size * 0.5;
|
|
15366
|
+
const sceneCenterY = size * 0.575;
|
|
15367
|
+
const bob = Math.sin(timeMs / 940 + animationPhase) * size * 0.013;
|
|
15368
|
+
const meshCenter = {
|
|
15369
|
+
x: interaction.bodyOffsetX * size * 0.044 + size * morphologyProfile.body.centerXJitterRatio * 0.5,
|
|
15370
|
+
y: -size * 0.03 + interaction.bodyOffsetY * size * 0.026 + bob,
|
|
15371
|
+
z: interaction.intensity * size * 0.018,
|
|
15372
|
+
};
|
|
15373
|
+
const rotationY = -0.14 +
|
|
15374
|
+
Math.sin(timeMs / 2600 + animationPhase) * 0.04 +
|
|
15375
|
+
interaction.bodyOffsetX * 0.2 +
|
|
15376
|
+
interaction.gazeX * 0.78;
|
|
15377
|
+
const rotationX = -0.06 +
|
|
15378
|
+
Math.cos(timeMs / 3000 + animationPhase * 0.7) * 0.02 -
|
|
15379
|
+
interaction.bodyOffsetY * 0.08 -
|
|
15380
|
+
interaction.gazeY * 0.34;
|
|
15381
|
+
const surfaceOptions = {
|
|
15382
|
+
radiusX: size * morphologyProfile.body.bodyRadiusRatio * morphologyProfile.body.horizontalStretch * 1.02,
|
|
15383
|
+
radiusY: size * morphologyProfile.body.bodyRadiusRatio * morphologyProfile.body.verticalStretch * 1.22,
|
|
15384
|
+
radiusZ: size *
|
|
15385
|
+
morphologyProfile.body.bodyRadiusRatio *
|
|
15386
|
+
(0.98 + (morphologyProfile.body.horizontalStretch - 1) * 0.2),
|
|
15387
|
+
morphologyProfile,
|
|
15388
|
+
timeMs,
|
|
15389
|
+
animationPhase,
|
|
15390
|
+
};
|
|
15391
|
+
const surfacePatches = resolveVisibleBlobbyOctopusPatches({
|
|
15392
|
+
...surfaceOptions,
|
|
15393
|
+
center: meshCenter,
|
|
15394
|
+
rotationX,
|
|
15395
|
+
rotationY,
|
|
15396
|
+
sceneCenterX,
|
|
15397
|
+
sceneCenterY,
|
|
15398
|
+
size,
|
|
15399
|
+
palette,
|
|
15400
|
+
});
|
|
15401
|
+
const eyeLatitude = clampNumber$1(morphologyProfile.face.eyeCenterYOffsetRatio * 4.4, -0.16, 0.11);
|
|
15402
|
+
const eyeLongitude = clampNumber$1(morphologyProfile.face.eyeSpacingRatio * 3.25, 0.2, 0.34);
|
|
15403
|
+
const mouthLatitude = clampNumber$1(eyeLatitude + 0.19 + morphologyProfile.face.mouthYOffsetRatio * 1.08, 0.08, 0.34);
|
|
15404
|
+
const mouthCenterLongitude = clampNumber$1(morphologyProfile.face.mouthCenterOffsetRatio * 5.8, -0.08, 0.08);
|
|
15405
|
+
const mouthHalfLongitude = clampNumber$1(eyeLongitude * 0.82, 0.16, 0.29);
|
|
15406
|
+
const mouthCurveLatitude = clampNumber$1(mouthLatitude + morphologyProfile.face.mouthCurveDepthRatio * 0.85, mouthLatitude + 0.03, 0.42);
|
|
15407
|
+
drawAvatarFrame(context, size, palette);
|
|
15408
|
+
drawBlobbyOctopusAtmosphere(context, size, palette, sceneCenterX, sceneCenterY, interaction, timeMs);
|
|
15409
|
+
drawBlobbyOctopusShadow(context, size, palette, interaction, timeMs, morphologyProfile);
|
|
15410
|
+
for (const surfacePatch of surfacePatches.sort((firstSurfacePatch, secondSurfacePatch) => firstSurfacePatch.averageDepth - secondSurfacePatch.averageDepth)) {
|
|
15411
|
+
drawBlobbySurfacePatch(context, surfacePatch);
|
|
15412
|
+
}
|
|
15413
|
+
const leftEyeLocalCenter = sampleBlobbyOctopusSurfacePoint(surfaceOptions, eyeLatitude, -eyeLongitude);
|
|
15414
|
+
const rightEyeLocalCenter = sampleBlobbyOctopusSurfacePoint(surfaceOptions, eyeLatitude, eyeLongitude);
|
|
15415
|
+
const eyeRadiusX = size * morphologyProfile.face.eyeRadiusXRatio * 0.78;
|
|
15416
|
+
const eyeRadiusY = eyeRadiusX * morphologyProfile.face.eyeHeightRatio * 0.92;
|
|
15417
|
+
drawProjectedOrganicEye(context, leftEyeLocalCenter, eyeRadiusX, eyeRadiusY, meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + eyeRandom() * 0.7, interaction, morphologyProfile.face.eyeStyle);
|
|
15418
|
+
drawProjectedOrganicEye(context, rightEyeLocalCenter, eyeRadiusX, eyeRadiusY, meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + 0.9 + eyeRandom() * 0.7, interaction, morphologyProfile.face.eyeStyle);
|
|
15419
|
+
drawProjectedOrganicMouth(context, [
|
|
15420
|
+
sampleBlobbyOctopusSurfacePoint(surfaceOptions, mouthLatitude, mouthCenterLongitude - mouthHalfLongitude),
|
|
15421
|
+
sampleBlobbyOctopusSurfacePoint(surfaceOptions, mouthCurveLatitude, mouthCenterLongitude),
|
|
15422
|
+
sampleBlobbyOctopusSurfacePoint(surfaceOptions, mouthLatitude, mouthCenterLongitude + mouthHalfLongitude),
|
|
15423
|
+
], meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, palette, size);
|
|
15424
|
+
},
|
|
15425
|
+
};
|
|
15426
|
+
/**
|
|
15427
|
+
* Draws the deep-water glow behind the continuous octopus mesh.
|
|
15428
|
+
*
|
|
15429
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
15430
|
+
*/
|
|
15431
|
+
function drawBlobbyOctopusAtmosphere(context, size, palette, sceneCenterX, sceneCenterY, interaction, timeMs) {
|
|
15432
|
+
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);
|
|
15433
|
+
glowGradient.addColorStop(0, `${palette.highlight}5e`);
|
|
15434
|
+
glowGradient.addColorStop(0.38, `${palette.accent}26`);
|
|
15435
|
+
glowGradient.addColorStop(1, `${palette.highlight}00`);
|
|
15436
|
+
context.fillStyle = glowGradient;
|
|
15437
|
+
context.fillRect(0, 0, size, size);
|
|
15438
|
+
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);
|
|
15439
|
+
lowerGradient.addColorStop(0, `${palette.secondary}22`);
|
|
15440
|
+
lowerGradient.addColorStop(1, `${palette.secondary}00`);
|
|
15441
|
+
context.fillStyle = lowerGradient;
|
|
15442
|
+
context.fillRect(0, 0, size, size);
|
|
15443
|
+
}
|
|
15444
|
+
/**
|
|
15445
|
+
* Draws the soft floor shadow that anchors the single mesh in the frame.
|
|
15446
|
+
*
|
|
15447
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
15448
|
+
*/
|
|
15449
|
+
function drawBlobbyOctopusShadow(context, size, palette, interaction, timeMs, morphologyProfile) {
|
|
15137
15450
|
context.save();
|
|
15138
|
-
context.
|
|
15139
|
-
context.
|
|
15140
|
-
context.beginPath();
|
|
15141
|
-
context.ellipse(0, 0, projectedRadiusX, projectedRadiusY, 0, 0, Math.PI * 2);
|
|
15142
|
-
context.fillStyle = '#f8fbff';
|
|
15143
|
-
context.fill();
|
|
15144
|
-
context.clip();
|
|
15145
|
-
const irisGradient = context.createRadialGradient(-projectedRadiusX * 0.2, -projectedRadiusY * 0.26, projectedRadiusX * 0.05, 0, 0, projectedRadiusX * 0.92);
|
|
15146
|
-
irisGradient.addColorStop(0, palette.highlight);
|
|
15147
|
-
irisGradient.addColorStop(0.56, palette.secondary);
|
|
15148
|
-
irisGradient.addColorStop(1, palette.shadow);
|
|
15149
|
-
context.beginPath();
|
|
15150
|
-
context.ellipse(pupilOffsetX, pupilOffsetY, projectedRadiusX * 0.62 * eyeStyle.irisScale, projectedRadiusY * 0.72 * eyeStyle.irisScale, 0, 0, Math.PI * 2);
|
|
15151
|
-
context.fillStyle = irisGradient;
|
|
15152
|
-
context.fill();
|
|
15451
|
+
context.fillStyle = `${palette.shadow}66`;
|
|
15452
|
+
context.filter = `blur(${size * 0.024}px)`;
|
|
15153
15453
|
context.beginPath();
|
|
15154
|
-
context.ellipse(
|
|
15155
|
-
context.fillStyle = palette.ink;
|
|
15454
|
+
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);
|
|
15156
15455
|
context.fill();
|
|
15157
|
-
context.beginPath();
|
|
15158
|
-
context.ellipse(pupilOffsetX - projectedRadiusX * 0.22, pupilOffsetY - projectedRadiusY * 0.24, projectedRadiusX * 0.12, projectedRadiusY * 0.14, 0, 0, Math.PI * 2);
|
|
15159
|
-
context.fillStyle = '#ffffff';
|
|
15160
|
-
context.fill();
|
|
15161
|
-
context.restore();
|
|
15162
|
-
context.save();
|
|
15163
|
-
context.translate(projectedCenterPoint.x, projectedCenterPoint.y);
|
|
15164
|
-
context.rotate(rotation);
|
|
15165
|
-
context.beginPath();
|
|
15166
|
-
context.ellipse(0, 0, projectedRadiusX, projectedRadiusY, 0, 0, Math.PI * 2);
|
|
15167
|
-
context.strokeStyle = `${palette.shadow}cc`;
|
|
15168
|
-
context.lineWidth = projectedRadiusX * 0.16;
|
|
15169
|
-
context.stroke();
|
|
15170
|
-
context.beginPath();
|
|
15171
|
-
context.moveTo(-projectedRadiusX * 0.88, -projectedRadiusY * eyeStyle.upperLidInsetRatio);
|
|
15172
|
-
context.quadraticCurveTo(0, -projectedRadiusY * (eyeStyle.upperLidArchRatio - interaction.gazeY * 0.16 + interaction.intensity * 0.08), projectedRadiusX * 0.88, -projectedRadiusY * eyeStyle.upperLidInsetRatio);
|
|
15173
|
-
context.strokeStyle = `${palette.shadow}73`;
|
|
15174
|
-
context.lineWidth = projectedRadiusX * 0.14;
|
|
15175
|
-
context.lineCap = 'round';
|
|
15176
|
-
context.stroke();
|
|
15177
|
-
if (eyeStyle.lowerLidOpacity > 0) {
|
|
15178
|
-
context.beginPath();
|
|
15179
|
-
context.moveTo(-projectedRadiusX * 0.74, projectedRadiusY * 0.2);
|
|
15180
|
-
context.quadraticCurveTo(0, projectedRadiusY * 0.38, projectedRadiusX * 0.74, projectedRadiusY * 0.2);
|
|
15181
|
-
context.strokeStyle = `${palette.highlight}${formatAlphaHex(eyeStyle.lowerLidOpacity)}`;
|
|
15182
|
-
context.lineWidth = projectedRadiusX * 0.08;
|
|
15183
|
-
context.lineCap = 'round';
|
|
15184
|
-
context.stroke();
|
|
15185
|
-
}
|
|
15186
15456
|
context.restore();
|
|
15187
15457
|
}
|
|
15188
15458
|
/**
|
|
15189
|
-
*
|
|
15459
|
+
* Resolves all visible projected patches for the single blobby octopus mesh.
|
|
15190
15460
|
*
|
|
15191
|
-
* @private helper of `
|
|
15461
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
15192
15462
|
*/
|
|
15193
|
-
function
|
|
15194
|
-
const
|
|
15195
|
-
|
|
15196
|
-
|
|
15463
|
+
function resolveVisibleBlobbyOctopusPatches(options) {
|
|
15464
|
+
const { center, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, morphologyProfile, animationPhase, timeMs, } = options;
|
|
15465
|
+
const latitudePatchCount = 12;
|
|
15466
|
+
const longitudePatchCount = 24;
|
|
15467
|
+
const surfacePatches = [];
|
|
15468
|
+
for (let latitudeIndex = 0; latitudeIndex < latitudePatchCount; latitudeIndex++) {
|
|
15469
|
+
const startLatitude = -Math.PI / 2 + (latitudeIndex / latitudePatchCount) * Math.PI;
|
|
15470
|
+
const endLatitude = -Math.PI / 2 + ((latitudeIndex + 1) / latitudePatchCount) * Math.PI;
|
|
15471
|
+
const centerLatitude = (startLatitude + endLatitude) / 2;
|
|
15472
|
+
const verticalProgress = (Math.sin(centerLatitude) + 1) / 2;
|
|
15473
|
+
for (let longitudeIndex = 0; longitudeIndex < longitudePatchCount; longitudeIndex++) {
|
|
15474
|
+
const startLongitude = -Math.PI + (longitudeIndex / longitudePatchCount) * Math.PI * 2;
|
|
15475
|
+
const endLongitude = -Math.PI + ((longitudeIndex + 1) / longitudePatchCount) * Math.PI * 2;
|
|
15476
|
+
const centerLongitude = (startLongitude + endLongitude) / 2;
|
|
15477
|
+
const localCorners = [
|
|
15478
|
+
sampleBlobbyOctopusSurfacePoint(options, startLatitude, startLongitude),
|
|
15479
|
+
sampleBlobbyOctopusSurfacePoint(options, startLatitude, endLongitude),
|
|
15480
|
+
sampleBlobbyOctopusSurfacePoint(options, endLatitude, endLongitude),
|
|
15481
|
+
sampleBlobbyOctopusSurfacePoint(options, endLatitude, startLongitude),
|
|
15482
|
+
];
|
|
15483
|
+
const transformedCorners = localCorners.map((localCorner) => transformScenePoint(localCorner, center, rotationX, rotationY));
|
|
15484
|
+
const surfaceNormal = normalizeVector3(crossProduct3D(subtractPoint3D(transformedCorners[1], transformedCorners[0]), subtractPoint3D(transformedCorners[2], transformedCorners[0])));
|
|
15485
|
+
if (surfaceNormal.z <= 0.01) {
|
|
15486
|
+
continue;
|
|
15487
|
+
}
|
|
15488
|
+
const projectedCorners = transformedCorners.map((transformedCorner) => projectScenePoint(transformedCorner, size, sceneCenterX, sceneCenterY));
|
|
15489
|
+
surfacePatches.push({
|
|
15490
|
+
corners: projectedCorners,
|
|
15491
|
+
averageDepth: transformedCorners.reduce((depthSum, transformedCorner) => depthSum + transformedCorner.z, 0) /
|
|
15492
|
+
transformedCorners.length,
|
|
15493
|
+
lightIntensity: clampNumber$1(dotProduct3D(surfaceNormal, LIGHT_DIRECTION), -1, 1),
|
|
15494
|
+
fillStyle: resolveBlobbySurfacePatchFillStyle(palette, verticalProgress, Math.max(0, Math.cos(centerLongitude)), resolveLowerLobeWave(centerLongitude, morphologyProfile, animationPhase, timeMs)),
|
|
15495
|
+
outlineColor: verticalProgress < 0.58 ? `${palette.highlight}73` : `${palette.shadow}8a`,
|
|
15496
|
+
});
|
|
15497
|
+
}
|
|
15197
15498
|
}
|
|
15198
|
-
|
|
15199
|
-
context.beginPath();
|
|
15200
|
-
context.moveTo(projectedPoints[0].x, projectedPoints[0].y);
|
|
15201
|
-
context.quadraticCurveTo(projectedPoints[1].x, projectedPoints[1].y, projectedPoints[2].x, projectedPoints[2].y);
|
|
15202
|
-
context.strokeStyle = `${palette.ink}b8`;
|
|
15203
|
-
context.lineWidth = Math.max(1.1, size * 0.009);
|
|
15204
|
-
context.lineCap = 'round';
|
|
15205
|
-
context.stroke();
|
|
15499
|
+
return surfacePatches;
|
|
15206
15500
|
}
|
|
15207
15501
|
/**
|
|
15208
|
-
*
|
|
15502
|
+
* Samples one point on the continuous Octopus 3D 2 surface.
|
|
15503
|
+
*
|
|
15504
|
+
* The lower hemisphere widens and falls into soft lobe waves so the octopus stays one connected mesh
|
|
15505
|
+
* instead of switching to separately rendered tentacles.
|
|
15506
|
+
*
|
|
15507
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
15508
|
+
*/
|
|
15509
|
+
function sampleBlobbyOctopusSurfacePoint(options, latitude, longitude) {
|
|
15510
|
+
const { radiusX, radiusY, radiusZ, morphologyProfile, timeMs, animationPhase } = options;
|
|
15511
|
+
const cosineLatitude = Math.max(0, Math.cos(latitude));
|
|
15512
|
+
const verticalProgress = (Math.sin(latitude) + 1) / 2;
|
|
15513
|
+
const upperBlend = Math.pow(1 - verticalProgress, 1.2);
|
|
15514
|
+
const lowerBlend = Math.pow(verticalProgress, 1.42);
|
|
15515
|
+
const lowerLobeWave = resolveLowerLobeWave(longitude, morphologyProfile, animationPhase, timeMs);
|
|
15516
|
+
const skirtEnvelope = Math.pow(cosineLatitude, 0.5) * lowerBlend;
|
|
15517
|
+
const horizontalScale = 1.02 +
|
|
15518
|
+
skirtEnvelope * (0.34 + (morphologyProfile.tentacles.rootSpreadScale - 1) * 0.22 + lowerLobeWave * 0.22) -
|
|
15519
|
+
upperBlend * 0.08;
|
|
15520
|
+
const depthScale = 1.04 +
|
|
15521
|
+
upperBlend * 0.16 +
|
|
15522
|
+
Math.max(0, Math.cos(longitude)) * 0.1 +
|
|
15523
|
+
skirtEnvelope * (0.08 + lowerLobeWave * 0.06) -
|
|
15524
|
+
Math.max(0, -Math.cos(longitude)) * 0.04;
|
|
15525
|
+
const lowerDrop = skirtEnvelope *
|
|
15526
|
+
radiusY *
|
|
15527
|
+
(0.28 + lowerLobeWave * 0.14 + (morphologyProfile.tentacles.flowLengthScale - 1) * 0.12);
|
|
15528
|
+
const swayX = Math.sin(timeMs / 1250 + longitude * 1.8 + animationPhase) * skirtEnvelope * radiusX * 0.05;
|
|
15529
|
+
const swayZ = Math.cos(timeMs / 1480 + longitude * 1.2 - animationPhase * 0.7) * skirtEnvelope * radiusZ * 0.03;
|
|
15530
|
+
return {
|
|
15531
|
+
x: Math.sin(longitude) * cosineLatitude * radiusX * horizontalScale + swayX,
|
|
15532
|
+
y: Math.sin(latitude) * radiusY * (1 + upperBlend * 0.14) -
|
|
15533
|
+
upperBlend * radiusY * 0.1 +
|
|
15534
|
+
lowerDrop +
|
|
15535
|
+
Math.sin(timeMs / 1780 + animationPhase + latitude * 1.4) * skirtEnvelope * radiusY * 0.02,
|
|
15536
|
+
z: Math.cos(longitude) * cosineLatitude * radiusZ * depthScale + swayZ,
|
|
15537
|
+
};
|
|
15538
|
+
}
|
|
15539
|
+
/**
|
|
15540
|
+
* Resolves the soft lower-lobe wave that makes the silhouette read more like a real octopus.
|
|
15209
15541
|
*
|
|
15210
|
-
* @private helper of `
|
|
15542
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
15211
15543
|
*/
|
|
15212
|
-
function
|
|
15213
|
-
|
|
15214
|
-
|
|
15215
|
-
context.lineTo(corners[1].x, corners[1].y);
|
|
15216
|
-
context.lineTo(corners[2].x, corners[2].y);
|
|
15217
|
-
context.lineTo(corners[3].x, corners[3].y);
|
|
15218
|
-
context.closePath();
|
|
15219
|
-
context.fillStyle = fillStyle;
|
|
15220
|
-
context.fill();
|
|
15544
|
+
function resolveLowerLobeWave(longitude, morphologyProfile, animationPhase, timeMs) {
|
|
15545
|
+
const lobeCount = Math.max(4, Math.round((morphologyProfile.body.lobeCount + morphologyProfile.tentacles.count) / 2));
|
|
15546
|
+
return (Math.cos(longitude * lobeCount + animationPhase + timeMs / 1040) + 1) / 2;
|
|
15221
15547
|
}
|
|
15222
15548
|
/**
|
|
15223
|
-
*
|
|
15549
|
+
* Resolves one base fill tone for a surface patch on the single octopus mesh.
|
|
15224
15550
|
*
|
|
15225
|
-
* @private helper of `
|
|
15551
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
15226
15552
|
*/
|
|
15227
|
-
function
|
|
15228
|
-
|
|
15229
|
-
|
|
15230
|
-
.
|
|
15553
|
+
function resolveBlobbySurfacePatchFillStyle(palette, verticalProgress, forwardness, lowerLobeWave) {
|
|
15554
|
+
const tonalProgress = clampNumber$1(verticalProgress + lowerLobeWave * 0.12 - forwardness * 0.07, 0, 1);
|
|
15555
|
+
if (tonalProgress < 0.16) {
|
|
15556
|
+
return palette.highlight;
|
|
15557
|
+
}
|
|
15558
|
+
if (tonalProgress < 0.34) {
|
|
15559
|
+
return palette.secondary;
|
|
15560
|
+
}
|
|
15561
|
+
if (tonalProgress < 0.72) {
|
|
15562
|
+
return forwardness > 0.58 ? palette.secondary : palette.primary;
|
|
15563
|
+
}
|
|
15564
|
+
return `${palette.shadow}f2`;
|
|
15565
|
+
}
|
|
15566
|
+
/**
|
|
15567
|
+
* Draws one projected patch with soft octopus shading.
|
|
15568
|
+
*
|
|
15569
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
15570
|
+
*/
|
|
15571
|
+
function drawBlobbySurfacePatch(context, surfacePatch) {
|
|
15572
|
+
drawProjectedQuad(context, surfacePatch.corners, surfacePatch.fillStyle);
|
|
15573
|
+
if (surfacePatch.lightIntensity > 0) {
|
|
15574
|
+
drawProjectedQuad(context, surfacePatch.corners, `rgba(255, 255, 255, ${0.16 * surfacePatch.lightIntensity})`);
|
|
15575
|
+
}
|
|
15576
|
+
else if (surfacePatch.lightIntensity < 0) {
|
|
15577
|
+
drawProjectedQuad(context, surfacePatch.corners, `rgba(0, 0, 0, ${0.24 * Math.abs(surfacePatch.lightIntensity)})`);
|
|
15578
|
+
}
|
|
15579
|
+
context.save();
|
|
15580
|
+
context.beginPath();
|
|
15581
|
+
context.moveTo(surfacePatch.corners[0].x, surfacePatch.corners[0].y);
|
|
15582
|
+
for (let cornerIndex = 1; cornerIndex < surfacePatch.corners.length; cornerIndex++) {
|
|
15583
|
+
context.lineTo(surfacePatch.corners[cornerIndex].x, surfacePatch.corners[cornerIndex].y);
|
|
15584
|
+
}
|
|
15585
|
+
context.closePath();
|
|
15586
|
+
context.strokeStyle = surfacePatch.outlineColor;
|
|
15587
|
+
context.lineWidth = Math.max(1, getProjectedQuadPerimeter(surfacePatch.corners) * 0.0042);
|
|
15588
|
+
context.lineJoin = 'round';
|
|
15589
|
+
context.stroke();
|
|
15590
|
+
context.restore();
|
|
15231
15591
|
}
|
|
15232
15592
|
|
|
15233
15593
|
/* eslint-disable no-magic-numbers */
|
|
@@ -15999,6 +16359,7 @@ const AVATAR_VISUALS = [
|
|
|
15999
16359
|
octopus2AvatarVisual,
|
|
16000
16360
|
octopus3AvatarVisual,
|
|
16001
16361
|
octopus3dAvatarVisual,
|
|
16362
|
+
octopus3d2AvatarVisual,
|
|
16002
16363
|
asciiOctopusAvatarVisual,
|
|
16003
16364
|
minecraftAvatarVisual,
|
|
16004
16365
|
minecraft2AvatarVisual,
|
|
@@ -21411,11 +21772,11 @@ function buildCandidateEncodings(options) {
|
|
|
21411
21772
|
});
|
|
21412
21773
|
}
|
|
21413
21774
|
/**
|
|
21414
|
-
*
|
|
21775
|
+
* Prepares one attachment for best-effort text decoding.
|
|
21415
21776
|
*
|
|
21416
|
-
* @private
|
|
21777
|
+
* @private function of decodeAttachmentAsText
|
|
21417
21778
|
*/
|
|
21418
|
-
function
|
|
21779
|
+
function createDecodeAttachmentPreparation(input, options) {
|
|
21419
21780
|
var _a;
|
|
21420
21781
|
const maxBytes = Math.max(1, Math.floor((_a = options.maxBytes) !== null && _a !== void 0 ? _a : DEFAULT_ATTACHMENT_TEXT_DECODE_BYTES));
|
|
21421
21782
|
const forceText = options.forceText === true;
|
|
@@ -21429,54 +21790,102 @@ function decodeAttachmentAsText(input, options = {}) {
|
|
|
21429
21790
|
const inspection = inspectBytes(truncatedBytes);
|
|
21430
21791
|
const trustedTextMime = isTrustedTextMimeType(mimeType);
|
|
21431
21792
|
const trustedBinaryMime = isTrustedBinaryMimeType(mimeType);
|
|
21793
|
+
const shouldTreatAsBinary = (trustedBinaryMime || inspection.looksBinary) && !trustedTextMime;
|
|
21432
21794
|
if (isTruncated) {
|
|
21433
21795
|
warnings.push(`Decoded only the first ${maxBytes} bytes of \`${input.filename}\` because the attachment exceeded the text preview limit.`);
|
|
21434
21796
|
}
|
|
21435
|
-
|
|
21436
|
-
|
|
21437
|
-
|
|
21438
|
-
|
|
21439
|
-
|
|
21440
|
-
|
|
21441
|
-
|
|
21442
|
-
|
|
21443
|
-
|
|
21444
|
-
|
|
21445
|
-
|
|
21797
|
+
return {
|
|
21798
|
+
warnings,
|
|
21799
|
+
charset,
|
|
21800
|
+
bom,
|
|
21801
|
+
inspection,
|
|
21802
|
+
truncatedBytes,
|
|
21803
|
+
isTruncated,
|
|
21804
|
+
forceText,
|
|
21805
|
+
shouldTreatAsBinary,
|
|
21806
|
+
};
|
|
21807
|
+
}
|
|
21808
|
+
/**
|
|
21809
|
+
* Returns an early result when the attachment should stay classified as binary.
|
|
21810
|
+
*
|
|
21811
|
+
* @private function of decodeAttachmentAsText
|
|
21812
|
+
*/
|
|
21813
|
+
function createBinaryDecodeResult(preparation) {
|
|
21814
|
+
if (!preparation.shouldTreatAsBinary) {
|
|
21815
|
+
return null;
|
|
21446
21816
|
}
|
|
21447
|
-
if (
|
|
21448
|
-
warnings.push('File content looks binary, but text decoding was forced with `forceText`.');
|
|
21817
|
+
if (preparation.forceText) {
|
|
21818
|
+
preparation.warnings.push('File content looks binary, but text decoding was forced with `forceText`.');
|
|
21819
|
+
return null;
|
|
21449
21820
|
}
|
|
21450
|
-
|
|
21451
|
-
|
|
21821
|
+
preparation.warnings.push('File content looks binary, so text decoding was skipped.');
|
|
21822
|
+
return {
|
|
21823
|
+
text: '',
|
|
21824
|
+
encodingUsed: 'binary',
|
|
21825
|
+
confidence: 1,
|
|
21826
|
+
warnings: preparation.warnings,
|
|
21827
|
+
wasBinary: true,
|
|
21828
|
+
isTruncated: preparation.isTruncated,
|
|
21829
|
+
};
|
|
21830
|
+
}
|
|
21831
|
+
/**
|
|
21832
|
+
* Warns when the declared charset cannot be used by the runtime decoder.
|
|
21833
|
+
*
|
|
21834
|
+
* @private function of decodeAttachmentAsText
|
|
21835
|
+
*/
|
|
21836
|
+
function addUnsupportedCharsetWarning(preparation) {
|
|
21837
|
+
if (preparation.charset && !isSupportedEncoding(preparation.charset)) {
|
|
21838
|
+
preparation.warnings.push(`Ignored unsupported declared charset \`${preparation.charset}\` and used best-effort detection instead.`);
|
|
21452
21839
|
}
|
|
21453
|
-
|
|
21454
|
-
|
|
21455
|
-
|
|
21456
|
-
|
|
21457
|
-
|
|
21458
|
-
|
|
21459
|
-
|
|
21460
|
-
|
|
21840
|
+
}
|
|
21841
|
+
/**
|
|
21842
|
+
* Returns the byte slice that should actually be decoded as text.
|
|
21843
|
+
*
|
|
21844
|
+
* @private function of decodeAttachmentAsText
|
|
21845
|
+
*/
|
|
21846
|
+
function getBytesToDecode(preparation) {
|
|
21847
|
+
return preparation.bom ? preparation.truncatedBytes.subarray(preparation.bom.offset) : preparation.truncatedBytes;
|
|
21848
|
+
}
|
|
21849
|
+
/**
|
|
21850
|
+
* Decodes all candidate encodings and sorts the successful results by score.
|
|
21851
|
+
*
|
|
21852
|
+
* @private function of decodeAttachmentAsText
|
|
21853
|
+
*/
|
|
21854
|
+
function decodeAttachmentCandidates(preparation) {
|
|
21855
|
+
return buildCandidateEncodings({
|
|
21856
|
+
charset: preparation.charset && isSupportedEncoding(preparation.charset) ? preparation.charset : null,
|
|
21857
|
+
bom: preparation.bom,
|
|
21858
|
+
inspection: preparation.inspection,
|
|
21859
|
+
})
|
|
21461
21860
|
.map(({ encoding, source }) => {
|
|
21462
|
-
const decoded = decodeWithEncoding(
|
|
21861
|
+
const decoded = decodeWithEncoding(getBytesToDecode(preparation), encoding);
|
|
21463
21862
|
return decoded ? { ...decoded, source } : null;
|
|
21464
21863
|
})
|
|
21465
21864
|
.filter((candidate) => candidate !== null)
|
|
21466
21865
|
.sort((left, right) => left.score - right.score);
|
|
21467
|
-
|
|
21468
|
-
|
|
21469
|
-
|
|
21470
|
-
|
|
21471
|
-
|
|
21472
|
-
|
|
21473
|
-
|
|
21474
|
-
|
|
21475
|
-
|
|
21476
|
-
|
|
21477
|
-
|
|
21478
|
-
|
|
21479
|
-
|
|
21866
|
+
}
|
|
21867
|
+
/**
|
|
21868
|
+
* Returns the fallback result used when no text decoder could be applied.
|
|
21869
|
+
*
|
|
21870
|
+
* @private function of decodeAttachmentAsText
|
|
21871
|
+
*/
|
|
21872
|
+
function createNoDecoderAvailableResult(preparation) {
|
|
21873
|
+
preparation.warnings.push('No supported text decoder was available.');
|
|
21874
|
+
return {
|
|
21875
|
+
text: '',
|
|
21876
|
+
encodingUsed: 'binary',
|
|
21877
|
+
confidence: 0,
|
|
21878
|
+
warnings: preparation.warnings,
|
|
21879
|
+
wasBinary: true,
|
|
21880
|
+
isTruncated: preparation.isTruncated,
|
|
21881
|
+
};
|
|
21882
|
+
}
|
|
21883
|
+
/**
|
|
21884
|
+
* Estimates confidence for the winning decoded text candidate.
|
|
21885
|
+
*
|
|
21886
|
+
* @private function of decodeAttachmentAsText
|
|
21887
|
+
*/
|
|
21888
|
+
function computeDecodeConfidence(bestCandidate, secondBestCandidate, preparation) {
|
|
21480
21889
|
const baseConfidence = bestCandidate.source === 'bom'
|
|
21481
21890
|
? 1
|
|
21482
21891
|
: bestCandidate.source === 'charset'
|
|
@@ -21489,27 +21898,62 @@ function decodeAttachmentAsText(input, options = {}) {
|
|
|
21489
21898
|
? 0.82
|
|
21490
21899
|
: 0.62;
|
|
21491
21900
|
const scoreMargin = secondBestCandidate ? Math.max(0, secondBestCandidate.score - bestCandidate.score) : 0.2;
|
|
21492
|
-
|
|
21901
|
+
return Math.max(0.2, Math.min(preparation.shouldTreatAsBinary && preparation.forceText ? 0.45 : 1, baseConfidence + Math.min(0.18, scoreMargin / 2)));
|
|
21902
|
+
}
|
|
21903
|
+
/**
|
|
21904
|
+
* Appends user-facing warnings derived from the chosen decoded text candidate.
|
|
21905
|
+
*
|
|
21906
|
+
* @private function of decodeAttachmentAsText
|
|
21907
|
+
*/
|
|
21908
|
+
function addDecodeWarnings(bestCandidate, confidence, preparation) {
|
|
21493
21909
|
if (bestCandidate.source === 'heuristic' && bestCandidate.encoding !== 'utf-8') {
|
|
21494
|
-
warnings.push(`Encoding was guessed as \`${bestCandidate.encoding}\`.`);
|
|
21910
|
+
preparation.warnings.push(`Encoding was guessed as \`${bestCandidate.encoding}\`.`);
|
|
21495
21911
|
}
|
|
21496
21912
|
if (bestCandidate.source === 'heuristic' &&
|
|
21497
21913
|
bestCandidate.encoding === 'utf-8' &&
|
|
21498
21914
|
bestCandidate.replacementCount > 0) {
|
|
21499
|
-
warnings.push('UTF-8 decoding produced replacement characters, so the extracted text may contain errors.');
|
|
21915
|
+
preparation.warnings.push('UTF-8 decoding produced replacement characters, so the extracted text may contain errors.');
|
|
21500
21916
|
}
|
|
21501
21917
|
if (confidence < 0.6) {
|
|
21502
|
-
warnings.push('Decoding confidence is low, so the extracted text may contain errors.');
|
|
21918
|
+
preparation.warnings.push('Decoding confidence is low, so the extracted text may contain errors.');
|
|
21503
21919
|
}
|
|
21920
|
+
}
|
|
21921
|
+
/**
|
|
21922
|
+
* Creates the final decoded-text result from the chosen candidate and accumulated metadata.
|
|
21923
|
+
*
|
|
21924
|
+
* @private function of decodeAttachmentAsText
|
|
21925
|
+
*/
|
|
21926
|
+
function createDecodedTextResult(bestCandidate, confidence, preparation) {
|
|
21504
21927
|
return {
|
|
21505
|
-
text: isTruncated ? appendTruncatedMarker(bestCandidate.text) : bestCandidate.text,
|
|
21928
|
+
text: preparation.isTruncated ? appendTruncatedMarker(bestCandidate.text) : bestCandidate.text,
|
|
21506
21929
|
encodingUsed: bestCandidate.encoding,
|
|
21507
21930
|
confidence,
|
|
21508
|
-
warnings,
|
|
21931
|
+
warnings: preparation.warnings,
|
|
21509
21932
|
wasBinary: false,
|
|
21510
|
-
isTruncated,
|
|
21933
|
+
isTruncated: preparation.isTruncated,
|
|
21511
21934
|
};
|
|
21512
21935
|
}
|
|
21936
|
+
/**
|
|
21937
|
+
* Best-effort decoder for uploaded or remote file bytes whose extension or encoding may be unknown.
|
|
21938
|
+
*
|
|
21939
|
+
* @private internal utility for shared text decoding
|
|
21940
|
+
*/
|
|
21941
|
+
function decodeAttachmentAsText(input, options = {}) {
|
|
21942
|
+
const preparation = createDecodeAttachmentPreparation(input, options);
|
|
21943
|
+
const binaryResult = createBinaryDecodeResult(preparation);
|
|
21944
|
+
if (binaryResult) {
|
|
21945
|
+
return binaryResult;
|
|
21946
|
+
}
|
|
21947
|
+
addUnsupportedCharsetWarning(preparation);
|
|
21948
|
+
const decodedCandidates = decodeAttachmentCandidates(preparation);
|
|
21949
|
+
const bestCandidate = decodedCandidates[0];
|
|
21950
|
+
if (!bestCandidate) {
|
|
21951
|
+
return createNoDecoderAvailableResult(preparation);
|
|
21952
|
+
}
|
|
21953
|
+
const confidence = computeDecodeConfidence(bestCandidate, decodedCandidates[1], preparation);
|
|
21954
|
+
addDecodeWarnings(bestCandidate, confidence, preparation);
|
|
21955
|
+
return createDecodedTextResult(bestCandidate, confidence, preparation);
|
|
21956
|
+
}
|
|
21513
21957
|
|
|
21514
21958
|
/**
|
|
21515
21959
|
* Base GitHub API URL.
|
|
@@ -33867,10 +34311,7 @@ function createAvailableProviderMessage(llmToolStatus, index, env) {
|
|
|
33867
34311
|
* @private internal function of `$registeredLlmToolsMessage`
|
|
33868
34312
|
*/
|
|
33869
34313
|
function createProviderStatusMessages(llmToolStatus, env) {
|
|
33870
|
-
return [
|
|
33871
|
-
createInstallationStatusMessage(llmToolStatus),
|
|
33872
|
-
createConfigurationStatusMessage(llmToolStatus, env),
|
|
33873
|
-
];
|
|
34314
|
+
return [createInstallationStatusMessage(llmToolStatus), createConfigurationStatusMessage(llmToolStatus, env)];
|
|
33874
34315
|
}
|
|
33875
34316
|
/**
|
|
33876
34317
|
* Creates the installation-status sentence for one provider.
|
|
@@ -36131,7 +36572,10 @@ class OpenAiCompatibleModelCatalog {
|
|
|
36131
36572
|
Cannot find model in ${this.options.getTitle()} models with name "${defaultModelName}" which should be used as default.
|
|
36132
36573
|
|
|
36133
36574
|
Available models:
|
|
36134
|
-
${block(this.options
|
|
36575
|
+
${block(this.options
|
|
36576
|
+
.getHardcodedModels()
|
|
36577
|
+
.map(({ modelName }) => `- "${modelName}"`)
|
|
36578
|
+
.join('\n'))}
|
|
36135
36579
|
|
|
36136
36580
|
Model "${defaultModelName}" is probably not available anymore, not installed, inaccessible or misconfigured.
|
|
36137
36581
|
|
|
@@ -36485,7 +36929,8 @@ class OpenAiCompatibleNonChatPromptCaller {
|
|
|
36485
36929
|
};
|
|
36486
36930
|
let rawPromptContent = templateParameters(content, { ...parameters, modelName });
|
|
36487
36931
|
if ('attachments' in prompt && Array.isArray(prompt.attachments) && prompt.attachments.length > 0) {
|
|
36488
|
-
rawPromptContent +=
|
|
36932
|
+
rawPromptContent +=
|
|
36933
|
+
'\n\n' + prompt.attachments.map((attachment) => `Image attachment: ${attachment.url}`).join('\n');
|
|
36489
36934
|
}
|
|
36490
36935
|
const rawRequest = {
|
|
36491
36936
|
...modelSettings,
|
|
@@ -36590,7 +37035,9 @@ class OpenAiCompatibleRequestManager {
|
|
|
36590
37035
|
* Schedules one request through the shared limiter and retry policy.
|
|
36591
37036
|
*/
|
|
36592
37037
|
async executeRateLimitedRequest(requestFn) {
|
|
36593
|
-
return this.limiter
|
|
37038
|
+
return this.limiter
|
|
37039
|
+
.schedule(() => this.makeRequestWithNetworkRetry(requestFn))
|
|
37040
|
+
.catch((error) => {
|
|
36594
37041
|
assertsError(error);
|
|
36595
37042
|
if (this.options.isVerbose) {
|
|
36596
37043
|
console.info(colors.bgRed('error'), error);
|
|
@@ -37797,7 +38244,9 @@ class OpenAiVectorStoreFileBatchPoller {
|
|
|
37797
38244
|
pollingState.lastProgressAtMs = nowMs;
|
|
37798
38245
|
pollingState.lastProgressKey = progressKey;
|
|
37799
38246
|
}
|
|
37800
|
-
if (this.options.isVerbose &&
|
|
38247
|
+
if (this.options.isVerbose &&
|
|
38248
|
+
(statusCountsKey !== pollingState.lastCountsKey ||
|
|
38249
|
+
nowMs - pollingState.lastLogAtMs >= progressLogIntervalMs)) {
|
|
37801
38250
|
console.info('[🤰]', 'Vector store file batch status', {
|
|
37802
38251
|
vectorStoreId,
|
|
37803
38252
|
batchId,
|