@promptbook/browser 0.112.0-115 → 0.112.0-118

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.
Files changed (31) hide show
  1. package/esm/index.es.js +208 -56
  2. package/esm/index.es.js.map +1 -1
  3. package/esm/src/_packages/components.index.d.ts +2 -0
  4. package/esm/src/_packages/node.index.d.ts +20 -0
  5. package/esm/src/book-3.0/BookNodeAgentSource.d.ts +1 -1
  6. package/esm/src/book-3.0/CliAgent.d.ts +15 -17
  7. package/esm/src/book-3.0/agentFolderPaths.d.ts +30 -0
  8. package/esm/src/book-3.0/cliAgentEnv.d.ts +33 -0
  9. package/esm/src/book-components/BookEditor/BookEditorBrowserConfig.d.ts +2 -0
  10. package/esm/src/book-components/BookEditor/BookEditorForClient.d.ts +7 -0
  11. package/esm/src/book-components/BookEditor/createDeprecatedCommitmentDiagnostics.browser.d.ts +9 -0
  12. package/esm/src/cli/cli-commands/agent-folder/agentProjectPaths.d.ts +2 -30
  13. package/esm/src/cli/cli-commands/common/promptRunnerCliOptions.d.ts +2 -18
  14. package/esm/src/scrapers/website/utils/createShowdownConverter.d.ts +2 -2
  15. package/esm/src/version.d.ts +1 -1
  16. package/package.json +2 -3
  17. package/umd/index.umd.js +212 -57
  18. package/umd/index.umd.js.map +1 -1
  19. package/umd/src/_packages/components.index.d.ts +2 -0
  20. package/umd/src/_packages/node.index.d.ts +20 -0
  21. package/umd/src/book-3.0/BookNodeAgentSource.d.ts +1 -1
  22. package/umd/src/book-3.0/CliAgent.d.ts +15 -17
  23. package/umd/src/book-3.0/agentFolderPaths.d.ts +30 -0
  24. package/umd/src/book-3.0/cliAgentEnv.d.ts +33 -0
  25. package/umd/src/book-components/BookEditor/BookEditorBrowserConfig.d.ts +2 -0
  26. package/umd/src/book-components/BookEditor/BookEditorForClient.d.ts +7 -0
  27. package/umd/src/book-components/BookEditor/createDeprecatedCommitmentDiagnostics.browser.d.ts +9 -0
  28. package/umd/src/cli/cli-commands/agent-folder/agentProjectPaths.d.ts +2 -30
  29. package/umd/src/cli/cli-commands/common/promptRunnerCliOptions.d.ts +2 -18
  30. package/umd/src/scrapers/website/utils/createShowdownConverter.d.ts +2 -2
  31. package/umd/src/version.d.ts +1 -1
