@promptbook/components 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 +577 -518
  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 +1 -3
  17. package/umd/index.umd.js +581 -516
  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,17 +1,20 @@
1
1
  (function (global, factory) {
2
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('react/jsx-runtime'), require('spacetrim'), require('react'), require('crypto-js'), require('crypto-js/enc-hex'), require('path'), require('moment'), require('mime-types'), require('crypto'), require('react-dom'), require('@monaco-editor/react'), require('destroyable'), require('rxjs'), require('dompurify'), require('katex'), require('showdown'), require('html-to-image'), require('jspdf'), require('react-dom/client'), require('lucide-react'), require('moment/locale/cs'), require('waitasecond'), require('crypto-js/sha256'), require('papaparse'), require('@openai/agents'), require('colors'), require('bottleneck'), require('openai'), require('qrcode')) :
3
- typeof define === 'function' && define.amd ? define(['exports', 'react/jsx-runtime', 'spacetrim', 'react', 'crypto-js', 'crypto-js/enc-hex', 'path', 'moment', 'mime-types', 'crypto', 'react-dom', '@monaco-editor/react', 'destroyable', 'rxjs', 'dompurify', 'katex', 'showdown', 'html-to-image', 'jspdf', 'react-dom/client', 'lucide-react', 'moment/locale/cs', 'waitasecond', 'crypto-js/sha256', 'papaparse', '@openai/agents', 'colors', 'bottleneck', 'openai', 'qrcode'], factory) :
4
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["promptbook-components"] = {}, global.jsxRuntime, global.spacetrim, global.react, global.cryptoJs, global.hexEncoder, global.path, global.moment, global.mimeTypes, global.crypto$1, global.reactDom, global.MonacoEditor, global.destroyable, global.rxjs, global.createDOMPurify, global.katex, global.showdown, global.htmlToImage, global.jspdf, global.client, global.lucideReact, null, global.waitasecond, global.sha256, global.papaparse, global.agents, global.colors, global.Bottleneck, global.OpenAI, global.QRCode));
5
- })(this, (function (exports, jsxRuntime, spacetrim, react, cryptoJs, hexEncoder, path, moment, mimeTypes, crypto$1, reactDom, MonacoEditor, destroyable, rxjs, createDOMPurify, katex, showdown, htmlToImage, jspdf, client, lucideReact, cs, waitasecond, sha256, papaparse, agents, colors, Bottleneck, OpenAI, QRCode) { 'use strict';
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('react/jsx-runtime'), require('spacetrim'), require('react'), require('crypto-js'), require('crypto-js/enc-hex'), require('path'), require('moment'), require('mime-types'), require('react-dom'), require('@monaco-editor/react'), require('rxjs'), require('dompurify'), require('katex'), require('showdown'), require('html-to-image'), require('jspdf'), require('react-dom/client'), require('lucide-react'), require('moment/locale/cs'), require('waitasecond'), require('crypto-js/sha256'), require('papaparse'), require('@openai/agents'), require('colors'), require('bottleneck'), require('openai'), require('qrcode')) :
3
+ typeof define === 'function' && define.amd ? define(['exports', 'react/jsx-runtime', 'spacetrim', 'react', 'crypto-js', 'crypto-js/enc-hex', 'path', 'moment', 'mime-types', 'react-dom', '@monaco-editor/react', 'rxjs', 'dompurify', 'katex', 'showdown', 'html-to-image', 'jspdf', 'react-dom/client', 'lucide-react', 'moment/locale/cs', 'waitasecond', 'crypto-js/sha256', 'papaparse', '@openai/agents', 'colors', 'bottleneck', 'openai', 'qrcode'], factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["promptbook-components"] = {}, global.jsxRuntime, global.spacetrim, global.react, global.CryptoJS, global.hexEncoder, global.path, global.moment, global.mimeTypes, global.reactDom, global.MonacoEditor, global.rxjs, global.createDOMPurify, global.katex, global.showdown, global.htmlToImage, global.jspdf, global.client, global.lucideReact, null, global.waitasecond, global.sha256, global.papaparse, global.agents, global.colors, global.Bottleneck, global.OpenAI, global.QRCode));
5
+ })(this, (function (exports, jsxRuntime, spacetrim, react, CryptoJS, hexEncoder, path, moment, mimeTypes, reactDom, MonacoEditor, rxjs, createDOMPurify, katex, showdown, htmlToImage, jspdf, client, lucideReact, cs, waitasecond, sha256, papaparse, agents, colors, Bottleneck, OpenAI, QRCode) { '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 MonacoEditor__default = /*#__PURE__*/_interopDefaultLegacy(MonacoEditor);
12
13
  var createDOMPurify__default = /*#__PURE__*/_interopDefaultLegacy(createDOMPurify);
13
14
  var katex__default = /*#__PURE__*/_interopDefaultLegacy(katex);
15
+ var showdown__default = /*#__PURE__*/_interopDefaultLegacy(showdown);
14
16
  var sha256__default = /*#__PURE__*/_interopDefaultLegacy(sha256);
17
+ var papaparse__default = /*#__PURE__*/_interopDefaultLegacy(papaparse);
15
18
  var colors__default = /*#__PURE__*/_interopDefaultLegacy(colors);
16
19
  var Bottleneck__default = /*#__PURE__*/_interopDefaultLegacy(Bottleneck);
17
20
  var OpenAI__default = /*#__PURE__*/_interopDefaultLegacy(OpenAI);
@@ -31,7 +34,7 @@
31
34
  * @generated
32
35
  * @see https://github.com/webgptorg/promptbook
33
36
  */
34
- const PROMPTBOOK_ENGINE_VERSION = '0.112.0-115';
37
+ const PROMPTBOOK_ENGINE_VERSION = '0.112.0-118';
35
38
  /**
36
39
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
37
40
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -2767,21 +2770,22 @@
2767
2770
  * @private helper of `fractalAvatarVisual`
2768
2771
  */
2769
2772
  function drawDragonCurveLayer(context, points, options) {
2770
- const { size, primaryColor, secondaryColor, tertiaryColor, shadowColor, strokeWidth, timeMs, layerIndex } = options;
2773
+ const { primaryColor, secondaryColor, tertiaryColor, shadowColor, strokeWidth, timeMs, layerIndex } = options;
2771
2774
  const firstPoint = points[0];
2772
2775
  const lastPoint = points[points.length - 1];
2773
2776
  const ribbonGradient = context.createLinearGradient(firstPoint.x, firstPoint.y, lastPoint.x, lastPoint.y);
2774
2777
  ribbonGradient.addColorStop(0, `${primaryColor}f2`);
2775
2778
  ribbonGradient.addColorStop(0.5, `${secondaryColor}e6`);
2776
2779
  ribbonGradient.addColorStop(1, `${tertiaryColor}f2`);
2780
+ // Approximate the blurred shadow stroke with a wider semi-transparent stroke instead of
2781
+ // context.filter blur, which triggers a costly software rasterization pass every frame.
2777
2782
  context.save();
2778
2783
  context.beginPath();
2779
2784
  tracePolyline(context, points);
2780
- context.strokeStyle = `${shadowColor}82`;
2781
- context.lineWidth = strokeWidth * 1.8;
2785
+ context.strokeStyle = `${shadowColor}48`;
2786
+ context.lineWidth = strokeWidth * 4.5;
2782
2787
  context.lineJoin = 'round';
2783
2788
  context.lineCap = 'round';
2784
- context.filter = `blur(${size * 0.022}px)`;
2785
2789
  context.stroke();
2786
2790
  context.restore();
2787
2791
  context.beginPath();
@@ -3365,11 +3369,23 @@
3365
3369
  * @private helper of `minecraft2AvatarVisual`
3366
3370
  */
3367
3371
  function drawMinecraftShadow(context, size, palette, interaction, timeMs) {
3372
+ const cx = size * 0.5 + interaction.gazeX * size * 0.03;
3373
+ const cy = size * 0.85 + Math.sin(timeMs / 880) * size * 0.01;
3374
+ const rx = size * (0.16 + interaction.intensity * 0.015);
3375
+ const ry = size * 0.055;
3376
+ // Radial gradient approximates the blurry ellipse shadow without context.filter blur.
3368
3377
  context.save();
3369
- context.fillStyle = `${palette.shadow}66`;
3370
- context.filter = `blur(${size * 0.02}px)`;
3378
+ context.translate(cx, cy);
3379
+ context.scale(1, ry / rx);
3380
+ const blurRadius = rx * 1.4;
3381
+ const shadowGradient = context.createRadialGradient(0, 0, 0, 0, 0, blurRadius);
3382
+ shadowGradient.addColorStop(0, `${palette.shadow}7a`);
3383
+ shadowGradient.addColorStop(0.45, `${palette.shadow}44`);
3384
+ shadowGradient.addColorStop(0.8, `${palette.shadow}1a`);
3385
+ shadowGradient.addColorStop(1, `${palette.shadow}00`);
3386
+ context.fillStyle = shadowGradient;
3371
3387
  context.beginPath();
3372
- 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);
3388
+ context.arc(0, 0, blurRadius, 0, Math.PI * 2);
3373
3389
  context.fill();
3374
3390
  context.restore();
3375
3391
  }
@@ -3593,13 +3609,27 @@
3593
3609
  spotlight.addColorStop(1, `${palette.highlight}00`);
3594
3610
  context.fillStyle = spotlight;
3595
3611
  context.fillRect(0, 0, size, size);
3596
- context.save();
3597
- context.fillStyle = 'rgba(0, 0, 0, 0.22)';
3598
- context.filter = `blur(${size * 0.018}px)`;
3599
- context.beginPath();
3600
- context.ellipse(size * 0.5, size * 0.86, size * 0.2, size * 0.06, 0, 0, Math.PI * 2);
3601
- context.fill();
3602
- context.restore();
3612
+ {
3613
+ // Radial gradient approximates the blurry ellipse shadow without context.filter blur.
3614
+ const cx = size * 0.5;
3615
+ const cy = size * 0.86;
3616
+ const rx = size * 0.2;
3617
+ const ry = size * 0.06;
3618
+ const blurRadius = rx * 1.4;
3619
+ const shadowGradient = context.createRadialGradient(0, 0, 0, 0, 0, blurRadius);
3620
+ shadowGradient.addColorStop(0, 'rgba(0,0,0,0.28)');
3621
+ shadowGradient.addColorStop(0.45, 'rgba(0,0,0,0.14)');
3622
+ shadowGradient.addColorStop(0.8, 'rgba(0,0,0,0.05)');
3623
+ shadowGradient.addColorStop(1, 'rgba(0,0,0,0)');
3624
+ context.save();
3625
+ context.translate(cx, cy);
3626
+ context.scale(1, ry / rx);
3627
+ context.fillStyle = shadowGradient;
3628
+ context.beginPath();
3629
+ context.arc(0, 0, blurRadius, 0, Math.PI * 2);
3630
+ context.fill();
3631
+ context.restore();
3632
+ }
3603
3633
  drawVoxelCuboid(context, {
3604
3634
  x: bodyX,
3605
3635
  y: bodyY,
@@ -4651,6 +4681,35 @@
4651
4681
  y: -0.62,
4652
4682
  z: 0.94,
4653
4683
  });
4684
+ /**
4685
+ * Cache keyed by the `createRandom` factory reference (stable per mounted `<Avatar/>`).
4686
+ *
4687
+ * @private helper of `octopus3dAvatarVisual`
4688
+ */
4689
+ const octopus3dStableStateCache = new WeakMap();
4690
+ /**
4691
+ * Returns the stable per-avatar state, computing it on first access and caching for subsequent frames.
4692
+ *
4693
+ * @private helper of `octopus3dAvatarVisual`
4694
+ */
4695
+ function getOctopus3dStableState(createRandom) {
4696
+ const cached = octopus3dStableStateCache.get(createRandom);
4697
+ if (cached !== undefined) {
4698
+ return cached;
4699
+ }
4700
+ const animationRandom = createRandom('octopus3d-animation-profile');
4701
+ const eyeRandom = createRandom('octopus3d-eye-profile');
4702
+ const leftEyePhaseOffset = eyeRandom() * 0.6;
4703
+ const rightEyePhaseOffset = eyeRandom() * 0.6;
4704
+ const state = {
4705
+ morphologyProfile: createOctopus3MorphologyProfile(createRandom),
4706
+ animationPhase: animationRandom() * Math.PI * 2,
4707
+ leftEyePhaseOffset,
4708
+ rightEyePhaseOffset,
4709
+ };
4710
+ octopus3dStableStateCache.set(createRandom, state);
4711
+ return state;
4712
+ }
4654
4713
  /**
4655
4714
  * Proper 3D Octopus visual built from projected organic meshes and tentacles.
4656
4715
  *
@@ -4663,10 +4722,7 @@
4663
4722
  isAnimated: true,
4664
4723
  supportsPointerTracking: true,
4665
4724
  render({ context, size, palette, createRandom, timeMs, interaction }) {
4666
- const morphologyProfile = createOctopus3MorphologyProfile(createRandom);
4667
- const animationRandom = createRandom('octopus3d-animation-profile');
4668
- const eyeRandom = createRandom('octopus3d-eye-profile');
4669
- const animationPhase = animationRandom() * Math.PI * 2;
4725
+ const { morphologyProfile, animationPhase, leftEyePhaseOffset, rightEyePhaseOffset } = getOctopus3dStableState(createRandom);
4670
4726
  const sceneCenterX = size * 0.5;
4671
4727
  const sceneCenterY = size * 0.56;
4672
4728
  const bob = Math.sin(timeMs / 920 + animationPhase) * size * 0.014;
@@ -4763,12 +4819,12 @@
4763
4819
  x: -faceEyeSpacing,
4764
4820
  y: faceEyeYOffset,
4765
4821
  z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, -faceEyeSpacing, faceEyeYOffset),
4766
- }, faceEyeRadiusX, faceEyeRadiusY, mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + eyeRandom() * 0.6, interaction, morphologyProfile.face.eyeStyle);
4822
+ }, faceEyeRadiusX, faceEyeRadiusY, mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + leftEyePhaseOffset, interaction, morphologyProfile.face.eyeStyle);
4767
4823
  drawProjectedOrganicEye(context, {
4768
4824
  x: faceEyeSpacing,
4769
4825
  y: faceEyeYOffset,
4770
4826
  z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, faceEyeSpacing, faceEyeYOffset),
4771
- }, faceEyeRadiusX, faceEyeRadiusY, mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + 0.7 + eyeRandom() * 0.6, interaction, morphologyProfile.face.eyeStyle);
4827
+ }, faceEyeRadiusX, faceEyeRadiusY, mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + 0.7 + rightEyePhaseOffset, interaction, morphologyProfile.face.eyeStyle);
4772
4828
  drawProjectedOrganicMouth(context, [
4773
4829
  {
4774
4830
  x: -mouthHalfWidth,
@@ -4812,14 +4868,28 @@
4812
4868
  /**
4813
4869
  * Draws the soft ground shadow below the octopus.
4814
4870
  *
4871
+ * Uses a scaled radial gradient instead of `context.filter = 'blur()'` to approximate the
4872
+ * blurry ellipse without triggering a costly software rasterization pass on every frame.
4873
+ *
4815
4874
  * @private helper of `octopus3dAvatarVisual`
4816
4875
  */
4817
4876
  function drawOctopus3dShadow(context, size, palette, interaction, timeMs) {
4877
+ const cx = size * 0.5 + interaction.gazeX * size * 0.04;
4878
+ const cy = size * 0.87 + Math.sin(timeMs / 920) * size * 0.008;
4879
+ const rx = size * (0.18 + interaction.intensity * 0.02);
4880
+ const ry = size * 0.06;
4818
4881
  context.save();
4819
- context.fillStyle = `${palette.shadow}66`;
4820
- context.filter = `blur(${size * 0.022}px)`;
4882
+ context.translate(cx, cy);
4883
+ context.scale(1, ry / rx);
4884
+ const blurRadius = rx * 1.4;
4885
+ const shadowGradient = context.createRadialGradient(0, 0, 0, 0, 0, blurRadius);
4886
+ shadowGradient.addColorStop(0, `${palette.shadow}7a`);
4887
+ shadowGradient.addColorStop(0.45, `${palette.shadow}44`);
4888
+ shadowGradient.addColorStop(0.8, `${palette.shadow}1a`);
4889
+ shadowGradient.addColorStop(1, `${palette.shadow}00`);
4890
+ context.fillStyle = shadowGradient;
4821
4891
  context.beginPath();
4822
- 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);
4892
+ context.arc(0, 0, blurRadius, 0, Math.PI * 2);
4823
4893
  context.fill();
4824
4894
  context.restore();
4825
4895
  }
@@ -5050,6 +5120,35 @@
5050
5120
  y: -0.6,
5051
5121
  z: 0.98,
5052
5122
  });
