@promptbook/components 0.112.0-64 → 0.112.0-66
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/esm/index.es.js +982 -264
- package/esm/index.es.js.map +1 -1
- package/esm/src/_packages/components.index.d.ts +0 -2
- package/esm/src/_packages/core.index.d.ts +2 -2
- package/esm/src/_packages/types.index.d.ts +0 -2
- package/esm/src/avatars/types/AvatarVisualDefinition.d.ts +1 -1
- package/esm/src/avatars/visuals/minecraft2AvatarVisual.d.ts +7 -0
- package/esm/src/avatars/visuals/minecraftAvatarVisualShared.d.ts +48 -0
- package/esm/src/book-2.0/book-language-documentation/BookLanguageDocumentationExample.d.ts +27 -0
- package/esm/src/book-2.0/book-language-documentation/bookLanguageCommonPitfalls.d.ts +25 -0
- package/esm/src/book-2.0/book-language-documentation/bookLanguageDocumentationExamples.d.ts +10 -0
- package/esm/src/book-2.0/book-language-documentation/createStandaloneBookLanguageMarkdown.d.ts +14 -0
- package/esm/src/book-2.0/book-language-documentation/renderGroupedCommitmentDocumentationMarkdown.d.ts +43 -0
- package/esm/src/book-components/Chat/types/ChatMessage.d.ts +0 -34
- package/esm/src/cli/cli-commands/coder/ensureCoderGitignoreFile.d.ts +1 -1
- package/esm/src/commitments/KNOWLEDGE/KNOWLEDGE.d.ts +0 -11
- package/esm/src/commitments/_common/toolRuntimeContext.d.ts +0 -6
- package/esm/src/config.d.ts +3 -3
- package/esm/src/formfactors/index.d.ts +2 -2
- package/esm/src/formfactors/matcher/MatcherFormfactorDefinition.d.ts +1 -1
- package/esm/src/formfactors/translator/TranslatorFormfactorDefinition.d.ts +1 -1
- package/esm/src/llm-providers/openai/OpenAiAgentKitExecutionTools.d.ts +0 -4
- package/esm/src/llm-providers/openai/OpenAiAgentKitExecutionToolsOptions.d.ts +0 -9
- package/esm/src/utils/files/getPromptbookTempPath.d.ts +24 -0
- package/esm/src/version.d.ts +1 -1
- package/package.json +1 -1
- package/umd/index.umd.js +985 -267
- package/umd/index.umd.js.map +1 -1
- package/umd/src/_packages/components.index.d.ts +0 -2
- package/umd/src/_packages/core.index.d.ts +2 -2
- package/umd/src/_packages/types.index.d.ts +0 -2
- package/umd/src/avatars/types/AvatarVisualDefinition.d.ts +1 -1
- package/umd/src/avatars/visuals/minecraft2AvatarVisual.d.ts +7 -0
- package/umd/src/avatars/visuals/minecraftAvatarVisualShared.d.ts +48 -0
- package/umd/src/book-2.0/book-language-documentation/BookLanguageDocumentationExample.d.ts +27 -0
- package/umd/src/book-2.0/book-language-documentation/bookLanguageCommonPitfalls.d.ts +25 -0
- package/umd/src/book-2.0/book-language-documentation/bookLanguageDocumentationExamples.d.ts +10 -0
- package/umd/src/book-2.0/book-language-documentation/createStandaloneBookLanguageMarkdown.d.ts +14 -0
- package/umd/src/book-2.0/book-language-documentation/renderGroupedCommitmentDocumentationMarkdown.d.ts +43 -0
- package/umd/src/book-2.0/book-language-documentation/renderGroupedCommitmentDocumentationMarkdown.test.d.ts +1 -0
- package/umd/src/book-components/Chat/types/ChatMessage.d.ts +0 -34
- package/umd/src/cli/cli-commands/coder/ensureCoderGitignoreFile.d.ts +1 -1
- package/umd/src/commitments/KNOWLEDGE/KNOWLEDGE.d.ts +0 -11
- package/umd/src/commitments/_common/toolRuntimeContext.d.ts +0 -6
- package/umd/src/config.d.ts +3 -3
- package/umd/src/formfactors/index.d.ts +2 -2
- package/umd/src/formfactors/matcher/MatcherFormfactorDefinition.d.ts +1 -1
- package/umd/src/formfactors/translator/TranslatorFormfactorDefinition.d.ts +1 -1
- package/umd/src/llm-providers/openai/OpenAiAgentKitExecutionTools.d.ts +0 -4
- package/umd/src/llm-providers/openai/OpenAiAgentKitExecutionToolsOptions.d.ts +0 -9
- package/umd/src/utils/files/getPromptbookTempPath.d.ts +24 -0
- package/umd/src/utils/files/getPromptbookTempPath.test.d.ts +1 -0
- package/umd/src/version.d.ts +1 -1
- /package/esm/src/{commitments/KNOWLEDGE/KNOWLEDGE.test.d.ts → book-2.0/book-language-documentation/renderGroupedCommitmentDocumentationMarkdown.test.d.ts} +0 -0
- /package/{umd/src/commitments/KNOWLEDGE/KNOWLEDGE.test.d.ts → esm/src/utils/files/getPromptbookTempPath.test.d.ts} +0 -0
package/esm/index.es.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
2
2
|
import { spaceTrim as spaceTrim$1 } from 'spacetrim';
|
|
3
|
+
import { posix, basename, join, dirname, isAbsolute } from 'path';
|
|
3
4
|
import { useMemo, useId, useState, memo, useRef, useEffect, createContext, useContext, useCallback, forwardRef } from 'react';
|
|
4
5
|
import { SHA256 } from 'crypto-js';
|
|
5
6
|
import hexEncoder from 'crypto-js/enc-hex';
|
|
6
|
-
import { basename, join, dirname, isAbsolute } from 'path';
|
|
7
7
|
import { randomBytes } from 'crypto';
|
|
8
8
|
import moment from 'moment';
|
|
9
9
|
import { lookup, extension } from 'mime-types';
|
|
@@ -40,7 +40,7 @@ const BOOK_LANGUAGE_VERSION = '2.0.0';
|
|
|
40
40
|
* @generated
|
|
41
41
|
* @see https://github.com/webgptorg/promptbook
|
|
42
42
|
*/
|
|
43
|
-
const PROMPTBOOK_ENGINE_VERSION = '0.112.0-
|
|
43
|
+
const PROMPTBOOK_ENGINE_VERSION = '0.112.0-66';
|
|
44
44
|
/**
|
|
45
45
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
|
46
46
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -973,6 +973,29 @@ function saturate(amount) {
|
|
|
973
973
|
}
|
|
974
974
|
// TODO: Maybe implement by mix+hsl
|
|
975
975
|
|
|
976
|
+
/**
|
|
977
|
+
* Relative directory name without the `./` prefix for Git ignore rules and glob patterns.
|
|
978
|
+
*
|
|
979
|
+
* @private internal utility for Promptbook-owned temp files
|
|
980
|
+
*/
|
|
981
|
+
const PROMPTBOOK_TEMP_DIRECTORY_NAME = '.promptbook';
|
|
982
|
+
/**
|
|
983
|
+
* Builds one project-relative path inside the shared Promptbook working directory.
|
|
984
|
+
*
|
|
985
|
+
* @private internal utility for Promptbook-owned temp files
|
|
986
|
+
*/
|
|
987
|
+
function getPromptbookTempPath(...pathSegments) {
|
|
988
|
+
return `./${getPromptbookTempPosixPath(...pathSegments)}`;
|
|
989
|
+
}
|
|
990
|
+
/**
|
|
991
|
+
* Builds one POSIX path fragment inside the shared Promptbook working directory for globs and generated text files.
|
|
992
|
+
*
|
|
993
|
+
* @private internal utility for Promptbook-owned temp files
|
|
994
|
+
*/
|
|
995
|
+
function getPromptbookTempPosixPath(...pathSegments) {
|
|
996
|
+
return posix.join(PROMPTBOOK_TEMP_DIRECTORY_NAME, ...pathSegments);
|
|
997
|
+
}
|
|
998
|
+
|
|
976
999
|
/**
|
|
977
1000
|
* Returns the same value that is passed as argument.
|
|
978
1001
|
* No side effects.
|
|
@@ -1175,7 +1198,6 @@ const DEFAULT_MAX_CONCURRENT_UPLOADS = 5;
|
|
|
1175
1198
|
*/
|
|
1176
1199
|
const DEFAULT_MAX_EXECUTION_ATTEMPTS = 7; // <- TODO: [🤹♂️]
|
|
1177
1200
|
// <- TODO: [🕝] Make also `AGENTS_DIRNAME_ALTERNATIVES`
|
|
1178
|
-
// TODO: Just `.promptbook` in config, hardcode subfolders like `download-cache` or `execution-cache`
|
|
1179
1201
|
/**
|
|
1180
1202
|
* Where to store the temporary downloads
|
|
1181
1203
|
*
|
|
@@ -1183,7 +1205,15 @@ const DEFAULT_MAX_EXECUTION_ATTEMPTS = 7; // <- TODO: [🤹♂️]
|
|
|
1183
1205
|
*
|
|
1184
1206
|
* @public exported from `@promptbook/core`
|
|
1185
1207
|
*/
|
|
1186
|
-
const DEFAULT_DOWNLOAD_CACHE_DIRNAME = '
|
|
1208
|
+
const DEFAULT_DOWNLOAD_CACHE_DIRNAME = getPromptbookTempPath('download-cache');
|
|
1209
|
+
/**
|
|
1210
|
+
* Where to store the cache of executions for promptbook CLI
|
|
1211
|
+
*
|
|
1212
|
+
* Note: When the folder does not exist, it is created recursively
|
|
1213
|
+
*
|
|
1214
|
+
* @public exported from `@promptbook/core`
|
|
1215
|
+
*/
|
|
1216
|
+
getPromptbookTempPath('execution-cache');
|
|
1187
1217
|
/**
|
|
1188
1218
|
* Where to store the scrape cache
|
|
1189
1219
|
*
|
|
@@ -1191,7 +1221,7 @@ const DEFAULT_DOWNLOAD_CACHE_DIRNAME = './.promptbook/download-cache';
|
|
|
1191
1221
|
*
|
|
1192
1222
|
* @public exported from `@promptbook/core`
|
|
1193
1223
|
*/
|
|
1194
|
-
const DEFAULT_SCRAPE_CACHE_DIRNAME = '
|
|
1224
|
+
const DEFAULT_SCRAPE_CACHE_DIRNAME = getPromptbookTempPath('scrape-cache');
|
|
1195
1225
|
/**
|
|
1196
1226
|
* Default remote server URL for the Promptbook
|
|
1197
1227
|
*
|
|
@@ -2825,6 +2855,177 @@ function drawFractalCore(context, size, palette, timeMs, corePhase) {
|
|
|
2825
2855
|
context.restore();
|
|
2826
2856
|
}
|
|
2827
2857
|
|
|
2858
|
+
/* eslint-disable no-magic-numbers */
|
|
2859
|
+
/**
|
|
2860
|
+
* Builds the seeded six-face texture pack used by the Minecraft-style head cuboid.
|
|
2861
|
+
*
|
|
2862
|
+
* @param random Seeded random generator.
|
|
2863
|
+
* @param palette Derived avatar palette.
|
|
2864
|
+
* @param hasHeadband Whether the generated avatar should include a colored headband.
|
|
2865
|
+
* @returns Head cuboid textures.
|
|
2866
|
+
*
|
|
2867
|
+
* @private helper of the Minecraft avatar visuals
|
|
2868
|
+
*/
|
|
2869
|
+
function createMinecraftHeadTextures(random, palette, hasHeadband) {
|
|
2870
|
+
const faceTexture = createMinecraftFaceTexture(random, palette, hasHeadband);
|
|
2871
|
+
const hairColor = random() < 0.5 ? palette.primary : palette.secondary;
|
|
2872
|
+
const skinColor = palette.highlight;
|
|
2873
|
+
const headbandColor = hasHeadband ? palette.accent : hairColor;
|
|
2874
|
+
const sideTexture = createFilledTexture(skinColor);
|
|
2875
|
+
const backTexture = createFilledTexture(skinColor);
|
|
2876
|
+
const topTexture = createFilledTexture(hairColor);
|
|
2877
|
+
const bottomTexture = createFilledTexture(`${palette.shadow}cc`);
|
|
2878
|
+
fillTextureRect(sideTexture, 0, 0, 8, 3, hairColor);
|
|
2879
|
+
fillTextureRect(backTexture, 0, 0, 8, 5, hairColor);
|
|
2880
|
+
fillTextureRect(backTexture, 1, 5, 6, 1, hairColor);
|
|
2881
|
+
if (hasHeadband) {
|
|
2882
|
+
fillTextureRect(sideTexture, 0, 2, 8, 1, headbandColor);
|
|
2883
|
+
fillTextureRect(backTexture, 0, 2, 8, 1, headbandColor);
|
|
2884
|
+
fillTextureRect(topTexture, 0, 4, 8, 1, headbandColor);
|
|
2885
|
+
}
|
|
2886
|
+
sideTexture[4][4] = `${palette.shadow}99`;
|
|
2887
|
+
sideTexture[5][4] = `${palette.shadow}cc`;
|
|
2888
|
+
backTexture[6][2] = `${palette.shadow}99`;
|
|
2889
|
+
backTexture[6][5] = `${palette.shadow}99`;
|
|
2890
|
+
return {
|
|
2891
|
+
front: faceTexture,
|
|
2892
|
+
back: backTexture,
|
|
2893
|
+
left: sideTexture,
|
|
2894
|
+
right: mirrorMinecraftTexture(sideTexture),
|
|
2895
|
+
top: topTexture,
|
|
2896
|
+
bottom: bottomTexture,
|
|
2897
|
+
};
|
|
2898
|
+
}
|
|
2899
|
+
/**
|
|
2900
|
+
* Builds the seeded six-face texture pack used by the Minecraft-style torso cuboid.
|
|
2901
|
+
*
|
|
2902
|
+
* @param random Seeded random generator.
|
|
2903
|
+
* @param palette Derived avatar palette.
|
|
2904
|
+
* @returns Torso cuboid textures.
|
|
2905
|
+
*
|
|
2906
|
+
* @private helper of the Minecraft avatar visuals
|
|
2907
|
+
*/
|
|
2908
|
+
function createMinecraftTorsoTextures(random, palette) {
|
|
2909
|
+
const frontTexture = createMinecraftShirtTexture(random, palette);
|
|
2910
|
+
const sideTexture = createFilledTexture(palette.primary);
|
|
2911
|
+
const backTexture = createFilledTexture(palette.primary);
|
|
2912
|
+
const topTexture = createFilledTexture(`${palette.highlight}dd`);
|
|
2913
|
+
const bottomTexture = createFilledTexture(`${palette.shadow}dd`);
|
|
2914
|
+
const stripeColor = random() < 0.5 ? palette.secondary : palette.highlight;
|
|
2915
|
+
fillTextureRect(sideTexture, 0, 0, 8, 2, palette.shadow);
|
|
2916
|
+
fillTextureRect(backTexture, 0, 0, 8, 2, palette.shadow);
|
|
2917
|
+
fillTextureRect(backTexture, 3, 2, 2, 6, stripeColor);
|
|
2918
|
+
fillTextureRect(sideTexture, 4, 2, 1, 6, stripeColor);
|
|
2919
|
+
fillTextureRect(topTexture, 0, 0, 8, 2, palette.shadow);
|
|
2920
|
+
fillTextureRect(topTexture, 2, 2, 4, 4, stripeColor);
|
|
2921
|
+
return {
|
|
2922
|
+
front: frontTexture,
|
|
2923
|
+
back: backTexture,
|
|
2924
|
+
left: sideTexture,
|
|
2925
|
+
right: mirrorMinecraftTexture(sideTexture),
|
|
2926
|
+
top: topTexture,
|
|
2927
|
+
bottom: bottomTexture,
|
|
2928
|
+
};
|
|
2929
|
+
}
|
|
2930
|
+
/**
|
|
2931
|
+
* Mirrors one Minecraft texture horizontally.
|
|
2932
|
+
*
|
|
2933
|
+
* @param texture Source texture.
|
|
2934
|
+
* @returns Mirrored texture copy.
|
|
2935
|
+
*
|
|
2936
|
+
* @private helper of the Minecraft avatar visuals
|
|
2937
|
+
*/
|
|
2938
|
+
function mirrorMinecraftTexture(texture) {
|
|
2939
|
+
return texture.map((row) => [...row].reverse());
|
|
2940
|
+
}
|
|
2941
|
+
/**
|
|
2942
|
+
* Creates the front-face pixel texture for the cube head.
|
|
2943
|
+
*
|
|
2944
|
+
* @param random Seeded random generator.
|
|
2945
|
+
* @param palette Derived avatar palette.
|
|
2946
|
+
* @param hasHeadband Whether the avatar should render a headband row.
|
|
2947
|
+
* @returns 8x8 pixel texture.
|
|
2948
|
+
*
|
|
2949
|
+
* @private helper of the Minecraft avatar visuals
|
|
2950
|
+
*/
|
|
2951
|
+
function createMinecraftFaceTexture(random, palette, hasHeadband) {
|
|
2952
|
+
const texture = createFilledTexture(palette.highlight);
|
|
2953
|
+
const hairlineColor = random() < 0.5 ? palette.primary : palette.secondary;
|
|
2954
|
+
const cheekColor = random() < 0.5 ? `${palette.accent}bb` : `${palette.secondary}bb`;
|
|
2955
|
+
fillTextureRect(texture, 0, 0, 8, 2, hairlineColor);
|
|
2956
|
+
texture[2][0] = hairlineColor;
|
|
2957
|
+
texture[2][7] = hairlineColor;
|
|
2958
|
+
texture[3][0] = hairlineColor;
|
|
2959
|
+
texture[3][7] = hairlineColor;
|
|
2960
|
+
if (hasHeadband) {
|
|
2961
|
+
fillTextureRect(texture, 0, 2, 8, 1, palette.accent);
|
|
2962
|
+
}
|
|
2963
|
+
texture[3][2] = palette.ink;
|
|
2964
|
+
texture[3][5] = palette.ink;
|
|
2965
|
+
texture[4][2] = '#ffffff';
|
|
2966
|
+
texture[4][5] = '#ffffff';
|
|
2967
|
+
texture[5][1] = cheekColor;
|
|
2968
|
+
texture[5][6] = cheekColor;
|
|
2969
|
+
texture[5][3] = palette.shadow;
|
|
2970
|
+
texture[5][4] = palette.shadow;
|
|
2971
|
+
texture[6][3] = palette.shadow;
|
|
2972
|
+
texture[6][4] = palette.shadow;
|
|
2973
|
+
return texture;
|
|
2974
|
+
}
|
|
2975
|
+
/**
|
|
2976
|
+
* Creates the front-face pixel texture for the torso.
|
|
2977
|
+
*
|
|
2978
|
+
* @param random Seeded random generator.
|
|
2979
|
+
* @param palette Derived avatar palette.
|
|
2980
|
+
* @returns 8x8 torso texture.
|
|
2981
|
+
*
|
|
2982
|
+
* @private helper of the Minecraft avatar visuals
|
|
2983
|
+
*/
|
|
2984
|
+
function createMinecraftShirtTexture(random, palette) {
|
|
2985
|
+
const texture = createFilledTexture(palette.primary);
|
|
2986
|
+
const stripeColor = random() < 0.5 ? palette.secondary : palette.highlight;
|
|
2987
|
+
fillTextureRect(texture, 0, 0, 8, 2, palette.shadow);
|
|
2988
|
+
for (let rowIndex = 2; rowIndex < 8; rowIndex++) {
|
|
2989
|
+
texture[rowIndex][3] = stripeColor;
|
|
2990
|
+
texture[rowIndex][4] = stripeColor;
|
|
2991
|
+
}
|
|
2992
|
+
texture[4][1] = palette.accent;
|
|
2993
|
+
texture[4][6] = palette.accent;
|
|
2994
|
+
texture[5][2] = palette.highlight;
|
|
2995
|
+
texture[5][5] = palette.highlight;
|
|
2996
|
+
return texture;
|
|
2997
|
+
}
|
|
2998
|
+
/**
|
|
2999
|
+
* Creates one solid-color 8x8 Minecraft texture.
|
|
3000
|
+
*
|
|
3001
|
+
* @param color Fill color.
|
|
3002
|
+
* @returns Filled 8x8 texture.
|
|
3003
|
+
*
|
|
3004
|
+
* @private helper of the Minecraft avatar visuals
|
|
3005
|
+
*/
|
|
3006
|
+
function createFilledTexture(color) {
|
|
3007
|
+
return Array.from({ length: 8 }, () => Array.from({ length: 8 }, () => color));
|
|
3008
|
+
}
|
|
3009
|
+
/**
|
|
3010
|
+
* Fills one rectangular area inside a mutable Minecraft texture.
|
|
3011
|
+
*
|
|
3012
|
+
* @param texture Mutable target texture.
|
|
3013
|
+
* @param x Left texture coordinate.
|
|
3014
|
+
* @param y Top texture coordinate.
|
|
3015
|
+
* @param width Rectangle width.
|
|
3016
|
+
* @param height Rectangle height.
|
|
3017
|
+
* @param color Fill color.
|
|
3018
|
+
*
|
|
3019
|
+
* @private helper of the Minecraft avatar visuals
|
|
3020
|
+
*/
|
|
3021
|
+
function fillTextureRect(texture, x, y, width, height, color) {
|
|
3022
|
+
for (let rowIndex = y; rowIndex < y + height; rowIndex++) {
|
|
3023
|
+
for (let columnIndex = x; columnIndex < x + width; columnIndex++) {
|
|
3024
|
+
texture[rowIndex][columnIndex] = color;
|
|
3025
|
+
}
|
|
3026
|
+
}
|
|
3027
|
+
}
|
|
3028
|
+
|
|
2828
3029
|
/* eslint-disable no-magic-numbers */
|
|
2829
3030
|
/**
|
|
2830
3031
|
* Minecraft-style 3D avatar visual.
|
|
@@ -2849,8 +3050,8 @@ const minecraftAvatarVisual = {
|
|
|
2849
3050
|
const bodyX = size * 0.33;
|
|
2850
3051
|
const bodyY = headY + headSize * 0.96;
|
|
2851
3052
|
const hasHeadband = random() < 0.5;
|
|
2852
|
-
const
|
|
2853
|
-
const
|
|
3053
|
+
const headTextures = createMinecraftHeadTextures(createRandom('minecraft-face'), palette, hasHeadband);
|
|
3054
|
+
const torsoTextures = createMinecraftTorsoTextures(createRandom('minecraft-shirt'), palette);
|
|
2854
3055
|
drawAvatarFrame(context, size, palette);
|
|
2855
3056
|
const spotlight = context.createRadialGradient(size * 0.5, size * 0.18, size * 0.05, size * 0.5, size * 0.18, size * 0.5);
|
|
2856
3057
|
spotlight.addColorStop(0, `${palette.highlight}66`);
|
|
@@ -2870,7 +3071,7 @@ const minecraftAvatarVisual = {
|
|
|
2870
3071
|
width: bodyWidth,
|
|
2871
3072
|
height: bodyHeight,
|
|
2872
3073
|
depth: bodyDepth,
|
|
2873
|
-
frontTexture:
|
|
3074
|
+
frontTexture: torsoTextures.front,
|
|
2874
3075
|
topColor: `${palette.highlight}cc`,
|
|
2875
3076
|
sideColor: `${palette.secondary}dd`,
|
|
2876
3077
|
outlineColor: `${palette.shadow}aa`,
|
|
@@ -2881,7 +3082,7 @@ const minecraftAvatarVisual = {
|
|
|
2881
3082
|
width: headSize,
|
|
2882
3083
|
height: headSize,
|
|
2883
3084
|
depth,
|
|
2884
|
-
frontTexture:
|
|
3085
|
+
frontTexture: headTextures.front,
|
|
2885
3086
|
topColor: `${palette.highlight}ee`,
|
|
2886
3087
|
sideColor: `${palette.secondary}ee`,
|
|
2887
3088
|
outlineColor: `${palette.shadow}cc`,
|
|
@@ -2946,72 +3147,505 @@ function drawVoxelCuboid(context, cuboid) {
|
|
|
2946
3147
|
context.closePath();
|
|
2947
3148
|
context.stroke();
|
|
2948
3149
|
}
|
|
3150
|
+
|
|
3151
|
+
/* eslint-disable no-magic-numbers */
|
|
2949
3152
|
/**
|
|
2950
|
-
*
|
|
3153
|
+
* Fixed scene camera distance used for the proper-3D projection.
|
|
2951
3154
|
*
|
|
2952
|
-
* @
|
|
3155
|
+
* @private helper of `minecraft2AvatarVisual`
|
|
3156
|
+
*/
|
|
3157
|
+
const CAMERA_DISTANCE_RATIO = 1.4;
|
|
3158
|
+
/**
|
|
3159
|
+
* Shared light direction used to shade projected cuboid faces.
|
|
3160
|
+
*
|
|
3161
|
+
* @private helper of `minecraft2AvatarVisual`
|
|
3162
|
+
*/
|
|
3163
|
+
const LIGHT_DIRECTION = normalizeVector3({
|
|
3164
|
+
x: 0.4,
|
|
3165
|
+
y: -0.65,
|
|
3166
|
+
z: 0.92,
|
|
3167
|
+
});
|
|
3168
|
+
/**
|
|
3169
|
+
* Minecraft 3D 2 avatar visual.
|
|
3170
|
+
*
|
|
3171
|
+
* @private built-in avatar visual
|
|
3172
|
+
*/
|
|
3173
|
+
const minecraft2AvatarVisual = {
|
|
3174
|
+
id: 'minecraft2',
|
|
3175
|
+
title: 'Minecraft 3D 2',
|
|
3176
|
+
description: 'Proper 3D Minecraft-style portrait with textured cuboids and pointer-driven head turns.',
|
|
3177
|
+
isAnimated: true,
|
|
3178
|
+
supportsPointerTracking: true,
|
|
3179
|
+
render({ context, size, palette, createRandom, timeMs, interaction }) {
|
|
3180
|
+
const spotlightY = size * 0.22;
|
|
3181
|
+
const headRandom = createRandom('minecraft2-head');
|
|
3182
|
+
const hasHeadband = headRandom() < 0.5;
|
|
3183
|
+
const headTextures = createMinecraftHeadTextures(createRandom('minecraft2-head-textures'), palette, hasHeadband);
|
|
3184
|
+
const torsoTextures = createMinecraftTorsoTextures(createRandom('minecraft2-body-textures'), palette);
|
|
3185
|
+
const bob = Math.sin(timeMs / 880) * size * 0.014;
|
|
3186
|
+
const bodyYaw = -0.24 + Math.sin(timeMs / 2300) * 0.06 + interaction.bodyOffsetX * 0.16;
|
|
3187
|
+
const bodyPitch = -0.12 + Math.cos(timeMs / 2800) * 0.02 - interaction.bodyOffsetY * 0.06;
|
|
3188
|
+
const headYaw = -0.18 + Math.sin(timeMs / 1900 + 0.6) * 0.05 + interaction.gazeX * 0.62;
|
|
3189
|
+
const headPitch = -0.12 + Math.cos(timeMs / 2400 + 1.1) * 0.03 - interaction.gazeY * 0.38;
|
|
3190
|
+
const sceneCenterX = size * 0.5;
|
|
3191
|
+
const sceneCenterY = size * 0.57;
|
|
3192
|
+
const bodyWidth = size * 0.225;
|
|
3193
|
+
const bodyHeight = size * 0.245;
|
|
3194
|
+
const bodyDepth = size * 0.145;
|
|
3195
|
+
const headSize = size * 0.24;
|
|
3196
|
+
const headLift = size * 0.205;
|
|
3197
|
+
const headForwardShift = interaction.intensity * size * 0.018;
|
|
3198
|
+
const sceneCuboids = [
|
|
3199
|
+
{
|
|
3200
|
+
center: {
|
|
3201
|
+
x: interaction.bodyOffsetX * size * 0.026,
|
|
3202
|
+
y: size * 0.05 + interaction.bodyOffsetY * size * 0.018 + bob,
|
|
3203
|
+
z: 0,
|
|
3204
|
+
},
|
|
3205
|
+
width: bodyWidth,
|
|
3206
|
+
height: bodyHeight,
|
|
3207
|
+
depth: bodyDepth,
|
|
3208
|
+
rotationX: bodyPitch,
|
|
3209
|
+
rotationY: bodyYaw,
|
|
3210
|
+
textures: torsoTextures,
|
|
3211
|
+
outlineColor: `${palette.shadow}cc`,
|
|
3212
|
+
},
|
|
3213
|
+
{
|
|
3214
|
+
center: {
|
|
3215
|
+
x: interaction.bodyOffsetX * size * 0.018 + interaction.gazeX * size * 0.016,
|
|
3216
|
+
y: -headLift + bob * 1.15,
|
|
3217
|
+
z: headForwardShift,
|
|
3218
|
+
},
|
|
3219
|
+
width: headSize,
|
|
3220
|
+
height: headSize,
|
|
3221
|
+
depth: headSize,
|
|
3222
|
+
rotationX: headPitch,
|
|
3223
|
+
rotationY: headYaw,
|
|
3224
|
+
textures: headTextures,
|
|
3225
|
+
outlineColor: `${palette.shadow}dd`,
|
|
3226
|
+
},
|
|
3227
|
+
];
|
|
3228
|
+
const visibleFaces = sceneCuboids
|
|
3229
|
+
.flatMap((cuboid) => resolveVisibleCuboidFaces(cuboid, size, sceneCenterX, sceneCenterY))
|
|
3230
|
+
.sort((firstFace, secondFace) => firstFace.averageDepth - secondFace.averageDepth);
|
|
3231
|
+
drawAvatarFrame(context, size, palette);
|
|
3232
|
+
drawMinecraftBackdrop(context, size, palette, sceneCenterX, spotlightY, interaction, timeMs);
|
|
3233
|
+
drawMinecraftShadow(context, size, palette, interaction, timeMs);
|
|
3234
|
+
for (const visibleFace of visibleFaces) {
|
|
3235
|
+
drawTexturedProjectedFace(context, visibleFace);
|
|
3236
|
+
}
|
|
3237
|
+
},
|
|
3238
|
+
};
|
|
3239
|
+
/**
|
|
3240
|
+
* Draws the shared background atmosphere behind the Minecraft 3D 2 portrait.
|
|
3241
|
+
*
|
|
3242
|
+
* @param context Canvas 2D context.
|
|
3243
|
+
* @param size Canvas size in CSS pixels.
|
|
2953
3244
|
* @param palette Derived avatar palette.
|
|
2954
|
-
* @param
|
|
2955
|
-
* @
|
|
3245
|
+
* @param sceneCenterX Horizontal scene center.
|
|
3246
|
+
* @param spotlightY Vertical spotlight anchor.
|
|
3247
|
+
* @param interaction Smoothed pointer-aware interaction state.
|
|
3248
|
+
* @param timeMs Current animation time in milliseconds.
|
|
2956
3249
|
*
|
|
2957
|
-
* @private helper of `
|
|
3250
|
+
* @private helper of `minecraft2AvatarVisual`
|
|
2958
3251
|
*/
|
|
2959
|
-
function
|
|
2960
|
-
const
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
|
|
2965
|
-
|
|
3252
|
+
function drawMinecraftBackdrop(context, size, palette, sceneCenterX, spotlightY, interaction, timeMs) {
|
|
3253
|
+
const spotlightGradient = context.createRadialGradient(sceneCenterX + interaction.gazeX * size * 0.08, spotlightY + interaction.gazeY * size * 0.05, size * 0.03, sceneCenterX, spotlightY, size * 0.52);
|
|
3254
|
+
spotlightGradient.addColorStop(0, `${palette.highlight}66`);
|
|
3255
|
+
spotlightGradient.addColorStop(0.42, `${palette.accent}1d`);
|
|
3256
|
+
spotlightGradient.addColorStop(1, `${palette.highlight}00`);
|
|
3257
|
+
context.fillStyle = spotlightGradient;
|
|
3258
|
+
context.fillRect(0, 0, size, size);
|
|
3259
|
+
const rimGradient = context.createLinearGradient(0, size * 0.14, 0, size * 0.92);
|
|
3260
|
+
rimGradient.addColorStop(0, `${palette.highlight}12`);
|
|
3261
|
+
rimGradient.addColorStop(0.55, `${palette.secondary}0a`);
|
|
3262
|
+
rimGradient.addColorStop(1, `${palette.shadow}00`);
|
|
3263
|
+
context.fillStyle = rimGradient;
|
|
3264
|
+
context.fillRect(0, 0, size, size);
|
|
3265
|
+
context.save();
|
|
3266
|
+
context.globalAlpha = 0.08 + interaction.intensity * 0.04;
|
|
3267
|
+
context.fillStyle = palette.highlight;
|
|
3268
|
+
context.beginPath();
|
|
3269
|
+
context.arc(size * 0.72 + Math.sin(timeMs / 1600) * size * 0.03, size * 0.2 + Math.cos(timeMs / 1400) * size * 0.018, size * 0.025, 0, Math.PI * 2);
|
|
3270
|
+
context.fill();
|
|
3271
|
+
context.restore();
|
|
3272
|
+
}
|
|
3273
|
+
/**
|
|
3274
|
+
* Draws the soft floor shadow used to anchor the cuboids in the frame.
|
|
3275
|
+
*
|
|
3276
|
+
* @param context Canvas 2D context.
|
|
3277
|
+
* @param size Canvas size in CSS pixels.
|
|
3278
|
+
* @param palette Derived avatar palette.
|
|
3279
|
+
* @param interaction Smoothed pointer-aware interaction state.
|
|
3280
|
+
* @param timeMs Current animation time in milliseconds.
|
|
3281
|
+
*
|
|
3282
|
+
* @private helper of `minecraft2AvatarVisual`
|
|
3283
|
+
*/
|
|
3284
|
+
function drawMinecraftShadow(context, size, palette, interaction, timeMs) {
|
|
3285
|
+
context.save();
|
|
3286
|
+
context.fillStyle = `${palette.shadow}66`;
|
|
3287
|
+
context.filter = `blur(${size * 0.02}px)`;
|
|
3288
|
+
context.beginPath();
|
|
3289
|
+
context.ellipse(size * 0.5 + interaction.gazeX * size * 0.03, size * 0.85 + Math.sin(timeMs / 880) * size * 0.01, size * (0.16 + interaction.intensity * 0.015), size * 0.055, 0, 0, Math.PI * 2);
|
|
3290
|
+
context.fill();
|
|
3291
|
+
context.restore();
|
|
3292
|
+
}
|
|
3293
|
+
/**
|
|
3294
|
+
* Resolves all visible projected faces for one scene cuboid.
|
|
3295
|
+
*
|
|
3296
|
+
* @param cuboid Scene cuboid definition.
|
|
3297
|
+
* @param size Canvas size in CSS pixels.
|
|
3298
|
+
* @param sceneCenterX Horizontal scene center.
|
|
3299
|
+
* @param sceneCenterY Vertical scene center.
|
|
3300
|
+
* @returns Visible faces sorted later by depth.
|
|
3301
|
+
*
|
|
3302
|
+
* @private helper of `minecraft2AvatarVisual`
|
|
3303
|
+
*/
|
|
3304
|
+
function resolveVisibleCuboidFaces(cuboid, size, sceneCenterX, sceneCenterY) {
|
|
3305
|
+
const halfWidth = cuboid.width / 2;
|
|
3306
|
+
const halfHeight = cuboid.height / 2;
|
|
3307
|
+
const halfDepth = cuboid.depth / 2;
|
|
3308
|
+
const faceDefinitions = [
|
|
3309
|
+
{
|
|
3310
|
+
texture: cuboid.textures.front,
|
|
3311
|
+
corners: [
|
|
3312
|
+
{ x: -halfWidth, y: -halfHeight, z: halfDepth },
|
|
3313
|
+
{ x: halfWidth, y: -halfHeight, z: halfDepth },
|
|
3314
|
+
{ x: halfWidth, y: halfHeight, z: halfDepth },
|
|
3315
|
+
{ x: -halfWidth, y: halfHeight, z: halfDepth },
|
|
3316
|
+
],
|
|
3317
|
+
},
|
|
3318
|
+
{
|
|
3319
|
+
texture: cuboid.textures.back,
|
|
3320
|
+
corners: [
|
|
3321
|
+
{ x: halfWidth, y: -halfHeight, z: -halfDepth },
|
|
3322
|
+
{ x: -halfWidth, y: -halfHeight, z: -halfDepth },
|
|
3323
|
+
{ x: -halfWidth, y: halfHeight, z: -halfDepth },
|
|
3324
|
+
{ x: halfWidth, y: halfHeight, z: -halfDepth },
|
|
3325
|
+
],
|
|
3326
|
+
},
|
|
3327
|
+
{
|
|
3328
|
+
texture: cuboid.textures.right,
|
|
3329
|
+
corners: [
|
|
3330
|
+
{ x: halfWidth, y: -halfHeight, z: halfDepth },
|
|
3331
|
+
{ x: halfWidth, y: -halfHeight, z: -halfDepth },
|
|
3332
|
+
{ x: halfWidth, y: halfHeight, z: -halfDepth },
|
|
3333
|
+
{ x: halfWidth, y: halfHeight, z: halfDepth },
|
|
3334
|
+
],
|
|
3335
|
+
},
|
|
3336
|
+
{
|
|
3337
|
+
texture: cuboid.textures.left,
|
|
3338
|
+
corners: [
|
|
3339
|
+
{ x: -halfWidth, y: -halfHeight, z: -halfDepth },
|
|
3340
|
+
{ x: -halfWidth, y: -halfHeight, z: halfDepth },
|
|
3341
|
+
{ x: -halfWidth, y: halfHeight, z: halfDepth },
|
|
3342
|
+
{ x: -halfWidth, y: halfHeight, z: -halfDepth },
|
|
3343
|
+
],
|
|
3344
|
+
},
|
|
3345
|
+
{
|
|
3346
|
+
texture: cuboid.textures.top,
|
|
3347
|
+
corners: [
|
|
3348
|
+
{ x: -halfWidth, y: -halfHeight, z: -halfDepth },
|
|
3349
|
+
{ x: halfWidth, y: -halfHeight, z: -halfDepth },
|
|
3350
|
+
{ x: halfWidth, y: -halfHeight, z: halfDepth },
|
|
3351
|
+
{ x: -halfWidth, y: -halfHeight, z: halfDepth },
|
|
3352
|
+
],
|
|
3353
|
+
},
|
|
3354
|
+
{
|
|
3355
|
+
texture: cuboid.textures.bottom,
|
|
3356
|
+
corners: [
|
|
3357
|
+
{ x: -halfWidth, y: halfHeight, z: halfDepth },
|
|
3358
|
+
{ x: halfWidth, y: halfHeight, z: halfDepth },
|
|
3359
|
+
{ x: halfWidth, y: halfHeight, z: -halfDepth },
|
|
3360
|
+
{ x: -halfWidth, y: halfHeight, z: -halfDepth },
|
|
3361
|
+
],
|
|
3362
|
+
},
|
|
3363
|
+
];
|
|
3364
|
+
const visibleFaces = faceDefinitions
|
|
3365
|
+
.map((faceDefinition) => {
|
|
3366
|
+
const transformedCorners = faceDefinition.corners.map((corner) => transformScenePoint(corner, cuboid.center, cuboid.rotationX, cuboid.rotationY));
|
|
3367
|
+
const faceNormal = normalizeVector3(crossProduct3D(subtractPoint3D(transformedCorners[1], transformedCorners[0]), subtractPoint3D(transformedCorners[2], transformedCorners[0])));
|
|
3368
|
+
if (faceNormal.z <= 0.02) {
|
|
3369
|
+
return null;
|
|
2966
3370
|
}
|
|
3371
|
+
const projectedCorners = transformedCorners.map((corner) => projectScenePoint(corner, size, sceneCenterX, sceneCenterY));
|
|
3372
|
+
return {
|
|
3373
|
+
corners: projectedCorners,
|
|
3374
|
+
texture: faceDefinition.texture,
|
|
3375
|
+
averageDepth: transformedCorners.reduce((depthSum, corner) => depthSum + corner.z, 0) / transformedCorners.length,
|
|
3376
|
+
lightIntensity: clampNumber$1(dotProduct3D(faceNormal, LIGHT_DIRECTION), -1, 1),
|
|
3377
|
+
outlineColor: cuboid.outlineColor,
|
|
3378
|
+
};
|
|
3379
|
+
});
|
|
3380
|
+
return visibleFaces.filter((visibleFace) => visibleFace !== null);
|
|
3381
|
+
}
|
|
3382
|
+
/**
|
|
3383
|
+
* Draws one projected textured face by tessellating its texture cells into quads.
|
|
3384
|
+
*
|
|
3385
|
+
* @param context Canvas 2D context.
|
|
3386
|
+
* @param face Visible projected face.
|
|
3387
|
+
*
|
|
3388
|
+
* @private helper of `minecraft2AvatarVisual`
|
|
3389
|
+
*/
|
|
3390
|
+
function drawTexturedProjectedFace(context, face) {
|
|
3391
|
+
var _a;
|
|
3392
|
+
const rows = face.texture.length;
|
|
3393
|
+
const columns = ((_a = face.texture[0]) === null || _a === void 0 ? void 0 : _a.length) || 0;
|
|
3394
|
+
if (rows === 0 || columns === 0) {
|
|
3395
|
+
return;
|
|
2967
3396
|
}
|
|
2968
|
-
|
|
2969
|
-
|
|
2970
|
-
|
|
2971
|
-
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
|
|
3397
|
+
for (let rowIndex = 0; rowIndex < rows; rowIndex++) {
|
|
3398
|
+
for (let columnIndex = 0; columnIndex < columns; columnIndex++) {
|
|
3399
|
+
const startX = columnIndex / columns;
|
|
3400
|
+
const endX = (columnIndex + 1) / columns;
|
|
3401
|
+
const startY = rowIndex / rows;
|
|
3402
|
+
const endY = (rowIndex + 1) / rows;
|
|
3403
|
+
drawProjectedQuad(context, [
|
|
3404
|
+
interpolateProjectedQuad(face.corners, startX, startY),
|
|
3405
|
+
interpolateProjectedQuad(face.corners, endX, startY),
|
|
3406
|
+
interpolateProjectedQuad(face.corners, endX, endY),
|
|
3407
|
+
interpolateProjectedQuad(face.corners, startX, endY),
|
|
3408
|
+
], face.texture[rowIndex][columnIndex]);
|
|
2975
3409
|
}
|
|
2976
3410
|
}
|
|
2977
|
-
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
|
|
3411
|
+
if (face.lightIntensity > 0) {
|
|
3412
|
+
drawProjectedQuad(context, face.corners, `rgba(255, 255, 255, ${0.15 * face.lightIntensity})`);
|
|
3413
|
+
}
|
|
3414
|
+
else if (face.lightIntensity < 0) {
|
|
3415
|
+
drawProjectedQuad(context, face.corners, `rgba(0, 0, 0, ${0.22 * Math.abs(face.lightIntensity)})`);
|
|
3416
|
+
}
|
|
3417
|
+
context.save();
|
|
3418
|
+
context.beginPath();
|
|
3419
|
+
context.moveTo(face.corners[0].x, face.corners[0].y);
|
|
3420
|
+
for (let cornerIndex = 1; cornerIndex < face.corners.length; cornerIndex++) {
|
|
3421
|
+
context.lineTo(face.corners[cornerIndex].x, face.corners[cornerIndex].y);
|
|
3422
|
+
}
|
|
3423
|
+
context.closePath();
|
|
3424
|
+
context.strokeStyle = face.outlineColor;
|
|
3425
|
+
context.lineWidth = Math.max(1.1, getProjectedQuadPerimeter(face.corners) * 0.0045);
|
|
3426
|
+
context.lineJoin = 'round';
|
|
3427
|
+
context.stroke();
|
|
3428
|
+
context.restore();
|
|
2988
3429
|
}
|
|
2989
3430
|
/**
|
|
2990
|
-
*
|
|
3431
|
+
* Draws one filled projected quad.
|
|
2991
3432
|
*
|
|
2992
|
-
* @param
|
|
2993
|
-
* @param
|
|
2994
|
-
* @
|
|
3433
|
+
* @param context Canvas 2D context.
|
|
3434
|
+
* @param corners Quad corners in clockwise order.
|
|
3435
|
+
* @param fillStyle CSS fill style.
|
|
2995
3436
|
*
|
|
2996
|
-
* @private helper of `
|
|
3437
|
+
* @private helper of `minecraft2AvatarVisual`
|
|
2997
3438
|
*/
|
|
2998
|
-
function
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3439
|
+
function drawProjectedQuad(context, corners, fillStyle) {
|
|
3440
|
+
context.beginPath();
|
|
3441
|
+
context.moveTo(corners[0].x, corners[0].y);
|
|
3442
|
+
context.lineTo(corners[1].x, corners[1].y);
|
|
3443
|
+
context.lineTo(corners[2].x, corners[2].y);
|
|
3444
|
+
context.lineTo(corners[3].x, corners[3].y);
|
|
3445
|
+
context.closePath();
|
|
3446
|
+
context.fillStyle = fillStyle;
|
|
3447
|
+
context.fill();
|
|
3448
|
+
}
|
|
3449
|
+
/**
|
|
3450
|
+
* Interpolates one point inside a projected quad across both quad axes.
|
|
3451
|
+
*
|
|
3452
|
+
* @param corners Quad corners in clockwise order.
|
|
3453
|
+
* @param horizontalRatio Horizontal ratio in the range `[0, 1]`.
|
|
3454
|
+
* @param verticalRatio Vertical ratio in the range `[0, 1]`.
|
|
3455
|
+
* @returns Interpolated projected point.
|
|
3456
|
+
*
|
|
3457
|
+
* @private helper of `minecraft2AvatarVisual`
|
|
3458
|
+
*/
|
|
3459
|
+
function interpolateProjectedQuad(corners, horizontalRatio, verticalRatio) {
|
|
3460
|
+
const topPoint = interpolateProjectedPoint(corners[0], corners[1], horizontalRatio);
|
|
3461
|
+
const bottomPoint = interpolateProjectedPoint(corners[3], corners[2], horizontalRatio);
|
|
3462
|
+
return interpolateProjectedPoint(topPoint, bottomPoint, verticalRatio);
|
|
3463
|
+
}
|
|
3464
|
+
/**
|
|
3465
|
+
* Interpolates between two projected points.
|
|
3466
|
+
*
|
|
3467
|
+
* @param startPoint Start point.
|
|
3468
|
+
* @param endPoint End point.
|
|
3469
|
+
* @param ratio Interpolation ratio in the range `[0, 1]`.
|
|
3470
|
+
* @returns Interpolated projected point.
|
|
3471
|
+
*
|
|
3472
|
+
* @private helper of `minecraft2AvatarVisual`
|
|
3473
|
+
*/
|
|
3474
|
+
function interpolateProjectedPoint(startPoint, endPoint, ratio) {
|
|
3475
|
+
return {
|
|
3476
|
+
x: startPoint.x + (endPoint.x - startPoint.x) * ratio,
|
|
3477
|
+
y: startPoint.y + (endPoint.y - startPoint.y) * ratio,
|
|
3478
|
+
z: startPoint.z + (endPoint.z - startPoint.z) * ratio,
|
|
3479
|
+
};
|
|
3480
|
+
}
|
|
3481
|
+
/**
|
|
3482
|
+
* Projects one rotated scene point into canvas coordinates.
|
|
3483
|
+
*
|
|
3484
|
+
* @param point Scene point.
|
|
3485
|
+
* @param size Canvas size in CSS pixels.
|
|
3486
|
+
* @param sceneCenterX Horizontal scene center.
|
|
3487
|
+
* @param sceneCenterY Vertical scene center.
|
|
3488
|
+
* @returns Projected point.
|
|
3489
|
+
*
|
|
3490
|
+
* @private helper of `minecraft2AvatarVisual`
|
|
3491
|
+
*/
|
|
3492
|
+
function projectScenePoint(point, size, sceneCenterX, sceneCenterY) {
|
|
3493
|
+
const cameraDistance = size * CAMERA_DISTANCE_RATIO;
|
|
3494
|
+
const perspectiveScale = cameraDistance / Math.max(cameraDistance - point.z, cameraDistance * 0.35);
|
|
3495
|
+
return {
|
|
3496
|
+
x: sceneCenterX + point.x * perspectiveScale,
|
|
3497
|
+
y: sceneCenterY + point.y * perspectiveScale,
|
|
3498
|
+
z: point.z,
|
|
3499
|
+
};
|
|
3500
|
+
}
|
|
3501
|
+
/**
|
|
3502
|
+
* Applies the local cuboid rotations and translation to one scene point.
|
|
3503
|
+
*
|
|
3504
|
+
* @param localPoint Point in cuboid-local space.
|
|
3505
|
+
* @param center Cuboid center in scene space.
|
|
3506
|
+
* @param rotationX Cuboid pitch in radians.
|
|
3507
|
+
* @param rotationY Cuboid yaw in radians.
|
|
3508
|
+
* @returns Transformed scene-space point.
|
|
3509
|
+
*
|
|
3510
|
+
* @private helper of `minecraft2AvatarVisual`
|
|
3511
|
+
*/
|
|
3512
|
+
function transformScenePoint(localPoint, center, rotationX, rotationY) {
|
|
3513
|
+
const yawedPoint = rotatePointAroundY(localPoint, rotationY);
|
|
3514
|
+
const pitchedPoint = rotatePointAroundX(yawedPoint, rotationX);
|
|
3515
|
+
return {
|
|
3516
|
+
x: center.x + pitchedPoint.x,
|
|
3517
|
+
y: center.y + pitchedPoint.y,
|
|
3518
|
+
z: center.z + pitchedPoint.z,
|
|
3519
|
+
};
|
|
3520
|
+
}
|
|
3521
|
+
/**
|
|
3522
|
+
* Rotates one point around the local Y axis.
|
|
3523
|
+
*
|
|
3524
|
+
* @param point Source point.
|
|
3525
|
+
* @param angle Rotation angle in radians.
|
|
3526
|
+
* @returns Rotated point.
|
|
3527
|
+
*
|
|
3528
|
+
* @private helper of `minecraft2AvatarVisual`
|
|
3529
|
+
*/
|
|
3530
|
+
function rotatePointAroundY(point, angle) {
|
|
3531
|
+
const cosine = Math.cos(angle);
|
|
3532
|
+
const sine = Math.sin(angle);
|
|
3533
|
+
return {
|
|
3534
|
+
x: point.x * cosine + point.z * sine,
|
|
3535
|
+
y: point.y,
|
|
3536
|
+
z: -point.x * sine + point.z * cosine,
|
|
3537
|
+
};
|
|
3538
|
+
}
|
|
3539
|
+
/**
|
|
3540
|
+
* Rotates one point around the local X axis.
|
|
3541
|
+
*
|
|
3542
|
+
* @param point Source point.
|
|
3543
|
+
* @param angle Rotation angle in radians.
|
|
3544
|
+
* @returns Rotated point.
|
|
3545
|
+
*
|
|
3546
|
+
* @private helper of `minecraft2AvatarVisual`
|
|
3547
|
+
*/
|
|
3548
|
+
function rotatePointAroundX(point, angle) {
|
|
3549
|
+
const cosine = Math.cos(angle);
|
|
3550
|
+
const sine = Math.sin(angle);
|
|
3551
|
+
return {
|
|
3552
|
+
x: point.x,
|
|
3553
|
+
y: point.y * cosine - point.z * sine,
|
|
3554
|
+
z: point.y * sine + point.z * cosine,
|
|
3555
|
+
};
|
|
3556
|
+
}
|
|
3557
|
+
/**
|
|
3558
|
+
* Subtracts one 3D point from another.
|
|
3559
|
+
*
|
|
3560
|
+
* @param leftPoint Left point.
|
|
3561
|
+
* @param rightPoint Right point.
|
|
3562
|
+
* @returns Difference vector.
|
|
3563
|
+
*
|
|
3564
|
+
* @private helper of `minecraft2AvatarVisual`
|
|
3565
|
+
*/
|
|
3566
|
+
function subtractPoint3D(leftPoint, rightPoint) {
|
|
3567
|
+
return {
|
|
3568
|
+
x: leftPoint.x - rightPoint.x,
|
|
3569
|
+
y: leftPoint.y - rightPoint.y,
|
|
3570
|
+
z: leftPoint.z - rightPoint.z,
|
|
3571
|
+
};
|
|
3572
|
+
}
|
|
3573
|
+
/**
|
|
3574
|
+
* Computes the 3D cross product of two vectors.
|
|
3575
|
+
*
|
|
3576
|
+
* @param leftVector Left vector.
|
|
3577
|
+
* @param rightVector Right vector.
|
|
3578
|
+
* @returns Cross product.
|
|
3579
|
+
*
|
|
3580
|
+
* @private helper of `minecraft2AvatarVisual`
|
|
3581
|
+
*/
|
|
3582
|
+
function crossProduct3D(leftVector, rightVector) {
|
|
3583
|
+
return {
|
|
3584
|
+
x: leftVector.y * rightVector.z - leftVector.z * rightVector.y,
|
|
3585
|
+
y: leftVector.z * rightVector.x - leftVector.x * rightVector.z,
|
|
3586
|
+
z: leftVector.x * rightVector.y - leftVector.y * rightVector.x,
|
|
3587
|
+
};
|
|
3588
|
+
}
|
|
3589
|
+
/**
|
|
3590
|
+
* Computes the 3D dot product of two vectors.
|
|
3591
|
+
*
|
|
3592
|
+
* @param leftVector Left vector.
|
|
3593
|
+
* @param rightVector Right vector.
|
|
3594
|
+
* @returns Dot product.
|
|
3595
|
+
*
|
|
3596
|
+
* @private helper of `minecraft2AvatarVisual`
|
|
3597
|
+
*/
|
|
3598
|
+
function dotProduct3D(leftVector, rightVector) {
|
|
3599
|
+
return leftVector.x * rightVector.x + leftVector.y * rightVector.y + leftVector.z * rightVector.z;
|
|
3600
|
+
}
|
|
3601
|
+
/**
|
|
3602
|
+
* Normalizes one 3D vector while keeping zero vectors stable.
|
|
3603
|
+
*
|
|
3604
|
+
* @param vector Source vector.
|
|
3605
|
+
* @returns Normalized vector.
|
|
3606
|
+
*
|
|
3607
|
+
* @private helper of `minecraft2AvatarVisual`
|
|
3608
|
+
*/
|
|
3609
|
+
function normalizeVector3(vector) {
|
|
3610
|
+
const length = Math.hypot(vector.x, vector.y, vector.z);
|
|
3611
|
+
if (length === 0) {
|
|
3612
|
+
return vector;
|
|
3005
3613
|
}
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3614
|
+
return {
|
|
3615
|
+
x: vector.x / length,
|
|
3616
|
+
y: vector.y / length,
|
|
3617
|
+
z: vector.z / length,
|
|
3618
|
+
};
|
|
3619
|
+
}
|
|
3620
|
+
/**
|
|
3621
|
+
* Clamps one number into the provided range.
|
|
3622
|
+
*
|
|
3623
|
+
* @param value Input value.
|
|
3624
|
+
* @param minimumValue Inclusive lower bound.
|
|
3625
|
+
* @param maximumValue Inclusive upper bound.
|
|
3626
|
+
* @returns Clamped value.
|
|
3627
|
+
*
|
|
3628
|
+
* @private helper of `minecraft2AvatarVisual`
|
|
3629
|
+
*/
|
|
3630
|
+
function clampNumber$1(value, minimumValue, maximumValue) {
|
|
3631
|
+
return Math.min(maximumValue, Math.max(minimumValue, value));
|
|
3632
|
+
}
|
|
3633
|
+
/**
|
|
3634
|
+
* Measures the perimeter of one projected quad.
|
|
3635
|
+
*
|
|
3636
|
+
* @param corners Quad corners.
|
|
3637
|
+
* @returns Perimeter length.
|
|
3638
|
+
*
|
|
3639
|
+
* @private helper of `minecraft2AvatarVisual`
|
|
3640
|
+
*/
|
|
3641
|
+
function getProjectedQuadPerimeter(corners) {
|
|
3642
|
+
let perimeter = 0;
|
|
3643
|
+
for (let cornerIndex = 0; cornerIndex < corners.length; cornerIndex++) {
|
|
3644
|
+
const currentCorner = corners[cornerIndex];
|
|
3645
|
+
const nextCorner = corners[(cornerIndex + 1) % corners.length];
|
|
3646
|
+
perimeter += Math.hypot(nextCorner.x - currentCorner.x, nextCorner.y - currentCorner.y);
|
|
3009
3647
|
}
|
|
3010
|
-
|
|
3011
|
-
texture[4][6] = palette.accent;
|
|
3012
|
-
texture[5][2] = palette.highlight;
|
|
3013
|
-
texture[5][5] = palette.highlight;
|
|
3014
|
-
return texture;
|
|
3648
|
+
return perimeter;
|
|
3015
3649
|
}
|
|
3016
3650
|
|
|
3017
3651
|
/* eslint-disable no-magic-numbers */
|
|
@@ -4616,6 +5250,7 @@ const AVATAR_VISUALS = [
|
|
|
4616
5250
|
octopus3AvatarVisual,
|
|
4617
5251
|
asciiOctopusAvatarVisual,
|
|
4618
5252
|
minecraftAvatarVisual,
|
|
5253
|
+
minecraft2AvatarVisual,
|
|
4619
5254
|
fractalAvatarVisual,
|
|
4620
5255
|
orbAvatarVisual,
|
|
4621
5256
|
];
|
|
@@ -10898,18 +11533,6 @@ function parseDataUrlKnowledgeSource(source) {
|
|
|
10898
11533
|
}
|
|
10899
11534
|
// Note: [💞] Ignore a discrepancy between file name and entity name
|
|
10900
11535
|
|
|
10901
|
-
/**
|
|
10902
|
-
* Name of the tool used by agents to search configured `KNOWLEDGE` sources.
|
|
10903
|
-
*
|
|
10904
|
-
* @public exported from `@promptbook/core`
|
|
10905
|
-
*/
|
|
10906
|
-
const KNOWLEDGE_SEARCH_TOOL_NAME = 'knowledge_search';
|
|
10907
|
-
/**
|
|
10908
|
-
* Title of the system-message section generated for `KNOWLEDGE` commitments.
|
|
10909
|
-
*
|
|
10910
|
-
* @private constant of `KnowledgeCommitmentDefinition`
|
|
10911
|
-
*/
|
|
10912
|
-
const KNOWLEDGE_SEARCH_SYSTEM_SECTION_TITLE = 'Knowledge Search';
|
|
10913
11536
|
/**
|
|
10914
11537
|
* KNOWLEDGE commitment definition
|
|
10915
11538
|
*
|
|
@@ -11031,17 +11654,9 @@ class KnowledgeCommitmentDefinition extends BaseCommitmentDefinition {
|
|
|
11031
11654
|
knowledgeInfoEntries.push(`Knowledge Source Inline: ${inlineSource.filename} (derived from inline content and processed for retrieval during chat)`);
|
|
11032
11655
|
}
|
|
11033
11656
|
if (knowledgeInfoEntries.length === 0) {
|
|
11034
|
-
return
|
|
11657
|
+
return nextRequirements;
|
|
11035
11658
|
}
|
|
11036
|
-
return
|
|
11037
|
-
}
|
|
11038
|
-
/**
|
|
11039
|
-
* Gets human-readable titles for tool functions provided by this commitment.
|
|
11040
|
-
*/
|
|
11041
|
-
getToolTitles() {
|
|
11042
|
-
return {
|
|
11043
|
-
[KNOWLEDGE_SEARCH_TOOL_NAME]: 'Knowledge search',
|
|
11044
|
-
};
|
|
11659
|
+
return this.appendToSystemMessage(nextRequirements, knowledgeInfoEntries.join('\n'), '\n\n');
|
|
11045
11660
|
}
|
|
11046
11661
|
}
|
|
11047
11662
|
/**
|
|
@@ -11055,128 +11670,6 @@ function hasMeaningfulNonUrlText(content, urls) {
|
|
|
11055
11670
|
const significantText = contentWithoutUrls.replace(/[\s.,!?;:'"`()[\]{}<>/-]+/g, '');
|
|
11056
11671
|
return significantText.length > 0;
|
|
11057
11672
|
}
|
|
11058
|
-
/**
|
|
11059
|
-
* Adds the shared `knowledge_search` tool definition and the consolidated system-message section.
|
|
11060
|
-
*
|
|
11061
|
-
* @param requirements - Requirements after one `KNOWLEDGE` commitment was applied.
|
|
11062
|
-
* @returns Requirements with the knowledge search instructions and tool definition.
|
|
11063
|
-
*
|
|
11064
|
-
* @private internal utility of `KnowledgeCommitmentDefinition`
|
|
11065
|
-
*/
|
|
11066
|
-
function addKnowledgeSearchToolAndSystemSection(requirements) {
|
|
11067
|
-
const nextRequirements = addKnowledgeSearchTool(requirements);
|
|
11068
|
-
const section = createKnowledgeSearchSystemSection(nextRequirements);
|
|
11069
|
-
const sectionHeader = `## ${KNOWLEDGE_SEARCH_SYSTEM_SECTION_TITLE}`;
|
|
11070
|
-
if (nextRequirements.systemMessage.includes(sectionHeader)) {
|
|
11071
|
-
return {
|
|
11072
|
-
...nextRequirements,
|
|
11073
|
-
systemMessage: nextRequirements.systemMessage.replace(new RegExp(`## ${KNOWLEDGE_SEARCH_SYSTEM_SECTION_TITLE.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}[\\s\\S]*?(?=\\n\\n##|$)`), section),
|
|
11074
|
-
};
|
|
11075
|
-
}
|
|
11076
|
-
return {
|
|
11077
|
-
...nextRequirements,
|
|
11078
|
-
systemMessage: nextRequirements.systemMessage.trim()
|
|
11079
|
-
? `${nextRequirements.systemMessage}\n\n${section}`
|
|
11080
|
-
: section,
|
|
11081
|
-
};
|
|
11082
|
-
}
|
|
11083
|
-
/**
|
|
11084
|
-
* Adds the `knowledge_search` model tool when it is not already present.
|
|
11085
|
-
*
|
|
11086
|
-
* @param requirements - Current model requirements.
|
|
11087
|
-
* @returns Requirements with the tool definition available to the model.
|
|
11088
|
-
*
|
|
11089
|
-
* @private internal utility of `KnowledgeCommitmentDefinition`
|
|
11090
|
-
*/
|
|
11091
|
-
function addKnowledgeSearchTool(requirements) {
|
|
11092
|
-
const existingTools = requirements.tools || [];
|
|
11093
|
-
if (existingTools.some((tool) => tool.name === KNOWLEDGE_SEARCH_TOOL_NAME)) {
|
|
11094
|
-
return requirements;
|
|
11095
|
-
}
|
|
11096
|
-
return {
|
|
11097
|
-
...requirements,
|
|
11098
|
-
tools: [
|
|
11099
|
-
...existingTools,
|
|
11100
|
-
{
|
|
11101
|
-
name: KNOWLEDGE_SEARCH_TOOL_NAME,
|
|
11102
|
-
description: spaceTrim$1(`
|
|
11103
|
-
Search the agent's configured knowledge sources and return relevant excerpts with citation ids.
|
|
11104
|
-
Use this before answering questions that may depend on the agent's KNOWLEDGE commitments.
|
|
11105
|
-
`),
|
|
11106
|
-
parameters: {
|
|
11107
|
-
type: 'object',
|
|
11108
|
-
properties: {
|
|
11109
|
-
query: {
|
|
11110
|
-
type: 'string',
|
|
11111
|
-
description: 'The natural-language search query for the knowledge base.',
|
|
11112
|
-
},
|
|
11113
|
-
limit: {
|
|
11114
|
-
type: 'integer',
|
|
11115
|
-
description: 'Maximum number of matching source excerpts to return.',
|
|
11116
|
-
},
|
|
11117
|
-
},
|
|
11118
|
-
required: ['query'],
|
|
11119
|
-
},
|
|
11120
|
-
},
|
|
11121
|
-
],
|
|
11122
|
-
};
|
|
11123
|
-
}
|
|
11124
|
-
/**
|
|
11125
|
-
* Creates the model-facing system-message section for knowledge search.
|
|
11126
|
-
*
|
|
11127
|
-
* @param requirements - Current model requirements.
|
|
11128
|
-
* @returns Markdown system-message section.
|
|
11129
|
-
*
|
|
11130
|
-
* @private internal utility of `KnowledgeCommitmentDefinition`
|
|
11131
|
-
*/
|
|
11132
|
-
function createKnowledgeSearchSystemSection(requirements) {
|
|
11133
|
-
const sourceEntries = createKnowledgeSourceSystemEntries(requirements);
|
|
11134
|
-
const sourceList = sourceEntries.length > 0 ? sourceEntries.map((entry) => `- ${entry}`).join('\n') : '- None';
|
|
11135
|
-
return spaceTrim$1(`
|
|
11136
|
-
## ${KNOWLEDGE_SEARCH_SYSTEM_SECTION_TITLE}
|
|
11137
|
-
|
|
11138
|
-
- Use \`${KNOWLEDGE_SEARCH_TOOL_NAME}\` to search the configured knowledge sources before answering questions that depend on this agent's knowledge base.
|
|
11139
|
-
- Base source-backed factual answers on the returned excerpts.
|
|
11140
|
-
- When you use a returned excerpt, include its citation marker in the answer body, for example \`[0:0]\`.
|
|
11141
|
-
- If the search returns no relevant information, say that the knowledge base did not contain the answer instead of inventing it.
|
|
11142
|
-
|
|
11143
|
-
Configured knowledge sources:
|
|
11144
|
-
${sourceList}
|
|
11145
|
-
`);
|
|
11146
|
-
}
|
|
11147
|
-
/**
|
|
11148
|
-
* Builds a stable list of configured knowledge sources for system-message diagnostics.
|
|
11149
|
-
*
|
|
11150
|
-
* @param requirements - Current model requirements.
|
|
11151
|
-
* @returns Human-readable source entries.
|
|
11152
|
-
*
|
|
11153
|
-
* @private internal utility of `KnowledgeCommitmentDefinition`
|
|
11154
|
-
*/
|
|
11155
|
-
function createKnowledgeSourceSystemEntries(requirements) {
|
|
11156
|
-
var _a;
|
|
11157
|
-
const entries = [];
|
|
11158
|
-
const seenEntries = new Set();
|
|
11159
|
-
for (const source of requirements.knowledgeSources || []) {
|
|
11160
|
-
const entry = `Source URL: ${source} (processed for retrieval during chat)`;
|
|
11161
|
-
if (seenEntries.has(entry)) {
|
|
11162
|
-
continue;
|
|
11163
|
-
}
|
|
11164
|
-
seenEntries.add(entry);
|
|
11165
|
-
entries.push(entry);
|
|
11166
|
-
}
|
|
11167
|
-
const inlineSources = (((_a = requirements._metadata) === null || _a === void 0 ? void 0 : _a.inlineKnowledgeSources) || [])
|
|
11168
|
-
.map((source) => source.filename)
|
|
11169
|
-
.filter(Boolean);
|
|
11170
|
-
for (const filename of inlineSources) {
|
|
11171
|
-
const entry = `Knowledge Source Inline: ${filename} (Inline source: processed for retrieval during chat)`;
|
|
11172
|
-
if (seenEntries.has(entry)) {
|
|
11173
|
-
continue;
|
|
11174
|
-
}
|
|
11175
|
-
seenEntries.add(entry);
|
|
11176
|
-
entries.push(entry);
|
|
11177
|
-
}
|
|
11178
|
-
return entries;
|
|
11179
|
-
}
|
|
11180
11673
|
|
|
11181
11674
|
/**
|
|
11182
11675
|
* LANGUAGE commitment definition
|
|
@@ -13764,7 +14257,11 @@ class PersonaCommitmentDefinition extends BaseCommitmentDefinition {
|
|
|
13764
14257
|
// Create new system message with persona at the beginning
|
|
13765
14258
|
// Format: "You are {agentName}\n{personaContent}"
|
|
13766
14259
|
// The # PERSONA comment will be removed later by removeCommentsFromSystemMessage
|
|
13767
|
-
const personaSection =
|
|
14260
|
+
const personaSection = spaceTrim$1((block) => `
|
|
14261
|
+
# PERSONA
|
|
14262
|
+
You are ${agentName}
|
|
14263
|
+
${block(mergedPersonaContent)}
|
|
14264
|
+
`);
|
|
13768
14265
|
const newSystemMessage = cleanedMessage ? `${personaSection}\n\n${cleanedMessage}` : personaSection;
|
|
13769
14266
|
return {
|
|
13770
14267
|
...requirements,
|
|
@@ -14666,7 +15163,10 @@ function buildTeamSystemMessageBody(teamEntries) {
|
|
|
14666
15163
|
*/
|
|
14667
15164
|
function buildTeamToolDescription(entry) {
|
|
14668
15165
|
const detailLines = collectTeamEntryDetails(entry).map(({ label, content }) => `${label}: ${content}`);
|
|
14669
|
-
return
|
|
15166
|
+
return spaceTrim$1((block) => `
|
|
15167
|
+
Consult teammate ${entry.teammate.label}
|
|
15168
|
+
${block(detailLines.join('\n'))}
|
|
15169
|
+
`);
|
|
14670
15170
|
}
|
|
14671
15171
|
/**
|
|
14672
15172
|
* Collects structured teammate details that should stay visible to the model.
|
|
@@ -20182,7 +20682,10 @@ function createListedTimeoutsAssistantMessage(options) {
|
|
|
20182
20682
|
if (hiddenCount > 0) {
|
|
20183
20683
|
summaryRows.push(`...and ${hiddenCount} more.`);
|
|
20184
20684
|
}
|
|
20185
|
-
return
|
|
20685
|
+
return spaceTrim$1((block) => `
|
|
20686
|
+
Found ${options.total} ${options.total === 1 ? 'timeout' : 'timeouts'}:
|
|
20687
|
+
${block(summaryRows.join('\n'))}
|
|
20688
|
+
`);
|
|
20186
20689
|
}
|
|
20187
20690
|
/**
|
|
20188
20691
|
* Formats one timeout row for assistant-visible timeout listings.
|
|
@@ -38167,6 +38670,174 @@ function extractMcpServers(agentSource) {
|
|
|
38167
38670
|
.filter(Boolean);
|
|
38168
38671
|
}
|
|
38169
38672
|
|
|
38673
|
+
/**
|
|
38674
|
+
* End-to-end examples used by the standalone Book language documentation.
|
|
38675
|
+
*
|
|
38676
|
+
* These are intentionally compact but complete, so they can be copy-pasted and
|
|
38677
|
+
* used as practical starting points.
|
|
38678
|
+
*
|
|
38679
|
+
* @private internal utility of `createStandaloneBookLanguageMarkdown`
|
|
38680
|
+
*/
|
|
38681
|
+
[
|
|
38682
|
+
{
|
|
38683
|
+
id: 'minimal-hello-world-agent',
|
|
38684
|
+
title: 'Minimal hello-world agent',
|
|
38685
|
+
goal: 'Create the smallest useful agent with identity and greeting.',
|
|
38686
|
+
source: spaceTrim$1(`
|
|
38687
|
+
Hello World Agent
|
|
38688
|
+
|
|
38689
|
+
GOAL Be a concise and friendly assistant.
|
|
38690
|
+
INITIAL MESSAGE Hello! I am ready to help.
|
|
38691
|
+
CLOSED
|
|
38692
|
+
`),
|
|
38693
|
+
walkthrough: [
|
|
38694
|
+
'The first line (`Hello World Agent`) is the agent name.',
|
|
38695
|
+
'`GOAL` defines the effective role and profile text.',
|
|
38696
|
+
'`INITIAL MESSAGE` sets a deterministic first message for a new chat.',
|
|
38697
|
+
'`CLOSED` prevents conversational self-modification.',
|
|
38698
|
+
],
|
|
38699
|
+
},
|
|
38700
|
+
{
|
|
38701
|
+
id: 'tool-using-browser-search-agent',
|
|
38702
|
+
title: 'Tool-using agent (Browser + Search engine)',
|
|
38703
|
+
goal: 'Enable internet research with clear sourcing behavior.',
|
|
38704
|
+
source: spaceTrim$1(`
|
|
38705
|
+
Web Research Assistant
|
|
38706
|
+
|
|
38707
|
+
GOAL Research topics using fresh and verifiable information.
|
|
38708
|
+
USE SEARCH ENGINE Prefer official sources and recent publications.
|
|
38709
|
+
USE BROWSER
|
|
38710
|
+
RULE Verify important claims across multiple sources when possible.
|
|
38711
|
+
RULE Include source links in your final answer.
|
|
38712
|
+
INITIAL MESSAGE Ask me what topic you want to research and how deep the report should be.
|
|
38713
|
+
`),
|
|
38714
|
+
walkthrough: [
|
|
38715
|
+
'`USE SEARCH ENGINE` provides web search tooling and optional search instructions.',
|
|
38716
|
+
'`USE BROWSER` enables URL fetching and interactive browsing tools.',
|
|
38717
|
+
'`RULE` commitments make reliability behavior explicit and repeatable.',
|
|
38718
|
+
'This pattern is ideal for current-events and fact-checking agents.',
|
|
38719
|
+
],
|
|
38720
|
+
},
|
|
38721
|
+
{
|
|
38722
|
+
id: 'rule-and-knowledge-agent',
|
|
38723
|
+
title: 'Agent with RULE and KNOWLEDGE',
|
|
38724
|
+
goal: 'Ground responses in explicit constraints and curated sources.',
|
|
38725
|
+
source: spaceTrim$1(`
|
|
38726
|
+
Support Policy Assistant
|
|
38727
|
+
|
|
38728
|
+
GOAL Answer questions about support policy.
|
|
38729
|
+
KNOWLEDGE Refunds are available within 30 days with proof of purchase.
|
|
38730
|
+
KNOWLEDGE https://example.com/support-policy
|
|
38731
|
+
RULE If a policy item is missing in available knowledge, say it explicitly.
|
|
38732
|
+
RULE Never invent legal or policy statements.
|
|
38733
|
+
INITIAL MESSAGE I can explain refund and support rules from provided knowledge.
|
|
38734
|
+
`),
|
|
38735
|
+
walkthrough: [
|
|
38736
|
+
'`KNOWLEDGE` may be inline text or an external URL/document.',
|
|
38737
|
+
'`RULE` commitments define non-negotiable behavior constraints.',
|
|
38738
|
+
'Combining both creates predictable, grounded policy responses.',
|
|
38739
|
+
'Use this pattern for compliance, support, and internal procedures.',
|
|
38740
|
+
],
|
|
38741
|
+
},
|
|
38742
|
+
{
|
|
38743
|
+
id: 'memory-agent-with-long-term-memory',
|
|
38744
|
+
title: 'MEMORY agent with long-term memory',
|
|
38745
|
+
goal: 'Persist user preferences across conversations.',
|
|
38746
|
+
source: spaceTrim$1(`
|
|
38747
|
+
Customer Success Memory Agent
|
|
38748
|
+
|
|
38749
|
+
GOAL Support SaaS customers while remembering relevant setup and preference context.
|
|
38750
|
+
MEMORY Remember product setup, user goals, and communication preferences.
|
|
38751
|
+
RULE Store only user-approved preferences and project context.
|
|
38752
|
+
RULE Never store secrets or sensitive data unless explicitly requested and allowed.
|
|
38753
|
+
INITIAL MESSAGE I can remember your setup and preferences for future sessions.
|
|
38754
|
+
`),
|
|
38755
|
+
walkthrough: [
|
|
38756
|
+
'`MEMORY` adds runtime memory tools and memory-specific system guidance.',
|
|
38757
|
+
'`RULE` commitments narrow what should be remembered to reduce privacy risks.',
|
|
38758
|
+
'In Agents Server, memory is runtime-backed and user-scoped.',
|
|
38759
|
+
'Use this for assistants that must preserve context over time.',
|
|
38760
|
+
],
|
|
38761
|
+
},
|
|
38762
|
+
{
|
|
38763
|
+
id: 'use-project-and-wallet-integration-agent',
|
|
38764
|
+
title: 'USE PROJECT and WALLET external integration',
|
|
38765
|
+
goal: 'Work with GitHub repositories and wallet-backed credentials.',
|
|
38766
|
+
source: spaceTrim$1(`
|
|
38767
|
+
Repository Maintainer
|
|
38768
|
+
|
|
38769
|
+
GOAL Maintain a GitHub repository and prepare safe pull requests.
|
|
38770
|
+
USE PROJECT https://github.com/acme/website
|
|
38771
|
+
WALLET Store credentials for repository operations.
|
|
38772
|
+
RULE Before editing files, explain the planned change and impacted paths.
|
|
38773
|
+
RULE Never reveal raw credentials in chat output.
|
|
38774
|
+
INITIAL MESSAGE I can inspect the repository and help you prepare PR-ready changes.
|
|
38775
|
+
`),
|
|
38776
|
+
walkthrough: [
|
|
38777
|
+
'`USE PROJECT` enables repository tools for listing, reading, editing files, and creating PRs.',
|
|
38778
|
+
'Credentials are resolved from wallet records at runtime in Agents Server.',
|
|
38779
|
+
'`WALLET` is kept here as a compatibility marker, but current Book 2.0 parsing treats it as deprecated/ignored.',
|
|
38780
|
+
'In current runtime behavior, wallet-backed integrations are driven by commitments such as `USE PROJECT` and `USE EMAIL`.',
|
|
38781
|
+
],
|
|
38782
|
+
},
|
|
38783
|
+
{
|
|
38784
|
+
id: 'use-calendar-integration-agent',
|
|
38785
|
+
title: 'USE CALENDAR integration',
|
|
38786
|
+
goal: 'Coordinate meetings and schedules through a connected Google Calendar.',
|
|
38787
|
+
source: spaceTrim$1(`
|
|
38788
|
+
Calendar Assistant
|
|
38789
|
+
|
|
38790
|
+
GOAL Schedule meetings and keep the calendar conflict-free.
|
|
38791
|
+
USE CALENDAR https://calendar.google.com/calendar/u/0/r
|
|
38792
|
+
SCOPES https://www.googleapis.com/auth/calendar
|
|
38793
|
+
RULE Confirm destructive actions before deleting an event.
|
|
38794
|
+
INITIAL MESSAGE Tell me the meeting details and I will schedule it in your calendar.
|
|
38795
|
+
`),
|
|
38796
|
+
walkthrough: [
|
|
38797
|
+
'`USE CALENDAR` enables calendar tools for listing, reading, creating, updating, and deleting events.',
|
|
38798
|
+
'The first calendar URL identifies which calendar integration should be used.',
|
|
38799
|
+
'`SCOPES` can explicitly request required Google Calendar OAuth permissions.',
|
|
38800
|
+
'Credentials are resolved from wallet-backed Google Calendar OAuth records at runtime in Agents Server.',
|
|
38801
|
+
],
|
|
38802
|
+
},
|
|
38803
|
+
{
|
|
38804
|
+
id: 'agents-team-example',
|
|
38805
|
+
title: 'Agents TEAM (with in-book teammates)',
|
|
38806
|
+
goal: 'Delegate sub-tasks to specialized teammates.',
|
|
38807
|
+
source: spaceTrim$1(`
|
|
38808
|
+
Team Manager
|
|
38809
|
+
|
|
38810
|
+
GOAL Coordinate specialists and deliver one consolidated answer.
|
|
38811
|
+
TEAM Ask {Legal Reviewer} for legal constraints and {Implementation Reviewer} for technical feasibility.
|
|
38812
|
+
RULE Always summarize teammate outputs into one action plan.
|
|
38813
|
+
|
|
38814
|
+
---
|
|
38815
|
+
|
|
38816
|
+
Legal Reviewer
|
|
38817
|
+
|
|
38818
|
+
FROM VOID
|
|
38819
|
+
GOAL Review legal and compliance risk.
|
|
38820
|
+
RULE Flag legal/compliance risk and uncertainty clearly.
|
|
38821
|
+
CLOSED
|
|
38822
|
+
|
|
38823
|
+
---
|
|
38824
|
+
|
|
38825
|
+
Implementation Reviewer
|
|
38826
|
+
|
|
38827
|
+
FROM VOID
|
|
38828
|
+
GOAL Review implementation effort and delivery risk.
|
|
38829
|
+
RULE Estimate complexity and identify blockers.
|
|
38830
|
+
CLOSED
|
|
38831
|
+
`),
|
|
38832
|
+
walkthrough: [
|
|
38833
|
+
'The main agent delegates via `TEAM` commitment.',
|
|
38834
|
+
'References in `{...}` are resolved against embedded agents inside the same book (split by `---`).',
|
|
38835
|
+
'Each teammate can be isolated with `FROM VOID` for deterministic specialization.',
|
|
38836
|
+
'This pattern works well for multi-role review and decision support.',
|
|
38837
|
+
],
|
|
38838
|
+
},
|
|
38839
|
+
];
|
|
38840
|
+
|
|
38170
38841
|
/**
|
|
38171
38842
|
* Gets all tool titles provided by all commitments
|
|
38172
38843
|
*
|
|
@@ -38417,6 +39088,72 @@ const EXPECTATION_UNITS = ['CHARACTERS', 'WORDS', 'SENTENCES', 'LINES', 'PARAGRA
|
|
|
38417
39088
|
},
|
|
38418
39089
|
});
|
|
38419
39090
|
|
|
39091
|
+
/**
|
|
39092
|
+
* Matcher is form of app that evaluates (spreadsheet) content against defined criteria or patterns,
|
|
39093
|
+
* determining if it matches or meets specific requirements. Used for classification,
|
|
39094
|
+
* validation, filtering, and quality assessment of inputs.
|
|
39095
|
+
*
|
|
39096
|
+
* @public exported from `@promptbook/core`
|
|
39097
|
+
*/
|
|
39098
|
+
({
|
|
39099
|
+
name: 'EXPERIMENTAL_MATCHER',
|
|
39100
|
+
description: spaceTrim$1(`
|
|
39101
|
+
An evaluation system that determines whether content meets specific criteria or patterns.
|
|
39102
|
+
Used for content validation, quality assessment, and intelligent filtering tasks. Currently in experimental phase.
|
|
39103
|
+
`),
|
|
39104
|
+
documentationUrl: `https://github.com/webgptorg/promptbook/discussions/177`,
|
|
39105
|
+
pipelineInterface: {
|
|
39106
|
+
inputParameters: [
|
|
39107
|
+
/* Input parameters for content to be matched and criteria to match against */
|
|
39108
|
+
{
|
|
39109
|
+
name: 'nonce',
|
|
39110
|
+
description: 'Just to prevent EXPERIMENTAL_MATCHER to be set as implicit formfactor',
|
|
39111
|
+
isInput: true,
|
|
39112
|
+
isOutput: false,
|
|
39113
|
+
},
|
|
39114
|
+
],
|
|
39115
|
+
outputParameters: [
|
|
39116
|
+
/* Output parameters containing match results, confidence scores, and relevant metadata */
|
|
39117
|
+
],
|
|
39118
|
+
},
|
|
39119
|
+
});
|
|
39120
|
+
|
|
39121
|
+
/**
|
|
39122
|
+
* Translator is form of app that transforms input text from one form to another,
|
|
39123
|
+
* such as language translation, style conversion, tone modification, or other text transformations.
|
|
39124
|
+
*
|
|
39125
|
+
* @public exported from `@promptbook/core`
|
|
39126
|
+
*/
|
|
39127
|
+
({
|
|
39128
|
+
name: 'TRANSLATOR',
|
|
39129
|
+
description: spaceTrim$1(`
|
|
39130
|
+
A text transformation system that converts input content into different forms,
|
|
39131
|
+
including language translations, paraphrasing, style conversions, and tone adjustments.
|
|
39132
|
+
This form factor takes one input and produces one transformed output.
|
|
39133
|
+
`),
|
|
39134
|
+
documentationUrl: `https://github.com/webgptorg/promptbook/discussions/175`,
|
|
39135
|
+
pipelineInterface: {
|
|
39136
|
+
inputParameters: [
|
|
39137
|
+
{
|
|
39138
|
+
name: 'inputMessage',
|
|
39139
|
+
description: `Input message to be translated`,
|
|
39140
|
+
isInput: true,
|
|
39141
|
+
isOutput: false,
|
|
39142
|
+
},
|
|
39143
|
+
],
|
|
39144
|
+
outputParameters: [
|
|
39145
|
+
{
|
|
39146
|
+
name: 'outputMessage',
|
|
39147
|
+
description: `Translated output message`,
|
|
39148
|
+
isInput: false,
|
|
39149
|
+
isOutput: true,
|
|
39150
|
+
},
|
|
39151
|
+
],
|
|
39152
|
+
// <- TODO: [🤓] Maybe add {summary}
|
|
39153
|
+
// <- TODO: [🧠] maybe change to {inputText}, {inputText} / or make system for any name of first input and first outpur parameter
|
|
39154
|
+
},
|
|
39155
|
+
});
|
|
39156
|
+
|
|
38420
39157
|
/**
|
|
38421
39158
|
* Register for LLM tools metadata.
|
|
38422
39159
|
*
|
|
@@ -38594,11 +39331,11 @@ function formatChatAttachmentContext(attachments) {
|
|
|
38594
39331
|
if (attachments.length === 0) {
|
|
38595
39332
|
return '';
|
|
38596
39333
|
}
|
|
38597
|
-
return
|
|
38598
|
-
|
|
38599
|
-
|
|
38600
|
-
|
|
38601
|
-
|
|
39334
|
+
return spaceTrim$1((block) => `
|
|
39335
|
+
${CHAT_ATTACHMENTS_HEADING}
|
|
39336
|
+
${block(attachments.map((attachment) => formatChatAttachmentLine(attachment)).join('\n'))}
|
|
39337
|
+
${CHAT_ATTACHMENTS_INSTRUCTION}
|
|
39338
|
+
`);
|
|
38602
39339
|
}
|
|
38603
39340
|
|
|
38604
39341
|
/**
|
|
@@ -38839,24 +39576,24 @@ function formatResolvedChatAttachmentContent(contentResolution) {
|
|
|
38839
39576
|
: ''}`
|
|
38840
39577
|
: null;
|
|
38841
39578
|
const warningsLine = contentResolution.warnings.length > 0 ? `Warnings: ${contentResolution.warnings.join(' | ')}` : null;
|
|
38842
|
-
|
|
39579
|
+
const metadataLines = [decodingLine, warningsLine].filter((line) => Boolean(line)).join('\n');
|
|
39580
|
+
const resolvedContent = contentResolution.content;
|
|
39581
|
+
if (!resolvedContent) {
|
|
38843
39582
|
const reason = contentResolution.reason || 'content unavailable';
|
|
38844
|
-
return
|
|
38845
|
-
|
|
38846
|
-
|
|
39583
|
+
return spaceTrim$1((block) => `
|
|
39584
|
+
- ${attachmentLabel}: ${reason}. URL: ${contentResolution.attachment.url}
|
|
39585
|
+
${block(metadataLines)}
|
|
39586
|
+
`);
|
|
38847
39587
|
}
|
|
38848
39588
|
const truncatedLabel = contentResolution.isTruncated ? ' [truncated]' : '';
|
|
38849
|
-
return
|
|
38850
|
-
|
|
38851
|
-
|
|
38852
|
-
|
|
38853
|
-
|
|
38854
|
-
|
|
38855
|
-
|
|
38856
|
-
|
|
38857
|
-
]
|
|
38858
|
-
.filter(Boolean)
|
|
38859
|
-
.join('\n');
|
|
39589
|
+
return spaceTrim$1((block) => `
|
|
39590
|
+
File: ${attachmentLabel}${truncatedLabel}
|
|
39591
|
+
URL: ${contentResolution.attachment.url}
|
|
39592
|
+
${block(metadataLines)}
|
|
39593
|
+
\`\`\`text
|
|
39594
|
+
${block(resolvedContent)}
|
|
39595
|
+
\`\`\`
|
|
39596
|
+
`);
|
|
38860
39597
|
}
|
|
38861
39598
|
/**
|
|
38862
39599
|
* Formats inline attachment-content context section for the model.
|
|
@@ -38870,11 +39607,14 @@ function formatChatAttachmentContentContext(resolvedContents) {
|
|
|
38870
39607
|
if (resolvedContents.length === 0) {
|
|
38871
39608
|
return '';
|
|
38872
39609
|
}
|
|
38873
|
-
return
|
|
38874
|
-
|
|
38875
|
-
|
|
38876
|
-
|
|
38877
|
-
|
|
39610
|
+
return spaceTrim$1((block) => `
|
|
39611
|
+
${CHAT_ATTACHMENT_CONTENT_HEADING}
|
|
39612
|
+
${CHAT_ATTACHMENT_CONTENT_INSTRUCTION}
|
|
39613
|
+
|
|
39614
|
+
${block(resolvedContents
|
|
39615
|
+
.map((resolvedContent) => formatResolvedChatAttachmentContent(resolvedContent))
|
|
39616
|
+
.join('\n\n'))}
|
|
39617
|
+
`);
|
|
38878
39618
|
}
|
|
38879
39619
|
|
|
38880
39620
|
/**
|
|
@@ -40019,9 +40759,11 @@ class OpenAiCompatibleUnsupportedParameterRetrier {
|
|
|
40019
40759
|
* Creates the retry-history error message shared by all OpenAI-compatible model variants.
|
|
40020
40760
|
*/
|
|
40021
40761
|
createAttemptHistoryError(finalErrorMessage) {
|
|
40022
|
-
return new PipelineExecutionError(
|
|
40023
|
-
|
|
40024
|
-
|
|
40762
|
+
return new PipelineExecutionError(spaceTrim$1((block) => `
|
|
40763
|
+
All attempts failed. Attempt history:
|
|
40764
|
+
${block(formatUnsupportedParameterAttemptHistory(this.attemptStack))}
|
|
40765
|
+
Final error: ${finalErrorMessage}
|
|
40766
|
+
`));
|
|
40025
40767
|
}
|
|
40026
40768
|
}
|
|
40027
40769
|
|
|
@@ -42615,7 +43357,7 @@ class OpenAiAgentKitExecutionTools extends OpenAiVectorStoreHandler {
|
|
|
42615
43357
|
});
|
|
42616
43358
|
}
|
|
42617
43359
|
let vectorStoreId = cachedVectorStoreId;
|
|
42618
|
-
if (
|
|
43360
|
+
if (!vectorStoreId && knowledgeSources && knowledgeSources.length > 0) {
|
|
42619
43361
|
const vectorStoreResult = await this.createVectorStoreWithKnowledgeSources({
|
|
42620
43362
|
client: await this.getClient(),
|
|
42621
43363
|
name,
|
|
@@ -42624,19 +43366,13 @@ class OpenAiAgentKitExecutionTools extends OpenAiVectorStoreHandler {
|
|
|
42624
43366
|
});
|
|
42625
43367
|
vectorStoreId = vectorStoreResult.vectorStoreId;
|
|
42626
43368
|
}
|
|
42627
|
-
else if (
|
|
43369
|
+
else if (vectorStoreId && this.options.isVerbose) {
|
|
42628
43370
|
console.info('[🤰]', 'Using cached vector store for AgentKit agent', {
|
|
42629
43371
|
name,
|
|
42630
43372
|
vectorStoreId,
|
|
42631
43373
|
});
|
|
42632
43374
|
}
|
|
42633
|
-
|
|
42634
|
-
vectorStoreId = undefined;
|
|
42635
|
-
}
|
|
42636
|
-
const agentKitTools = this.buildAgentKitTools({
|
|
42637
|
-
tools,
|
|
42638
|
-
vectorStoreId,
|
|
42639
|
-
});
|
|
43375
|
+
const agentKitTools = this.buildAgentKitTools({ tools, vectorStoreId });
|
|
42640
43376
|
const openAiAgentKitAgent = new Agent$1({
|
|
42641
43377
|
name,
|
|
42642
43378
|
model: this.agentKitModelName,
|
|
@@ -42655,7 +43391,7 @@ class OpenAiAgentKitExecutionTools extends OpenAiVectorStoreHandler {
|
|
|
42655
43391
|
name,
|
|
42656
43392
|
model: this.agentKitModelName,
|
|
42657
43393
|
toolCount: agentKitTools.length,
|
|
42658
|
-
hasVectorStore:
|
|
43394
|
+
hasVectorStore: Boolean(vectorStoreId),
|
|
42659
43395
|
});
|
|
42660
43396
|
}
|
|
42661
43397
|
return preparedAgent;
|
|
@@ -43154,12 +43890,6 @@ class OpenAiAgentKitExecutionTools extends OpenAiVectorStoreHandler {
|
|
|
43154
43890
|
get agentKitOptions() {
|
|
43155
43891
|
return this.options;
|
|
43156
43892
|
}
|
|
43157
|
-
/**
|
|
43158
|
-
* Returns true when hosted OpenAI vector-store search should back `knowledgeSources`.
|
|
43159
|
-
*/
|
|
43160
|
-
get isNativeKnowledgeSearchEnabled() {
|
|
43161
|
-
return this.agentKitOptions.isNativeKnowledgeSearchEnabled !== false;
|
|
43162
|
-
}
|
|
43163
43893
|
/**
|
|
43164
43894
|
* Discriminant for type guards.
|
|
43165
43895
|
*/
|
|
@@ -48887,7 +49617,6 @@ const TOOL_TITLES = {
|
|
|
48887
49617
|
request_wallet_record: { title: 'Requesting wallet', emoji: '👛' },
|
|
48888
49618
|
web_search: { title: 'Searching the web', emoji: '🔎' },
|
|
48889
49619
|
deep_search: { title: 'Deep research', emoji: '🔬' },
|
|
48890
|
-
knowledge_search: { title: 'Searching knowledge', emoji: '📚' },
|
|
48891
49620
|
useSearchEngine: { title: 'Searching the web', emoji: '🔎' },
|
|
48892
49621
|
search: { title: 'Searching the web', emoji: '🔎' },
|
|
48893
49622
|
useBrowser: { title: 'Browsing the web', emoji: '🌐' },
|
|
@@ -49763,13 +50492,6 @@ const ChatMessageItem = memo(
|
|
|
49763
50492
|
content: sanitizedContentWithoutButtons,
|
|
49764
50493
|
citations: message.citations,
|
|
49765
50494
|
}), [message.citations, sanitizedContentWithoutButtons]);
|
|
49766
|
-
const structuredSourceCitations = useMemo(() => {
|
|
49767
|
-
const footnoteSourceKeys = new Set(citationFootnoteRenderModel.footnotes.map((footnote) => footnote.citation.source.trim().toLowerCase()));
|
|
49768
|
-
return (message.sources || []).filter((source) => {
|
|
49769
|
-
const sourceKey = source.source.trim().toLowerCase();
|
|
49770
|
-
return sourceKey && !footnoteSourceKeys.has(sourceKey);
|
|
49771
|
-
});
|
|
49772
|
-
}, [citationFootnoteRenderModel.footnotes, message.sources]);
|
|
49773
50495
|
const contentSegments = useMemo(() => splitMessageContentIntoSegments(citationFootnoteRenderModel.content), [citationFootnoteRenderModel.content]);
|
|
49774
50496
|
const hasMapSegment = useMemo(() => contentSegments.some((segment) => segment.type === 'map'), [contentSegments]);
|
|
49775
50497
|
const [localHoveredRating, setLocalHoveredRating] = useState(0);
|
|
@@ -50041,7 +50763,7 @@ const ChatMessageItem = memo(
|
|
|
50041
50763
|
'--message-bg-color': isAgentArticleMode ? articleModeBackgroundColor : color.toHex(),
|
|
50042
50764
|
'--message-text-color': isAgentArticleMode ? articleModeTextColor : colorOfText.toHex(),
|
|
50043
50765
|
'--chat-message-swipe-offset': swipeTranslation,
|
|
50044
|
-
}, onPointerDown: handleReplyPointerDown, onPointerMove: handleReplyPointerMove, onPointerUp: handleReplyPointerEnd, onPointerCancel: resetReplySwipe, children: [isReplyActionEnabled && (jsx("div", { className: classNames(styles$5.replySwipeIndicator, isMe && styles$5.replySwipeIndicatorRight, isReplySwipeArmed && styles$5.replySwipeIndicatorActive), "aria-hidden": "true", children: jsx(Reply, { className: styles$5.replySwipeIndicatorIcon }) })), !shouldRenderArticleActionsBar && renderMessageReadAndCopyControls(), message.isVoiceCall && (jsx("div", { className: styles$5.voiceCallIndicator, children: jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "currentColor", children: jsx("path", { d: "M6.62 10.79c1.44 2.83 3.76 5.14 6.59 6.59l2.2-2.2c.27-.27.67-.36 1.02-.24 1.12.37 2.33.57 3.57.57.55 0 1 .45 1 1V20c0 .55-.45 1-1 1-9.39 0-17-7.61-17-17 0-.55.45-1 1-1h3.5c.55 0 1 .45 1 1 0 1.25.2 2.45.57 3.57.11.35.03.74-.25 1.02l-2.2 2.2z" }) }) })), replyingToMessage && replyPreviewText && replySenderLabel && (jsx(ChatReplyPreview, { label: replyPreviewLabel, senderLabel: replySenderLabel, previewText: replyPreviewText, className: styles$5.replyBubblePreview })), jsx("div", { ref: contentWithoutButtonsRef, children: jsx(ChatMessageRichContent, { content: message.content, contentSegments: contentSegments, streamingFeaturePlaceholderKind: streamingFeaturePlaceholderKind, onCreateAgent: onCreateAgent, mode: mode }) }), message.attachments && message.attachments.length > 0 && (jsx("div", { className: styles$5.attachments, children: message.attachments.map((attachment, index) => (jsxs("a", { href: attachment.url, target: "_blank", rel: "noopener noreferrer", className: styles$5.attachment, title: attachment.name, children: [jsx("span", { className: styles$5.attachmentIcon, children: "\uD83D\uDCCE" }), jsx("span", { className: styles$5.attachmentName, children: attachment.name })] }, index))) })), jsx(ChatMessageToolCallChips, { chips: toolCallChips, onToolCallClick: onToolCallClick }), citationFootnoteRenderModel.footnotes.length > 0 && (jsx("div", { className: styles$5.citationFootnotes, children: citationFootnoteRenderModel.footnotes.map((footnote) => (jsxs("div", { className: styles$5.citationFootnoteItem, children: [jsx("span", { className: styles$5.citationFootnoteNumber, children: footnote.number }), jsx(SourceChip, { citation: footnote.citation, onClick: onCitationClick, isCitationIdVisible: false })] }, `citation-footnote-${footnote.number}-${footnote.citation.source}`))) })),
|
|
50766
|
+
}, onPointerDown: handleReplyPointerDown, onPointerMove: handleReplyPointerMove, onPointerUp: handleReplyPointerEnd, onPointerCancel: resetReplySwipe, children: [isReplyActionEnabled && (jsx("div", { className: classNames(styles$5.replySwipeIndicator, isMe && styles$5.replySwipeIndicatorRight, isReplySwipeArmed && styles$5.replySwipeIndicatorActive), "aria-hidden": "true", children: jsx(Reply, { className: styles$5.replySwipeIndicatorIcon }) })), !shouldRenderArticleActionsBar && renderMessageReadAndCopyControls(), message.isVoiceCall && (jsx("div", { className: styles$5.voiceCallIndicator, children: jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "currentColor", children: jsx("path", { d: "M6.62 10.79c1.44 2.83 3.76 5.14 6.59 6.59l2.2-2.2c.27-.27.67-.36 1.02-.24 1.12.37 2.33.57 3.57.57.55 0 1 .45 1 1V20c0 .55-.45 1-1 1-9.39 0-17-7.61-17-17 0-.55.45-1 1-1h3.5c.55 0 1 .45 1 1 0 1.25.2 2.45.57 3.57.11.35.03.74-.25 1.02l-2.2 2.2z" }) }) })), replyingToMessage && replyPreviewText && replySenderLabel && (jsx(ChatReplyPreview, { label: replyPreviewLabel, senderLabel: replySenderLabel, previewText: replyPreviewText, className: styles$5.replyBubblePreview })), jsx("div", { ref: contentWithoutButtonsRef, children: jsx(ChatMessageRichContent, { content: message.content, contentSegments: contentSegments, streamingFeaturePlaceholderKind: streamingFeaturePlaceholderKind, onCreateAgent: onCreateAgent, mode: mode }) }), message.attachments && message.attachments.length > 0 && (jsx("div", { className: styles$5.attachments, children: message.attachments.map((attachment, index) => (jsxs("a", { href: attachment.url, target: "_blank", rel: "noopener noreferrer", className: styles$5.attachment, title: attachment.name, children: [jsx("span", { className: styles$5.attachmentIcon, children: "\uD83D\uDCCE" }), jsx("span", { className: styles$5.attachmentName, children: attachment.name })] }, index))) })), jsx(ChatMessageToolCallChips, { chips: toolCallChips, onToolCallClick: onToolCallClick }), citationFootnoteRenderModel.footnotes.length > 0 && (jsx("div", { className: styles$5.citationFootnotes, children: citationFootnoteRenderModel.footnotes.map((footnote) => (jsxs("div", { className: styles$5.citationFootnoteItem, children: [jsx("span", { className: styles$5.citationFootnoteNumber, children: footnote.number }), jsx(SourceChip, { citation: footnote.citation, onClick: onCitationClick, isCitationIdVisible: false })] }, `citation-footnote-${footnote.number}-${footnote.citation.source}`))) })), transitiveCitations.length > 0 && (jsx("div", { className: styles$5.sourceCitations, children: transitiveCitations.map((citation, index) => (jsx(SourceChip, { citation: citation, suffix: `by ${citation.origin.label}`, onClick: onCitationClick }, `team-source-${citation.source}-${index}`))) })), shouldShowButtons && (jsx("div", { className: styles$5.messageButtons, children: renderableButtons.map(({ button, buttonIndex }) => (jsx("button", { type: "button", className: classNames(styles$5.messageButton, button.type === 'action' && styles$5.actionMessageButton), onClick: (event) => {
|
|
50045
50767
|
event.stopPropagation();
|
|
50046
50768
|
if (button.type === 'message') {
|
|
50047
50769
|
const quickMessageHandler = onQuickMessageButton || onMessage;
|
|
@@ -50093,9 +50815,6 @@ const ChatMessageItem = memo(
|
|
|
50093
50815
|
if (prev.message.citations !== next.message.citations) {
|
|
50094
50816
|
return false;
|
|
50095
50817
|
}
|
|
50096
|
-
if (prev.message.sources !== next.message.sources) {
|
|
50097
|
-
return false;
|
|
50098
|
-
}
|
|
50099
50818
|
if (JSON.stringify(prev.message.attachments) !== JSON.stringify(next.message.attachments)) {
|
|
50100
50819
|
return false;
|
|
50101
50820
|
}
|
|
@@ -51510,7 +52229,7 @@ function renderSearchToolCallDetails(options) {
|
|
|
51510
52229
|
const { results, rawText } = extractSearchResults(resultRaw);
|
|
51511
52230
|
const hasResults = results.length > 0;
|
|
51512
52231
|
const hasRawText = !hasResults && !!rawText && rawText.trim().length > 0;
|
|
51513
|
-
return (jsxs(Fragment, { children: [jsxs("div", { className: styles$5.searchModalHeader, children: [jsx("span", { className: styles$5.searchModalIcon, children: "\uD83D\uDD0E" }), jsx("h3", { className: styles$5.searchModalQuery, children: args.query || args.searchText || 'Search Results' })] }), jsx("div", { className: styles$5.searchModalContent, children: hasResults ? (jsx("div", { className: styles$5.searchResultsList, children: results.map((item, index) => (jsxs("div", { className: styles$5.searchResultItem, children: [jsx("div", { className: styles$5.searchResultUrl, children: item.url && (jsx("a", { href: item.url, target: "_blank", rel: "noreferrer", children: item.url })) }), jsx("h4", { className: styles$5.searchResultTitle, children: item.url ? (jsx("a", { href: item.url, target: "_blank", rel: "noreferrer", children: item.title ||
|
|
52232
|
+
return (jsxs(Fragment, { children: [jsxs("div", { className: styles$5.searchModalHeader, children: [jsx("span", { className: styles$5.searchModalIcon, children: "\uD83D\uDD0E" }), jsx("h3", { className: styles$5.searchModalQuery, children: args.query || args.searchText || 'Search Results' })] }), jsx("div", { className: styles$5.searchModalContent, children: hasResults ? (jsx("div", { className: styles$5.searchResultsList, children: results.map((item, index) => (jsxs("div", { className: styles$5.searchResultItem, children: [jsx("div", { className: styles$5.searchResultUrl, children: item.url && (jsx("a", { href: item.url, target: "_blank", rel: "noreferrer", children: item.url })) }), jsx("h4", { className: styles$5.searchResultTitle, children: item.url ? (jsx("a", { href: item.url, target: "_blank", rel: "noreferrer", children: item.title || 'Untitled' })) : (item.title || 'Untitled') }), jsx("p", { className: styles$5.searchResultSnippet, children: item.snippet || item.content || '' })] }, index))) })) : hasRawText ? (jsx(MarkdownContent, { className: styles$5.searchResultsRaw, content: rawText })) : toolCallState !== 'COMPLETE' ? (jsxs(Fragment, { children: [renderToolCallProgressPlaceholder({
|
|
51514
52233
|
title: 'Search results pending',
|
|
51515
52234
|
message: resolveToolCallProgressMessage(toolCall),
|
|
51516
52235
|
}), jsxs("div", { className: styles$5.toolCallDetailsCard, children: [jsxs("div", { className: styles$5.toolCallDetailsCardRow, children: [jsx("strong", { children: "Query" }), jsx("span", { children: String(args.query || args.searchText || 'Search query is being prepared.') })] }), args.location && (jsxs("div", { className: styles$5.toolCallDetailsCardRow, children: [jsx("strong", { children: "Location" }), jsx("span", { children: String(args.location) })] })), args.engine && (jsxs("div", { className: styles$5.toolCallDetailsCardRow, children: [jsx("strong", { children: "Engine" }), jsx("span", { children: String(args.engine) })] }))] })] })) : (jsx("div", { className: styles$5.noResults, children: resultRaw ? 'No search results found.' : 'Search results are not available.' })) })] }));
|
|
@@ -52090,7 +52809,6 @@ function renderGenericToolCallDetails(options) {
|
|
|
52090
52809
|
function isSearchToolCallName(toolName) {
|
|
52091
52810
|
return (toolName === 'web_search' ||
|
|
52092
52811
|
toolName === 'deep_search' ||
|
|
52093
|
-
toolName === 'knowledge_search' ||
|
|
52094
52812
|
toolName === 'useSearchEngine' ||
|
|
52095
52813
|
toolName === 'search');
|
|
52096
52814
|
}
|