package/umd/index.umd.js CHANGED
@@ -1,14 +1,16 @@
1
1
  (function (global, factory) {
2
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('spacetrim'), require('destroyable'), require('rxjs'), require('crypto'), require('crypto-js'), require('crypto-js/enc-hex'), require('path'), require('moment'), require('mime-types'), require('waitasecond'), require('crypto-js/sha256'), require('papaparse'), require('@openai/agents'), require('colors'), require('bottleneck'), require('openai')) :
3
- typeof define === 'function' && define.amd ? define(['exports', 'spacetrim', 'destroyable', 'rxjs', 'crypto', 'crypto-js', 'crypto-js/enc-hex', 'path', 'moment', 'mime-types', 'waitasecond', 'crypto-js/sha256', 'papaparse', '@openai/agents', 'colors', 'bottleneck', 'openai'], factory) :
4
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["promptbook-browser"] = {}, global.spacetrim, global.destroyable, global.rxjs, global.crypto, global.cryptoJs, global.hexEncoder, global.path, global.moment, global.mimeTypes, global.waitasecond, global.sha256, global.papaparse, global.agents, global.colors, global.Bottleneck, global.OpenAI));
5
- })(this, (function (exports, spacetrim, destroyable, rxjs, crypto, cryptoJs, hexEncoder, path, moment, mimeTypes, waitasecond, sha256, papaparse, agents, colors, Bottleneck, OpenAI) { 'use strict';
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('spacetrim'), require('destroyable'), require('rxjs'), require('crypto-js'), require('crypto-js/enc-hex'), require('path'), require('moment'), require('mime-types'), require('waitasecond'), require('crypto-js/sha256'), require('papaparse'), require('@openai/agents'), require('colors'), require('bottleneck'), require('openai')) :
3
+ typeof define === 'function' && define.amd ? define(['exports', 'spacetrim', 'destroyable', 'rxjs', 'crypto-js', 'crypto-js/enc-hex', 'path', 'moment', 'mime-types', 'waitasecond', 'crypto-js/sha256', 'papaparse', '@openai/agents', 'colors', 'bottleneck', 'openai'], factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["promptbook-browser"] = {}, global.spacetrim, global.destroyable, global.rxjs, global.CryptoJS, global.hexEncoder, global.path, global.moment, global.mimeTypes, global.waitasecond, global.sha256, global.papaparse, global.agents, global.colors, global.Bottleneck, global.OpenAI));
5
+ })(this, (function (exports, spacetrim, destroyable, rxjs, CryptoJS, hexEncoder, path, moment, mimeTypes, waitasecond, sha256, papaparse, agents, colors, Bottleneck, OpenAI) { 'use strict';
6
6
 
7
7
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
8
8
 
9
+ var CryptoJS__default = /*#__PURE__*/_interopDefaultLegacy(CryptoJS);
9
10
  var hexEncoder__default = /*#__PURE__*/_interopDefaultLegacy(hexEncoder);
10
11
  var moment__default = /*#__PURE__*/_interopDefaultLegacy(moment);
11
12
  var sha256__default = /*#__PURE__*/_interopDefaultLegacy(sha256);
13
+ var papaparse__default = /*#__PURE__*/_interopDefaultLegacy(papaparse);
12
14
  var colors__default = /*#__PURE__*/_interopDefaultLegacy(colors);
13
15
  var Bottleneck__default = /*#__PURE__*/_interopDefaultLegacy(Bottleneck);
14
16
  var OpenAI__default = /*#__PURE__*/_interopDefaultLegacy(OpenAI);
@@ -27,7 +29,7 @@
27
29
  * @generated
28
30
  * @see https://github.com/webgptorg/promptbook
29
31
  */
30
- const PROMPTBOOK_ENGINE_VERSION = '0.112.0-115';
32
+ const PROMPTBOOK_ENGINE_VERSION = '0.112.0-118';
31
33
  /**
32
34
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
33
35
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -2330,7 +2332,7 @@
2330
2332
  * @public exported from `@promptbook/utils`
2331
2333
  */
2332
2334
  function computeHash(value) {
2333
- return cryptoJs.SHA256(hexEncoder__default["default"].parse(spacetrim.spaceTrim(valueToString(value)))).toString( /* hex */);
2335
+ return CryptoJS__default["default"].SHA256(hexEncoder__default["default"].parse(spacetrim.spaceTrim(valueToString(value)))).toString( /* hex */);
2334
2336
  }
2335
2337
  // TODO: [🥬][🥬] Use this ACRY
2336
2338
 
@@ -6159,21 +6161,22 @@
6159
6161
  * @private helper of `fractalAvatarVisual`
6160
6162
  */
6161
6163
  function drawDragonCurveLayer(context, points, options) {
6162
- const { size, primaryColor, secondaryColor, tertiaryColor, shadowColor, strokeWidth, timeMs, layerIndex } = options;
6164
+ const { primaryColor, secondaryColor, tertiaryColor, shadowColor, strokeWidth, timeMs, layerIndex } = options;
6163
6165
  const firstPoint = points[0];
6164
6166
  const lastPoint = points[points.length - 1];
6165
6167
  const ribbonGradient = context.createLinearGradient(firstPoint.x, firstPoint.y, lastPoint.x, lastPoint.y);
6166
6168
  ribbonGradient.addColorStop(0, `${primaryColor}f2`);
6167
6169
  ribbonGradient.addColorStop(0.5, `${secondaryColor}e6`);
6168
6170
  ribbonGradient.addColorStop(1, `${tertiaryColor}f2`);
6171
+ // Approximate the blurred shadow stroke with a wider semi-transparent stroke instead of
6172
+ // context.filter blur, which triggers a costly software rasterization pass every frame.
6169
6173
  context.save();
6170
6174
  context.beginPath();
6171
6175
  tracePolyline(context, points);
6172
- context.strokeStyle = `${shadowColor}82`;
6173
- context.lineWidth = strokeWidth * 1.8;
6176
+ context.strokeStyle = `${shadowColor}48`;
6177
+ context.lineWidth = strokeWidth * 4.5;
6174
6178
  context.lineJoin = 'round';
6175
6179
  context.lineCap = 'round';
6176
- context.filter = `blur(${size * 0.022}px)`;
6177
6180
  context.stroke();
6178
6181
  context.restore();
6179
6182
  context.beginPath();
@@ -6757,11 +6760,23 @@
6757
6760
  * @private helper of `minecraft2AvatarVisual`
6758
6761
  */
6759
6762
  function drawMinecraftShadow(context, size, palette, interaction, timeMs) {
6763
+ const cx = size * 0.5 + interaction.gazeX * size * 0.03;
6764
+ const cy = size * 0.85 + Math.sin(timeMs / 880) * size * 0.01;
6765
+ const rx = size * (0.16 + interaction.intensity * 0.015);
6766
+ const ry = size * 0.055;
6767
+ // Radial gradient approximates the blurry ellipse shadow without context.filter blur.
6760
6768
  context.save();
6761
- context.fillStyle = `${palette.shadow}66`;
6762
- context.filter = `blur(${size * 0.02}px)`;
6769
+ context.translate(cx, cy);
6770
+ context.scale(1, ry / rx);
6771
+ const blurRadius = rx * 1.4;
6772
+ const shadowGradient = context.createRadialGradient(0, 0, 0, 0, 0, blurRadius);
6773
+ shadowGradient.addColorStop(0, `${palette.shadow}7a`);
6774
+ shadowGradient.addColorStop(0.45, `${palette.shadow}44`);
6775
+ shadowGradient.addColorStop(0.8, `${palette.shadow}1a`);
6776
+ shadowGradient.addColorStop(1, `${palette.shadow}00`);
6777
+ context.fillStyle = shadowGradient;
6763
6778
  context.beginPath();
6764
- 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);
6779
+ context.arc(0, 0, blurRadius, 0, Math.PI * 2);
6765
6780
  context.fill();
6766
6781
  context.restore();
6767
6782
  }
@@ -6985,13 +7000,27 @@
6985
7000
  spotlight.addColorStop(1, `${palette.highlight}00`);
6986
7001
  context.fillStyle = spotlight;
6987
7002
  context.fillRect(0, 0, size, size);
6988
- context.save();
6989
- context.fillStyle = 'rgba(0, 0, 0, 0.22)';
6990
- context.filter = `blur(${size * 0.018}px)`;
6991
- context.beginPath();
6992
- context.ellipse(size * 0.5, size * 0.86, size * 0.2, size * 0.06, 0, 0, Math.PI * 2);
6993
- context.fill();
6994
- context.restore();
7003
+ {
7004
+ // Radial gradient approximates the blurry ellipse shadow without context.filter blur.
7005
+ const cx = size * 0.5;
7006
+ const cy = size * 0.86;
7007
+ const rx = size * 0.2;
7008
+ const ry = size * 0.06;
7009
+ const blurRadius = rx * 1.4;
7010
+ const shadowGradient = context.createRadialGradient(0, 0, 0, 0, 0, blurRadius);
7011
+ shadowGradient.addColorStop(0, 'rgba(0,0,0,0.28)');
7012
+ shadowGradient.addColorStop(0.45, 'rgba(0,0,0,0.14)');
7013
+ shadowGradient.addColorStop(0.8, 'rgba(0,0,0,0.05)');
7014
+ shadowGradient.addColorStop(1, 'rgba(0,0,0,0)');
7015
+ context.save();
7016
+ context.translate(cx, cy);
7017
+ context.scale(1, ry / rx);
7018
+ context.fillStyle = shadowGradient;
7019
+ context.beginPath();
7020
+ context.arc(0, 0, blurRadius, 0, Math.PI * 2);
7021
+ context.fill();
7022
+ context.restore();
7023
+ }
6995
7024
  drawVoxelCuboid(context, {
6996
7025
  x: bodyX,
6997
7026
  y: bodyY,
@@ -8043,6 +8072,35 @@
8043
8072
  y: -0.62,
8044
8073
  z: 0.94,
8045
8074
  });
8075
+ /**
8076
+ * Cache keyed by the `createRandom` factory reference (stable per mounted `<Avatar/>`).
8077
+ *
8078
+ * @private helper of `octopus3dAvatarVisual`
8079
+ */
8080
+ const octopus3dStableStateCache = new WeakMap();
8081
+ /**
8082
+ * Returns the stable per-avatar state, computing it on first access and caching for subsequent frames.
8083
+ *
8084
+ * @private helper of `octopus3dAvatarVisual`
8085
+ */
8086
+ function getOctopus3dStableState(createRandom) {
8087
+ const cached = octopus3dStableStateCache.get(createRandom);
8088
+ if (cached !== undefined) {
8089
+ return cached;
8090
+ }
8091
+ const animationRandom = createRandom('octopus3d-animation-profile');
8092
+ const eyeRandom = createRandom('octopus3d-eye-profile');
8093
+ const leftEyePhaseOffset = eyeRandom() * 0.6;
8094
+ const rightEyePhaseOffset = eyeRandom() * 0.6;
8095
+ const state = {
8096
+ morphologyProfile: createOctopus3MorphologyProfile(createRandom),
8097
+ animationPhase: animationRandom() * Math.PI * 2,
8098
+ leftEyePhaseOffset,
8099
+ rightEyePhaseOffset,
8100
+ };
8101
+ octopus3dStableStateCache.set(createRandom, state);
8102
+ return state;
8103
+ }
8046
8104
  /**
8047
8105
  * Proper 3D Octopus visual built from projected organic meshes and tentacles.
8048
8106
  *
@@ -8055,10 +8113,7 @@
8055
8113
  isAnimated: true,
8056
8114
  supportsPointerTracking: true,
8057
8115
  render({ context, size, palette, createRandom, timeMs, interaction }) {
8058
- const morphologyProfile = createOctopus3MorphologyProfile(createRandom);
8059
- const animationRandom = createRandom('octopus3d-animation-profile');
8060
- const eyeRandom = createRandom('octopus3d-eye-profile');
8061
- const animationPhase = animationRandom() * Math.PI * 2;
8116
+ const { morphologyProfile, animationPhase, leftEyePhaseOffset, rightEyePhaseOffset } = getOctopus3dStableState(createRandom);
8062
8117
  const sceneCenterX = size * 0.5;
8063
8118
  const sceneCenterY = size * 0.56;
8064
8119
  const bob = Math.sin(timeMs / 920 + animationPhase) * size * 0.014;
@@ -8155,12 +8210,12 @@
8155
8210
  x: -faceEyeSpacing,
8156
8211
  y: faceEyeYOffset,
8157
8212
  z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, -faceEyeSpacing, faceEyeYOffset),
8158
- }, faceEyeRadiusX, faceEyeRadiusY, mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + eyeRandom() * 0.6, interaction, morphologyProfile.face.eyeStyle);
8213
+ }, faceEyeRadiusX, faceEyeRadiusY, mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + leftEyePhaseOffset, interaction, morphologyProfile.face.eyeStyle);
8159
8214
  drawProjectedOrganicEye(context, {
8160
8215
  x: faceEyeSpacing,
8161
8216
  y: faceEyeYOffset,
8162
8217
  z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, faceEyeSpacing, faceEyeYOffset),
8163
- }, faceEyeRadiusX, faceEyeRadiusY, mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + 0.7 + eyeRandom() * 0.6, interaction, morphologyProfile.face.eyeStyle);
8218
+ }, faceEyeRadiusX, faceEyeRadiusY, mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + 0.7 + rightEyePhaseOffset, interaction, morphologyProfile.face.eyeStyle);
8164
8219
  drawProjectedOrganicMouth(context, [
8165
8220
  {
8166
8221
  x: -mouthHalfWidth,
@@ -8204,14 +8259,28 @@
8204
8259
  /**
8205
8260
  * Draws the soft ground shadow below the octopus.
8206
8261
  *
8262
+ * Uses a scaled radial gradient instead of `context.filter = 'blur()'` to approximate the
8263
+ * blurry ellipse without triggering a costly software rasterization pass on every frame.
8264
+ *
8207
8265
  * @private helper of `octopus3dAvatarVisual`
8208
8266
  */
8209
8267
  function drawOctopus3dShadow(context, size, palette, interaction, timeMs) {
8268
+ const cx = size * 0.5 + interaction.gazeX * size * 0.04;
8269
+ const cy = size * 0.87 + Math.sin(timeMs / 920) * size * 0.008;
8270
+ const rx = size * (0.18 + interaction.intensity * 0.02);
8271
+ const ry = size * 0.06;
8210
8272
  context.save();
8211
- context.fillStyle = `${palette.shadow}66`;
8212
- context.filter = `blur(${size * 0.022}px)`;
8273
+ context.translate(cx, cy);
8274
+ context.scale(1, ry / rx);
8275
+ const blurRadius = rx * 1.4;
8276
+ const shadowGradient = context.createRadialGradient(0, 0, 0, 0, 0, blurRadius);
8277
+ shadowGradient.addColorStop(0, `${palette.shadow}7a`);
8278
+ shadowGradient.addColorStop(0.45, `${palette.shadow}44`);
8279
+ shadowGradient.addColorStop(0.8, `${palette.shadow}1a`);
8280
+ shadowGradient.addColorStop(1, `${palette.shadow}00`);
8281
+ context.fillStyle = shadowGradient;
8213
8282
  context.beginPath();
8214
- context.ellipse(size * 0.5 + interaction.gazeX * size * 0.04, size * 0.87 + Math.sin(timeMs / 920) * size * 0.008, size * (0.18 + interaction.intensity * 0.02), size * 0.06, 0, 0, Math.PI * 2);
8283
+ context.arc(0, 0, blurRadius, 0, Math.PI * 2);
8215
8284
  context.fill();
8216
8285
  context.restore();
8217
8286
  }
@@ -8442,6 +8511,35 @@
8442
8511
  y: -0.6,
8443
8512
  z: 0.98,
8444
8513
  });
8514
+ /**
8515
+ * Cache keyed by the `createRandom` factory reference (stable per mounted `<Avatar/>`).
8516
+ *
8517
+ * @private helper of `octopus3d2AvatarVisual`
8518
+ */
8519
+ const octopus3d2StableStateCache = new WeakMap();
8520
+ /**
8521
+ * Returns the stable per-avatar state, computing it on first access and caching for subsequent frames.
8522
+ *
8523
+ * @private helper of `octopus3d2AvatarVisual`
8524
+ */
8525
+ function getOctopus3d2StableState(createRandom) {
8526
+ const cached = octopus3d2StableStateCache.get(createRandom);
8527
+ if (cached !== undefined) {
8528
+ return cached;
8529
+ }
8530
+ const animationRandom = createRandom('octopus3d2-animation-profile');
8531
+ const eyeRandom = createRandom('octopus3d2-eye-profile');
8532
+ const leftEyePhaseOffset = eyeRandom() * 0.7;
8533
+ const rightEyePhaseOffset = eyeRandom() * 0.7;
8534
+ const state = {
8535
+ morphologyProfile: createOctopus3MorphologyProfile(createRandom),
8536
+ animationPhase: animationRandom() * Math.PI * 2,
8537
+ leftEyePhaseOffset,
8538
+ rightEyePhaseOffset,
8539
+ };
8540
+ octopus3d2StableStateCache.set(createRandom, state);
8541
+ return state;
8542
+ }
8445
8543
  /**
8446
8544
  * Octopus 3D 2 avatar visual.
8447
8545
  *
@@ -8454,10 +8552,7 @@
8454
8552
  isAnimated: true,
8455
8553
  supportsPointerTracking: true,
8456
8554
  render({ context, size, palette, createRandom, timeMs, interaction }) {
8457
- const morphologyProfile = createOctopus3MorphologyProfile(createRandom);
8458
- const animationRandom = createRandom('octopus3d2-animation-profile');
8459
- const eyeRandom = createRandom('octopus3d2-eye-profile');
8460
- const animationPhase = animationRandom() * Math.PI * 2;
8555
+ const { morphologyProfile, animationPhase, leftEyePhaseOffset, rightEyePhaseOffset } = getOctopus3d2StableState(createRandom);
8461
8556
  const sceneCenterX = size * 0.5;
8462
8557
  const sceneCenterY = size * 0.575;
8463
8558
  const bob = Math.sin(timeMs / 940 + animationPhase) * size * 0.013;
@@ -8510,8 +8605,8 @@
8510
8605
  const rightEyeLocalCenter = sampleBlobbyOctopusSurfacePoint(surfaceOptions, eyeLatitude, eyeLongitude);
8511
8606
  const eyeRadiusX = size * morphologyProfile.face.eyeRadiusXRatio * 0.78;
8512
8607
  const eyeRadiusY = eyeRadiusX * morphologyProfile.face.eyeHeightRatio * 0.92;
8513
- drawProjectedOrganicEye(context, leftEyeLocalCenter, eyeRadiusX, eyeRadiusY, meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + eyeRandom() * 0.7, interaction, morphologyProfile.face.eyeStyle);
8514
- drawProjectedOrganicEye(context, rightEyeLocalCenter, eyeRadiusX, eyeRadiusY, meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + 0.9 + eyeRandom() * 0.7, interaction, morphologyProfile.face.eyeStyle);
8608
+ drawProjectedOrganicEye(context, leftEyeLocalCenter, eyeRadiusX, eyeRadiusY, meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + leftEyePhaseOffset, interaction, morphologyProfile.face.eyeStyle);
8609
+ drawProjectedOrganicEye(context, rightEyeLocalCenter, eyeRadiusX, eyeRadiusY, meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + 0.9 + rightEyePhaseOffset, interaction, morphologyProfile.face.eyeStyle);
8515
8610
  drawProjectedOrganicMouth(context, [
8516
8611
  sampleBlobbyOctopusSurfacePoint(surfaceOptions, mouthLatitude, mouthCenterLongitude - mouthHalfLongitude),
8517
8612
  sampleBlobbyOctopusSurfacePoint(surfaceOptions, mouthCurveLatitude, mouthCenterLongitude),
@@ -8540,14 +8635,28 @@
8540
8635
  /**
8541
8636
  * Draws the soft floor shadow that anchors the single mesh in the frame.
8542
8637
  *
8638
+ * Uses a scaled radial gradient instead of `context.filter = 'blur()'` to approximate the
8639
+ * blurry ellipse without triggering a costly software rasterization pass on every frame.
8640
+ *
8543
8641
  * @private helper of `octopus3d2AvatarVisual`
8544
8642
  */
8545
8643
  function drawBlobbyOctopusShadow(context, size, palette, interaction, timeMs, morphologyProfile) {
8644
+ const cx = size * 0.5 + interaction.gazeX * size * 0.045;
8645
+ const cy = size * 0.88 + Math.sin(timeMs / 940) * size * 0.008;
8646
+ const rx = size * (0.18 + (morphologyProfile.body.horizontalStretch - 1) * 0.04 + interaction.intensity * 0.018);
8647
+ const ry = size * 0.062;
8546
8648
  context.save();
8547
- context.fillStyle = `${palette.shadow}66`;
8548
- context.filter = `blur(${size * 0.024}px)`;
8649
+ context.translate(cx, cy);
8650
+ context.scale(1, ry / rx);
8651
+ const blurRadius = rx * 1.4;
8652
+ const shadowGradient = context.createRadialGradient(0, 0, 0, 0, 0, blurRadius);
8653
+ shadowGradient.addColorStop(0, `${palette.shadow}7a`);
8654
+ shadowGradient.addColorStop(0.45, `${palette.shadow}44`);
8655
+ shadowGradient.addColorStop(0.8, `${palette.shadow}1a`);
8656
+ shadowGradient.addColorStop(1, `${palette.shadow}00`);
8657
+ context.fillStyle = shadowGradient;
8549
8658
  context.beginPath();
8550
- 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);
8659
+ context.arc(0, 0, blurRadius, 0, Math.PI * 2);
8551
8660
  context.fill();
8552
8661
  context.restore();
8553
8662
  }