5123
+ /**
5124
+ * Cache keyed by the `createRandom` factory reference (stable per mounted `<Avatar/>`).
5125
+ *
5126
+ * @private helper of `octopus3d2AvatarVisual`
5127
+ */
5128
+ const octopus3d2StableStateCache = new WeakMap();
5129
+ /**
5130
+ * Returns the stable per-avatar state, computing it on first access and caching for subsequent frames.
5131
+ *
5132
+ * @private helper of `octopus3d2AvatarVisual`
5133
+ */
5134
+ function getOctopus3d2StableState(createRandom) {
5135
+ const cached = octopus3d2StableStateCache.get(createRandom);
5136
+ if (cached !== undefined) {
5137
+ return cached;
5138
+ }
5139
+ const animationRandom = createRandom('octopus3d2-animation-profile');
5140
+ const eyeRandom = createRandom('octopus3d2-eye-profile');
5141
+ const leftEyePhaseOffset = eyeRandom() * 0.7;
5142
+ const rightEyePhaseOffset = eyeRandom() * 0.7;
5143
+ const state = {
5144
+ morphologyProfile: createOctopus3MorphologyProfile(createRandom),
5145
+ animationPhase: animationRandom() * Math.PI * 2,
5146
+ leftEyePhaseOffset,
5147
+ rightEyePhaseOffset,
5148
+ };
5149
+ octopus3d2StableStateCache.set(createRandom, state);
5150
+ return state;
5151
+ }
5053
5152
  /**
5054
5153
  * Octopus 3D 2 avatar visual.
5055
5154
  *
@@ -5062,10 +5161,7 @@
5062
5161
  isAnimated: true,
5063
5162
  supportsPointerTracking: true,
5064
5163
  render({ context, size, palette, createRandom, timeMs, interaction }) {
5065
- const morphologyProfile = createOctopus3MorphologyProfile(createRandom);
5066
- const animationRandom = createRandom('octopus3d2-animation-profile');
5067
- const eyeRandom = createRandom('octopus3d2-eye-profile');
5068
- const animationPhase = animationRandom() * Math.PI * 2;
5164
+ const { morphologyProfile, animationPhase, leftEyePhaseOffset, rightEyePhaseOffset } = getOctopus3d2StableState(createRandom);
5069
5165
  const sceneCenterX = size * 0.5;
5070
5166
  const sceneCenterY = size * 0.575;
5071
5167
  const bob = Math.sin(timeMs / 940 + animationPhase) * size * 0.013;
@@ -5118,8 +5214,8 @@
5118
5214
  const rightEyeLocalCenter = sampleBlobbyOctopusSurfacePoint(surfaceOptions, eyeLatitude, eyeLongitude);
5119
5215
  const eyeRadiusX = size * morphologyProfile.face.eyeRadiusXRatio * 0.78;
5120
5216
  const eyeRadiusY = eyeRadiusX * morphologyProfile.face.eyeHeightRatio * 0.92;
5121
- drawProjectedOrganicEye(context, leftEyeLocalCenter, eyeRadiusX, eyeRadiusY, meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + eyeRandom() * 0.7, interaction, morphologyProfile.face.eyeStyle);
5122
- drawProjectedOrganicEye(context, rightEyeLocalCenter, eyeRadiusX, eyeRadiusY, meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + 0.9 + eyeRandom() * 0.7, interaction, morphologyProfile.face.eyeStyle);
5217
+ drawProjectedOrganicEye(context, leftEyeLocalCenter, eyeRadiusX, eyeRadiusY, meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + leftEyePhaseOffset, interaction, morphologyProfile.face.eyeStyle);
5218
+ drawProjectedOrganicEye(context, rightEyeLocalCenter, eyeRadiusX, eyeRadiusY, meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + 0.9 + rightEyePhaseOffset, interaction, morphologyProfile.face.eyeStyle);
5123
5219
  drawProjectedOrganicMouth(context, [
5124
5220
  sampleBlobbyOctopusSurfacePoint(surfaceOptions, mouthLatitude, mouthCenterLongitude - mouthHalfLongitude),
5125
5221
  sampleBlobbyOctopusSurfacePoint(surfaceOptions, mouthCurveLatitude, mouthCenterLongitude),
@@ -5148,14 +5244,28 @@
5148
5244
  /**
5149
5245
  * Draws the soft floor shadow that anchors the single mesh in the frame.
5150
5246
  *
5247
+ * Uses a scaled radial gradient instead of `context.filter = 'blur()'` to approximate the
5248
+ * blurry ellipse without triggering a costly software rasterization pass on every frame.
5249
+ *
5151
5250
  * @private helper of `octopus3d2AvatarVisual`
5152
5251
  */
5153
5252
  function drawBlobbyOctopusShadow(context, size, palette, interaction, timeMs, morphologyProfile) {
5253
+ const cx = size * 0.5 + interaction.gazeX * size * 0.045;
5254
+ const cy = size * 0.88 + Math.sin(timeMs / 940) * size * 0.008;
5255
+ const rx = size * (0.18 + (morphologyProfile.body.horizontalStretch - 1) * 0.04 + interaction.intensity * 0.018);
5256
+ const ry = size * 0.062;
5154
5257
  context.save();
5155
- context.fillStyle = `${palette.shadow}66`;
5156
- context.filter = `blur(${size * 0.024}px)`;
5258
+ context.translate(cx, cy);
5259
+ context.scale(1, ry / rx);
5260
+ const blurRadius = rx * 1.4;
5261
+ const shadowGradient = context.createRadialGradient(0, 0, 0, 0, 0, blurRadius);
5262
+ shadowGradient.addColorStop(0, `${palette.shadow}7a`);
5263
+ shadowGradient.addColorStop(0.45, `${palette.shadow}44`);
5264
+ shadowGradient.addColorStop(0.8, `${palette.shadow}1a`);
5265
+ shadowGradient.addColorStop(1, `${palette.shadow}00`);
5266
+ context.fillStyle = shadowGradient;
5157
5267
  context.beginPath();
5158
- 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);
5268
+ context.arc(0, 0, blurRadius, 0, Math.PI * 2);
5159
5269
  context.fill();
5160
5270
  context.restore();
5161
5271
  }
@@ -5311,6 +5421,40 @@
5311
5421
  * @private helper of `octopus3d3AvatarVisual`
5312
5422
  */
5313
5423
  const OCTOPUS_TENTACLE_COUNT = 8;
5424
+ /**
5425
+ * Cache keyed by the `createRandom` factory reference, which is stable for the lifetime of one
5426
+ * mounted `<Avatar/>` component (created inside `resolveAvatarRenderDefinition` and held in a
5427
+ * React `useMemo`). Using a `WeakMap` ensures the entry is collected when the component unmounts.
5428
+ *
5429
+ * @private helper of `octopus3d3AvatarVisual`
5430
+ */
5431
+ const stableStateCache = new WeakMap();
5432
+ /**
5433
+ * Returns the stable per-avatar state, computing it on first access and returning the cached
5434
+ * result on every subsequent call within the same `<Avatar/>` mount.
5435
+ *
5436
+ * @private helper of `octopus3d3AvatarVisual`
5437
+ */
5438
+ function getOctopus3d3StableState(createRandom) {
5439
+ const cached = stableStateCache.get(createRandom);
5440
+ if (cached !== undefined) {
5441
+ return cached;
5442
+ }
5443
+ const morphologyProfile = createOctopus3MorphologyProfile(createRandom);
5444
+ const animationRandom = createRandom('octopus3d3-animation-profile');
5445
+ const eyeRandom = createRandom('octopus3d3-eye-profile');
5446
+ const leftEyePhaseOffset = eyeRandom() * 0.7;
5447
+ const rightEyePhaseOffset = eyeRandom() * 0.7;
5448
+ const state = {
5449
+ morphologyProfile,
5450
+ animationPhase: animationRandom() * Math.PI * 2,
5451
+ leftEyePhaseOffset,
5452
+ rightEyePhaseOffset,
5453
+ tentacleProfiles: createContinuousTentacleProfiles(createRandom, morphologyProfile),
5454
+ };
5455
+ stableStateCache.set(createRandom, state);
5456
+ return state;
5457
+ }
5314
5458
  /**
5315
5459
  * Octopus 3D 3 avatar visual.
5316
5460
  *
@@ -5323,11 +5467,7 @@
5323
5467
  isAnimated: true,
5324
5468
  supportsPointerTracking: true,
5325
5469
  render({ context, size, palette, createRandom, timeMs, interaction }) {
5326
- const morphologyProfile = createOctopus3MorphologyProfile(createRandom);
5327
- const animationRandom = createRandom('octopus3d3-animation-profile');
5328
- const eyeRandom = createRandom('octopus3d3-eye-profile');
5329
- const animationPhase = animationRandom() * Math.PI * 2;
5330
- const tentacleProfiles = createContinuousTentacleProfiles(createRandom, morphologyProfile);
5470
+ const { morphologyProfile, animationPhase, leftEyePhaseOffset, rightEyePhaseOffset, tentacleProfiles } = getOctopus3d3StableState(createRandom);
5331
5471
  const sceneCenterX = size * 0.5;
5332
5472
  const sceneCenterY = size * 0.535;
5333
5473
  const bob = Math.sin(timeMs / 960 + animationPhase) * size * 0.012;
@@ -5404,8 +5544,8 @@
5404
5544
  size,
5405
5545
  palette,
5406
5546
  });
5407
- drawProjectedOrganicEye(context, sampleContinuousOctopusSurfacePoint(surfaceOptions, eyeLatitude, -eyeLongitude), eyeRadiusX, eyeRadiusY, meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + eyeRandom() * 0.7, interaction, morphologyProfile.face.eyeStyle);
5408
- 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);
5547
+ drawProjectedOrganicEye(context, sampleContinuousOctopusSurfacePoint(surfaceOptions, eyeLatitude, -eyeLongitude), eyeRadiusX, eyeRadiusY, meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + leftEyePhaseOffset, interaction, morphologyProfile.face.eyeStyle);
5548
+ drawProjectedOrganicEye(context, sampleContinuousOctopusSurfacePoint(surfaceOptions, eyeLatitude, eyeLongitude), eyeRadiusX, eyeRadiusY, meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + 0.85 + rightEyePhaseOffset, interaction, morphologyProfile.face.eyeStyle);
5409
5549
  drawProjectedOrganicMouth(context, [
5410
5550
  sampleContinuousOctopusSurfacePoint(surfaceOptions, mouthLatitude, mouthCenterLongitude - mouthHalfLongitude),
5411
5551
  sampleContinuousOctopusSurfacePoint(surfaceOptions, mouthCurveLatitude, mouthCenterLongitude),
@@ -5456,14 +5596,30 @@
5456
5596
  /**
5457
5597
  * Draws the soft lower shadow that anchors the octopus in the avatar frame.
5458
5598
  *
5599
+ * Uses a scaled radial gradient instead of `context.filter = 'blur()'` to approximate the
5600
+ * blurry ellipse without triggering a costly software rasterization pass on every frame.
5601
+ *
5459
5602
  * @private helper of `octopus3d3AvatarVisual`
5460
5603
  */
5461
5604
  function drawContinuousOctopusShadow(context, size, palette, interaction, timeMs, morphologyProfile) {
5605
+ const cx = size * 0.5 + interaction.gazeX * size * 0.045;
5606
+ const cy = size * 0.9 + Math.sin(timeMs / 980) * size * 0.007;
5607
+ const rx = size * (0.19 + morphologyProfile.tentacles.rootSpreadScale * 0.022 + interaction.intensity * 0.02);
5608
+ const ry = size * 0.06;
5609
+ // Scale the context so that drawing a circle produces the correct ellipse aspect ratio,
5610
+ // then fill with a radial gradient that approximates the blurry edge without context.filter.
5462
5611
  context.save();
5463
- context.fillStyle = `${palette.shadow}66`;
5464
- context.filter = `blur(${size * 0.025}px)`;
5612
+ context.translate(cx, cy);
5613
+ context.scale(1, ry / rx);
5614
+ const blurRadius = rx * 1.4;
5615
+ const shadowGradient = context.createRadialGradient(0, 0, 0, 0, 0, blurRadius);
5616
+ shadowGradient.addColorStop(0, `${palette.shadow}7a`);
5617
+ shadowGradient.addColorStop(0.45, `${palette.shadow}44`);
5618
+ shadowGradient.addColorStop(0.8, `${palette.shadow}1a`);
5619
+ shadowGradient.addColorStop(1, `${palette.shadow}00`);
5620
+ context.fillStyle = shadowGradient;
5465
5621
  context.beginPath();
5466
- 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);
5622
+ context.arc(0, 0, blurRadius, 0, Math.PI * 2);
5467
5623
  context.fill();
5468
5624
  context.restore();
5469
5625
  }
@@ -7062,7 +7218,7 @@
7062
7218
  * @public exported from `@promptbook/utils`
7063
7219
  */
7064
7220
  function computeHash(value) {
7065
- return cryptoJs.SHA256(hexEncoder__default["default"].parse(spacetrim.spaceTrim(valueToString(value)))).toString( /* hex */);
7221
+ return CryptoJS__default["default"].SHA256(hexEncoder__default["default"].parse(spacetrim.spaceTrim(valueToString(value)))).toString( /* hex */);
7066
7222
  }
7067
7223
  // TODO: [🥬][🥬] Use this ACRY
7068
7224
 
@@ -18456,7 +18612,7 @@
18456
18612
  * @private internal helper function
18457
18613
  */
18458
18614
  function $randomToken(randomness) {
18459
- return crypto$1.randomBytes(randomness).toString('hex');
18615
+ return CryptoJS__default["default"].lib.WordArray.random(randomness).toString(CryptoJS__default["default"].enc.Hex);
18460
18616
  }
18461
18617
  // TODO: [🤶] Maybe export through `@promptbook/utils` or `@promptbook/random` package
18462
18618
  // TODO: Maybe use nanoid instead https://github.com/ai/nanoid
@@ -20577,7 +20733,7 @@
20577
20733
  * Regex pattern to match horizontal lines (markdown thematic breaks)
20578
20734
  * Matches 3 or more hyphens, underscores, or asterisks (with optional spaces between)
20579
20735
  */
