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