@@ -8703,6 +8812,40 @@
8703
8812
  * @private helper of `octopus3d3AvatarVisual`
8704
8813
  */
8705
8814
  const OCTOPUS_TENTACLE_COUNT = 8;
8815
+ /**
8816
+ * Cache keyed by the `createRandom` factory reference, which is stable for the lifetime of one
8817
+ * mounted `<Avatar/>` component (created inside `resolveAvatarRenderDefinition` and held in a
8818
+ * React `useMemo`). Using a `WeakMap` ensures the entry is collected when the component unmounts.
8819
+ *
8820
+ * @private helper of `octopus3d3AvatarVisual`
8821
+ */
8822
+ const stableStateCache = new WeakMap();
8823
+ /**
8824
+ * Returns the stable per-avatar state, computing it on first access and returning the cached
8825
+ * result on every subsequent call within the same `<Avatar/>` mount.
8826
+ *
8827
+ * @private helper of `octopus3d3AvatarVisual`
8828
+ */
8829
+ function getOctopus3d3StableState(createRandom) {
8830
+ const cached = stableStateCache.get(createRandom);
8831
+ if (cached !== undefined) {
8832
+ return cached;
8833
+ }
8834
+ const morphologyProfile = createOctopus3MorphologyProfile(createRandom);
8835
+ const animationRandom = createRandom('octopus3d3-animation-profile');
8836
+ const eyeRandom = createRandom('octopus3d3-eye-profile');
8837
+ const leftEyePhaseOffset = eyeRandom() * 0.7;
8838
+ const rightEyePhaseOffset = eyeRandom() * 0.7;
8839
+ const state = {
8840
+ morphologyProfile,
8841
+ animationPhase: animationRandom() * Math.PI * 2,
8842
+ leftEyePhaseOffset,
8843
+ rightEyePhaseOffset,
8844
+ tentacleProfiles: createContinuousTentacleProfiles(createRandom, morphologyProfile),
8845
+ };
8846
+ stableStateCache.set(createRandom, state);
8847
+ return state;
8848
+ }
8706
8849
  /**
8707
8850
  * Octopus 3D 3 avatar visual.
8708
8851
  *
@@ -8715,11 +8858,7 @@
8715
8858
  isAnimated: true,
8716
8859
  supportsPointerTracking: true,
8717
8860
  render({ context, size, palette, createRandom, timeMs, interaction }) {
8718
- const morphologyProfile = createOctopus3MorphologyProfile(createRandom);
8719
- const animationRandom = createRandom('octopus3d3-animation-profile');
8720
- const eyeRandom = createRandom('octopus3d3-eye-profile');
8721
- const animationPhase = animationRandom() * Math.PI * 2;
8722
- const tentacleProfiles = createContinuousTentacleProfiles(createRandom, morphologyProfile);
8861
+ const { morphologyProfile, animationPhase, leftEyePhaseOffset, rightEyePhaseOffset, tentacleProfiles } = getOctopus3d3StableState(createRandom);
8723
8862
  const sceneCenterX = size * 0.5;
8724
8863
  const sceneCenterY = size * 0.535;
8725
8864
  const bob = Math.sin(timeMs / 960 + animationPhase) * size * 0.012;
@@ -8796,8 +8935,8 @@
8796
8935
  size,
8797
8936
  palette,
8798
8937
  });
8799
- drawProjectedOrganicEye(context, sampleContinuousOctopusSurfacePoint(surfaceOptions, eyeLatitude, -eyeLongitude), eyeRadiusX, eyeRadiusY, meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + eyeRandom() * 0.7, interaction, morphologyProfile.face.eyeStyle);
8800
- drawProjectedOrganicEye(context, sampleContinuousOctopusSurfacePoint(surfaceOptions, eyeLatitude, eyeLongitude), eyeRadiusX, eyeRadiusY, meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + 0.85 + eyeRandom() * 0.7, interaction, morphologyProfile.face.eyeStyle);
8938
+ drawProjectedOrganicEye(context, sampleContinuousOctopusSurfacePoint(surfaceOptions, eyeLatitude, -eyeLongitude), eyeRadiusX, eyeRadiusY, meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + leftEyePhaseOffset, interaction, morphologyProfile.face.eyeStyle);
8939
+ drawProjectedOrganicEye(context, sampleContinuousOctopusSurfacePoint(surfaceOptions, eyeLatitude, eyeLongitude), eyeRadiusX, eyeRadiusY, meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + 0.85 + rightEyePhaseOffset, interaction, morphologyProfile.face.eyeStyle);
8801
8940
  drawProjectedOrganicMouth(context, [
8802
8941
  sampleContinuousOctopusSurfacePoint(surfaceOptions, mouthLatitude, mouthCenterLongitude - mouthHalfLongitude),
8803
8942
  sampleContinuousOctopusSurfacePoint(surfaceOptions, mouthCurveLatitude, mouthCenterLongitude),
@@ -8848,14 +8987,30 @@
8848
8987
  /**
8849
8988
  * Draws the soft lower shadow that anchors the octopus in the avatar frame.
8850
8989
  *
8990
+ * Uses a scaled radial gradient instead of `context.filter = 'blur()'` to approximate the
8991
+ * blurry ellipse without triggering a costly software rasterization pass on every frame.
8992
+ *
8851
8993
  * @private helper of `octopus3d3AvatarVisual`
8852
8994
  */