20580
- const HORIZONTAL_LINE_PATTERN$1 = /^[\s]*[-_*][\s]*[-_*][\s]*[-_*][\s]*[-_*]*[\s]*$/;
20736
+ const HORIZONTAL_LINE_PATTERN$2 = /^[\s]*[-_*][\s]*[-_*][\s]*[-_*][\s]*[-_*]*[\s]*$/;
20581
20737
  /**
20582
20738
  * Parses agent source using the new commitment system with multiline support
20583
20739
  * This function replaces the hardcoded commitment parsing in the original parseAgentSource
@@ -20666,7 +20822,7 @@
20666
20822
  }
20667
20823
  }
20668
20824
  // Check if this is a horizontal line (ends any current commitment)
20669
- const isHorizontalLine = HORIZONTAL_LINE_PATTERN$1.test(line);
20825
+ const isHorizontalLine = HORIZONTAL_LINE_PATTERN$2.test(line);
20670
20826
  if (isHorizontalLine) {
20671
20827
  // Save the current commitment if it exists
20672
20828
  if (currentCommitment) {
@@ -21611,6 +21767,56 @@
21611
21767
  // TODO: [🥴] Implement counting in formats - like JSON, CSV, XML,...
21612
21768
  // TODO: [🧠][✌️] Make some Promptbook-native token system
21613
21769
 
21770
+ /**
21771
+ * Core Promptbook server configuration
21772
+ *
21773
+ * Used for "Adam" agent which is built in as default ancestor for new agents and other well known agents
21774
+ *
21775
+ * @public exported from `@promptbook/core`
21776
+ */
21777
+ const CORE_AGENTS_SERVER = {
21778
+ title: 'Promptbook Core',
21779
+ description: `Core Promptbook server used for Adam agent which is built in as default ancestor for new agents and other well known agents.`,
21780
+ owner: PROMPTBOOK_LEGAL_ENTITY,
21781
+ url: 'https://core.ptbk.io/',
21782
+ };
21783
+ // <- TODO: [🆎] Allow to override (set) well-known agent names via Metadata
21784
+ /**
21785
+ * Available agents servers for the Promptbook
21786
+ *
21787
+ * Tip: 💡 If you are running your own server, you can add it to this list by creating a pull request!
21788
+ *
21789
+ * @public exported from `@promptbook/core`
21790
+ */
21791
+ const PUBLIC_AGENTS_SERVERS = [
21792
+ CORE_AGENTS_SERVER,
21793
+ {
21794
+ title: 'Promptbook Gallery',
21795
+ description: `Gallery of ideas, AI professions,... like AI Agenta photobank.`,
21796
+ owner: PROMPTBOOK_LEGAL_ENTITY,
21797
+ url: 'https://gallery.ptbk.io/',
21798
+ },
21799
+ {
21800
+ title: 'Promptbook Testing server 6',
21801
+ description: `General-purpose testing server.`,
21802
+ owner: PROMPTBOOK_LEGAL_ENTITY,
21803
+ url: 'https://s6.ptbk.io/',
21804
+ },
21805
+ {
21806
+ title: 'Promptbook Testing server 7',
21807
+ description: `General-purpose testing server.`,
21808
+ owner: PROMPTBOOK_LEGAL_ENTITY,
21809
+ url: 'https://s7.ptbk.io/',
21810
+ },
21811
+ {
21812
+ title: 'Promptbook Testing server 8',
21813
+ description: `General-purpose testing server.`,
21814
+ owner: PROMPTBOOK_LEGAL_ENTITY,
21815
+ url: 'https://s8.ptbk.io/',
21816
+ },
21817
+ ];
21818
+ // Note: [💞] Ignore a discrepancy between file name and entity name
21819
+
21614
21820
  var css_248z$d = ".BookEditor-module_BookEditor__s-0PU{width:100%}.BookEditor-module_bookEditorContainer__wLMwM{box-sizing:border-box;height:100%;padding:10px 25px 0;position:relative;width:100%}.BookEditor-module_bookEditorContainer__wLMwM.BookEditor-module_isVerbose__VQ6iL{background-color:rgba(0,0,0,.05);outline:1px dotted rgba(0,0,0,.5)}.BookEditor-module_isVerbose__VQ6iL{outline:2px dotted #ff7526}.BookEditor-module_bookEditorWrapper__twppD{background-color:#fff;border:1px solid rgba(209,213,219,.8);border-radius:1rem;box-shadow:0 1px 2px 0 rgba(0,0,0,.05);overflow:hidden;padding-top:10px;transition:box-shadow .2s ease-in-out}.BookEditor-module_isVerbose__VQ6iL .BookEditor-module_bookEditorWrapper__twppD{overflow:visible}.BookEditor-module_bookEditorWrapper__twppD:hover{box-shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -1px rgba(0,0,0,.06)}.BookEditor-module_BookEditor__s-0PU[data-book-editor-theme=dark] .BookEditor-module_bookEditorWrapper__twppD{background:linear-gradient(180deg,rgba(15,23,42,.98),rgba(8,15,28,.98));border-color:rgba(51,65,85,.92);box-shadow:0 20px 45px rgba(2,6,23,.4)}.BookEditor-module_BookEditor__s-0PU[data-book-editor-theme=dark] .BookEditor-module_bookEditorWrapper__twppD:hover{box-shadow:0 24px 50px rgba(2,6,23,.48)}.BookEditor-module_bookEditorWrapper__twppD.BookEditor-module_isBorderRadiusDisabled__h1I3v{border-radius:0}.BookEditor-module_dropOverlay__xWWoX{align-items:center;background-color:rgba(0,0,0,.5);bottom:0;color:#fff;display:flex;font-size:1.5rem;justify-content:center;left:0;pointer-events:none;position:absolute;right:0;top:0;z-index:100}.BookEditor-module_bookEditorActionbar__KW6dc{position:absolute;right:55px;top:10px;z-index:100}.BookEditor-module_fullscreen__rktsl{border:none;border-radius:0;bottom:0;box-shadow:none;height:100%;left:0;padding-top:50px;position:fixed;right:0;top:0;width:100%;z-index:9999}.BookEditor-module_button__hS390{align-items:center;background-color:#fff;border:1px solid #d1d5db;border-radius:.375rem;box-shadow:0 1px 2px 0 rgba(0,0,0,.05);color:#374151;cursor:pointer;display:inline-flex;gap:.5rem;padding:.5rem 1rem;transition:all .2s ease-in-out}.BookEditor-module_button__hS390:hover{background-color:#f9fafb;border-color:#b7bcce;box-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px 0 rgba(0,0,0,.06)}.BookEditor-module_BookEditor__s-0PU[data-book-editor-theme=dark] .BookEditor-module_button__hS390{background-color:rgba(15,23,42,.92);border-color:rgba(71,85,105,.9);box-shadow:0 1px 2px 0 rgba(2,6,23,.35);color:#e2e8f0}.BookEditor-module_BookEditor__s-0PU[data-book-editor-theme=dark] .BookEditor-module_button__hS390:hover{background-color:rgba(30,41,59,.98);border-color:rgba(125,211,252,.5);box-shadow:0 10px 24px rgba(2,6,23,.35)}.BookEditor-module_savedNotification__OiX9L{align-items:center;animation:BookEditor-module_fadeOut__q8JnR 2s forwards;background-color:rgba(0,0,0,.7);border-radius:.5rem;color:#fff;display:flex;font-size:1.25rem;gap:.5rem;left:50%;padding:1rem 2rem;pointer-events:none;position:absolute;top:50%;transform:translate(-50%,-50%);z-index:1000}.BookEditor-module_BookEditor__s-0PU[data-book-editor-theme=dark] .BookEditor-module_savedNotification__OiX9L{background-color:rgba(2,6,23,.86);border:1px solid rgba(51,65,85,.9);color:#e2e8f0}.BookEditor-module_uploadPanel__2JJtD{background:hsla(0,0%,100%,.98);border:1px solid rgba(209,213,219,.9);border-radius:12px;bottom:20px;box-shadow:0 12px 30px rgba(15,23,42,.15);display:flex;flex-direction:column;gap:10px;max-width:calc(100% - 40px);padding:12px;position:absolute;right:20px;width:420px;z-index:220}.BookEditor-module_BookEditor__s-0PU[data-book-editor-theme=dark] .BookEditor-module_uploadPanel__2JJtD{background:rgba(8,15,28,.96);border-color:rgba(51,65,85,.9);box-shadow:0 18px 40px rgba(2,6,23,.45)}.BookEditor-module_uploadPanelHeader__pdJd2{align-items:center;display:flex;gap:12px;justify-content:space-between}.BookEditor-module_uploadPanelTitle__TJIVF{color:#111827;font-size:.95rem;font-weight:600}.BookEditor-module_BookEditor__s-0PU[data-book-editor-theme=dark] .BookEditor-module_uploadPanelTitle__TJIVF{color:#f8fafc}.BookEditor-module_uploadPanelHeaderMeta__Xw0uI{color:#6b7280;font-size:.75rem}.BookEditor-module_BookEditor__s-0PU[data-book-editor-theme=dark] .BookEditor-module_uploadPanelHeaderMeta__Xw0uI,.BookEditor-module_BookEditor__s-0PU[data-book-editor-theme=dark] .BookEditor-module_uploadPanelSummary__rwSbG,.BookEditor-module_BookEditor__s-0PU[data-book-editor-theme=dark] .BookEditor-module_uploadRowMeta__1lz9h,.BookEditor-module_BookEditor__s-0PU[data-book-editor-theme=dark] .BookEditor-module_uploadRowStatus__jsUb-{color:#94a3b8}.BookEditor-module_uploadPanelSummary__rwSbG{color:#6b7280;display:grid;font-size:.75rem;gap:4px 12px;grid-template-columns:1fr 1fr}.BookEditor-module_uploadPanelProgressBar__a6pjf{background:#e5e7eb;border-radius:999px;height:6px;overflow:hidden}.BookEditor-module_uploadPanelProgressFill__l-TKR{background:linear-gradient(90deg,#2563eb,#10b981);height:100%;transition:width .2s ease}.BookEditor-module_BookEditor__s-0PU[data-book-editor-theme=dark] .BookEditor-module_uploadPanelProgressBar__a6pjf,.BookEditor-module_BookEditor__s-0PU[data-book-editor-theme=dark] .BookEditor-module_uploadRowProgressBar__NoBA7{background:#1e293b}.BookEditor-module_uploadPanelList__VxEd5{display:flex;flex-direction:column;gap:8px;max-height:220px;overflow-y:auto;padding-right:4px}.BookEditor-module_uploadRow__QiSFg{background:#fff;border:1px solid #e5e7eb;border-radius:10px;display:flex;flex-direction:column;gap:6px;padding:8px}.BookEditor-module_BookEditor__s-0PU[data-book-editor-theme=dark] .BookEditor-module_uploadRow__QiSFg{background:rgba(15,23,42,.92);border-color:#334155}.BookEditor-module_uploadRowHeader__po0j5{align-items:center;display:flex;gap:8px;justify-content:space-between}.BookEditor-module_uploadRowName__doQRO{color:#111827;font-size:.8rem;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.BookEditor-module_BookEditor__s-0PU[data-book-editor-theme=dark] .BookEditor-module_uploadRowName__doQRO{color:#f8fafc}.BookEditor-module_uploadRowStatus__jsUb-{color:#6b7280;font-size:.7rem}.BookEditor-module_uploadRowMeta__1lz9h{color:#6b7280;display:flex;font-size:.7rem;justify-content:space-between}.BookEditor-module_uploadRowProgressBar__NoBA7{background:#e5e7eb;border-radius:999px;height:4px;overflow:hidden}.BookEditor-module_uploadRowProgressFill__TrP7e{background:#3b82f6;height:100%;transition:width .2s ease}.BookEditor-module_uploadRowActions__5Y1Mq{display:flex;gap:6px}.BookEditor-module_uploadActionButton__CqJrr{background:#f9fafb;border:1px solid #d1d5db;border-radius:6px;color:#374151;cursor:pointer;font-size:.7rem;padding:2px 8px;transition:all .15s ease-in-out}.BookEditor-module_uploadActionButton__CqJrr:hover{background:#eef2f7;border-color:#cbd5f5}.BookEditor-module_BookEditor__s-0PU[data-book-editor-theme=dark] .BookEditor-module_uploadActionButton__CqJrr{background:#0f172a;border-color:#475569;color:#e2e8f0}.BookEditor-module_BookEditor__s-0PU[data-book-editor-theme=dark] .BookEditor-module_uploadActionButton__CqJrr:hover{background:#1e293b;border-color:#7dd3fc}.BookEditor-module_uploadRowError__eEHWw{color:#b91c1c;font-size:.7rem}.BookEditor-module_aboutPromptbookInformation__eiBL0{color:#111827;font-family:var(--font-poppins,system-ui,-apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif);font-size:.95rem;line-height:1.6;max-width:680px}.BookEditor-module_aboutPromptbookInformation__eiBL0>:first-child{margin-top:0}.BookEditor-module_aboutPromptbookInformation__eiBL0>:last-child{margin-bottom:0}.BookEditor-module_aboutPromptbookInformation__eiBL0 h1,.BookEditor-module_aboutPromptbookInformation__eiBL0 h2{color:#0f172a;font-weight:650;line-height:1.25}.BookEditor-module_aboutPromptbookInformation__eiBL0 h1{font-size:1.5rem;margin:0 0 .75rem}.BookEditor-module_aboutPromptbookInformation__eiBL0 h2{font-size:1.15rem;margin:1.35rem 0 .55rem}.BookEditor-module_aboutPromptbookInformation__eiBL0 p{margin:0 0 .9rem}.BookEditor-module_aboutPromptbookInformation__eiBL0 ol,.BookEditor-module_aboutPromptbookInformation__eiBL0 ul{display:grid;gap:.35rem;margin:.55rem 0 1rem;padding-left:1.35rem}.BookEditor-module_aboutPromptbookInformation__eiBL0 a{color:#2563eb;text-decoration:underline;text-underline-offset:.16em}.BookEditor-module_aboutPromptbookInformation__eiBL0 code{background:rgba(15,23,42,.06);border:1px solid rgba(15,23,42,.12);border-radius:6px;color:#111827;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,monospace;font-size:.9em;padding:.12em .34em}@keyframes BookEditor-module_fadeOut__q8JnR{0%{opacity:0}10%{opacity:1}70%{opacity:1}to{opacity:0}}\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkJvb2tFZGl0b3IubW9kdWxlLmNzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxxQ0FFSSxVQUNKLENBRUEsOENBS0kscUJBQXNCLENBSHRCLFdBQVksQ0FFWixtQkFBb0IsQ0FEcEIsaUJBQWtCLENBRmxCLFVBS0osQ0FFQSxpRkFFSSxnQ0FBcUMsQ0FDckMsaUNBRUosQ0FFQSxvQ0FDSSwwQkFDSixDQUVBLDRDQUtJLHFCQUF1QixDQUR2QixxQ0FBMEMsQ0FGMUMsa0JBQW1CLENBSW5CLHNDQUEyQyxDQUwzQyxlQUFnQixDQUVoQixnQkFBaUIsQ0FJakIscUNBQ0osQ0FDQSxnRkFFSSxnQkFFSixDQUVBLGtEQUNJLHVFQUNKLENBRUEsOEdBRUksdUVBQWtGLENBRGxGLCtCQUFvQyxDQUVwQyxzQ0FDSixDQUVBLG9IQUNJLHVDQUNKLENBVUEsNEZBQ0ksZUFDSixDQUVBLHNDQVNJLGtCQUFtQixDQUhuQiwrQkFBb0MsQ0FEcEMsUUFBUyxDQUVULFVBQVksQ0FDWixZQUFhLENBR2IsZ0JBQWlCLENBRGpCLHNCQUF1QixDQVB2QixNQUFPLENBVVAsbUJBQW9CLENBWnBCLGlCQUFrQixDQUdsQixPQUFRLENBRlIsS0FBTSxDQVVOLFdBRUosQ0FRQSw4Q0FDSSxpQkFBa0IsQ0FFbEIsVUFBVyxDQURYLFFBQVMsQ0FFVCxXQUNKLENBRUEscUNBV0ksV0FBWSxDQUZaLGVBQWdCLENBSmhCLFFBQVMsQ0FPVCxlQUFnQixDQUxoQixXQUFZLENBSlosTUFBTyxDQU9QLGdCQUFpQixDQVRqQixjQUFlLENBR2YsT0FBUSxDQUZSLEtBQU0sQ0FJTixVQUFXLENBRVgsWUFLSixDQUVBLGlDQU9JLGtCQUFtQixDQU5uQixxQkFBc0IsQ0FDdEIsd0JBQXlCLENBQ3pCLHFCQUF1QixDQU92QixzQ0FBMkMsQ0FEM0MsYUFBYyxDQUpkLGNBQWUsQ0FDZixtQkFBb0IsQ0FFcEIsU0FBVyxDQUpYLGtCQUFvQixDQU9wQiw4QkFDSixDQUVBLHVDQUNJLHdCQUF5QixDQUN6QixvQkFBcUIsQ0FDckIsaUVBQ0osQ0FFQSxtR0FDSSxtQ0FBd0MsQ0FDeEMsK0JBQW9DLENBRXBDLHVDQUE0QyxDQUQ1QyxhQUVKLENBRUEseUdBQ0ksbUNBQXdDLENBQ3hDLGlDQUFzQyxDQUN0Qyx1Q0FDSixDQUVBLDRDQWFJLGtCQUFtQixDQUVuQixzREFBOEIsQ0FWOUIsK0JBQW9DLENBR3BDLG1CQUFxQixDQUZyQixVQUFZLENBTVosWUFBYSxDQUhiLGlCQUFrQixDQUtsQixTQUFXLENBWFgsUUFBUyxDQUlULGlCQUFrQixDQUlsQixtQkFBb0IsQ0FWcEIsaUJBQWtCLENBQ2xCLE9BQVEsQ0FFUiw4QkFBZ0MsQ0FNaEMsWUFNSixDQUVBLDhHQUNJLGlDQUFzQyxDQUV0QyxrQ0FBdUMsQ0FEdkMsYUFFSixDQUVBLHNDQU1JLDhCQUFxQyxDQUNyQyxxQ0FBMEMsQ0FDMUMsa0JBQW1CLENBTG5CLFdBQVksQ0FNWix5Q0FBOEMsQ0FFOUMsWUFBYSxDQUNiLHFCQUFzQixDQUN0QixRQUFTLENBUlQsMkJBQTRCLENBSzVCLFlBQWEsQ0FUYixpQkFBa0IsQ0FDbEIsVUFBVyxDQUVYLFdBQVksQ0FVWixXQUNKLENBRUEsd0dBQ0ksNEJBQWlDLENBQ2pDLDhCQUFtQyxDQUNuQyx1Q0FDSixDQUVBLDRDQUVJLGtCQUFtQixDQURuQixZQUFhLENBR2IsUUFBUyxDQURULDZCQUVKLENBRUEsMkNBR0ksYUFBYyxDQURkLGdCQUFrQixDQURsQixlQUdKLENBRUEsNkdBQ0ksYUFDSixDQUVBLGdEQUVJLGFBQWMsQ0FEZCxnQkFFSixDQUVBLHViQUlJLGFBQ0osQ0FFQSw2Q0FLSSxhQUFjLENBSmQsWUFBYSxDQUdiLGdCQUFrQixDQURsQixZQUFhLENBRGIsNkJBSUosQ0FFQSxpREFFSSxrQkFBbUIsQ0FDbkIsbUJBQW9CLENBRnBCLFVBQVcsQ0FHWCxlQUNKLENBRUEsa0RBRUksaURBQW9ELENBRHBELFdBQVksQ0FFWix5QkFDSixDQUVBLG9PQUVJLGtCQUNKLENBRUEsMENBQ0ksWUFBYSxDQUNiLHFCQUFzQixDQUN0QixPQUFRLENBQ1IsZ0JBQWlCLENBQ2pCLGVBQWdCLENBQ2hCLGlCQUNKLENBRUEsb0NBT0ksZUFBZ0IsQ0FOaEIsd0JBQXlCLENBQ3pCLGtCQUFtQixDQUVuQixZQUFhLENBQ2IscUJBQXNCLENBQ3RCLE9BQVEsQ0FIUixXQUtKLENBRUEsc0dBRUksNkJBQWtDLENBRGxDLG9CQUVKLENBRUEsMENBRUksa0JBQW1CLENBRG5CLFlBQWEsQ0FHYixPQUFRLENBRFIsNkJBRUosQ0FFQSx3Q0FHSSxhQUFjLENBRmQsZUFBaUIsQ0FDakIsZUFBZ0IsQ0FFaEIsZUFBZ0IsQ0FDaEIsc0JBQXVCLENBQ3ZCLGtCQUNKLENBRUEsMEdBQ0ksYUFDSixDQUVBLDBDQUVJLGFBQWMsQ0FEZCxlQUVKLENBRUEsd0NBSUksYUFBYyxDQUhkLFlBQWEsQ0FFYixlQUFpQixDQURqQiw2QkFHSixDQUVBLCtDQUVJLGtCQUFtQixDQUNuQixtQkFBb0IsQ0FGcEIsVUFBVyxDQUdYLGVBQ0osQ0FFQSxnREFFSSxrQkFBbUIsQ0FEbkIsV0FBWSxDQUVaLHlCQUNKLENBRUEsMkNBQ0ksWUFBYSxDQUNiLE9BQ0osQ0FFQSw2Q0FFSSxrQkFBbUIsQ0FEbkIsd0JBQXlCLENBS3pCLGlCQUFrQixDQUhsQixhQUFjLENBSWQsY0FBZSxDQUhmLGVBQWlCLENBQ2pCLGVBQWdCLENBR2hCLCtCQUNKLENBRUEsbURBQ0ksa0JBQW1CLENBQ25CLG9CQUNKLENBRUEsK0dBRUksa0JBQW1CLENBRG5CLG9CQUFxQixDQUVyQixhQUNKLENBRUEscUhBQ0ksa0JBQW1CLENBQ25CLG9CQUNKLENBRUEseUNBRUksYUFBYyxDQURkLGVBRUosQ0FFQSxxREFFSSxhQUFjLENBQ2QsZ0dBQXNHLENBQ3RHLGdCQUFrQixDQUNsQixlQUFnQixDQUpoQixlQUtKLENBRUEsa0VBQ0ksWUFDSixDQUVBLGlFQUNJLGVBQ0osQ0FFQSxnSEFFSSxhQUFjLENBQ2QsZUFBZ0IsQ0FDaEIsZ0JBQ0osQ0FFQSx3REFFSSxnQkFBaUIsQ0FEakIsaUJBRUosQ0FFQSx3REFFSSxpQkFBa0IsQ0FEbEIsdUJBRUosQ0FFQSx1REFDSSxnQkFDSixDQUVBLGdIQUVJLFlBQWEsQ0FDYixVQUFZLENBQ1osb0JBQXNCLENBQ3RCLG9CQUNKLENBRUEsdURBQ0ksYUFBYyxDQUNkLHlCQUEwQixDQUMxQiwyQkFDSixDQUVBLDBEQUlJLDZCQUFrQyxDQUZsQyxtQ0FBd0MsQ0FDeEMsaUJBQWtCLENBRWxCLGFBQWMsQ0FDZCx1RkFBZ0csQ0FDaEcsY0FBZ0IsQ0FOaEIsbUJBT0osQ0FFQSw0Q0FDSSxHQUNJLFNBQ0osQ0FDQSxJQUNJLFNBQ0osQ0FDQSxJQUNJLFNBQ0osQ0FDQSxHQUNJLFNBQ0osQ0FDSiIsImZpbGUiOiJCb29rRWRpdG9yLm1vZHVsZS5jc3MiLCJzb3VyY2VzQ29udGVudCI6WyIuQm9va0VkaXRvciB7XG4gICAgLyogaGVpZ2h0OiA0NTBweDsgKi9cbiAgICB3aWR0aDogMTAwJTtcbn1cblxuLmJvb2tFZGl0b3JDb250YWluZXIge1xuICAgIHdpZHRoOiAxMDAlO1xuICAgIGhlaWdodDogMTAwJTtcbiAgICBwb3NpdGlvbjogcmVsYXRpdmU7XG4gICAgcGFkZGluZzogMTBweCAyNXB4IDA7XG4gICAgYm94LXNpemluZzogYm9yZGVyLWJveDtcbn1cblxuLmJvb2tFZGl0b3JDb250YWluZXIuaXNWZXJib3NlIHtcbiAgICAvKiovXG4gICAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSgwLCAwLCAwLCAwLjA1KTtcbiAgICBvdXRsaW5lOiAxcHggZG90dGVkIHJnYmEoMCwgMCwgMCwgMC41KTtcbiAgICAvKiovXG59XG5cbi5pc1ZlcmJvc2Uge1xuICAgIG91dGxpbmU6IDJweCBkb3R0ZWQgcmdiKDI1NSAxMTcgMzgpO1xufVxuXG4uYm9va0VkaXRvcldyYXBwZXIge1xuICAgIG92ZXJmbG93OiBoaWRkZW47XG4gICAgYm9yZGVyLXJhZGl1czogMXJlbTtcbiAgICBwYWRkaW5nLXRvcDogMTBweDtcbiAgICBib3JkZXI6IDFweCBzb2xpZCByZ2JhKDIwOSwgMjEzLCAyMTksIDAuOCk7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogd2hpdGU7XG4gICAgYm94LXNoYWRvdzogMCAxcHggMnB4IDAgcmdiYSgwLCAwLCAwLCAwLjA1KTtcbiAgICB0cmFuc2l0aW9uOiBib3gtc2hhZG93IDAuMnMgZWFzZS1pbi1vdXQ7XG59XG4uaXNWZXJib3NlIC5ib29rRWRpdG9yV3JhcHBlciB7XG4gICAgLyoqL1xuICAgIG92ZXJmbG93OiB2aXNpYmxlO1xuICAgIC8qKi9cbn1cblxuLmJvb2tFZGl0b3JXcmFwcGVyOmhvdmVyIHtcbiAgICBib3gtc2hhZG93OiAwIDRweCA2cHggLTFweCByZ2JhKDAsIDAsIDAsIDAuMSksIDAgMnB4IDRweCAtMXB4IHJnYmEoMCwgMCwgMCwgMC4wNik7XG59XG5cbi5Cb29rRWRpdG9yW2RhdGEtYm9vay1lZGl0b3ItdGhlbWU9J2RhcmsnXSAuYm9va0VkaXRvcldyYXBwZXIge1xuICAgIGJvcmRlci1jb2xvcjogcmdiYSg1MSwgNjUsIDg1LCAwLjkyKTtcbiAgICBiYWNrZ3JvdW5kOiBsaW5lYXItZ3JhZGllbnQoMTgwZGVnLCByZ2JhKDE1LCAyMywgNDIsIDAuOTgpLCByZ2JhKDgsIDE1LCAyOCwgMC45OCkpO1xuICAgIGJveC1zaGFkb3c6IDAgMjBweCA0NXB4IHJnYmEoMiwgNiwgMjMsIDAuNCk7XG59XG5cbi5Cb29rRWRpdG9yW2RhdGEtYm9vay1lZGl0b3ItdGhlbWU9J2RhcmsnXSAuYm9va0VkaXRvcldyYXBwZXI6aG92ZXIge1xuICAgIGJveC1zaGFkb3c6IDAgMjRweCA1MHB4IHJnYmEoMiwgNiwgMjMsIDAuNDgpO1xufVxuXG4uYm9va0VkaXRvcldyYXBwZXI6Zm9jdXMtd2l0aGluIHtcbiAgICAvKlxuICAgIG91dGxpbmU6IDJweCBzb2xpZCB0cmFuc3BhcmVudDtcbiAgICBvdXRsaW5lLW9mZnNldDogMnB4O1xuICAgIGJveC1zaGFkb3c6IDAgMCAwIDNweCByZ2JhKDk5LCAxMDIsIDI0MSwgMC40KTtcbiAgICAqL1xufVxuXG4uYm9va0VkaXRvcldyYXBwZXIuaXNCb3JkZXJSYWRpdXNEaXNhYmxlZCB7XG4gICAgYm9yZGVyLXJhZGl1czogMDtcbn1cblxuLmRyb3BPdmVybGF5IHtcbiAgICBwb3NpdGlvbjogYWJzb2x1dGU7XG4gICAgdG9wOiAwO1xuICAgIGxlZnQ6IDA7XG4gICAgcmlnaHQ6IDA7XG4gICAgYm90dG9tOiAwO1xuICAgIGJhY2tncm91bmQtY29sb3I6IHJnYmEoMCwgMCwgMCwgMC41KTtcbiAgICBjb2xvcjogd2hpdGU7XG4gICAgZGlzcGxheTogZmxleDtcbiAgICBhbGlnbi1pdGVtczogY2VudGVyO1xuICAgIGp1c3RpZnktY29udGVudDogY2VudGVyO1xuICAgIGZvbnQtc2l6ZTogMS41cmVtO1xuICAgIHotaW5kZXg6IDEwMDtcbiAgICBwb2ludGVyLWV2ZW50czogbm9uZTtcbn1cblxuLypcbi5ib29rRWRpdG9yQ29udGFpbmVyIDpnbG9iYWwoLnZpZXctbGluZSkge1xuICAgIGJvcmRlci1ib3R0b206IDFweCBzb2xpZCAjZWVlOyAvKiA8LSBOb3RlOiBgUFJPTVBUQk9PS19TWU5UQVhfQ09MT1JTLkxJTkVgICogL1xufVxuKi9cblxuLmJvb2tFZGl0b3JBY3Rpb25iYXIge1xuICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgICB0b3A6IDEwcHg7XG4gICAgcmlnaHQ6IDU1cHg7XG4gICAgei1pbmRleDogMTAwO1xufVxuXG4uZnVsbHNjcmVlbiB7XG4gICAgcG9zaXRpb246IGZpeGVkO1xuICAgIHRvcDogMDtcbiAgICBsZWZ0OiAwO1xuICAgIHJpZ2h0OiAwO1xuICAgIGJvdHRvbTogMDtcbiAgICB3aWR0aDogMTAwJTtcbiAgICBoZWlnaHQ6IDEwMCU7XG4gICAgei1pbmRleDogOTk5OTtcbiAgICBib3JkZXItcmFkaXVzOiAwO1xuICAgIHBhZGRpbmctdG9wOiA1MHB4O1xuICAgIGJvcmRlcjogbm9uZTtcbiAgICBib3gtc2hhZG93OiBub25lO1xufVxuXG4uYnV0dG9uIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmZmO1xuICAgIGJvcmRlcjogMXB4IHNvbGlkICNkMWQ1ZGI7XG4gICAgYm9yZGVyLXJhZGl1czogMC4zNzVyZW07XG4gICAgcGFkZGluZzogMC41cmVtIDFyZW07XG4gICAgY3Vyc29yOiBwb2ludGVyO1xuICAgIGRpc3BsYXk6IGlubGluZS1mbGV4O1xuICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gICAgZ2FwOiAwLjVyZW07XG4gICAgY29sb3I6ICMzNzQxNTE7XG4gICAgYm94LXNoYWRvdzogMCAxcHggMnB4IDAgcmdiYSgwLCAwLCAwLCAwLjA1KTtcbiAgICB0cmFuc2l0aW9uOiBhbGwgMC4ycyBlYXNlLWluLW91dDtcbn1cblxuLmJ1dHRvbjpob3ZlciB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogI2Y5ZmFmYjtcbiAgICBib3JkZXItY29sb3I6ICNiN2JjY2U7XG4gICAgYm94LXNoYWRvdzogMCAxcHggM3B4IDAgcmdiYSgwLCAwLCAwLCAwLjEpLCAwIDFweCAycHggMCByZ2JhKDAsIDAsIDAsIDAuMDYpO1xufVxuXG4uQm9va0VkaXRvcltkYXRhLWJvb2stZWRpdG9yLXRoZW1lPSdkYXJrJ10gLmJ1dHRvbiB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSgxNSwgMjMsIDQyLCAwLjkyKTtcbiAgICBib3JkZXItY29sb3I6IHJnYmEoNzEsIDg1LCAxMDUsIDAuOSk7XG4gICAgY29sb3I6ICNlMmU4ZjA7XG4gICAgYm94LXNoYWRvdzogMCAxcHggMnB4IDAgcmdiYSgyLCA2LCAyMywgMC4zNSk7XG59XG5cbi5Cb29rRWRpdG9yW2RhdGEtYm9vay1lZGl0b3ItdGhlbWU9J2RhcmsnXSAuYnV0dG9uOmhvdmVyIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDMwLCA0MSwgNTksIDAuOTgpO1xuICAgIGJvcmRlci1jb2xvcjogcmdiYSgxMjUsIDIxMSwgMjUyLCAwLjUpO1xuICAgIGJveC1zaGFkb3c6IDAgMTBweCAyNHB4IHJnYmEoMiwgNiwgMjMsIDAuMzUpO1xufVxuXG4uc2F2ZWROb3RpZmljYXRpb24ge1xuICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgICB0b3A6IDUwJTtcbiAgICBsZWZ0OiA1MCU7XG4gICAgdHJhbnNmb3JtOiB0cmFuc2xhdGUoLTUwJSwgLTUwJSk7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSgwLCAwLCAwLCAwLjcpO1xuICAgIGNvbG9yOiB3aGl0ZTtcbiAgICBwYWRkaW5nOiAxcmVtIDJyZW07XG4gICAgYm9yZGVyLXJhZGl1czogMC41cmVtO1xuICAgIGZvbnQtc2l6ZTogMS4yNXJlbTtcbiAgICB6LWluZGV4OiAxMDAwO1xuICAgIHBvaW50ZXItZXZlbnRzOiBub25lO1xuICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgICBnYXA6IDAuNXJlbTtcbiAgICBhbmltYXRpb246IGZhZGVPdXQgMnMgZm9yd2FyZHM7XG59XG5cbi5Cb29rRWRpdG9yW2RhdGEtYm9vay1lZGl0b3ItdGhlbWU9J2RhcmsnXSAuc2F2ZWROb3RpZmljYXRpb24ge1xuICAgIGJhY2tncm91bmQtY29sb3I6IHJnYmEoMiwgNiwgMjMsIDAuODYpO1xuICAgIGNvbG9yOiAjZTJlOGYwO1xuICAgIGJvcmRlcjogMXB4IHNvbGlkIHJnYmEoNTEsIDY1LCA4NSwgMC45KTtcbn1cblxuLnVwbG9hZFBhbmVsIHtcbiAgICBwb3NpdGlvbjogYWJzb2x1dGU7XG4gICAgcmlnaHQ6IDIwcHg7XG4gICAgYm90dG9tOiAyMHB4O1xuICAgIHdpZHRoOiA0MjBweDtcbiAgICBtYXgtd2lkdGg6IGNhbGMoMTAwJSAtIDQwcHgpO1xuICAgIGJhY2tncm91bmQ6IHJnYmEoMjU1LCAyNTUsIDI1NSwgMC45OCk7XG4gICAgYm9yZGVyOiAxcHggc29saWQgcmdiYSgyMDksIDIxMywgMjE5LCAwLjkpO1xuICAgIGJvcmRlci1yYWRpdXM6IDEycHg7XG4gICAgYm94LXNoYWRvdzogMCAxMnB4IDMwcHggcmdiYSgxNSwgMjMsIDQyLCAwLjE1KTtcbiAgICBwYWRkaW5nOiAxMnB4O1xuICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcbiAgICBnYXA6IDEwcHg7XG4gICAgei1pbmRleDogMjIwO1xufVxuXG4uQm9va0VkaXRvcltkYXRhLWJvb2stZWRpdG9yLXRoZW1lPSdkYXJrJ10gLnVwbG9hZFBhbmVsIHtcbiAgICBiYWNrZ3JvdW5kOiByZ2JhKDgsIDE1LCAyOCwgMC45Nik7XG4gICAgYm9yZGVyLWNvbG9yOiByZ2JhKDUxLCA2NSwgODUsIDAuOSk7XG4gICAgYm94LXNoYWRvdzogMCAxOHB4IDQwcHggcmdiYSgyLCA2LCAyMywgMC40NSk7XG59XG5cbi51cGxvYWRQYW5lbEhlYWRlciB7XG4gICAgZGlzcGxheTogZmxleDtcbiAgICBhbGlnbi1pdGVtczogY2VudGVyO1xuICAgIGp1c3RpZnktY29udGVudDogc3BhY2UtYmV0d2VlbjtcbiAgICBnYXA6IDEycHg7XG59XG5cbi51cGxvYWRQYW5lbFRpdGxlIHtcbiAgICBmb250LXdlaWdodDogNjAwO1xuICAgIGZvbnQtc2l6ZTogMC45NXJlbTtcbiAgICBjb2xvcjogIzExMTgyNztcbn1cblxuLkJvb2tFZGl0b3JbZGF0YS1ib29rLWVkaXRvci10aGVtZT0nZGFyayddIC51cGxvYWRQYW5lbFRpdGxlIHtcbiAgICBjb2xvcjogI2Y4ZmFmYztcbn1cblxuLnVwbG9hZFBhbmVsSGVhZGVyTWV0YSB7XG4gICAgZm9udC1zaXplOiAwLjc1cmVtO1xuICAgIGNvbG9yOiAjNmI3MjgwO1xufVxuXG4uQm9va0VkaXRvcltkYXRhLWJvb2stZWRpdG9yLXRoZW1lPSdkYXJrJ10gLnVwbG9hZFBhbmVsSGVhZGVyTWV0YSxcbi5Cb29rRWRpdG9yW2RhdGEtYm9vay1lZGl0b3ItdGhlbWU9J2RhcmsnXSAudXBsb2FkUGFuZWxTdW1tYXJ5LFxuLkJvb2tFZGl0b3JbZGF0YS1ib29rLWVkaXRvci10aGVtZT0nZGFyayddIC51cGxvYWRSb3dTdGF0dXMsXG4uQm9va0VkaXRvcltkYXRhLWJvb2stZWRpdG9yLXRoZW1lPSdkYXJrJ10gLnVwbG9hZFJvd01ldGEge1xuICAgIGNvbG9yOiAjOTRhM2I4O1xufVxuXG4udXBsb2FkUGFuZWxTdW1tYXJ5IHtcbiAgICBkaXNwbGF5OiBncmlkO1xuICAgIGdyaWQtdGVtcGxhdGUtY29sdW1uczogMWZyIDFmcjtcbiAgICBnYXA6IDRweCAxMnB4O1xuICAgIGZvbnQtc2l6ZTogMC43NXJlbTtcbiAgICBjb2xvcjogIzZiNzI4MDtcbn1cblxuLnVwbG9hZFBhbmVsUHJvZ3Jlc3NCYXIge1xuICAgIGhlaWdodDogNnB4O1xuICAgIGJhY2tncm91bmQ6ICNlNWU3ZWI7XG4gICAgYm9yZGVyLXJhZGl1czogOTk5cHg7XG4gICAgb3ZlcmZsb3c6IGhpZGRlbjtcbn1cblxuLnVwbG9hZFBhbmVsUHJvZ3Jlc3NGaWxsIHtcbiAgICBoZWlnaHQ6IDEwMCU7XG4gICAgYmFja2dyb3VuZDogbGluZWFyLWdyYWRpZW50KDkwZGVnLCAjMjU2M2ViLCAjMTBiOTgxKTtcbiAgICB0cmFuc2l0aW9uOiB3aWR0aCAwLjJzIGVhc2U7XG59XG5cbi5Cb29rRWRpdG9yW2RhdGEtYm9vay1lZGl0b3ItdGhlbWU9J2RhcmsnXSAudXBsb2FkUGFuZWxQcm9ncmVzc0Jhcixcbi5Cb29rRWRpdG9yW2RhdGEtYm9vay1lZGl0b3ItdGhlbWU9J2RhcmsnXSAudXBsb2FkUm93UHJvZ3Jlc3NCYXIge1xuICAgIGJhY2tncm91bmQ6ICMxZTI5M2I7XG59XG5cbi51cGxvYWRQYW5lbExpc3Qge1xuICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcbiAgICBnYXA6IDhweDtcbiAgICBtYXgtaGVpZ2h0OiAyMjBweDtcbiAgICBvdmVyZmxvdy15OiBhdXRvO1xuICAgIHBhZGRpbmctcmlnaHQ6IDRweDtcbn1cblxuLnVwbG9hZFJvdyB7XG4gICAgYm9yZGVyOiAxcHggc29saWQgI2U1ZTdlYjtcbiAgICBib3JkZXItcmFkaXVzOiAxMHB4O1xuICAgIHBhZGRpbmc6IDhweDtcbiAgICBkaXNwbGF5OiBmbGV4O1xuICAgIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XG4gICAgZ2FwOiA2cHg7XG4gICAgYmFja2dyb3VuZDogI2ZmZjtcbn1cblxuLkJvb2tFZGl0b3JbZGF0YS1ib29rLWVkaXRvci10aGVtZT0nZGFyayddIC51cGxvYWRSb3cge1xuICAgIGJvcmRlci1jb2xvcjogIzMzNDE1NTtcbiAgICBiYWNrZ3JvdW5kOiByZ2JhKDE1LCAyMywgNDIsIDAuOTIpO1xufVxuXG4udXBsb2FkUm93SGVhZGVyIHtcbiAgICBkaXNwbGF5OiBmbGV4O1xuICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gICAganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuO1xuICAgIGdhcDogOHB4O1xufVxuXG4udXBsb2FkUm93TmFtZSB7XG4gICAgZm9udC1zaXplOiAwLjhyZW07XG4gICAgZm9udC13ZWlnaHQ6IDYwMDtcbiAgICBjb2xvcjogIzExMTgyNztcbiAgICBvdmVyZmxvdzogaGlkZGVuO1xuICAgIHRleHQtb3ZlcmZsb3c6IGVsbGlwc2lzO1xuICAgIHdoaXRlLXNwYWNlOiBub3dyYXA7XG59XG5cbi5Cb29rRWRpdG9yW2RhdGEtYm9vay1lZGl0b3ItdGhlbWU9J2RhcmsnXSAudXBsb2FkUm93TmFtZSB7XG4gICAgY29sb3I6ICNmOGZhZmM7XG59XG5cbi51cGxvYWRSb3dTdGF0dXMge1xuICAgIGZvbnQtc2l6ZTogMC43cmVtO1xuICAgIGNvbG9yOiAjNmI3MjgwO1xufVxuXG4udXBsb2FkUm93TWV0YSB7XG4gICAgZGlzcGxheTogZmxleDtcbiAgICBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47XG4gICAgZm9udC1zaXplOiAwLjdyZW07XG4gICAgY29sb3I6ICM2YjcyODA7XG59XG5cbi51cGxvYWRSb3dQcm9ncmVzc0JhciB7XG4gICAgaGVpZ2h0OiA0cHg7XG4gICAgYmFja2dyb3VuZDogI2U1ZTdlYjtcbiAgICBib3JkZXItcmFkaXVzOiA5OTlweDtcbiAgICBvdmVyZmxvdzogaGlkZGVuO1xufVxuXG4udXBsb2FkUm93UHJvZ3Jlc3NGaWxsIHtcbiAgICBoZWlnaHQ6IDEwMCU7XG4gICAgYmFja2dyb3VuZDogIzNiODJmNjtcbiAgICB0cmFuc2l0aW9uOiB3aWR0aCAwLjJzIGVhc2U7XG59XG5cbi51cGxvYWRSb3dBY3Rpb25zIHtcbiAgICBkaXNwbGF5OiBmbGV4O1xuICAgIGdhcDogNnB4O1xufVxuXG4udXBsb2FkQWN0aW9uQnV0dG9uIHtcbiAgICBib3JkZXI6IDFweCBzb2xpZCAjZDFkNWRiO1xuICAgIGJhY2tncm91bmQ6ICNmOWZhZmI7XG4gICAgY29sb3I6ICMzNzQxNTE7XG4gICAgZm9udC1zaXplOiAwLjdyZW07XG4gICAgcGFkZGluZzogMnB4IDhweDtcbiAgICBib3JkZXItcmFkaXVzOiA2cHg7XG4gICAgY3Vyc29yOiBwb2ludGVyO1xuICAgIHRyYW5zaXRpb246IGFsbCAwLjE1cyBlYXNlLWluLW91dDtcbn1cblxuLnVwbG9hZEFjdGlvbkJ1dHRvbjpob3ZlciB7XG4gICAgYmFja2dyb3VuZDogI2VlZjJmNztcbiAgICBib3JkZXItY29sb3I6ICNjYmQ1ZjU7XG59XG5cbi5Cb29rRWRpdG9yW2RhdGEtYm9vay1lZGl0b3ItdGhlbWU9J2RhcmsnXSAudXBsb2FkQWN0aW9uQnV0dG9uIHtcbiAgICBib3JkZXItY29sb3I6ICM0NzU1Njk7XG4gICAgYmFja2dyb3VuZDogIzBmMTcyYTtcbiAgICBjb2xvcjogI2UyZThmMDtcbn1cblxuLkJvb2tFZGl0b3JbZGF0YS1ib29rLWVkaXRvci10aGVtZT0nZGFyayddIC51cGxvYWRBY3Rpb25CdXR0b246aG92ZXIge1xuICAgIGJhY2tncm91bmQ6ICMxZTI5M2I7XG4gICAgYm9yZGVyLWNvbG9yOiAjN2RkM2ZjO1xufVxuXG4udXBsb2FkUm93RXJyb3Ige1xuICAgIGZvbnQtc2l6ZTogMC43cmVtO1xuICAgIGNvbG9yOiAjYjkxYzFjO1xufVxuXG4uYWJvdXRQcm9tcHRib29rSW5mb3JtYXRpb24ge1xuICAgIG1heC13aWR0aDogNjgwcHg7XG4gICAgY29sb3I6ICMxMTE4Mjc7XG4gICAgZm9udC1mYW1pbHk6IHZhcigtLWZvbnQtcG9wcGlucywgc3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBCbGlua01hY1N5c3RlbUZvbnQsICdTZWdvZSBVSScsIHNhbnMtc2VyaWYpO1xuICAgIGZvbnQtc2l6ZTogMC45NXJlbTtcbiAgICBsaW5lLWhlaWdodDogMS42O1xufVxuXG4uYWJvdXRQcm9tcHRib29rSW5mb3JtYXRpb24gPiA6Zmlyc3QtY2hpbGQge1xuICAgIG1hcmdpbi10b3A6IDA7XG59XG5cbi5hYm91dFByb21wdGJvb2tJbmZvcm1hdGlvbiA+IDpsYXN0LWNoaWxkIHtcbiAgICBtYXJnaW4tYm90dG9tOiAwO1xufVxuXG4uYWJvdXRQcm9tcHRib29rSW5mb3JtYXRpb24gaDEsXG4uYWJvdXRQcm9tcHRib29rSW5mb3JtYXRpb24gaDIge1xuICAgIGNvbG9yOiAjMGYxNzJhO1xuICAgIGZvbnQtd2VpZ2h0OiA2NTA7XG4gICAgbGluZS1oZWlnaHQ6IDEuMjU7XG59XG5cbi5hYm91dFByb21wdGJvb2tJbmZvcm1hdGlvbiBoMSB7XG4gICAgbWFyZ2luOiAwIDAgMC43NXJlbTtcbiAgICBmb250LXNpemU6IDEuNXJlbTtcbn1cblxuLmFib3V0UHJvbXB0Ym9va0luZm9ybWF0aW9uIGgyIHtcbiAgICBtYXJnaW46IDEuMzVyZW0gMCAwLjU1cmVtO1xuICAgIGZvbnQtc2l6ZTogMS4xNXJlbTtcbn1cblxuLmFib3V0UHJvbXB0Ym9va0luZm9ybWF0aW9uIHAge1xuICAgIG1hcmdpbjogMCAwIDAuOXJlbTtcbn1cblxuLmFib3V0UHJvbXB0Ym9va0luZm9ybWF0aW9uIHVsLFxuLmFib3V0UHJvbXB0Ym9va0luZm9ybWF0aW9uIG9sIHtcbiAgICBkaXNwbGF5OiBncmlkO1xuICAgIGdhcDogMC4zNXJlbTtcbiAgICBtYXJnaW46IDAuNTVyZW0gMCAxcmVtO1xuICAgIHBhZGRpbmctbGVmdDogMS4zNXJlbTtcbn1cblxuLmFib3V0UHJvbXB0Ym9va0luZm9ybWF0aW9uIGEge1xuICAgIGNvbG9yOiAjMjU2M2ViO1xuICAgIHRleHQtZGVjb3JhdGlvbjogdW5kZXJsaW5lO1xuICAgIHRleHQtdW5kZXJsaW5lLW9mZnNldDogMC4xNmVtO1xufVxuXG4uYWJvdXRQcm9tcHRib29rSW5mb3JtYXRpb24gY29kZSB7XG4gICAgcGFkZGluZzogMC4xMmVtIDAuMzRlbTtcbiAgICBib3JkZXI6IDFweCBzb2xpZCByZ2JhKDE1LCAyMywgNDIsIDAuMTIpO1xuICAgIGJvcmRlci1yYWRpdXM6IDZweDtcbiAgICBiYWNrZ3JvdW5kOiByZ2JhKDE1LCAyMywgNDIsIDAuMDYpO1xuICAgIGNvbG9yOiAjMTExODI3O1xuICAgIGZvbnQtZmFtaWx5OiB1aS1tb25vc3BhY2UsIFNGTW9uby1SZWd1bGFyLCBNZW5sbywgTW9uYWNvLCBDb25zb2xhcywgJ0xpYmVyYXRpb24gTW9ubycsIG1vbm9zcGFjZTtcbiAgICBmb250LXNpemU6IDAuOWVtO1xufVxuXG5Aa2V5ZnJhbWVzIGZhZGVPdXQge1xuICAgIDAlIHtcbiAgICAgICAgb3BhY2l0eTogMDtcbiAgICB9XG4gICAgMTAlIHtcbiAgICAgICAgb3BhY2l0eTogMTtcbiAgICB9XG4gICAgNzAlIHtcbiAgICAgICAgb3BhY2l0eTogMTtcbiAgICB9XG4gICAgMTAwJSB7XG4gICAgICAgIG9wYWNpdHk6IDA7XG4gICAgfVxufVxuIl19 */";
