@promptbook/remote-server 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 +211 -59
  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 +215 -59
  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/esm/index.es.js CHANGED
@@ -9,19 +9,18 @@ import { Server } from 'socket.io';
9
9
  import { stat, access, constants, readFile, writeFile, readdir, mkdir, watch, rm } from 'fs/promises';
10
10
  import { Readability } from '@mozilla/readability';
11
11
  import { JSDOM } from 'jsdom';
12
- import { SHA256 } from 'crypto-js';
12
+ import CryptoJS from 'crypto-js';
13
13
  import hexEncoder from 'crypto-js/enc-hex';
14
- import { Converter } from 'showdown';
14
+ import showdown from 'showdown';
15
15
  import * as OpenApiValidator from 'express-openapi-validator';
16
16
  import swaggerUi from 'swagger-ui-express';
17
17
  import { createElement } from 'react';
18
18
  import { renderToStaticMarkup } from 'react-dom/server';
19
19
  import { Subject, BehaviorSubject } from 'rxjs';
20
- import { randomBytes } from 'crypto';
21
20
  import moment from 'moment';
22
21
  import { lookup, extension } from 'mime-types';
23
22
  import sha256 from 'crypto-js/sha256';
24
- import { parse, unparse } from 'papaparse';
23
+ import papaparse from 'papaparse';
25
24
  import { fileSearchTool, tool, Agent as Agent$1, webSearchTool, run, setDefaultOpenAIClient, setDefaultOpenAIKey } from '@openai/agents';
26
25
  import Bottleneck from 'bottleneck';
27
26
  import OpenAI from 'openai';
@@ -40,7 +39,7 @@ const BOOK_LANGUAGE_VERSION = '2.0.0';
40
39
  * @generated
41
40
  * @see https://github.com/webgptorg/promptbook
42
41
  */
43
- const PROMPTBOOK_ENGINE_VERSION = '0.112.0-115';
42
+ const PROMPTBOOK_ENGINE_VERSION = '0.112.0-118';
44
43
  /**
45
44
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
46
45
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -1948,7 +1947,7 @@ class ParseError extends Error {
1948
1947
  * @private internal helper function
1949
1948
  */
1950
1949
  function $randomToken(randomness) {
1951
- return randomBytes(randomness).toString('hex');
1950
+ return CryptoJS.lib.WordArray.random(randomness).toString(CryptoJS.enc.Hex);
1952
1951
  }
1953
1952
  // TODO: [🤶] Maybe export through `@promptbook/utils` or `@promptbook/random` package
1954
1953
  // TODO: Maybe use nanoid instead https://github.com/ai/nanoid
@@ -5492,7 +5491,7 @@ function normalizeToKebabCase(text) {
5492
5491
  * @public exported from `@promptbook/editable`
5493
5492
  */
5494
5493
  function knowledgeSourceContentToName(knowledgeSourceContent) {
5495
- const hash = SHA256(hexEncoder.parse(JSON.stringify(knowledgeSourceContent)))
5494
+ const hash = CryptoJS.SHA256(hexEncoder.parse(JSON.stringify(knowledgeSourceContent)))
5496
5495
  // <- TODO: [🥬] Encapsulate sha256 to some private utility function
5497
5496
  .toString( /* hex */)
5498
5497
  .substring(0, 20);
@@ -6486,7 +6485,7 @@ function csvParse(value /* <- TODO: string_csv */, settings, schema /* <- TODO:
6486
6485
  console.warn('CSV string contains carriage return characters, but in the CSV settings the `newline` setting does not include them. Autohealing the CSV string.');
6487
6486
  value = value.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
6488
6487
  }
6489
- const csv = parse(value, settings);
6488
+ const csv = papaparse.parse(value, settings);
6490
6489
  return csv;
6491
6490
  }
6492
6491
 
@@ -6571,10 +6570,10 @@ const CsvFormatParser = {
6571
6570
  i > index ? { ...row, [outputParameterName]: PENDING_VALUE_PLACEHOLDER } : row,
6572
6571
  );
6573
6572
  */
6574
- await onProgress(unparse(mappedData, { ...settings, ...MANDATORY_CSV_SETTINGS }));
6573
+ await onProgress(papaparse.unparse(mappedData, { ...settings, ...MANDATORY_CSV_SETTINGS }));
6575
6574
  }
6576
6575
  }
6577
- return unparse(mappedData, { ...settings, ...MANDATORY_CSV_SETTINGS });
6576
+ return papaparse.unparse(mappedData, { ...settings, ...MANDATORY_CSV_SETTINGS });
6578
6577
  },