8853
8995
  function drawContinuousOctopusShadow(context, size, palette, interaction, timeMs, morphologyProfile) {
8996
+ const cx = size * 0.5 + interaction.gazeX * size * 0.045;
8997
+ const cy = size * 0.9 + Math.sin(timeMs / 980) * size * 0.007;
8998
+ const rx = size * (0.19 + morphologyProfile.tentacles.rootSpreadScale * 0.022 + interaction.intensity * 0.02);
8999
+ const ry = size * 0.06;
9000
+ // Scale the context so that drawing a circle produces the correct ellipse aspect ratio,
9001
+ // then fill with a radial gradient that approximates the blurry edge without context.filter.
8854
9002
  context.save();
8855
- context.fillStyle = `${palette.shadow}66`;
8856
- context.filter = `blur(${size * 0.025}px)`;
9003
+ context.translate(cx, cy);
9004
+ context.scale(1, ry / rx);
9005
+ const blurRadius = rx * 1.4;
9006
+ const shadowGradient = context.createRadialGradient(0, 0, 0, 0, 0, blurRadius);
9007
+ shadowGradient.addColorStop(0, `${palette.shadow}7a`);
9008
+ shadowGradient.addColorStop(0.45, `${palette.shadow}44`);
9009
+ shadowGradient.addColorStop(0.8, `${palette.shadow}1a`);
9010
+ shadowGradient.addColorStop(1, `${palette.shadow}00`);
9011
+ context.fillStyle = shadowGradient;
8857
9012
  context.beginPath();
8858
- context.ellipse(size * 0.5 + interaction.gazeX * size * 0.045, size * 0.9 + Math.sin(timeMs / 980) * size * 0.007, size * (0.19 + morphologyProfile.tentacles.rootSpreadScale * 0.022 + interaction.intensity * 0.02), size * 0.06, 0, 0, Math.PI * 2);
9013
+ context.arc(0, 0, blurRadius, 0, Math.PI * 2);
8859
9014
  context.fill();
8860
9015
  context.restore();
8861
9016
  }