21615
21821
  var styles$d = {"BookEditor":"BookEditor-module_BookEditor__s-0PU","bookEditorContainer":"BookEditor-module_bookEditorContainer__wLMwM","isVerbose":"BookEditor-module_isVerbose__VQ6iL","bookEditorWrapper":"BookEditor-module_bookEditorWrapper__twppD","isBorderRadiusDisabled":"BookEditor-module_isBorderRadiusDisabled__h1I3v","dropOverlay":"BookEditor-module_dropOverlay__xWWoX","bookEditorActionbar":"BookEditor-module_bookEditorActionbar__KW6dc","fullscreen":"BookEditor-module_fullscreen__rktsl","button":"BookEditor-module_button__hS390","savedNotification":"BookEditor-module_savedNotification__OiX9L","fadeOut":"BookEditor-module_fadeOut__q8JnR","uploadPanel":"BookEditor-module_uploadPanel__2JJtD","uploadPanelHeader":"BookEditor-module_uploadPanelHeader__pdJd2","uploadPanelTitle":"BookEditor-module_uploadPanelTitle__TJIVF","uploadPanelHeaderMeta":"BookEditor-module_uploadPanelHeaderMeta__Xw0uI","uploadPanelSummary":"BookEditor-module_uploadPanelSummary__rwSbG","uploadRowStatus":"BookEditor-module_uploadRowStatus__jsUb-","uploadRowMeta":"BookEditor-module_uploadRowMeta__1lz9h","uploadPanelProgressBar":"BookEditor-module_uploadPanelProgressBar__a6pjf","uploadPanelProgressFill":"BookEditor-module_uploadPanelProgressFill__l-TKR","uploadRowProgressBar":"BookEditor-module_uploadRowProgressBar__NoBA7","uploadPanelList":"BookEditor-module_uploadPanelList__VxEd5","uploadRow":"BookEditor-module_uploadRow__QiSFg","uploadRowHeader":"BookEditor-module_uploadRowHeader__po0j5","uploadRowName":"BookEditor-module_uploadRowName__doQRO","uploadRowProgressFill":"BookEditor-module_uploadRowProgressFill__TrP7e","uploadRowActions":"BookEditor-module_uploadRowActions__5Y1Mq","uploadActionButton":"BookEditor-module_uploadActionButton__CqJrr","uploadRowError":"BookEditor-module_uploadRowError__eEHWw","aboutPromptbookInformation":"BookEditor-module_aboutPromptbookInformation__eiBL0"};