6579
6578
  },
6580
6579
  {
@@ -6602,7 +6601,7 @@ const CsvFormatParser = {
6602
6601
  return /* not await */ mapCallback({ [key]: value }, index, array.length);
6603
6602
  }));
6604
6603
  }));
6605
- return unparse(mappedData, { ...settings, ...MANDATORY_CSV_SETTINGS });
6604
+ return papaparse.unparse(mappedData, { ...settings, ...MANDATORY_CSV_SETTINGS });
6606
6605
  },
6607
6606
  },
6608
6607
  ],
@@ -9531,7 +9530,7 @@ async function getScraperIntermediateSource(source, options) {
9531
9530
  const { filename: sourceFilename, url } = source;
9532
9531
  const { rootDirname, cacheDirname, intermediateFilesStrategy, extension, isVerbose } = options;
9533
9532
  // TODO: [👬] DRY
9534
- const hash = SHA256(
9533
+ const hash = CryptoJS.SHA256(
9535
9534
  // <- TODO: [🥬] Encapsulate sha256 to some private utility function
9536
9535
  hexEncoder.parse(sourceFilename || url || 'untitled'))
9537
9536
  .toString( /* hex */)
@@ -9622,7 +9621,7 @@ $scrapersMetadataRegister.register(websiteScraperMetadata);
9622
9621
  * @private utility of `WebsiteScraper`
9623
9622
  */
9624
9623
  function createShowdownConverter() {
9625
- return new Converter({
9624
+ return new showdown.Converter({
9626
9625
  flavor: 'github',
9627
9626
  /*
9628
9627
  > import showdownHighlight from 'showdown-highlight';
@@ -10814,7 +10813,7 @@ function normalizeWhitespaces(sentence) {
10814
10813
  * @public exported from `@promptbook/utils`
10815
10814
  */
10816
10815
  function computeHash(value) {
10817
- return SHA256(hexEncoder.parse(spaceTrim$1(valueToString(value)))).toString( /* hex */);
10816
+ return CryptoJS.SHA256(hexEncoder.parse(spaceTrim$1(valueToString(value)))).toString( /* hex */);
10818
10817
  }
10819
10818
  // TODO: [🥬][🥬] Use this ACRY
10820
10819
 
@@ -14240,21 +14239,22 @@ function getPointBounds(points) {
14240
14239
  * @private helper of `fractalAvatarVisual`
14241
14240
  */
14242
14241
  function drawDragonCurveLayer(context, points, options) {
14243
- const { size, primaryColor, secondaryColor, tertiaryColor, shadowColor, strokeWidth, timeMs, layerIndex } = options;
14242
+ const { primaryColor, secondaryColor, tertiaryColor, shadowColor, strokeWidth, timeMs, layerIndex } = options;
14244
14243
  const firstPoint = points[0];
14245
14244
  const lastPoint = points[points.length - 1];
14246
14245
  const ribbonGradient = context.createLinearGradient(firstPoint.x, firstPoint.y, lastPoint.x, lastPoint.y);
14247
14246
  ribbonGradient.addColorStop(0, `${primaryColor}f2`);
14248
14247
  ribbonGradient.addColorStop(0.5, `${secondaryColor}e6`);
14249
14248
  ribbonGradient.addColorStop(1, `${tertiaryColor}f2`);
14249
+ // Approximate the blurred shadow stroke with a wider semi-transparent stroke instead of
14250
+ // context.filter blur, which triggers a costly software rasterization pass every frame.
14250
14251
  context.save();
14251
14252
  context.beginPath();
14252
14253
  tracePolyline(context, points);
14253
- context.strokeStyle = `${shadowColor}82`;
14254
- context.lineWidth = strokeWidth * 1.8;
14254
+ context.strokeStyle = `${shadowColor}48`;
14255
+ context.lineWidth = strokeWidth * 4.5;
14255
14256
  context.lineJoin = 'round';
14256
14257
  context.lineCap = 'round';
14257
- context.filter = `blur(${size * 0.022}px)`;
14258
14258
  context.stroke();
14259
14259
  context.restore();
14260
14260
  context.beginPath();
@@ -14838,11 +14838,23 @@ function drawMinecraftBackdrop(context, size, palette, sceneCenterX, spotlightY,
14838
14838
  * @private helper of `minecraft2AvatarVisual`
14839
14839
  */
14840
14840
  function drawMinecraftShadow(context, size, palette, interaction, timeMs) {
14841
+ const cx = size * 0.5 + interaction.gazeX * size * 0.03;
14842
+ const cy = size * 0.85 + Math.sin(timeMs / 880) * size * 0.01;
14843
+ const rx = size * (0.16 + interaction.intensity * 0.015);
14844
+ const ry = size * 0.055;
14845
+ // Radial gradient approximates the blurry ellipse shadow without context.filter blur.
14841
14846
  context.save();
14842
- context.fillStyle = `${palette.shadow}66`;
14843
- context.filter = `blur(${size * 0.02}px)`;
14847
+ context.translate(cx, cy);
14848
+ context.scale(1, ry / rx);
14849
+ const blurRadius = rx * 1.4;
14850
+ const shadowGradient = context.createRadialGradient(0, 0, 0, 0, 0, blurRadius);
14851
+ shadowGradient.addColorStop(0, `${palette.shadow}7a`);
14852
+ shadowGradient.addColorStop(0.45, `${palette.shadow}44`);
14853
+ shadowGradient.addColorStop(0.8, `${palette.shadow}1a`);
14854
+ shadowGradient.addColorStop(1, `${palette.shadow}00`);
14855
+ context.fillStyle = shadowGradient;
14844
14856
  context.beginPath();
14845
- 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);
14857
+ context.arc(0, 0, blurRadius, 0, Math.PI * 2);
14846
14858
  context.fill();
14847
14859
  context.restore();
14848
14860
  }
@@ -15066,13 +15078,27 @@ const minecraftAvatarVisual = {
15066
15078
  spotlight.addColorStop(1, `${palette.highlight}00`);
15067
15079
  context.fillStyle = spotlight;
15068
15080
  context.fillRect(0, 0, size, size);
15069
- context.save();
15070
- context.fillStyle = 'rgba(0, 0, 0, 0.22)';
15071
- context.filter = `blur(${size * 0.018}px)`;
15072
- context.beginPath();
15073
- context.ellipse(size * 0.5, size * 0.86, size * 0.2, size * 0.06, 0, 0, Math.PI * 2);
15074
- context.fill();
15075
- context.restore();
15081
+ {
15082
+ // Radial gradient approximates the blurry ellipse shadow without context.filter blur.
15083
+ const cx = size * 0.5;
15084
+ const cy = size * 0.86;
15085
+ const rx = size * 0.2;
15086
+ const ry = size * 0.06;
15087
+ const blurRadius = rx * 1.4;
15088
+ const shadowGradient = context.createRadialGradient(0, 0, 0, 0, 0, blurRadius);
15089
+ shadowGradient.addColorStop(0, 'rgba(0,0,0,0.28)');
15090
+ shadowGradient.addColorStop(0.45, 'rgba(0,0,0,0.14)');
15091
+ shadowGradient.addColorStop(0.8, 'rgba(0,0,0,0.05)');
15092
+ shadowGradient.addColorStop(1, 'rgba(0,0,0,0)');
15093
+ context.save();
15094
+ context.translate(cx, cy);
15095
+ context.scale(1, ry / rx);
15096
+ context.fillStyle = shadowGradient;
15097
+ context.beginPath();
15098
+ context.arc(0, 0, blurRadius, 0, Math.PI * 2);
15099
+ context.fill();
15100
+ context.restore();
15101
+ }
15076
15102
  drawVoxelCuboid(context, {
15077
15103
  x: bodyX,
15078
15104
  y: bodyY,
@@ -16124,6 +16150,35 @@ const LIGHT_DIRECTION$2 = normalizeVector3({
16124
16150
  y: -0.62,
16125
16151
  z: 0.94,
16126
16152
  });
16153
+ /**
16154
+ * Cache keyed by the `createRandom` factory reference (stable per mounted `<Avatar/>`).
16155
+ *
16156
+ * @private helper of `octopus3dAvatarVisual`
16157
+ */
16158
+ const octopus3dStableStateCache = new WeakMap();
16159
+ /**
16160
+ * Returns the stable per-avatar state, computing it on first access and caching for subsequent frames.
16161
+ *
16162
+ * @private helper of `octopus3dAvatarVisual`
16163
+ */
16164
+ function getOctopus3dStableState(createRandom) {
16165
+ const cached = octopus3dStableStateCache.get(createRandom);
16166
+ if (cached !== undefined) {
16167
+ return cached;
16168
+ }
16169
+ const animationRandom = createRandom('octopus3d-animation-profile');
16170
+ const eyeRandom = createRandom('octopus3d-eye-profile');
16171
+ const leftEyePhaseOffset = eyeRandom() * 0.6;
16172
+ const rightEyePhaseOffset = eyeRandom() * 0.6;
16173
+ const state = {
16174
+ morphologyProfile: createOctopus3MorphologyProfile(createRandom),
16175
+ animationPhase: animationRandom() * Math.PI * 2,
16176
+ leftEyePhaseOffset,
16177
+ rightEyePhaseOffset,
16178
+ };
16179
+ octopus3dStableStateCache.set(createRandom, state);
16180
+ return state;
16181
+ }
16127
16182
  /**
16128
16183
  * Proper 3D Octopus visual built from projected organic meshes and tentacles.
16129
16184
  *
@@ -16136,10 +16191,7 @@ const octopus3dAvatarVisual = {
16136
16191
  isAnimated: true,
16137
16192
  supportsPointerTracking: true,
16138
16193
  render({ context, size, palette, createRandom, timeMs, interaction }) {
16139
- const morphologyProfile = createOctopus3MorphologyProfile(createRandom);
16140
- const animationRandom = createRandom('octopus3d-animation-profile');
16141
- const eyeRandom = createRandom('octopus3d-eye-profile');
16142
- const animationPhase = animationRandom() * Math.PI * 2;
16194
+ const { morphologyProfile, animationPhase, leftEyePhaseOffset, rightEyePhaseOffset } = getOctopus3dStableState(createRandom);
16143
16195
  const sceneCenterX = size * 0.5;
16144
16196
  const sceneCenterY = size * 0.56;
16145
16197
  const bob = Math.sin(timeMs / 920 + animationPhase) * size * 0.014;
@@ -16236,12 +16288,12 @@ const octopus3dAvatarVisual = {
16236
16288
  x: -faceEyeSpacing,
16237
16289
  y: faceEyeYOffset,
16238
16290
  z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, -faceEyeSpacing, faceEyeYOffset),
16239
- }, faceEyeRadiusX, faceEyeRadiusY, mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + eyeRandom() * 0.6, interaction, morphologyProfile.face.eyeStyle);
16291
+ }, faceEyeRadiusX, faceEyeRadiusY, mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + leftEyePhaseOffset, interaction, morphologyProfile.face.eyeStyle);
16240
16292
  drawProjectedOrganicEye(context, {
16241
16293
  x: faceEyeSpacing,
16242
16294
  y: faceEyeYOffset,
16243
16295
  z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, faceEyeSpacing, faceEyeYOffset),
16244
- }, faceEyeRadiusX, faceEyeRadiusY, mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + 0.7 + eyeRandom() * 0.6, interaction, morphologyProfile.face.eyeStyle);
16296
+ }, faceEyeRadiusX, faceEyeRadiusY, mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + 0.7 + rightEyePhaseOffset, interaction, morphologyProfile.face.eyeStyle);
16245
16297
  drawProjectedOrganicMouth(context, [
16246
16298
  {
16247
16299
  x: -mouthHalfWidth,
@@ -16285,14 +16337,28 @@ function drawOctopus3dAtmosphere(context, size, palette, sceneCenterX, sceneCent
16285
16337
  /**
16286
16338
  * Draws the soft ground shadow below the octopus.
16287
16339
  *
16340
+ * Uses a scaled radial gradient instead of `context.filter = 'blur()'` to approximate the
16341
+ * blurry ellipse without triggering a costly software rasterization pass on every frame.
16342
+ *
16288
16343
  * @private helper of `octopus3dAvatarVisual`
16289
16344
  */
16290
16345
  function drawOctopus3dShadow(context, size, palette, interaction, timeMs) {
16346
+ const cx = size * 0.5 + interaction.gazeX * size * 0.04;
16347
+ const cy = size * 0.87 + Math.sin(timeMs / 920) * size * 0.008;
16348
+ const rx = size * (0.18 + interaction.intensity * 0.02);
16349
+ const ry = size * 0.06;
16291
16350
  context.save();
16292
- context.fillStyle = `${palette.shadow}66`;
16293
- context.filter = `blur(${size * 0.022}px)`;
16351
+ context.translate(cx, cy);
16352
+ context.scale(1, ry / rx);
16353
+ const blurRadius = rx * 1.4;
16354
+ const shadowGradient = context.createRadialGradient(0, 0, 0, 0, 0, blurRadius);
16355
+ shadowGradient.addColorStop(0, `${palette.shadow}7a`);
16356
+ shadowGradient.addColorStop(0.45, `${palette.shadow}44`);
16357
+ shadowGradient.addColorStop(0.8, `${palette.shadow}1a`);
16358
+ shadowGradient.addColorStop(1, `${palette.shadow}00`);
16359
+ context.fillStyle = shadowGradient;
16294
16360
  context.beginPath();
16295
- 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);
16361
+ context.arc(0, 0, blurRadius, 0, Math.PI * 2);
16296
16362
  context.fill();
16297
16363
  context.restore();
16298
16364
  }
@@ -16523,6 +16589,35 @@ const LIGHT_DIRECTION$1 = normalizeVector3({
16523
16589
  y: -0.6,
16524
16590
  z: 0.98,
16525
16591
  });
16592
+ /**
16593
+ * Cache keyed by the `createRandom` factory reference (stable per mounted `<Avatar/>`).
16594
+ *
16595
+ * @private helper of `octopus3d2AvatarVisual`
16596
+ */
16597
+ const octopus3d2StableStateCache = new WeakMap();
16598
+ /**
16599
+ * Returns the stable per-avatar state, computing it on first access and caching for subsequent frames.
16600
+ *
16601
+ * @private helper of `octopus3d2AvatarVisual`
16602
+ */
16603
+ function getOctopus3d2StableState(createRandom) {
16604
+ const cached = octopus3d2StableStateCache.get(createRandom);
16605
+ if (cached !== undefined) {
16606
+ return cached;
16607
+ }
16608
+ const animationRandom = createRandom('octopus3d2-animation-profile');
16609
+ const eyeRandom = createRandom('octopus3d2-eye-profile');
16610
+ const leftEyePhaseOffset = eyeRandom() * 0.7;
16611
+ const rightEyePhaseOffset = eyeRandom() * 0.7;
16612
+ const state = {
16613
+ morphologyProfile: createOctopus3MorphologyProfile(createRandom),
16614
+ animationPhase: animationRandom() * Math.PI * 2,
16615
+ leftEyePhaseOffset,
16616
+ rightEyePhaseOffset,
16617
+ };
16618
+ octopus3d2StableStateCache.set(createRandom, state);
16619
+ return state;
16620
+ }
16526
16621
  /**
16527
16622
  * Octopus 3D 2 avatar visual.
16528
16623
  *
@@ -16535,10 +16630,7 @@ const octopus3d2AvatarVisual = {
16535
16630
  isAnimated: true,
16536
16631
  supportsPointerTracking: true,
16537
16632
  render({ context, size, palette, createRandom, timeMs, interaction }) {
16538
- const morphologyProfile = createOctopus3MorphologyProfile(createRandom);
16539
- const animationRandom = createRandom('octopus3d2-animation-profile');
16540
- const eyeRandom = createRandom('octopus3d2-eye-profile');
16541
- const animationPhase = animationRandom() * Math.PI * 2;
16633
+ const { morphologyProfile, animationPhase, leftEyePhaseOffset, rightEyePhaseOffset } = getOctopus3d2StableState(createRandom);
16542
16634
  const sceneCenterX = size * 0.5;
16543
16635
  const sceneCenterY = size * 0.575;
16544
16636
  const bob = Math.sin(timeMs / 940 + animationPhase) * size * 0.013;
@@ -16591,8 +16683,8 @@ const octopus3d2AvatarVisual = {
16591
16683
  const rightEyeLocalCenter = sampleBlobbyOctopusSurfacePoint(surfaceOptions, eyeLatitude, eyeLongitude);
16592
16684
  const eyeRadiusX = size * morphologyProfile.face.eyeRadiusXRatio * 0.78;
16593
16685
  const eyeRadiusY = eyeRadiusX * morphologyProfile.face.eyeHeightRatio * 0.92;
16594
- drawProjectedOrganicEye(context, leftEyeLocalCenter, eyeRadiusX, eyeRadiusY, meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + eyeRandom() * 0.7, interaction, morphologyProfile.face.eyeStyle);
16595
- drawProjectedOrganicEye(context, rightEyeLocalCenter, eyeRadiusX, eyeRadiusY, meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + 0.9 + eyeRandom() * 0.7, interaction, morphologyProfile.face.eyeStyle);
16686
+ drawProjectedOrganicEye(context, leftEyeLocalCenter, eyeRadiusX, eyeRadiusY, meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + leftEyePhaseOffset, interaction, morphologyProfile.face.eyeStyle);
16687
+ drawProjectedOrganicEye(context, rightEyeLocalCenter, eyeRadiusX, eyeRadiusY, meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + 0.9 + rightEyePhaseOffset, interaction, morphologyProfile.face.eyeStyle);
16596
16688
  drawProjectedOrganicMouth(context, [
16597
16689
  sampleBlobbyOctopusSurfacePoint(surfaceOptions, mouthLatitude, mouthCenterLongitude - mouthHalfLongitude),
16598
16690
  sampleBlobbyOctopusSurfacePoint(surfaceOptions, mouthCurveLatitude, mouthCenterLongitude),
@@ -16621,14 +16713,28 @@ function drawBlobbyOctopusAtmosphere(context, size, palette, sceneCenterX, scene
16621
16713
  /**
16622
16714
  * Draws the soft floor shadow that anchors the single mesh in the frame.
16623
16715
  *
16716
+ * Uses a scaled radial gradient instead of `context.filter = 'blur()'` to approximate the
16717
+ * blurry ellipse without triggering a costly software rasterization pass on every frame.
16718
+ *
16624
16719
  * @private helper of `octopus3d2AvatarVisual`
16625
16720
  */
16626
16721
  function drawBlobbyOctopusShadow(context, size, palette, interaction, timeMs, morphologyProfile) {
16722
+ const cx = size * 0.5 + interaction.gazeX * size * 0.045;
16723
+ const cy = size * 0.88 + Math.sin(timeMs / 940) * size * 0.008;
16724
+ const rx = size * (0.18 + (morphologyProfile.body.horizontalStretch - 1) * 0.04 + interaction.intensity * 0.018);
16725
+ const ry = size * 0.062;
16627
16726
  context.save();
16628
- context.fillStyle = `${palette.shadow}66`;
16629
- context.filter = `blur(${size * 0.024}px)`;
16727
+ context.translate(cx, cy);
16728
+ context.scale(1, ry / rx);
16729
+ const blurRadius = rx * 1.4;
16730
+ const shadowGradient = context.createRadialGradient(0, 0, 0, 0, 0, blurRadius);
16731
+ shadowGradient.addColorStop(0, `${palette.shadow}7a`);
16732
+ shadowGradient.addColorStop(0.45, `${palette.shadow}44`);
16733
+ shadowGradient.addColorStop(0.8, `${palette.shadow}1a`);
16734
+ shadowGradient.addColorStop(1, `${palette.shadow}00`);
16735
+ context.fillStyle = shadowGradient;
16630
16736
  context.beginPath();
16631
- 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);
16737
+ context.arc(0, 0, blurRadius, 0, Math.PI * 2);
16632
16738
  context.fill();
16633
16739
  context.restore();
16634
16740
  }
@@ -16784,6 +16890,40 @@ const LIGHT_DIRECTION = normalizeVector3({
16784
16890
  * @private helper of `octopus3d3AvatarVisual`
16785
16891
  */
16786
16892
  const OCTOPUS_TENTACLE_COUNT = 8;
16893
+ /**
16894
+ * Cache keyed by the `createRandom` factory reference, which is stable for the lifetime of one
16895
+ * mounted `<Avatar/>` component (created inside `resolveAvatarRenderDefinition` and held in a
16896
+ * React `useMemo`). Using a `WeakMap` ensures the entry is collected when the component unmounts.
16897
+ *
16898
+ * @private helper of `octopus3d3AvatarVisual`
16899
+ */
16900
+ const stableStateCache = new WeakMap();
16901
+ /**
16902
+ * Returns the stable per-avatar state, computing it on first access and returning the cached
16903
+ * result on every subsequent call within the same `<Avatar/>` mount.
16904
+ *
16905
+ * @private helper of `octopus3d3AvatarVisual`
16906
+ */
16907
+ function getOctopus3d3StableState(createRandom) {
16908
+ const cached = stableStateCache.get(createRandom);
16909
+ if (cached !== undefined) {
16910
+ return cached;
16911
+ }
16912
+ const morphologyProfile = createOctopus3MorphologyProfile(createRandom);
16913
+ const animationRandom = createRandom('octopus3d3-animation-profile');
16914
+ const eyeRandom = createRandom('octopus3d3-eye-profile');
16915
+ const leftEyePhaseOffset = eyeRandom() * 0.7;
16916
+ const rightEyePhaseOffset = eyeRandom() * 0.7;
16917
+ const state = {
16918
+ morphologyProfile,
16919
+ animationPhase: animationRandom() * Math.PI * 2,
16920
+ leftEyePhaseOffset,
16921
+ rightEyePhaseOffset,
16922
+ tentacleProfiles: createContinuousTentacleProfiles(createRandom, morphologyProfile),
16923
+ };
16924
+ stableStateCache.set(createRandom, state);
16925
+ return state;
16926
+ }
16787
16927
  /**
16788
16928
  * Octopus 3D 3 avatar visual.
16789
16929
  *
@@ -16796,11 +16936,7 @@ const octopus3d3AvatarVisual = {
16796
16936
  isAnimated: true,
16797
16937
  supportsPointerTracking: true,
16798
16938
  render({ context, size, palette, createRandom, timeMs, interaction }) {
16799
- const morphologyProfile = createOctopus3MorphologyProfile(createRandom);
16800
- const animationRandom = createRandom('octopus3d3-animation-profile');
16801
- const eyeRandom = createRandom('octopus3d3-eye-profile');
16802
- const animationPhase = animationRandom() * Math.PI * 2;
16803
- const tentacleProfiles = createContinuousTentacleProfiles(createRandom, morphologyProfile);
16939
+ const { morphologyProfile, animationPhase, leftEyePhaseOffset, rightEyePhaseOffset, tentacleProfiles } = getOctopus3d3StableState(createRandom);
16804
16940
  const sceneCenterX = size * 0.5;
16805
16941
  const sceneCenterY = size * 0.535;
16806
16942
  const bob = Math.sin(timeMs / 960 + animationPhase) * size * 0.012;
@@ -16877,8 +17013,8 @@ const octopus3d3AvatarVisual = {
16877
17013
  size,
16878
17014
  palette,
16879
17015
  });
16880
- drawProjectedOrganicEye(context, sampleContinuousOctopusSurfacePoint(surfaceOptions, eyeLatitude, -eyeLongitude), eyeRadiusX, eyeRadiusY, meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + eyeRandom() * 0.7, interaction, morphologyProfile.face.eyeStyle);
16881
- 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);
17016
+ drawProjectedOrganicEye(context, sampleContinuousOctopusSurfacePoint(surfaceOptions, eyeLatitude, -eyeLongitude), eyeRadiusX, eyeRadiusY, meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + leftEyePhaseOffset, interaction, morphologyProfile.face.eyeStyle);
17017
+ drawProjectedOrganicEye(context, sampleContinuousOctopusSurfacePoint(surfaceOptions, eyeLatitude, eyeLongitude), eyeRadiusX, eyeRadiusY, meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + 0.85 + rightEyePhaseOffset, interaction, morphologyProfile.face.eyeStyle);
16882
17018
  drawProjectedOrganicMouth(context, [
16883
17019
  sampleContinuousOctopusSurfacePoint(surfaceOptions, mouthLatitude, mouthCenterLongitude - mouthHalfLongitude),
16884
17020
  sampleContinuousOctopusSurfacePoint(surfaceOptions, mouthCurveLatitude, mouthCenterLongitude),
@@ -16929,14 +17065,30 @@ function drawContinuousOctopusAtmosphere(context, size, palette, sceneCenterX, s
16929
17065
  /**
16930
17066
  * Draws the soft lower shadow that anchors the octopus in the avatar frame.
16931
17067
  *
17068
+ * Uses a scaled radial gradient instead of `context.filter = 'blur()'` to approximate the
17069
+ * blurry ellipse without triggering a costly software rasterization pass on every frame.
17070
+ *
16932
17071
  * @private helper of `octopus3d3AvatarVisual`
16933
17072
  */
16934
17073
  function drawContinuousOctopusShadow(context, size, palette, interaction, timeMs, morphologyProfile) {
17074
+ const cx = size * 0.5 + interaction.gazeX * size * 0.045;
17075
+ const cy = size * 0.9 + Math.sin(timeMs / 980) * size * 0.007;
17076
+ const rx = size * (0.19 + morphologyProfile.tentacles.rootSpreadScale * 0.022 + interaction.intensity * 0.02);
17077
+ const ry = size * 0.06;
17078
+ // Scale the context so that drawing a circle produces the correct ellipse aspect ratio,
17079
+ // then fill with a radial gradient that approximates the blurry edge without context.filter.
16935
17080
  context.save();
16936
- context.fillStyle = `${palette.shadow}66`;
16937
- context.filter = `blur(${size * 0.025}px)`;
17081
+ context.translate(cx, cy);
17082
+ context.scale(1, ry / rx);
17083
+ const blurRadius = rx * 1.4;
17084
+ const shadowGradient = context.createRadialGradient(0, 0, 0, 0, 0, blurRadius);
17085
+ shadowGradient.addColorStop(0, `${palette.shadow}7a`);
17086
+ shadowGradient.addColorStop(0.45, `${palette.shadow}44`);
17087
+ shadowGradient.addColorStop(0.8, `${palette.shadow}1a`);
17088
+ shadowGradient.addColorStop(1, `${palette.shadow}00`);
17089
+ context.fillStyle = shadowGradient;
16938
17090
  context.beginPath();
16939
- 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);
17091
+ context.arc(0, 0, blurRadius, 0, Math.PI * 2);
16940
17092
  context.fill();
16941
17093
  context.restore();
16942
17094
  }
@@ -39669,7 +39821,7 @@ function emitAgentLlmExecutionToolsAssistantPreparationProgress(options) {
39669
39821
  * Computes one stable hash from a JSON-serializable value.
39670
39822
  */
39671
39823
  function computeJsonHash$1(value) {
39672
- return SHA256(JSON.stringify(value)).toString();
39824
+ return CryptoJS.SHA256(JSON.stringify(value)).toString();
39673
39825
  }
39674
39826
  /**
39675
39827
  * Handles OpenAI AgentKit-backed executions for `AgentLlmExecutionTools`.
@@ -39827,7 +39979,7 @@ AgentLlmExecutionToolsAgentKitRunner.vectorStoreCache = new Map();
39827
39979
  * Computes one stable hash from a JSON-serializable value.
39828
39980
  */
39829
39981
  function computeJsonHash(value) {
39830
- return SHA256(JSON.stringify(value)).toString();
39982
+ return CryptoJS.SHA256(JSON.stringify(value)).toString();
39831
39983
  }
39832
39984
  /**
39833
39985
  * Removes assistant-managed requirements before the prompt is executed via OpenAI Assistants.
@@ -40629,7 +40781,7 @@ class AgentLlmExecutionTools {
40629
40781
  * Returns a virtual model name representing the agent behavior.
40630
40782
  */
40631
40783
  get modelName() {
40632
- const hash = SHA256(hexEncoder.parse(this.options.agentSource)).toString( /* hex */);
40784
+ const hash = CryptoJS.SHA256(hexEncoder.parse(this.options.agentSource)).toString( /* hex */);
40633
40785
  const agentId = hash.substring(0, 10);
40634
40786
  return (normalizeToKebabCase(this.title) + '-' + agentId);
40635
40787
  }