@@ -17460,7 +17615,7 @@
17460
17615
  * @private internal helper function
17461
17616
  */
17462
17617
  function $randomToken(randomness) {
17463
- return crypto.randomBytes(randomness).toString('hex');
17618
+ return CryptoJS__default["default"].lib.WordArray.random(randomness).toString(CryptoJS__default["default"].enc.Hex);
17464
17619
  }
17465
17620
  // TODO: [🤶] Maybe export through `@promptbook/utils` or `@promptbook/random` package
17466
17621
  // TODO: Maybe use nanoid instead https://github.com/ai/nanoid
@@ -25354,7 +25509,7 @@
25354
25509
  * @public exported from `@promptbook/editable`
25355
25510
  */
25356
25511
  function knowledgeSourceContentToName(knowledgeSourceContent) {
25357
- const hash = cryptoJs.SHA256(hexEncoder__default["default"].parse(JSON.stringify(knowledgeSourceContent)))
25512
+ const hash = CryptoJS__default["default"].SHA256(hexEncoder__default["default"].parse(JSON.stringify(knowledgeSourceContent)))
25358
25513
  // <- TODO: [🥬] Encapsulate sha256 to some private utility function
25359
25514
  .toString( /* hex */)
25360
25515
  .substring(0, 20);
@@ -26202,7 +26357,7 @@
26202
26357
  console.warn('CSV string contains carriage return characters, but in the CSV settings the `newline` setting does not include them. Autohealing the CSV string.');
26203
26358
  value = value.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
26204
26359
  }