21616
21822
  styleInject(css_248z$d);
@@ -21642,135 +21848,6 @@
21642
21848
  return (jsxRuntime.jsxs("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: color, strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", ...props, children: [jsxRuntime.jsx("path", { d: "M4 17V7a3 3 0 0 1 3-3h10a3 3 0 0 1 3 3v7a3 3 0 0 1-3 3H7l-3 3z", fill: color, fillOpacity: "0.08", stroke: color }), jsxRuntime.jsx("path", { d: "M12 9v5", stroke: color }), jsxRuntime.jsx("path", { d: "M9.5 12.5L12 15l2.5-2.5", stroke: color })] }));
21643
21849
  }
21644
21850
 
21645
- /**
21646
- * Detects if the code is running in a browser environment in main thread (Not in a web worker)
21647
- *
21648
- * Note: `$` is used to indicate that this function is not a pure function - it looks at the global object to determine the environment
21649
- *
21650
- * @public exported from `@promptbook/utils`
21651
- */
21652
- function $isRunningInBrowser() {
21653
- try {
21654
- return typeof window !== 'undefined' && typeof window.document !== 'undefined';
21655
- }
21656
- catch (e) {
21657
- return false;
21658
- }
21659
- }
21660
- // TODO: [🎺]
21661
-
21662
- /**
21663
- * Converts Blob, File or MediaSource to url using URL.createObjectURL
21664
- *
21665
- * @public exported from `@promptbook/browser`
21666
- */
21667
- class ObjectUrl extends destroyable.Registration {
21668
- constructor(teardownLogic, src) {
21669
- super(teardownLogic);
21670
- this.src = src;
21671
- }
21672
- /**
21673
- * Creates ObjectUrl from multiple input types
21674
- * Note: DO NOT forget to call destroy() when you are done with it
21675
- */
21676
- static from(source, mimeType) {
21677
- if (typeof source === 'string') {
21678
- return ObjectUrl.fromString(source, mimeType);
21679
- }
21680
- if ((source instanceof Blob || source instanceof File) && source.type !== mimeType) {
21681
- throw new Error(`Source type ${source.type} does not match given mimeType ${mimeType}`);
21682
- }
21683
- return ObjectUrl.fromBlob(source);
21684
- }
21685
- /**
21686
- * Creates ObjectUrl from string
21687
- * Note: DO NOT forget to call destroy() when you are done with it
21688
- */
21689
- static fromString(source, mimeType) {
21690
- return ObjectUrl.fromBlob(new Blob([source], { type: mimeType }));
21691
- }
21692
- /**
21693
- * Creates ObjectUrl
21694
- * DO NOT forget to call destroy() when you are done with it
21695
- */
21696
- static fromBlob(source) {
21697
- const src = URL.createObjectURL(source);
21698
- return new ObjectUrl(() => {
21699
- URL.revokeObjectURL(src);
21700
- }, src);
21701
- }
21702
- /**
21703
- * Creates ObjectUrl:
21704
- * 1) With functionality for Blobs, Files or MediaSources
21705
- * 2) Just a wrapper for string urls
21706
- *
21707
- * DO NOT forget to call destroy() when you are done with it
21708
- */
21709
- static fromBlobOrUrl(source) {
21710
- if (typeof source === 'string' || source instanceof URL /* <- TODO: Probably check isValidUrl */) {
21711
- return new ObjectUrl(() => {
21712
- // Note: Nothing to do here
21713
- }, source.toString());
21714
- }
21715
- else {
21716
- return ObjectUrl.fromBlob(source);
21717
- }
21718
- }
21719
- /**
21720
- * Gets object url as string
21721
- * @alias src
21722
- */
21723
- get href() {
21724
- return this.src;
21725
- }
21726
- /**
21727
- * Gets object url as URL object
21728
- */
21729
- get url() {
21730
- return new URL(this.src);
21731
- }
21732
- }
21733
- // Note: [🔵] Code for browser file helper [ObjectUrl](src/utils/files/ObjectUrl.ts) should never be published outside of `@promptbook/browser`
21734
-
21735
- /**
21736
- * Download a File in a browser
21737
- *
21738
- * Note: `$` is used to indicate that this function is not a pure function - its purpose is to cause a side effect (download a file)
21739
- *
21740
- * @public exported from `@promptbook/browser`
21741
- */
21742
- async function $induceFileDownload(fileOrBlobOrUrl) {
21743
- if (!$isRunningInBrowser()) {
21744
- throw new Error('Function `$induceFileDownload` is available ONLY in browser');
21745
- }
21746
- const objectUrl = ObjectUrl.fromBlobOrUrl(fileOrBlobOrUrl);
21747
- const link = window.document.createElement('a');
21748
- link.href = objectUrl.href;
21749
- link.download = fileOrBlobOrUrl.name || 'untitled' /* <- TODO: Add proper extension according to url */;
21750
- link.click();
21751
- await objectUrl.destroy();
21752
- }
21753
- // Note: [🔵] Code for browser file helper [$induceFileDownload](src/utils/files/$induceFileDownload.ts) should never be published outside of `@promptbook/browser`
21754
-
21755
- /**
21756
- * Download a Book in a browser
21757
- *
21758
- * Note: `$` is used to indicate that this function is not a pure function - its purpose is to cause a side effect (download a file)
21759
- *
21760
- * @public exported from `@promptbook/browser`
21761
- */
21762
- async function $induceBookDownload(book) {
21763
- if (!$isRunningInBrowser()) {
21764
- throw new Error('Function `$induceBookDownload` is available ONLY in browser');
21765
- }
21766
- const { agentName } = parseAgentSource(book);
21767
- const bookFile = new File([book], `${titleToName(agentName || 'AI Avatar')}.book`, {
21768
- type: 'application/json',
21769
- });
21770
- return /* not await */ $induceFileDownload(bookFile);
21771
- }
21772
- // Note: [🔵] Code for browser file helper [$induceBookDownload](src/utils/files/$induceBookDownload.ts) should never be published outside of `@promptbook/browser`
21773
-
21774
21851
  /**
21775
21852
  * Renders an information/about icon.
21776
21853
  *
@@ -21987,54 +22064,21 @@
21987
22064
  }
21988
22065
 
21989
22066
  /**
21990
- * Core Promptbook server configuration
21991
- *
21992
- * Used for "Adam" agent which is built in as default ancestor for new agents and other well known agents
21993
- *
21994
- * @public exported from `@promptbook/core`
21995
- */
21996
- const CORE_AGENTS_SERVER = {
21997
- title: 'Promptbook Core',
21998
- description: `Core Promptbook server used for Adam agent which is built in as default ancestor for new agents and other well known agents.`,
21999
- owner: PROMPTBOOK_LEGAL_ENTITY,
22000
- url: 'https://core.ptbk.io/',
22001
- };
22002
- // <- TODO: [🆎] Allow to override (set) well-known agent names via Metadata
22003
- /**
22004
- * Available agents servers for the Promptbook
22067
+ * Detects if the code is running in a browser environment in main thread (Not in a web worker)
22005
22068
  *
22006
- * Tip: 💡 If you are running your own server, you can add it to this list by creating a pull request!
22069
+ * Note: `$` is used to indicate that this function is not a pure function - it looks at the global object to determine the environment
22007
22070
  *
22008
- * @public exported from `@promptbook/core`
22071
+ * @public exported from `@promptbook/utils`
22009
22072
  */
22010
- const PUBLIC_AGENTS_SERVERS = [
22011
- CORE_AGENTS_SERVER,
22012
- {
22013
- title: 'Promptbook Gallery',
22014
- description: `Gallery of ideas, AI professions,... like AI Agenta photobank.`,
22015
- owner: PROMPTBOOK_LEGAL_ENTITY,
22016
- url: 'https://gallery.ptbk.io/',
22017
- },
22018
- {
22019
- title: 'Promptbook Testing server 6',
22020
- description: `General-purpose testing server.`,
22021
- owner: PROMPTBOOK_LEGAL_ENTITY,
22022
- url: 'https://s6.ptbk.io/',
22023
- },
22024
- {
22025
- title: 'Promptbook Testing server 7',
22026
- description: `General-purpose testing server.`,
22027
- owner: PROMPTBOOK_LEGAL_ENTITY,
22028
- url: 'https://s7.ptbk.io/',
22029
- },
22030
- {
22031
- title: 'Promptbook Testing server 8',
22032
- description: `General-purpose testing server.`,
22033
- owner: PROMPTBOOK_LEGAL_ENTITY,
22034
- url: 'https://s8.ptbk.io/',
22035
- },
22036
- ];
22037
- // Note: [💞] Ignore a discrepancy between file name and entity name
22073
+ function $isRunningInBrowser() {
22074
+ try {
22075
+ return typeof window !== 'undefined' && typeof window.document !== 'undefined';
22076
+ }
22077
+ catch (e) {
22078
+ return false;
22079
+ }
22080
+ }
22081
+ // TODO: [🎺]
22038
22082
 
22039
22083
  /**
22040
22084
  * Detects if the code is running in jest environment
@@ -22124,9 +22168,32 @@
22124
22168
  ...$detectRuntimeEnvironment(),
22125
22169
  isCostPrevented: IS_COST_PREVENTED,
22126
22170
  };
22127
- return (jsxRuntime.jsxs("div", { className: styles$d.aboutPromptbookInformation, children: [jsxRuntime.jsx("h1", { children: NAME }), jsxRuntime.jsx("p", { children: CLAIM }), jsxRuntime.jsxs("ul", { children: [jsxRuntime.jsx("li", { children: jsxRuntime.jsxs("a", { href: "https://github.com/webgptorg/promptbook", target: "_blank", rel: "noopener noreferrer", children: ["Promptbook engine version ", jsxRuntime.jsx("code", { children: PROMPTBOOK_ENGINE_VERSION })] }) }), jsxRuntime.jsx("li", { children: jsxRuntime.jsxs("a", { href: "https://github.com/webgptorg/book", target: "_blank", rel: "noopener noreferrer", children: ["Book language version ", jsxRuntime.jsx("code", { children: BOOK_LANGUAGE_VERSION })] }) })] }), isServersInfoIncluded && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("h2", { children: "Servers" }), jsxRuntime.jsx("ol", { children: PUBLIC_AGENTS_SERVERS.map(({ title, description, url }) => (jsxRuntime.jsxs("li", { children: [jsxRuntime.jsx("strong", { children: title }), " ", description, ' ', jsxRuntime.jsx("a", { href: url, target: "_blank", rel: "noopener noreferrer", children: url })] }, url))) })] })), isRuntimeEnvironmentInfoIncluded && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("h2", { children: "Environment" }), jsxRuntime.jsx("ul", { children: Object.entries(runtimeEnvironmentInfo).map(([key, value]) => (jsxRuntime.jsxs("li", { children: [jsxRuntime.jsxs("strong", { children: [key, ":"] }), " ", valueToString(value)] }, key))) })] }))] }));
22171
+ return (jsxRuntime.jsxs("div", { className: styles$d.aboutPromptbookInformation, children: [jsxRuntime.jsx("h1", { children: NAME }), jsxRuntime.jsx("p", { children: CLAIM }), jsxRuntime.jsxs("ul", { children: [jsxRuntime.jsx("li", { children: jsxRuntime.jsxs("a", { href: "https://github.com/webgptorg/promptbook", target: "_blank", rel: "noopener noreferrer", children: ["Promptbook engine version ", jsxRuntime.jsx("code", { children: PROMPTBOOK_ENGINE_VERSION })] }) }), jsxRuntime.jsx("li", { children: jsxRuntime.jsxs("a", { href: "https://github.com/webgptorg/book", target: "_blank", rel: "noopener noreferrer", children: ["Book language version ", jsxRuntime.jsx("code", { children: BOOK_LANGUAGE_VERSION })] }) })] }), isServersInfoIncluded && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("h2", { children: "Servers" }), jsxRuntime.jsx("ol", { children: PUBLIC_AGENTS_SERVERS.map(({ title, description, url }) => (jsxRuntime.jsxs("li", { children: [jsxRuntime.jsx("strong", { children: title }), " ", description, ' ', jsxRuntime.jsx("a", { href: url, target: "_blank", rel: "noopener noreferrer", children: url })] }, url))) })] })), isRuntimeEnvironmentInfoIncluded && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("h2", { children: "Environment" }), jsxRuntime.jsx("ul", { children: Object.entries(runtimeEnvironmentInfo).map(([key, value]) => (jsxRuntime.jsxs("li", { children: [jsxRuntime.jsxs("strong", { children: [key, ":"] }), " ", String(value)] }, key))) })] }))] }));
22128
22172
  }
22129
22173
 
22174
+ function induceBookDownloadInBrowser(book) {
22175
+ const filename = `${normalizeBookDownloadName(extractBookTitle(book) || 'AI Avatar')}.book`;
22176
+ const objectUrl = URL.createObjectURL(new Blob([book], { type: 'application/json' }));
22177
+ const link = window.document.createElement('a');
22178
+ link.href = objectUrl;
22179
+ link.download = filename;
22180
+ link.click();
22181
+ URL.revokeObjectURL(objectUrl);
22182
+ }
22183
+ function extractBookTitle(book) {
22184
+ return (book
22185
+ .split(/\r?\n/)
22186
+ .map((line) => line.trim())
22187
+ .find(Boolean) || null);
22188
+ }
22189
+ function normalizeBookDownloadName(value) {
22190
+ return (value
22191
+ .normalize('NFD')
22192
+ .replace(/[\u0300-\u036f]/g, '')
22193
+ .replace(/[^\dA-Za-z]+/g, '-')
22194
+ .replace(/^-+|-+$/g, '')
22195
+ .toLowerCase() || 'ai-avatar');
22196
+ }
22130
22197
  /**
22131
22198
  * Handles book editor actionbar.
22132
22199
  *
@@ -22143,7 +22210,7 @@
22143
22210
  }, [value]);
22144
22211
  const handleDownload = react.useCallback(() => {
22145
22212
  const book = validateBook(valueRef.current || DEFAULT_BOOK);
22146
- /* not await */ $induceBookDownload(book);
22213
+ induceBookDownloadInBrowser(book);
22147
22214
  }, []);
22148
22215
  const actions = react.useMemo(() => {
22149
22216
  const _actions = [...(hoistedMenuItems || [])];
@@ -22258,144 +22325,15 @@
22258
22325
  }
22259
22326
 
22260
22327
  /**
22261
- * Gets a commitment definition by its type
22328
+ * Browser-compatible stub for `createDeprecatedCommitmentDiagnostics`.
22262
22329
  *
22263
- * @param type The commitment type to look up
22264
- * @returns The commitment definition or null if not found
22265
- *
22266
- * @public exported from `@promptbook/core`
22267
- */
22268
- function getCommitmentDefinition(type) {
22269
- return COMMITMENT_REGISTRY.find((commitmentDefinition) => commitmentDefinition.type === type) || null;
22270
- }
22271
-
22272
- /**
22273
- * Warning message used for unfinished commitments.
22274
- */
22275
- const UNFINISHED_COMMITMENT_MESSAGE = 'This commitment is unfinished and not ready to use. Be careful when using it.';
22276
- /**
22277
- * Low-level warning message used for low-level commitments.
22278
- */
22279
- const LOW_LEVEL_COMMITMENT_MESSAGE = 'This commitment is low-level and not used by most of the users. Be careful when using it.';
22280
- /**
22281
- * Short badge text used for deprecated commitments.
22282
- */
22283
- const DEPRECATED_COMMITMENT_BADGE_LABEL = 'Deprecated';
22284
- /**
22285
- * Short badge text used for unfinished and low-level commitments.
22286
- */
22287
- const LOW_LEVEL_COMMITMENT_BADGE_LABEL = 'Low-level';
22288
- /**
22289
- * Longer label used for deprecated commitments.
22290
- */
22291
- const DEPRECATED_COMMITMENT_DETAIL_LABEL = 'Deprecated commitment';
22292
- /**
22293
- * Longer label used for unfinished and low-level commitments.
22294
- */
22295
- const LOW_LEVEL_COMMITMENT_DETAIL_LABEL = 'Low-level commitment';
22296
- /**
22297
- * Prefix used when formatting replacement guidance.
22298
- */
22299
- const PREFERRED_REPLACEMENT_LABEL = 'Preferred replacement';
22300
- /**
22301
- * Formats preferred replacement guidance for deprecated commitments.
22302
- *
22303
- * @param replacedBy - Preferred replacement commitment keywords.
22304
- * @returns Optional replacement guidance sentence with leading space.
22305
- *
22306
- * @private internal utility of commitment catalog notices
22307
- */
22308
- function formatCommitmentReplacementText(replacedBy) {
22309
- if (!replacedBy || replacedBy.length === 0) {
22310
- return '';
22311
- }
22312
- return ` ${PREFERRED_REPLACEMENT_LABEL}: ${replacedBy.map((type) => `\`${type}\``).join(', ')}.`;
22313
- }
22314
- /**
22315
- * Resolves the notice metadata for deprecated, unfinished, or low-level commitments.
22316
- *
22317
- * @param definition - Commitment definition to inspect.
22318
- * @returns Notice metadata when the commitment should be surfaced with caution.
22319
- *
22320
- * @private internal utility of commitment catalog notices
22321
- */
22322
- function getCommitmentNoticeMetadata(definition) {
22323
- if (definition.isUnfinished) {
22324
- return {
22325
- kind: 'unfinished',
22326
- badgeLabel: LOW_LEVEL_COMMITMENT_BADGE_LABEL,
22327
- detailLabel: LOW_LEVEL_COMMITMENT_DETAIL_LABEL,
22328
- message: UNFINISHED_COMMITMENT_MESSAGE,
22329
- };
22330
- }
22331
- if (definition.isLowLevel) {
22332
- return {
22333
- kind: 'lowLevel',
22334
- badgeLabel: LOW_LEVEL_COMMITMENT_BADGE_LABEL,
22335
- detailLabel: LOW_LEVEL_COMMITMENT_DETAIL_LABEL,
22336
- message: LOW_LEVEL_COMMITMENT_MESSAGE,
22337
- };
22338
- }
22339
- if (definition.deprecation) {
22340
- return {
22341
- kind: 'deprecated',
22342
- badgeLabel: DEPRECATED_COMMITMENT_BADGE_LABEL,
22343
- detailLabel: DEPRECATED_COMMITMENT_DETAIL_LABEL,
22344
- message: definition.deprecation.message,
22345
- };
22346
- }
22347
- return null;
22348
- }
22349
-
22350
- /**
22351
- * Creates Book editor diagnostics for deprecated, unfinished, and low-level commitment keywords.
22352
- *
22353
- * The notice metadata is UI-only. This helper surfaces it in Monaco so legacy,
22354
- * unfinished, and low-level commitments remain functional while still guiding
22355
- * authors toward preferred replacements or cautioning them about low-level
22356
- * usage.
22357
- *
22358
- * @param agentSource - Current editor content.
22359
- * @returns Warning markers for deprecated, unfinished, and low-level commitment keywords.
22330
+ * In the browser build the full Node.js implementation is not available,
22331
+ * so this stub always returns an empty array to keep the editor functional.
22360
22332
  *
22361
22333
  * @private internal utility of `BookEditorMonaco`
22362
22334
  */
22363
- function createDeprecatedCommitmentDiagnostics(agentSource) {
22364
- var _a;
22365
- if (!(agentSource === null || agentSource === void 0 ? void 0 : agentSource.trim())) {
22366
- return [];
22367
- }
22368
- const parsed = parseAgentSourceWithCommitments(agentSource);
22369
- const diagnostics = [];
22370
- for (const commitment of parsed.commitments) {
22371
- const definition = getCommitmentDefinition(commitment.type);
22372
- const notice = definition ? getCommitmentNoticeMetadata(definition) : null;
22373
- if (!definition || !notice) {
22374
- continue;
22375
- }
22376
- const typeMatch = definition.createTypeRegex().exec(commitment.originalLine);
22377
- if (!((_a = typeMatch === null || typeMatch === void 0 ? void 0 : typeMatch.groups) === null || _a === void 0 ? void 0 : _a.type)) {
22378
- continue;
22379
- }
22380
- const matchedType = typeMatch.groups.type;
22381
- const leadingCharactersCount = typeMatch[0].length - matchedType.length;
22382
- const startColumn = leadingCharactersCount + 1;
22383
- const endColumn = startColumn + matchedType.length;
22384
- // Keep the diagnostic sentence compact while reusing the shared notice copy.
22385
- const message = notice.kind === 'deprecated'
22386
- ? `\`${commitment.type}\` is deprecated. ${notice.message}`
22387
- : `\`${commitment.type}\` is ${notice.message.replace(/^This commitment is\s+/u, '')}`;
22388
- diagnostics.push({
22389
- startLineNumber: commitment.lineNumber,
22390
- startColumn,
22391
- endLineNumber: commitment.lineNumber,
22392
- endColumn,
22393
- message,
22394
- source: 'Promptbook',
22395
- severity: 'warning',
22396
- });
22397
- }
22398
- return diagnostics;
22335
+ function createDeprecatedCommitmentDiagnostics(_agentSource) {
22336
+ return [];
22399
22337
  }