26205
- const csv = papaparse.parse(value, settings);
26360
+ const csv = papaparse__default["default"].parse(value, settings);
26206
26361
  return csv;
26207
26362
  }
26208
26363
 
@@ -26287,10 +26442,10 @@
26287
26442
  i > index ? { ...row, [outputParameterName]: PENDING_VALUE_PLACEHOLDER } : row,
26288
26443
  );
26289
26444
  */
26290
- await onProgress(papaparse.unparse(mappedData, { ...settings, ...MANDATORY_CSV_SETTINGS }));
26445
+ await onProgress(papaparse__default["default"].unparse(mappedData, { ...settings, ...MANDATORY_CSV_SETTINGS }));
26291
26446
  }
26292
26447
  }
26293
- return papaparse.unparse(mappedData, { ...settings, ...MANDATORY_CSV_SETTINGS });
26448
+ return papaparse__default["default"].unparse(mappedData, { ...settings, ...MANDATORY_CSV_SETTINGS });
26294
26449
  },
26295
26450
  },
26296
26451
  {
@@ -26318,7 +26473,7 @@
26318
26473
  return /* not await */ mapCallback({ [key]: value }, index, array.length);
26319
26474
  }));
26320
26475
  }));
26321
- return papaparse.unparse(mappedData, { ...settings, ...MANDATORY_CSV_SETTINGS });
26476
+ return papaparse__default["default"].unparse(mappedData, { ...settings, ...MANDATORY_CSV_SETTINGS });
26322
26477
  },