22400
22338
 
22401
22339
  /**
@@ -22754,103 +22692,6 @@
22754
22692
  };
22755
22693
  }
22756
22694
 
22757
- /**
22758
- * Priority order for the important commitments shown first in catalogues and intellisense.
22759
- *
22760
- * Canonical singular names stay ahead of their plural aliases so the most important
22761
- * commitments remain easy to scan.
22762
- *
22763
- * @private internal constant of commitment catalog sorting
22764
- */
22765
- const IMPORTANT_COMMITMENT_TYPE_SORT_ORDER = new Map([
22766
- ['GOAL', 0],
22767
- ['RULE', 1],
22768
- ['KNOWLEDGE', 2],
22769
- ['TEAM', 3],
22770
- ['GOALS', 4],
22771
- ['RULES', 5],
22772
- ]);
22773
- /**
22774
- * Sort rank used when unfinished, low-level, and deprecated commitments should be grouped last.
22775
- *
22776
- * @private internal constant of commitment catalog sorting
22777
- */
22778
- const COMMITMENT_STATUS_SORT_ORDER = {
22779
- normal: 0,
22780
- deprecated: 1,
22781
- unfinished: 2,
22782
- lowLevel: 3,
22783
- };
22784
- /**
22785
- * Resolves the relative sort rank of one commitment status.
22786
- *
22787
- * @param definition - Commitment definition to rank.
22788
- * @param options - Sorting options.
22789
- * @returns Relative sort rank for the definition.
22790
- *
22791
- * @private internal helper of commitment catalog sorting
22792
- */
22793
- function resolveCommitmentStatusSortRank(definition, options) {
22794
- let statusSortRank = COMMITMENT_STATUS_SORT_ORDER.normal;
22795
- if (options.isDeprecatedLast && definition.deprecation) {
22796
- statusSortRank = Math.max(statusSortRank, COMMITMENT_STATUS_SORT_ORDER.deprecated);
22797
- }
22798
- if (options.isUnfinishedLast && definition.isUnfinished) {
22799
- statusSortRank = Math.max(statusSortRank, COMMITMENT_STATUS_SORT_ORDER.unfinished);
22800
- }
22801
- if (options.isLowLevelLast && definition.isLowLevel) {
22802
- statusSortRank = Math.max(statusSortRank, COMMITMENT_STATUS_SORT_ORDER.lowLevel);
22803
- }
22804
- return statusSortRank;
22805
- }
22806
- /**
22807
- * Sorts commitment definitions so the important ones stay at the top.
22808
- *
22809
- * @param commitmentDefinitions - Definitions to sort.
22810
- * @param options - Sorting options.
22811
- * @returns Sorted commitment definitions.
22812
- *
22813
- * @private internal helper of commitment catalog sorting
22814
- */
22815
- function sortCommitmentDefinitions(commitmentDefinitions, options = {}) {
22816
- return [...commitmentDefinitions]
22817
- .map((definition, index) => ({
22818
- definition,
22819
- index,
22820
- }))
22821
- .sort((left, right) => {
22822
- var _a, _b;
22823
- if (left.definition.isImportant !== right.definition.isImportant) {
22824
- return left.definition.isImportant ? -1 : 1;
22825
- }
22826
- if (left.definition.isImportant && right.definition.isImportant) {
22827
- const leftPriority = (_a = IMPORTANT_COMMITMENT_TYPE_SORT_ORDER.get(left.definition.type)) !== null && _a !== void 0 ? _a : Number.MAX_SAFE_INTEGER;
22828
- const rightPriority = (_b = IMPORTANT_COMMITMENT_TYPE_SORT_ORDER.get(right.definition.type)) !== null && _b !== void 0 ? _b : Number.MAX_SAFE_INTEGER;
22829
- if (leftPriority !== rightPriority) {
22830
- return leftPriority - rightPriority;
22831
- }
22832
- }
22833
- const leftStatusSortRank = resolveCommitmentStatusSortRank(left.definition, options);
22834
- const rightStatusSortRank = resolveCommitmentStatusSortRank(right.definition, options);
22835
- if (leftStatusSortRank !== rightStatusSortRank) {
22836
- return leftStatusSortRank - rightStatusSortRank;
22837
- }
22838
- return left.index - right.index;
22839
- })
22840
- .map(({ definition }) => definition);
22841
- }
22842
-
22843
- /**
22844
- * Gets all available commitment definitions
22845
- *
22846
- * @returns Array of all commitment definitions
22847
- *
22848
- * @public exported from `@promptbook/core`
22849
- */
22850
- function getAllCommitmentDefinitions() {
22851
- return $deepFreeze(sortCommitmentDefinitions(COMMITMENT_REGISTRY, { isUnfinishedLast: true, isLowLevelLast: true }));
22852
- }
22853
-
22854
22695
  /**
22855
22696
  * Regex source for absolute URL references inside TEAM/FROM/IMPORT commitments.
22856
22697
  *
@@ -22874,12 +22715,38 @@
22874
22715
  *
22875
22716
  * @private function of BookEditorMonaco
22876
22717
  */
22877
- const AGENT_REFERENCE_COMMITMENT_TYPES = new Set([
22718
+ const AGENT_REFERENCE_COMMITMENT_TYPES = ['FROM', 'IMPORT', 'IMPORTS', 'TEAM'];
22719
+ /**
22720
+ * Commitment types known to the browser editor tokenizer.
22721
+ *
22722
+ * @private function of BookEditorMonaco
22723
+ */
22724
+ const BOOK_EDITOR_COMMITMENT_TYPES = [
22725
+ 'PERSONA',
22726
+ 'KNOWLEDGE',
22727
+ 'TASK',
22728
+ 'PROMPT',
22729
+ 'EXPECT',
22730
+ 'FORMAT',
22731
+ 'MODEL',
22732
+ 'SAMPLE',
22878
22733
  'FROM',
22879
22734
  'IMPORT',
22880
22735
  'IMPORTS',
22881
22736
  'TEAM',
22882
- ]);
22737
+ 'TODO',
22738
+ 'NOTE',
22739
+ 'NOTES',
22740
+ 'NONCE',
22741
+ ];
22742
+ /**
22743
+ * Regex pattern to match horizontal lines.
22744
+ *
22745
+ * @private function of BookEditorMonaco
22746
+ */
22747
+ const HORIZONTAL_LINE_PATTERN$1 = /^[\s]*[-_*][\s]*[-_*][\s]*[-_*][\s]*[-_*]*[\s]*$/;
22748
+ const BOOK_EDITOR_COMMITMENT_LINE_REGEX = createCommitmentLineRegex(BOOK_EDITOR_COMMITMENT_TYPES);
22749
+ const AGENT_REFERENCE_COMMITMENT_LINE_REGEX = createCommitmentLineRegex(AGENT_REFERENCE_COMMITMENT_TYPES);
22883
22750
  /**
22884
22751
  * Agent reference helpers for `BookEditorMonaco`.
22885
22752
  *
@@ -23034,26 +22901,60 @@
23034
22901
  * @private function of BookEditorMonaco
23035
22902
  */
23036
22903
  function collectAgentReferenceCommitmentLineRanges(content, sourceLines) {
23037
- var _a, _b;
23038
- const parsed = parseAgentSourceWithCommitments(content);
23039
22904
  const ranges = [];
23040
- for (let index = 0; index < parsed.commitments.length; index++) {
23041
- const commitment = parsed.commitments[index];
23042
- if (!commitment || !AGENT_REFERENCE_COMMITMENT_TYPES.has(commitment.type)) {
22905
+ let activeRangeStartLineNumber = null;
22906
+ let isInsideCodeBlock = false;
22907
+ const startLineIndex = findBookBodyStartLineIndex(sourceLines);
22908
+ for (let lineIndex = startLineIndex; lineIndex < sourceLines.length; lineIndex++) {
22909
+ const line = sourceLines[lineIndex] || '';
22910
+ const trimmedLine = line.trim();
22911
+ if (trimmedLine.startsWith('```')) {
22912
+ isInsideCodeBlock = !isInsideCodeBlock;
22913
+ continue;
22914
+ }
22915
+ if (isInsideCodeBlock) {
22916
+ continue;
22917
+ }
22918
+ if (HORIZONTAL_LINE_PATTERN$1.test(line)) {
22919
+ if (activeRangeStartLineNumber !== null) {
22920
+ ranges.push({
22921
+ startLineNumber: activeRangeStartLineNumber,
22922
+ endLineNumber: lineIndex,
22923
+ });
22924
+ activeRangeStartLineNumber = null;
22925
+ }
23043
22926
  continue;
23044
22927
  }
23045
- const nextCommitmentStartLine = (_b = (_a = parsed.commitments[index + 1]) === null || _a === void 0 ? void 0 : _a.lineNumber) !== null && _b !== void 0 ? _b : sourceLines.length + 1;
23046
- const endLineNumber = Math.min(nextCommitmentStartLine - 1, sourceLines.length);
23047
- if (commitment.lineNumber > endLineNumber) {
22928
+ if (!BOOK_EDITOR_COMMITMENT_LINE_REGEX.test(trimmedLine)) {
23048
22929
  continue;
23049
22930
  }
22931
+ if (activeRangeStartLineNumber !== null) {
22932
+ ranges.push({
22933
+ startLineNumber: activeRangeStartLineNumber,
22934
+ endLineNumber: lineIndex,
22935
+ });
22936
+ }
22937
+ activeRangeStartLineNumber = AGENT_REFERENCE_COMMITMENT_LINE_REGEX.test(trimmedLine) ? lineIndex + 1 : null;
22938
+ }
22939
+ if (activeRangeStartLineNumber !== null) {
23050
22940
  ranges.push({
23051
- startLineNumber: commitment.lineNumber,
23052
- endLineNumber,
22941
+ startLineNumber: activeRangeStartLineNumber,
22942
+ endLineNumber: sourceLines.length,
23053
22943
  });
23054
22944
  }
23055
22945
  return ranges;
23056
22946
  }
22947
+ function createCommitmentLineRegex(commitmentTypes) {
22948
+ const commitmentPattern = [...commitmentTypes]
22949
+ .sort((a, b) => b.length - a.length)
22950
+ .map((type) => type.replace(/\s+/, '\\s+'))
22951
+ .join('|');
22952
+ return new RegExp(`^\\s*(${commitmentPattern})(?=\\s|$)`, 'i');
22953
+ }
22954
+ function findBookBodyStartLineIndex(sourceLines) {
22955
+ const titleLineIndex = sourceLines.findIndex((line) => line.trim().length > 0);
22956
+ return titleLineIndex === -1 ? 0 : titleLineIndex + 1;
22957
+ }
23057
22958
  /**
23058
22959
  * Agent reference helpers for `BookEditorMonaco`.
23059
22960
  *
@@ -23281,19 +23182,26 @@
23281
23182
  monacoWithLanguageState[BOOK_EDITOR_LANGUAGE_INITIALIZED_FLAG] = true;
23282
23183
  monacoWithLanguageState[BOOK_EDITOR_THEME_MODE_FLAG] = renderedTheme;
23283
23184
  monaco.languages.register({ id: BookEditorMonacoConstants.BOOK_LANGUAGE_ID });
23284
- const commitmentDefinitions = getAllCommitmentDefinitions();
23285
- const commitmentTypes = [...new Set(commitmentDefinitions.map(({ type }) => type))];
23286
- const commitmentDefinitionByType = new Map(commitmentDefinitions.map((definition) => [definition.type, definition]));
23287
- const completionCommitmentTypes = [...commitmentTypes].sort((leftType, rightType) => {
23288
- const leftDefinition = commitmentDefinitionByType.get(leftType);
23289
- const rightDefinition = commitmentDefinitionByType.get(rightType);
23290
- const leftRank = (leftDefinition === null || leftDefinition === void 0 ? void 0 : leftDefinition.isUnfinished) ? 1 : 0;
23291
- const rightRank = (rightDefinition === null || rightDefinition === void 0 ? void 0 : rightDefinition.isUnfinished) ? 1 : 0;
23292
- if (leftRank !== rightRank) {
23293
- return leftRank - rightRank;
23294
- }
23295
- return commitmentTypes.indexOf(leftType) - commitmentTypes.indexOf(rightType);
23296
- });
23185
+ const commitmentTypes = [
23186
+ 'GOAL',
23187
+ 'RULE',
23188
+ 'PERSONA',
23189
+ 'KNOWLEDGE',
23190
+ 'TASK',
23191
+ 'PROMPT',
23192
+ 'EXPECT',
23193
+ 'FORMAT',
23194
+ 'MODEL',
23195
+ 'SAMPLE',
23196
+ 'FROM',
23197
+ 'IMPORT',
23198
+ 'IMPORTS',
23199
+ 'TEAM',
23200
+ ...TODO_COMMITMENT_TYPES,
23201
+ ...NOTE_COMMITMENT_TYPES,
23202
+ 'REMOVE',
23203
+ ];
23204
+ const completionCommitmentTypes = [...commitmentTypes];
23297
23205
  const noteLikeCommitmentTypeSet = new Set([...TODO_COMMITMENT_TYPES, ...NOTE_COMMITMENT_TYPES]);
23298
23206
  const noteLikeCommitmentStates = createNoteLikeCommitmentStates(commitmentTypes);
23299
23207
  const executableCommitmentTypes = commitmentTypes.filter((type) => !noteLikeCommitmentTypeSet.has(type.toUpperCase()));
@@ -23350,27 +23258,17 @@
23350
23258
  startColumn: word.startColumn,
23351
23259
  endColumn: word.endColumn,
23352
23260
  };
23353
- const suggestions = completionCommitmentTypes.map((type, index) => {
23354
- var _a;
23355
- const definition = commitmentDefinitionByType.get(type);
23356
- const notice = definition ? getCommitmentNoticeMetadata(definition) : null;
23357
- const completionDocumentation = notice
23358
- ? `${notice.detailLabel}. ${notice.message}${notice.kind === 'deprecated'
23359
- ? formatCommitmentReplacementText((_a = definition === null || definition === void 0 ? void 0 : definition.deprecation) === null || _a === void 0 ? void 0 : _a.replacedBy)
23360
- : ''}`
23361
- : (definition === null || definition === void 0 ? void 0 : definition.description) || 'Commitment';
23362
- return {
23363
- label: type,
23364
- kind: monaco.languages.CompletionItemKind.Keyword,
23365
- insertText: type,
23366
- range,
23367
- sortText: index.toString().padStart(4, '0'),
23368
- detail: (notice === null || notice === void 0 ? void 0 : notice.detailLabel) || 'Commitment',
23369
- documentation: {
23370
- value: completionDocumentation,
23371
- },
23372
- };
23373
- });
23261
+ const suggestions = completionCommitmentTypes.map((type, index) => ({
23262
+ label: type,
23263
+ kind: monaco.languages.CompletionItemKind.Keyword,
23264
+ insertText: type,
23265
+ range,
23266
+ sortText: index.toString().padStart(4, '0'),
23267
+ detail: 'Commitment',
23268
+ documentation: {
23269
+ value: 'Book commitment',
23270
+ },
23271
+ }));
23374
23272
  return { suggestions };
23375
23273
  },
23376
23274
  });
@@ -24656,7 +24554,7 @@
24656
24554
  editor,
24657
24555
  handleFiles,
24658
24556
  });
24659
- const combinedDiagnostics = [...(diagnostics || []), ...createDeprecatedCommitmentDiagnostics(value)];
24557
+ const combinedDiagnostics = [...(diagnostics || []), ...createDeprecatedCommitmentDiagnostics()];
24660
24558
  const isActionBarVisible = isBookEditorMonacoActionbarVisible({
24661
24559
  hoistedMenuItems,
24662
24560
  isUploadButtonShown,
@@ -24750,6 +24648,36 @@
24750
24648
  return isFullscreen && typeof document !== 'undefined' ? reactDom.createPortal(editorContent, document.body) : editorContent;
24751
24649
  }
24752
24650
 
24651
+ var BookEditor$1 = /*#__PURE__*/Object.freeze({
24652
+ __proto__: null,
24653
+ DEFAULT_BOOK_EDITOR_HEIGHT: DEFAULT_BOOK_EDITOR_HEIGHT,
24654
+ BookEditor: BookEditor
24655
+ });
24656
+
24657
+ /**
24658
+ * Renders a book editor
24659
+ *
24660
+ * @public exported from `@promptbook/components`
24661
+ */
24662
+ function BookEditorForClient(props) {
24663
+ const [BookEditorComponent, setBookEditorComponent] = react.useState(null);
24664
+ react.useEffect(() => {
24665
+ let isCancelled = false;
24666
+ void Promise.resolve().then(function () { return BookEditor$1; }).then(({ BookEditor }) => {
24667
+ if (!isCancelled) {
24668
+ setBookEditorComponent(() => BookEditor);
24669
+ }
24670
+ });
24671
+ return () => {
24672
+ isCancelled = true;
24673
+ };
24674
+ }, []);
24675
+ if (!BookEditorComponent) {
24676
+ return jsxRuntime.jsx("div", { style: { minHeight: 260 } });
24677
+ }
24678
+ return jsxRuntime.jsx(BookEditorComponent, { ...props });
24679
+ }
24680
+
24753
24681
  /**
24754
24682
  * Restricts an Updatable to a (2) BehaviorSubject variant
24755
24683
  *
@@ -26504,7 +26432,7 @@
26504
26432
  function createChatMarkdownConverter(options) {
26505
26433
  var _a;
26506
26434
  const citationReferenceClassName = (_a = options === null || options === void 0 ? void 0 : options.citationReferenceClassName) !== null && _a !== void 0 ? _a : DEFAULT_CITATION_REFERENCE_CLASS_NAME;
26507
- return new showdown.Converter({
26435
+ return new showdown__default["default"].Converter({
26508
26436
  flavor: 'github',
26509
26437
  tables: true,
26510
26438
  strikethrough: true,
@@ -30958,6 +30886,22 @@
30958
30886
  }
30959
30887
 
30960
30888
  // Note: [💞] Ignore a discrepancy between file name and entity name
30889
+ /**
30890
+ * Target frames per second for the shared avatar animation loop.
30891
+ *
30892
+ * Animated octopus visuals change slowly enough that 24 fps is indistinguishable
30893
+ * from 60 fps in practice, while cutting rendering work by ~60% when multiple
30894
+ * avatars are on screen simultaneously.
30895
+ *
30896
+ * @private utility of the avatar rendering system
30897
+ */
30898
+ const AVATAR_TARGET_FPS = 24;
30899
+ /**
30900
+ * Minimum elapsed time in milliseconds required between avatar render passes.
30901
+ *
30902
+ * @private utility of the avatar rendering system
30903
+ */
30904
+ const AVATAR_TARGET_FRAME_INTERVAL_MS = 1000 / AVATAR_TARGET_FPS;
30961
30905
  /**
30962
30906
  * Next registration id used by the shared avatar animation scheduler.
30963
30907
  *
@@ -30976,6 +30920,14 @@
30976
30920
  * @private utility of the avatar rendering system
30977
30921
  */
30978
30922
  let avatarAnimationFrameId = null;
30923
+ /**
30924
+ * Timestamp of the most recently rendered avatar frame.
30925
+ *
30926
+ * Used to throttle callbacks to `AVATAR_TARGET_FRAME_INTERVAL_MS`.
30927
+ *
30928
+ * @private utility of the avatar rendering system
30929
+ */
30930
+ let lastAvatarFrameTime = 0;
30979
30931
  /**
30980
30932
  * Registers one avatar animation callback in the shared animation loop.
30981
30933
  *
@@ -31010,8 +30962,11 @@
31010
30962
  }
31011
30963
  const runFrame = (now) => {
31012
30964
  avatarAnimationFrameId = null;
31013
- for (const avatarAnimationListener of [...avatarAnimationListeners.values()]) {
31014
- avatarAnimationListener(now);
30965
+ if (now - lastAvatarFrameTime >= AVATAR_TARGET_FRAME_INTERVAL_MS) {
30966
+ lastAvatarFrameTime = now;
30967
+ for (const avatarAnimationListener of [...avatarAnimationListeners.values()]) {
30968
+ avatarAnimationListener(now);
30969
+ }
31015
30970
  }
31016
30971
  ensureAvatarAnimationLoop();
31017
30972
  };
@@ -42678,6 +42633,103 @@
42678
42633
  return toolCalls;
42679
42634
  }
42680
42635
 
42636
+ /**
42637
+ * Priority order for the important commitments shown first in catalogues and intellisense.
42638
+ *
42639
+ * Canonical singular names stay ahead of their plural aliases so the most important
42640
+ * commitments remain easy to scan.
42641
+ *
42642
+ * @private internal constant of commitment catalog sorting
42643
+ */
42644
+ const IMPORTANT_COMMITMENT_TYPE_SORT_ORDER = new Map([
42645
+ ['GOAL', 0],
42646
+ ['RULE', 1],
42647
+ ['KNOWLEDGE', 2],
42648
+ ['TEAM', 3],
42649
+ ['GOALS', 4],
42650
+ ['RULES', 5],
42651
+ ]);
42652
+ /**
42653
+ * Sort rank used when unfinished, low-level, and deprecated commitments should be grouped last.
42654
+ *
42655
+ * @private internal constant of commitment catalog sorting
42656
+ */
42657
+ const COMMITMENT_STATUS_SORT_ORDER = {
42658
+ normal: 0,
42659
+ deprecated: 1,
42660
+ unfinished: 2,
42661
+ lowLevel: 3,
42662
+ };
42663
+ /**
42664
+ * Resolves the relative sort rank of one commitment status.
42665
+ *
42666
+ * @param definition - Commitment definition to rank.
42667
+ * @param options - Sorting options.
42668
+ * @returns Relative sort rank for the definition.
42669
+ *
42670
+ * @private internal helper of commitment catalog sorting
42671
+ */
42672
+ function resolveCommitmentStatusSortRank(definition, options) {
42673
+ let statusSortRank = COMMITMENT_STATUS_SORT_ORDER.normal;
42674
+ if (options.isDeprecatedLast && definition.deprecation) {
42675
+ statusSortRank = Math.max(statusSortRank, COMMITMENT_STATUS_SORT_ORDER.deprecated);
42676
+ }
42677
+ if (options.isUnfinishedLast && definition.isUnfinished) {
42678
+ statusSortRank = Math.max(statusSortRank, COMMITMENT_STATUS_SORT_ORDER.unfinished);
42679
+ }
42680
+ if (options.isLowLevelLast && definition.isLowLevel) {
42681
+ statusSortRank = Math.max(statusSortRank, COMMITMENT_STATUS_SORT_ORDER.lowLevel);
42682
+ }
42683
+ return statusSortRank;
42684
+ }
42685
+ /**
42686
+ * Sorts commitment definitions so the important ones stay at the top.
42687
+ *
42688
+ * @param commitmentDefinitions - Definitions to sort.
42689
+ * @param options - Sorting options.
42690
+ * @returns Sorted commitment definitions.
42691
+ *
42692
+ * @private internal helper of commitment catalog sorting
42693
+ */
42694
+ function sortCommitmentDefinitions(commitmentDefinitions, options = {}) {
42695
+ return [...commitmentDefinitions]
42696
+ .map((definition, index) => ({
42697
+ definition,
42698
+ index,
42699
+ }))
42700
+ .sort((left, right) => {
42701
+ var _a, _b;
42702
+ if (left.definition.isImportant !== right.definition.isImportant) {
42703
+ return left.definition.isImportant ? -1 : 1;
42704
+ }
42705
+ if (left.definition.isImportant && right.definition.isImportant) {
42706
+ const leftPriority = (_a = IMPORTANT_COMMITMENT_TYPE_SORT_ORDER.get(left.definition.type)) !== null && _a !== void 0 ? _a : Number.MAX_SAFE_INTEGER;
42707
+ const rightPriority = (_b = IMPORTANT_COMMITMENT_TYPE_SORT_ORDER.get(right.definition.type)) !== null && _b !== void 0 ? _b : Number.MAX_SAFE_INTEGER;
42708
+ if (leftPriority !== rightPriority) {
42709
+ return leftPriority - rightPriority;
42710
+ }
42711
+ }
42712
+ const leftStatusSortRank = resolveCommitmentStatusSortRank(left.definition, options);
42713
+ const rightStatusSortRank = resolveCommitmentStatusSortRank(right.definition, options);
42714
+ if (leftStatusSortRank !== rightStatusSortRank) {
42715
+ return leftStatusSortRank - rightStatusSortRank;
42716
+ }
42717
+ return left.index - right.index;
42718
+ })
42719
+ .map(({ definition }) => definition);
42720
+ }
42721
+
42722
+ /**
42723
+ * Gets all available commitment definitions
42724
+ *
42725
+ * @returns Array of all commitment definitions
42726
+ *
42727
+ * @public exported from `@promptbook/core`
42728
+ */
42729
+ function getAllCommitmentDefinitions() {
42730
+ return $deepFreeze(sortCommitmentDefinitions(COMMITMENT_REGISTRY, { isUnfinishedLast: true, isLowLevelLast: true }));
42731
+ }
42732
+
42681
42733
  /**
42682
42734
  * Gets all tool titles provided by all commitments
42683
42735
  *
@@ -45352,7 +45404,7 @@
45352
45404
  * @public exported from `@promptbook/editable`
45353
45405
  */
45354
45406
  function knowledgeSourceContentToName(knowledgeSourceContent) {
45355
- const hash = cryptoJs.SHA256(hexEncoder__default["default"].parse(JSON.stringify(knowledgeSourceContent)))
45407
+ const hash = CryptoJS__default["default"].SHA256(hexEncoder__default["default"].parse(JSON.stringify(knowledgeSourceContent)))
45356
45408
  // <- TODO: [🥬] Encapsulate sha256 to some private utility function
45357
45409
  .toString( /* hex */)
45358
45410
  .substring(0, 20);
@@ -46200,7 +46252,7 @@
46200
46252
  console.warn('CSV string contains carriage return characters, but in the CSV settings the `newline` setting does not include them. Autohealing the CSV string.');
46201
46253
  value = value.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
46202
46254
  }
46203
- const csv = papaparse.parse(value, settings);
46255
+ const csv = papaparse__default["default"].parse(value, settings);
46204
46256
  return csv;
46205
46257
  }
46206
46258
 
@@ -46285,10 +46337,10 @@
46285
46337
  i > index ? { ...row, [outputParameterName]: PENDING_VALUE_PLACEHOLDER } : row,
46286
46338
  );
46287
46339
  */
46288
- await onProgress(papaparse.unparse(mappedData, { ...settings, ...MANDATORY_CSV_SETTINGS }));
46340
+ await onProgress(papaparse__default["default"].unparse(mappedData, { ...settings, ...MANDATORY_CSV_SETTINGS }));
46289
46341
  }
46290
46342
  }
46291
- return papaparse.unparse(mappedData, { ...settings, ...MANDATORY_CSV_SETTINGS });
46343
+ return papaparse__default["default"].unparse(mappedData, { ...settings, ...MANDATORY_CSV_SETTINGS });
46292
46344
  },
46293
46345
  },
46294
46346
  {
@@ -46316,7 +46368,7 @@
46316
46368
  return /* not await */ mapCallback({ [key]: value }, index, array.length);
46317
46369
  }));
46318
46370
  }));
46319
- return papaparse.unparse(mappedData, { ...settings, ...MANDATORY_CSV_SETTINGS });
46371
+ return papaparse__default["default"].unparse(mappedData, { ...settings, ...MANDATORY_CSV_SETTINGS });
46320
46372
  },
46321
46373
  },
46322
46374
  ],
@@ -48333,6 +48385,18 @@
48333
48385
  }
48334
48386
  // TODO: [🐤] Deduplicate `AgentModelRequirements` and `ModelRequirements` model requirements
48335
48387
 
48388
+ /**
48389
+ * Gets a commitment definition by its type
48390
+ *
48391
+ * @param type The commitment type to look up
48392
+ * @returns The commitment definition or null if not found
48393
+ *
48394
+ * @public exported from `@promptbook/core`
48395
+ */
48396
+ function getCommitmentDefinition(type) {
48397
+ return COMMITMENT_REGISTRY.find((commitmentDefinition) => commitmentDefinition.type === type) || null;
48398
+ }
48399
+
48336
48400
  /**
48337
48401
  * Commitment types whose content may contain compact agent references that must be resolved before applying the commitment.
48338
48402
  *
@@ -54826,7 +54890,7 @@
54826
54890
  * Computes one stable hash from a JSON-serializable value.
54827
54891
  */
54828
54892
  function computeJsonHash$1(value) {
54829
- return cryptoJs.SHA256(JSON.stringify(value)).toString();
54893
+ return CryptoJS__default["default"].SHA256(JSON.stringify(value)).toString();
54830
54894
  }
54831
54895
  /**
54832
54896
  * Handles OpenAI AgentKit-backed executions for `AgentLlmExecutionTools`.
@@ -54984,7 +55048,7 @@
54984
55048
  * Computes one stable hash from a JSON-serializable value.
54985
55049
  */
54986
55050
  function computeJsonHash(value) {
54987
- return cryptoJs.SHA256(JSON.stringify(value)).toString();
55051
+ return CryptoJS__default["default"].SHA256(JSON.stringify(value)).toString();
54988
55052
  }
54989
55053
  /**
54990
55054
  * Removes assistant-managed requirements before the prompt is executed via OpenAI Assistants.
@@ -55840,7 +55904,7 @@
55840
55904
  * Returns a virtual model name representing the agent behavior.
55841
55905
  */
55842
55906
  get modelName() {
55843
- const hash = cryptoJs.SHA256(hexEncoder__default["default"].parse(this.options.agentSource)).toString( /* hex */);
55907
+ const hash = CryptoJS__default["default"].SHA256(hexEncoder__default["default"].parse(this.options.agentSource)).toString( /* hex */);
55844
55908
  const agentId = hash.substring(0, 10);
55845
55909
  return (normalizeToKebabCase(this.title) + '-' + agentId);
55846
55910
  }
@@ -59259,6 +59323,7 @@
59259
59323
  exports.BLOCKY_FLOW = BLOCKY_FLOW;
59260
59324
  exports.BOOK_LANGUAGE_VERSION = BOOK_LANGUAGE_VERSION;
59261
59325
  exports.BookEditor = BookEditor;
59326
+ exports.BookEditorForClient = BookEditorForClient;
59262
59327
  exports.BrandedQrCode = BrandedQrCode;
59263
59328
  exports.CHAT_SAVE_FORMATS = CHAT_SAVE_FORMATS;
59264
59329
  exports.Chat = Chat;