26323
26478
  },
26324
26479
  ],
@@ -35023,7 +35178,7 @@
35023
35178
  * Computes one stable hash from a JSON-serializable value.
35024
35179
  */
35025
35180
  function computeJsonHash$1(value) {
35026
- return cryptoJs.SHA256(JSON.stringify(value)).toString();
35181
+ return CryptoJS__default["default"].SHA256(JSON.stringify(value)).toString();
35027
35182
  }
35028
35183
  /**
35029
35184
  * Handles OpenAI AgentKit-backed executions for `AgentLlmExecutionTools`.
@@ -35181,7 +35336,7 @@
35181
35336
  * Computes one stable hash from a JSON-serializable value.
35182
35337
  */
35183
35338
  function computeJsonHash(value) {
35184
- return cryptoJs.SHA256(JSON.stringify(value)).toString();
35339
+ return CryptoJS__default["default"].SHA256(JSON.stringify(value)).toString();
35185
35340
  }
35186
35341
  /**
35187
35342
  * Removes assistant-managed requirements before the prompt is executed via OpenAI Assistants.
@@ -36037,7 +36192,7 @@
36037
36192
  * Returns a virtual model name representing the agent behavior.
36038
36193
  */
36039
36194
  get modelName() {
36040
- const hash = cryptoJs.SHA256(hexEncoder__default["default"].parse(this.options.agentSource)).toString( /* hex */);
36195
+ const hash = CryptoJS__default["default"].SHA256(hexEncoder__default["default"].parse(this.options.agentSource)).toString( /* hex */);
36041
36196
  const agentId = hash.substring(0, 10);
36042
36197
  return (normalizeToKebabCase(this.title) + '-' + agentId);
36043
36198
  }