@promptbook/components 0.112.0-126 → 0.112.0-128
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/esm/index.es.js +952 -243
- package/esm/index.es.js.map +1 -1
- package/esm/src/_packages/components.index.d.ts +2 -0
- package/esm/src/_packages/types.index.d.ts +2 -0
- package/esm/src/avatars/avatarAnimationScheduler.d.ts +4 -0
- package/esm/src/book-components/Chat/Chat/ChatCitationModal.d.ts +2 -0
- package/esm/src/book-components/Chat/Chat/ChatMessageItem.d.ts +4 -0
- package/esm/src/book-components/Chat/Chat/ChatMessageList.d.ts +4 -0
- package/esm/src/book-components/Chat/Chat/ChatProps.d.ts +5 -0
- package/esm/src/book-components/Chat/Chat/ChatToolCallModal.d.ts +2 -0
- package/esm/src/book-components/Chat/Chat/ChatToolCallModalContent.d.ts +3 -1
- package/esm/src/book-components/Chat/Chat/TeamToolCallModalContent.d.ts +2 -0
- package/esm/src/book-components/Chat/SourceChip/SourceChip.d.ts +6 -1
- package/esm/src/book-components/Chat/hooks/useResolvedCitationLabel.d.ts +12 -0
- package/esm/src/book-components/Chat/types/ChatMessage.d.ts +4 -0
- package/esm/src/book-components/Chat/types/ChatParticipant.d.ts +1 -1
- package/esm/src/book-components/Chat/types/CitationLabelResolver.d.ts +8 -0
- package/esm/src/book-components/Chat/utils/citationHelpers.d.ts +9 -0
- package/esm/src/book-components/Chat/utils/decodeJsonUnicodeEscapesInMarkdownText.d.ts +14 -0
- package/esm/src/book-components/Chat/utils/decodeJsonUnicodeEscapesInMarkdownText.test.d.ts +1 -0
- package/esm/src/book-components/Chat/utils/parseCitationsFromContent.d.ts +4 -0
- package/esm/src/version.d.ts +1 -1
- package/package.json +1 -1
- package/umd/index.umd.js +952 -243
- package/umd/index.umd.js.map +1 -1
- package/umd/src/_packages/components.index.d.ts +2 -0
- package/umd/src/_packages/types.index.d.ts +2 -0
- package/umd/src/avatars/avatarAnimationScheduler.d.ts +4 -0
- package/umd/src/book-components/Chat/Chat/ChatCitationModal.d.ts +2 -0
- package/umd/src/book-components/Chat/Chat/ChatMessageItem.d.ts +4 -0
- package/umd/src/book-components/Chat/Chat/ChatMessageList.d.ts +4 -0
- package/umd/src/book-components/Chat/Chat/ChatProps.d.ts +5 -0
- package/umd/src/book-components/Chat/Chat/ChatToolCallModal.d.ts +2 -0
- package/umd/src/book-components/Chat/Chat/ChatToolCallModalContent.d.ts +3 -1
- package/umd/src/book-components/Chat/Chat/TeamToolCallModalContent.d.ts +2 -0
- package/umd/src/book-components/Chat/SourceChip/SourceChip.d.ts +6 -1
- package/umd/src/book-components/Chat/hooks/useResolvedCitationLabel.d.ts +12 -0
- package/umd/src/book-components/Chat/types/ChatMessage.d.ts +4 -0
- package/umd/src/book-components/Chat/types/ChatParticipant.d.ts +1 -1
- package/umd/src/book-components/Chat/types/CitationLabelResolver.d.ts +8 -0
- package/umd/src/book-components/Chat/utils/citationHelpers.d.ts +9 -0
- package/umd/src/book-components/Chat/utils/decodeJsonUnicodeEscapesInMarkdownText.d.ts +14 -0
- package/umd/src/book-components/Chat/utils/decodeJsonUnicodeEscapesInMarkdownText.test.d.ts +1 -0
- package/umd/src/book-components/Chat/utils/parseCitationsFromContent.d.ts +4 -0
- package/umd/src/version.d.ts +1 -1
package/esm/index.es.js
CHANGED
|
@@ -40,7 +40,7 @@ const BOOK_LANGUAGE_VERSION = '2.0.0';
|
|
|
40
40
|
* @generated
|
|
41
41
|
* @see https://github.com/webgptorg/promptbook
|
|
42
42
|
*/
|
|
43
|
-
const PROMPTBOOK_ENGINE_VERSION = '0.112.0-
|
|
43
|
+
const PROMPTBOOK_ENGINE_VERSION = '0.112.0-128';
|
|
44
44
|
/**
|
|
45
45
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
|
46
46
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -5275,41 +5275,91 @@ function drawBlobbyOctopusShadow(context, size, palette, interaction, timeMs, mo
|
|
|
5275
5275
|
context.fill();
|
|
5276
5276
|
context.restore();
|
|
5277
5277
|
}
|
|
5278
|
+
/**
|
|
5279
|
+
* Number of latitude segments used by the single blobby octopus mesh.
|
|
5280
|
+
*
|
|
5281
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
5282
|
+
*/
|
|
5283
|
+
const LATITUDE_PATCH_COUNT$1 = 12;
|
|
5284
|
+
/**
|
|
5285
|
+
* Number of longitude segments used by the single blobby octopus mesh.
|
|
5286
|
+
*
|
|
5287
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
5288
|
+
*/
|
|
5289
|
+
const LONGITUDE_PATCH_COUNT$1 = 24;
|
|
5278
5290
|
/**
|
|
5279
5291
|
* Resolves all visible projected patches for the single blobby octopus mesh.
|
|
5280
5292
|
*
|
|
5293
|
+
* Within a single frame, mesh corner samples and longitude-only lobe-wave values are
|
|
5294
|
+
* quantized to the patch grid and computed once each rather than re-evaluated for every
|
|
5295
|
+
* patch corner — the patch loop alone would call `sampleBlobbyOctopusSurfacePoint`
|
|
5296
|
+
* `latitudePatchCount * longitudePatchCount * 4` times without caching, even though most
|
|
5297
|
+
* corners are shared between neighboring patches.
|
|
5298
|
+
*
|
|
5281
5299
|
* @private helper of `octopus3d2AvatarVisual`
|
|
5282
5300
|
*/
|
|
5283
5301
|
function resolveVisibleBlobbyOctopusPatches(options) {
|
|
5284
5302
|
const { center, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, morphologyProfile, animationPhase, timeMs, } = options;
|
|
5285
|
-
const latitudePatchCount =
|
|
5286
|
-
const longitudePatchCount =
|
|
5303
|
+
const latitudePatchCount = LATITUDE_PATCH_COUNT$1;
|
|
5304
|
+
const longitudePatchCount = LONGITUDE_PATCH_COUNT$1;
|
|
5287
5305
|
const surfacePatches = [];
|
|
5306
|
+
const latitudeBoundaries = new Float64Array(latitudePatchCount + 1);
|
|
5307
|
+
const longitudeBoundaries = new Float64Array(longitudePatchCount + 1);
|
|
5308
|
+
for (let boundaryIndex = 0; boundaryIndex <= latitudePatchCount; boundaryIndex++) {
|
|
5309
|
+
latitudeBoundaries[boundaryIndex] = -Math.PI / 2 + (boundaryIndex / latitudePatchCount) * Math.PI;
|
|
5310
|
+
}
|
|
5311
|
+
for (let boundaryIndex = 0; boundaryIndex <= longitudePatchCount; boundaryIndex++) {
|
|
5312
|
+
longitudeBoundaries[boundaryIndex] = -Math.PI + (boundaryIndex / longitudePatchCount) * Math.PI * 2;
|
|
5313
|
+
}
|
|
5314
|
+
const cachedLobeWavesByCornerLongitude = new Float64Array(longitudePatchCount + 1);
|
|
5315
|
+
for (let boundaryIndex = 0; boundaryIndex <= longitudePatchCount; boundaryIndex++) {
|
|
5316
|
+
cachedLobeWavesByCornerLongitude[boundaryIndex] = resolveLowerLobeWave(longitudeBoundaries[boundaryIndex], morphologyProfile, animationPhase, timeMs);
|
|
5317
|
+
}
|
|
5318
|
+
const cornerCount = (latitudePatchCount + 1) * (longitudePatchCount + 1);
|
|
5319
|
+
const transformedCornerSamples = new Array(cornerCount);
|
|
5320
|
+
for (let latitudeBoundaryIndex = 0; latitudeBoundaryIndex <= latitudePatchCount; latitudeBoundaryIndex++) {
|
|
5321
|
+
const cornerLatitude = latitudeBoundaries[latitudeBoundaryIndex];
|
|
5322
|
+
for (let longitudeBoundaryIndex = 0; longitudeBoundaryIndex <= longitudePatchCount; longitudeBoundaryIndex++) {
|
|
5323
|
+
const cornerLongitude = longitudeBoundaries[longitudeBoundaryIndex];
|
|
5324
|
+
const cornerIndex = latitudeBoundaryIndex * (longitudePatchCount + 1) + longitudeBoundaryIndex;
|
|
5325
|
+
const cornerSample = sampleBlobbyOctopusSurfacePointWithLongitudeCache(options, cornerLatitude, cornerLongitude, cachedLobeWavesByCornerLongitude[longitudeBoundaryIndex]);
|
|
5326
|
+
transformedCornerSamples[cornerIndex] = transformScenePoint(cornerSample, center, rotationX, rotationY);
|
|
5327
|
+
}
|
|
5328
|
+
}
|
|
5288
5329
|
for (let latitudeIndex = 0; latitudeIndex < latitudePatchCount; latitudeIndex++) {
|
|
5289
|
-
const startLatitude =
|
|
5290
|
-
const endLatitude =
|
|
5330
|
+
const startLatitude = latitudeBoundaries[latitudeIndex];
|
|
5331
|
+
const endLatitude = latitudeBoundaries[latitudeIndex + 1];
|
|
5291
5332
|
const centerLatitude = (startLatitude + endLatitude) / 2;
|
|
5292
5333
|
const verticalProgress = (Math.sin(centerLatitude) + 1) / 2;
|
|
5334
|
+
const startCornerRowOffset = latitudeIndex * (longitudePatchCount + 1);
|
|
5335
|
+
const endCornerRowOffset = (latitudeIndex + 1) * (longitudePatchCount + 1);
|
|
5293
5336
|
for (let longitudeIndex = 0; longitudeIndex < longitudePatchCount; longitudeIndex++) {
|
|
5294
|
-
const startLongitude =
|
|
5295
|
-
const endLongitude =
|
|
5337
|
+
const startLongitude = longitudeBoundaries[longitudeIndex];
|
|
5338
|
+
const endLongitude = longitudeBoundaries[longitudeIndex + 1];
|
|
5296
5339
|
const centerLongitude = (startLongitude + endLongitude) / 2;
|
|
5297
|
-
const
|
|
5298
|
-
|
|
5299
|
-
|
|
5300
|
-
|
|
5301
|
-
|
|
5340
|
+
const transformedCorners = [
|
|
5341
|
+
transformedCornerSamples[startCornerRowOffset + longitudeIndex],
|
|
5342
|
+
transformedCornerSamples[startCornerRowOffset + longitudeIndex + 1],
|
|
5343
|
+
transformedCornerSamples[endCornerRowOffset + longitudeIndex + 1],
|
|
5344
|
+
transformedCornerSamples[endCornerRowOffset + longitudeIndex],
|
|
5302
5345
|
];
|
|
5303
|
-
const transformedCorners = localCorners.map((localCorner) => transformScenePoint(localCorner, center, rotationX, rotationY));
|
|
5304
5346
|
const surfaceNormal = normalizeVector3(crossProduct3D(subtractPoint3D(transformedCorners[1], transformedCorners[0]), subtractPoint3D(transformedCorners[2], transformedCorners[0])));
|
|
5305
5347
|
if (surfaceNormal.z <= 0.01) {
|
|
5306
5348
|
continue;
|
|
5307
5349
|
}
|
|
5308
|
-
const projectedCorners =
|
|
5350
|
+
const projectedCorners = [
|
|
5351
|
+
projectScenePoint(transformedCorners[0], size, sceneCenterX, sceneCenterY),
|
|
5352
|
+
projectScenePoint(transformedCorners[1], size, sceneCenterX, sceneCenterY),
|
|
5353
|
+
projectScenePoint(transformedCorners[2], size, sceneCenterX, sceneCenterY),
|
|
5354
|
+
projectScenePoint(transformedCorners[3], size, sceneCenterX, sceneCenterY),
|
|
5355
|
+
];
|
|
5309
5356
|
surfacePatches.push({
|
|
5310
5357
|
corners: projectedCorners,
|
|
5311
|
-
averageDepth: transformedCorners.
|
|
5312
|
-
transformedCorners.
|
|
5358
|
+
averageDepth: (transformedCorners[0].z +
|
|
5359
|
+
transformedCorners[1].z +
|
|
5360
|
+
transformedCorners[2].z +
|
|
5361
|
+
transformedCorners[3].z) /
|
|
5362
|
+
4,
|
|
5313
5363
|
lightIntensity: clampNumber$1(dotProduct3D(surfaceNormal, LIGHT_DIRECTION$1), -1, 1),
|
|
5314
5364
|
fillStyle: resolveBlobbySurfacePatchFillStyle(palette, verticalProgress, Math.max(0, Math.cos(centerLongitude)), resolveLowerLobeWave(centerLongitude, morphologyProfile, animationPhase, timeMs)),
|
|
5315
5365
|
outlineColor: verticalProgress < 0.58 ? `${palette.highlight}73` : `${palette.shadow}8a`,
|
|
@@ -5327,12 +5377,21 @@ function resolveVisibleBlobbyOctopusPatches(options) {
|
|
|
5327
5377
|
* @private helper of `octopus3d2AvatarVisual`
|
|
5328
5378
|
*/
|
|
5329
5379
|
function sampleBlobbyOctopusSurfacePoint(options, latitude, longitude) {
|
|
5380
|
+
const { morphologyProfile, animationPhase, timeMs } = options;
|
|
5381
|
+
return sampleBlobbyOctopusSurfacePointWithLongitudeCache(options, latitude, longitude, resolveLowerLobeWave(longitude, morphologyProfile, animationPhase, timeMs));
|
|
5382
|
+
}
|
|
5383
|
+
/**
|
|
5384
|
+
* Samples one point on the continuous Octopus 3D 2 surface using a precomputed lower-lobe wave
|
|
5385
|
+
* to skip the per-call trig evaluation for `latitudePatchCount + 1` longitude-shared corners.
|
|
5386
|
+
*
|
|
5387
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
5388
|
+
*/
|
|
5389
|
+
function sampleBlobbyOctopusSurfacePointWithLongitudeCache(options, latitude, longitude, lowerLobeWave) {
|
|
5330
5390
|
const { radiusX, radiusY, radiusZ, morphologyProfile, timeMs, animationPhase } = options;
|
|
5331
5391
|
const cosineLatitude = Math.max(0, Math.cos(latitude));
|
|
5332
5392
|
const verticalProgress = (Math.sin(latitude) + 1) / 2;
|
|
5333
5393
|
const upperBlend = Math.pow(1 - verticalProgress, 1.2);
|
|
5334
5394
|
const lowerBlend = Math.pow(verticalProgress, 1.42);
|
|
5335
|
-
const lowerLobeWave = resolveLowerLobeWave(longitude, morphologyProfile, animationPhase, timeMs);
|
|
5336
5395
|
const skirtEnvelope = Math.pow(cosineLatitude, 0.5) * lowerBlend;
|
|
5337
5396
|
const horizontalScale = 1.02 +
|
|
5338
5397
|
skirtEnvelope * (0.34 + (morphologyProfile.tentacles.rootSpreadScale - 1) * 0.22 + lowerLobeWave * 0.22) -
|
|
@@ -5629,45 +5688,102 @@ function drawContinuousOctopusShadow(context, size, palette, interaction, timeMs
|
|
|
5629
5688
|
context.fill();
|
|
5630
5689
|
context.restore();
|
|
5631
5690
|
}
|
|
5691
|
+
/**
|
|
5692
|
+
* Number of latitude segments used by the continuous Octopus 3D 3 mesh.
|
|
5693
|
+
*
|
|
5694
|
+
* @private helper of `octopus3d3AvatarVisual`
|
|
5695
|
+
*/
|
|
5696
|
+
const LATITUDE_PATCH_COUNT = 16;
|
|
5697
|
+
/**
|
|
5698
|
+
* Number of longitude segments used by the continuous Octopus 3D 3 mesh.
|
|
5699
|
+
*
|
|
5700
|
+
* @private helper of `octopus3d3AvatarVisual`
|
|
5701
|
+
*/
|
|
5702
|
+
const LONGITUDE_PATCH_COUNT = 40;
|
|
5632
5703
|
/**
|
|
5633
5704
|
* Resolves visible projected patches for the continuous octopus mesh.
|
|
5634
5705
|
*
|
|
5706
|
+
* Within a single frame, mesh corner samples and longitude-only computations (tentacle
|
|
5707
|
+
* influence and lobe wave) are quantized to the patch grid and computed once each rather
|
|
5708
|
+
* than re-evaluated for every patch corner — the patch loop alone calls `sampleContinuousOctopusSurfacePoint`
|
|
5709
|
+
* for `latitudePatchCount * longitudePatchCount * 4` corners without caching, and each call
|
|
5710
|
+
* triggers an inner 8-iteration `Math.exp` loop, which dominates the per-frame cost.
|
|
5711
|
+
*
|
|
5635
5712
|
* @private helper of `octopus3d3AvatarVisual`
|
|
5636
5713
|
*/
|
|
5637
5714
|
function resolveVisibleContinuousOctopusPatches(options) {
|
|
5638
5715
|
const { center, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette } = options;
|
|
5639
|
-
const latitudePatchCount =
|
|
5640
|
-
const longitudePatchCount =
|
|
5716
|
+
const latitudePatchCount = LATITUDE_PATCH_COUNT;
|
|
5717
|
+
const longitudePatchCount = LONGITUDE_PATCH_COUNT;
|
|
5641
5718
|
const surfacePatches = [];
|
|
5719
|
+
const latitudeBoundaries = new Float64Array(latitudePatchCount + 1);
|
|
5720
|
+
const longitudeBoundaries = new Float64Array(longitudePatchCount + 1);
|
|
5721
|
+
for (let boundaryIndex = 0; boundaryIndex <= latitudePatchCount; boundaryIndex++) {
|
|
5722
|
+
latitudeBoundaries[boundaryIndex] = -Math.PI / 2 + (boundaryIndex / latitudePatchCount) * Math.PI;
|
|
5723
|
+
}
|
|
5724
|
+
for (let boundaryIndex = 0; boundaryIndex <= longitudePatchCount; boundaryIndex++) {
|
|
5725
|
+
longitudeBoundaries[boundaryIndex] = -Math.PI + (boundaryIndex / longitudePatchCount) * Math.PI * 2;
|
|
5726
|
+
}
|
|
5727
|
+
const cachedTentacleInfluencesByCornerLongitude = new Array(longitudePatchCount + 1);
|
|
5728
|
+
const cachedLobeWavesByCornerLongitude = new Float64Array(longitudePatchCount + 1);
|
|
5729
|
+
const cachedTentacleInfluencesByPatchCenterLongitude = new Array(longitudePatchCount);
|
|
5730
|
+
const cachedLobeWavesByPatchCenterLongitude = new Float64Array(longitudePatchCount);
|
|
5731
|
+
const cachedCosByPatchCenterLongitude = new Float64Array(longitudePatchCount);
|
|
5732
|
+
for (let boundaryIndex = 0; boundaryIndex <= longitudePatchCount; boundaryIndex++) {
|
|
5733
|
+
const cornerLongitude = longitudeBoundaries[boundaryIndex];
|
|
5734
|
+
cachedTentacleInfluencesByCornerLongitude[boundaryIndex] = resolveContinuousTentacleInfluence(options, cornerLongitude);
|
|
5735
|
+
cachedLobeWavesByCornerLongitude[boundaryIndex] = resolveContinuousLobeWave(options, cornerLongitude);
|
|
5736
|
+
}
|
|
5737
|
+
for (let longitudeIndex = 0; longitudeIndex < longitudePatchCount; longitudeIndex++) {
|
|
5738
|
+
const patchCenterLongitude = (longitudeBoundaries[longitudeIndex] + longitudeBoundaries[longitudeIndex + 1]) / 2;
|
|
5739
|
+
cachedTentacleInfluencesByPatchCenterLongitude[longitudeIndex] = resolveContinuousTentacleInfluence(options, patchCenterLongitude);
|
|
5740
|
+
cachedLobeWavesByPatchCenterLongitude[longitudeIndex] = resolveContinuousLobeWave(options, patchCenterLongitude);
|
|
5741
|
+
cachedCosByPatchCenterLongitude[longitudeIndex] = Math.max(0, Math.cos(patchCenterLongitude));
|
|
5742
|
+
}
|
|
5743
|
+
const cornerCount = (latitudePatchCount + 1) * (longitudePatchCount + 1);
|
|
5744
|
+
const transformedCornerSamples = new Array(cornerCount);
|
|
5745
|
+
for (let latitudeBoundaryIndex = 0; latitudeBoundaryIndex <= latitudePatchCount; latitudeBoundaryIndex++) {
|
|
5746
|
+
const cornerLatitude = latitudeBoundaries[latitudeBoundaryIndex];
|
|
5747
|
+
for (let longitudeBoundaryIndex = 0; longitudeBoundaryIndex <= longitudePatchCount; longitudeBoundaryIndex++) {
|
|
5748
|
+
const cornerLongitude = longitudeBoundaries[longitudeBoundaryIndex];
|
|
5749
|
+
const cornerIndex = latitudeBoundaryIndex * (longitudePatchCount + 1) + longitudeBoundaryIndex;
|
|
5750
|
+
const cornerSample = sampleContinuousOctopusSurfacePointWithLongitudeCache(options, cornerLatitude, cornerLongitude, cachedTentacleInfluencesByCornerLongitude[longitudeBoundaryIndex], cachedLobeWavesByCornerLongitude[longitudeBoundaryIndex]);
|
|
5751
|
+
transformedCornerSamples[cornerIndex] = transformScenePoint(cornerSample, center, rotationX, rotationY);
|
|
5752
|
+
}
|
|
5753
|
+
}
|
|
5642
5754
|
for (let latitudeIndex = 0; latitudeIndex < latitudePatchCount; latitudeIndex++) {
|
|
5643
|
-
const startLatitude =
|
|
5644
|
-
const endLatitude =
|
|
5755
|
+
const startLatitude = latitudeBoundaries[latitudeIndex];
|
|
5756
|
+
const endLatitude = latitudeBoundaries[latitudeIndex + 1];
|
|
5645
5757
|
const centerLatitude = (startLatitude + endLatitude) / 2;
|
|
5646
5758
|
const verticalProgress = (Math.sin(centerLatitude) + 1) / 2;
|
|
5759
|
+
const startCornerRowOffset = latitudeIndex * (longitudePatchCount + 1);
|
|
5760
|
+
const endCornerRowOffset = (latitudeIndex + 1) * (longitudePatchCount + 1);
|
|
5647
5761
|
for (let longitudeIndex = 0; longitudeIndex < longitudePatchCount; longitudeIndex++) {
|
|
5648
|
-
const
|
|
5649
|
-
|
|
5650
|
-
|
|
5651
|
-
|
|
5652
|
-
|
|
5653
|
-
sampleContinuousOctopusSurfacePoint(options, startLatitude, endLongitude),
|
|
5654
|
-
sampleContinuousOctopusSurfacePoint(options, endLatitude, endLongitude),
|
|
5655
|
-
sampleContinuousOctopusSurfacePoint(options, endLatitude, startLongitude),
|
|
5762
|
+
const transformedCorners = [
|
|
5763
|
+
transformedCornerSamples[startCornerRowOffset + longitudeIndex],
|
|
5764
|
+
transformedCornerSamples[startCornerRowOffset + longitudeIndex + 1],
|
|
5765
|
+
transformedCornerSamples[endCornerRowOffset + longitudeIndex + 1],
|
|
5766
|
+
transformedCornerSamples[endCornerRowOffset + longitudeIndex],
|
|
5656
5767
|
];
|
|
5657
|
-
const transformedCorners = localCorners.map((localCorner) => transformScenePoint(localCorner, center, rotationX, rotationY));
|
|
5658
5768
|
const surfaceNormal = normalizeVector3(crossProduct3D(subtractPoint3D(transformedCorners[1], transformedCorners[0]), subtractPoint3D(transformedCorners[2], transformedCorners[0])));
|
|
5659
5769
|
if (surfaceNormal.z <= 0.008) {
|
|
5660
5770
|
continue;
|
|
5661
5771
|
}
|
|
5662
|
-
const projectedCorners =
|
|
5663
|
-
|
|
5664
|
-
|
|
5772
|
+
const projectedCorners = [
|
|
5773
|
+
projectScenePoint(transformedCorners[0], size, sceneCenterX, sceneCenterY),
|
|
5774
|
+
projectScenePoint(transformedCorners[1], size, sceneCenterX, sceneCenterY),
|
|
5775
|
+
projectScenePoint(transformedCorners[2], size, sceneCenterX, sceneCenterY),
|
|
5776
|
+
projectScenePoint(transformedCorners[3], size, sceneCenterX, sceneCenterY),
|
|
5777
|
+
];
|
|
5665
5778
|
surfacePatches.push({
|
|
5666
5779
|
corners: projectedCorners,
|
|
5667
|
-
averageDepth: transformedCorners.
|
|
5668
|
-
transformedCorners.
|
|
5780
|
+
averageDepth: (transformedCorners[0].z +
|
|
5781
|
+
transformedCorners[1].z +
|
|
5782
|
+
transformedCorners[2].z +
|
|
5783
|
+
transformedCorners[3].z) /
|
|
5784
|
+
4,
|
|
5669
5785
|
lightIntensity: clampNumber$1(dotProduct3D(surfaceNormal, LIGHT_DIRECTION), -1, 1),
|
|
5670
|
-
fillStyle: resolveContinuousSurfacePatchFillStyle(palette, verticalProgress,
|
|
5786
|
+
fillStyle: resolveContinuousSurfacePatchFillStyle(palette, verticalProgress, cachedCosByPatchCenterLongitude[longitudeIndex], cachedTentacleInfluencesByPatchCenterLongitude[longitudeIndex].core, cachedLobeWavesByPatchCenterLongitude[longitudeIndex]),
|
|
5671
5787
|
outlineColor: verticalProgress < 0.54 ? `${palette.highlight}69` : `${palette.shadow}78`,
|
|
5672
5788
|
});
|
|
5673
5789
|
}
|
|
@@ -5683,16 +5799,27 @@ function resolveVisibleContinuousOctopusPatches(options) {
|
|
|
5683
5799
|
* @private helper of `octopus3d3AvatarVisual`
|
|
5684
5800
|
*/
|
|
5685
5801
|
function sampleContinuousOctopusSurfacePoint(options, latitude, longitude) {
|
|
5802
|
+
return sampleContinuousOctopusSurfacePointWithLongitudeCache(options, latitude, longitude, resolveContinuousTentacleInfluence(options, longitude), resolveContinuousLobeWave(options, longitude));
|
|
5803
|
+
}
|
|
5804
|
+
/**
|
|
5805
|
+
* Samples one point on the continuous Octopus 3D 3 surface using precomputed longitude-only
|
|
5806
|
+
* values to skip the per-call `Math.exp` tentacle-influence loop and the lobe-wave trig call.
|
|
5807
|
+
*
|
|
5808
|
+
* The patch loop quantizes the mesh into a fixed `(latitudePatchCount + 1) * (longitudePatchCount + 1)`
|
|
5809
|
+
* corner grid, so the same longitude is reused across every latitude row and each
|
|
5810
|
+
* tentacle/lobe value can be computed once per frame instead of `latitudePatchCount * 4` times.
|
|
5811
|
+
*
|
|
5812
|
+
* @private helper of `octopus3d3AvatarVisual`
|
|
5813
|
+
*/
|
|
5814
|
+
function sampleContinuousOctopusSurfacePointWithLongitudeCache(options, latitude, longitude, tentacleInfluence, lowerLobeWave) {
|
|
5686
5815
|
const { radiusX, radiusY, radiusZ, morphologyProfile, timeMs, animationPhase } = options;
|
|
5687
5816
|
const cosineLatitude = Math.max(0, Math.cos(latitude));
|
|
5688
5817
|
const verticalProgress = (Math.sin(latitude) + 1) / 2;
|
|
5689
5818
|
const upperBlend = Math.pow(1 - verticalProgress, 1.28);
|
|
5690
5819
|
const lowerBlend = smoothStep(0.38, 1, verticalProgress);
|
|
5691
5820
|
const tipBlend = smoothStep(0.68, 1, verticalProgress);
|
|
5692
|
-
const tentacleInfluence = resolveContinuousTentacleInfluence(options, longitude);
|
|
5693
5821
|
const centerPull = resolveSignedAngularDistance(longitude, tentacleInfluence.centerLongitude);
|
|
5694
5822
|
const effectiveLongitude = longitude + centerPull * lowerBlend * tentacleInfluence.core * (0.24 + tipBlend * 0.2);
|
|
5695
|
-
const lowerLobeWave = resolveContinuousLobeWave(options, longitude);
|
|
5696
5823
|
const mantleRipple = Math.sin(longitude * morphologyProfile.body.lobeCount +
|
|
5697
5824
|
animationPhase * 0.6 +
|
|
5698
5825
|
timeMs / (1750 + morphologyProfile.body.lobeCount * 30)) *
|
|
@@ -9381,8 +9508,11 @@ class GoalCommitmentDefinition extends BaseCommitmentDefinition {
|
|
|
9381
9508
|
if (!trimmedContent) {
|
|
9382
9509
|
return requirements;
|
|
9383
9510
|
}
|
|
9384
|
-
|
|
9385
|
-
|
|
9511
|
+
const goalSection = spaceTrim$1((block) => `
|
|
9512
|
+
## Goal
|
|
9513
|
+
|
|
9514
|
+
${block(trimmedContent)}
|
|
9515
|
+
`);
|
|
9386
9516
|
const requirementsWithGoal = this.appendToSystemMessage(requirements, goalSection, '\n\n');
|
|
9387
9517
|
return this.appendToPromptSuffix(requirementsWithGoal, trimmedContent);
|
|
9388
9518
|
}
|
|
@@ -9904,8 +10034,11 @@ class LanguageCommitmentDefinition extends BaseCommitmentDefinition {
|
|
|
9904
10034
|
if (!trimmedContent) {
|
|
9905
10035
|
return requirements;
|
|
9906
10036
|
}
|
|
9907
|
-
|
|
9908
|
-
|
|
10037
|
+
const languageSection = spaceTrim$1((block) => `
|
|
10038
|
+
## Language
|
|
10039
|
+
|
|
10040
|
+
- Your language is ${block(trimmedContent)}
|
|
10041
|
+
`);
|
|
9909
10042
|
return this.appendToSystemMessage(requirements, languageSection, '\n\n');
|
|
9910
10043
|
}
|
|
9911
10044
|
}
|
|
@@ -13485,7 +13618,15 @@ function buildTeammateMetadata(entry) {
|
|
|
13485
13618
|
* Builds the teammate request text, optionally including context.
|
|
13486
13619
|
*/
|
|
13487
13620
|
function buildTeammateRequest(message, context) {
|
|
13488
|
-
|
|
13621
|
+
if (!context) {
|
|
13622
|
+
return message;
|
|
13623
|
+
}
|
|
13624
|
+
return spaceTrim$1((block) => `
|
|
13625
|
+
${block(message)}
|
|
13626
|
+
|
|
13627
|
+
Context:
|
|
13628
|
+
${block(context)}
|
|
13629
|
+
`);
|
|
13489
13630
|
}
|
|
13490
13631
|
/**
|
|
13491
13632
|
* Builds a minimal chat prompt for teammate calls.
|
|
@@ -17508,7 +17649,11 @@ function createUseProjectToolFunctions() {
|
|
|
17508
17649
|
const lineRangedContent = applyOptionalLineRange(decodedContent, args.startLine, args.endLine);
|
|
17509
17650
|
const wasCharacterTruncated = lineRangedContent.length > MAX_PROJECT_FILE_CONTENT_CHARACTERS;
|
|
17510
17651
|
const contentToReturn = wasCharacterTruncated
|
|
17511
|
-
?
|
|
17652
|
+
? spaceTrim$1((block) => `
|
|
17653
|
+
${block(lineRangedContent.slice(0, MAX_PROJECT_FILE_CONTENT_CHARACTERS))}
|
|
17654
|
+
|
|
17655
|
+
[...truncated...]
|
|
17656
|
+
`)
|
|
17512
17657
|
: lineRangedContent;
|
|
17513
17658
|
const wasTruncated = decoded.isTruncated || wasCharacterTruncated;
|
|
17514
17659
|
if (wasCharacterTruncated) {
|
|
@@ -25810,11 +25955,19 @@ const FILE_EXTENSION_REGEX = /\.([a-z0-9]{1,10})$/i;
|
|
|
25810
25955
|
* Pattern matching punctuation that should be trimmed from citation tails.
|
|
25811
25956
|
*/
|
|
25812
25957
|
const TRAILING_PUNCTUATION_REGEX = /[.,;:!?)+\]]+$/;
|
|
25958
|
+
/**
|
|
25959
|
+
* Pattern matching filename separators that should become spaces in source labels.
|
|
25960
|
+
*/
|
|
25961
|
+
const FILENAME_SEPARATOR_REGEX = /[-_]+/g;
|
|
25962
|
+
/**
|
|
25963
|
+
* Pattern matching consecutive whitespace in display labels.
|
|
25964
|
+
*/
|
|
25965
|
+
const WHITESPACE_REGEX = /\s+/g;
|
|
25813
25966
|
/**
|
|
25814
25967
|
* Collapses consecutive whitespace into single spaces.
|
|
25815
25968
|
*/
|
|
25816
25969
|
function collapseWhitespace(value) {
|
|
25817
|
-
return value.replace(
|
|
25970
|
+
return value.replace(WHITESPACE_REGEX, ' ');
|
|
25818
25971
|
}
|
|
25819
25972
|
/**
|
|
25820
25973
|
* Trims a value before further citation normalization.
|
|
@@ -25887,6 +26040,10 @@ function isPlainTextCitation(citation) {
|
|
|
25887
26040
|
* @private utility of `<Chat/>` citation rendering
|
|
25888
26041
|
*/
|
|
25889
26042
|
function getCitationLabel(citation) {
|
|
26043
|
+
const title = normalizeCitationDisplayLabel(citation.title);
|
|
26044
|
+
if (title) {
|
|
26045
|
+
return title;
|
|
26046
|
+
}
|
|
25890
26047
|
const trimmed = trimToNormalized(citation.source);
|
|
25891
26048
|
if (!trimmed) {
|
|
25892
26049
|
return citation.source;
|
|
@@ -25898,7 +26055,7 @@ function getCitationLabel(citation) {
|
|
|
25898
26055
|
}
|
|
25899
26056
|
return collapsed.slice(0, TEXT_LABEL_LENGTH) + LABEL_ELLIPSIS;
|
|
25900
26057
|
}
|
|
25901
|
-
return
|
|
26058
|
+
return createReadableCitationSourceLabel(trimmed);
|
|
25902
26059
|
}
|
|
25903
26060
|
/**
|
|
25904
26061
|
* Resolves the preview URL used inside the citation modal iframe.
|
|
@@ -25917,8 +26074,134 @@ function resolveCitationPreviewUrl(citation, participants) {
|
|
|
25917
26074
|
const knowledgeUrl = resolveCitationUrl(trimmed, participants);
|
|
25918
26075
|
return explicitUrl || literalUrl || knowledgeUrl || null;
|
|
25919
26076
|
}
|
|
26077
|
+
/**
|
|
26078
|
+
* Creates a readable fallback label from a citation source when no title metadata is available.
|
|
26079
|
+
*
|
|
26080
|
+
* @param source - Raw citation source value.
|
|
26081
|
+
* @returns Human-friendly source label.
|
|
26082
|
+
*
|
|
26083
|
+
* @private utility of `<Chat/>` citation rendering
|
|
26084
|
+
*/
|
|
26085
|
+
function createReadableCitationSourceLabel(source) {
|
|
26086
|
+
const trimmed = trimToNormalized(source);
|
|
26087
|
+
if (!trimmed) {
|
|
26088
|
+
return source;
|
|
26089
|
+
}
|
|
26090
|
+
const parsedUrl = parseCitationUrl(trimmed);
|
|
26091
|
+
const filenameCandidate = parsedUrl
|
|
26092
|
+
? getUrlLabelCandidate(parsedUrl) || parsedUrl.hostname.replace(/^www\./i, '')
|
|
26093
|
+
: simplifyKnowledgeLabel(trimmed);
|
|
26094
|
+
return normalizeCitationDisplayLabel(filenameCandidate) || simplifyKnowledgeLabel(trimmed);
|
|
26095
|
+
}
|
|
26096
|
+
/**
|
|
26097
|
+
* Normalizes a citation label candidate for display.
|
|
26098
|
+
*
|
|
26099
|
+
* @param label - Raw candidate label.
|
|
26100
|
+
* @returns Cleaned label or `null` when empty.
|
|
26101
|
+
*
|
|
26102
|
+
* @private utility of `<Chat/>` citation rendering
|
|
26103
|
+
*/
|
|
26104
|
+
function normalizeCitationDisplayLabel(label) {
|
|
26105
|
+
const normalized = collapseWhitespace((label || '').replace(FILENAME_SEPARATOR_REGEX, ' ')).trim();
|
|
26106
|
+
return normalized || null;
|
|
26107
|
+
}
|
|
26108
|
+
/**
|
|
26109
|
+
* Parses one HTTP(S) citation URL, returning null for non-URL values.
|
|
26110
|
+
*
|
|
26111
|
+
* @param value - Candidate URL value.
|
|
26112
|
+
* @returns Parsed URL or null.
|
|
26113
|
+
*
|
|
26114
|
+
* @private utility of `<Chat/>` citation rendering
|
|
26115
|
+
*/
|
|
26116
|
+
function parseCitationUrl(value) {
|
|
26117
|
+
try {
|
|
26118
|
+
const url = new URL(value);
|
|
26119
|
+
return url.protocol === 'http:' || url.protocol === 'https:' ? url : null;
|
|
26120
|
+
}
|
|
26121
|
+
catch (_a) {
|
|
26122
|
+
return null;
|
|
26123
|
+
}
|
|
26124
|
+
}
|
|
26125
|
+
/**
|
|
26126
|
+
* Extracts a readable candidate from a URL path.
|
|
26127
|
+
*
|
|
26128
|
+
* @param url - Parsed citation URL.
|
|
26129
|
+
* @returns URL path label candidate or null.
|
|
26130
|
+
*
|
|
26131
|
+
* @private utility of `<Chat/>` citation rendering
|
|
26132
|
+
*/
|
|
26133
|
+
function getUrlLabelCandidate(url) {
|
|
26134
|
+
const pathSegments = url.pathname.split('/').filter(Boolean);
|
|
26135
|
+
const lastPathSegment = pathSegments[pathSegments.length - 1];
|
|
26136
|
+
if (!lastPathSegment) {
|
|
26137
|
+
return null;
|
|
26138
|
+
}
|
|
26139
|
+
try {
|
|
26140
|
+
return simplifyKnowledgeLabel(decodeURIComponent(lastPathSegment));
|
|
26141
|
+
}
|
|
26142
|
+
catch (_a) {
|
|
26143
|
+
return simplifyKnowledgeLabel(lastPathSegment);
|
|
26144
|
+
}
|
|
26145
|
+
}
|
|
25920
26146
|
// TODO: [💞] Spread into multiple files
|
|
25921
26147
|
|
|
26148
|
+
/**
|
|
26149
|
+
* Extracts one quick button definition from a markdown link query string.
|
|
26150
|
+
*
|
|
26151
|
+
* @param text The visible button label.
|
|
26152
|
+
* @param query Raw query-string payload captured from markdown.
|
|
26153
|
+
* @returns Parsed quick button definition or `null` when the link is not a supported quick button.
|
|
26154
|
+
*
|
|
26155
|
+
* @private internal helper of `parseMessageButtons`
|
|
26156
|
+
*/
|
|
26157
|
+
function parseQuickButtonDefinition(text, query) {
|
|
26158
|
+
const searchParams = new URLSearchParams(query);
|
|
26159
|
+
const message = searchParams.get('message');
|
|
26160
|
+
if (message !== null) {
|
|
26161
|
+
return {
|
|
26162
|
+
type: 'message',
|
|
26163
|
+
text,
|
|
26164
|
+
message,
|
|
26165
|
+
};
|
|
26166
|
+
}
|
|
26167
|
+
const code = searchParams.get('action');
|
|
26168
|
+
if (code !== null) {
|
|
26169
|
+
return {
|
|
26170
|
+
type: 'action',
|
|
26171
|
+
text,
|
|
26172
|
+
code,
|
|
26173
|
+
};
|
|
26174
|
+
}
|
|
26175
|
+
return null;
|
|
26176
|
+
}
|
|
26177
|
+
/**
|
|
26178
|
+
* Parses markdown quick buttons in the format `[Button Text](?message=...)` or `[Button Text](?action=...)`.
|
|
26179
|
+
* Returns both the content without supported quick buttons and the extracted button definitions.
|
|
26180
|
+
*
|
|
26181
|
+
* @param content The markdown content that may contain buttons
|
|
26182
|
+
* @returns Object with contentWithoutButtons and buttons array
|
|
26183
|
+
*
|
|
26184
|
+
* @public exported from `@promptbook/components`
|
|
26185
|
+
*/
|
|
26186
|
+
function parseMessageButtons(content) {
|
|
26187
|
+
const buttonRegex = /\[([^\]]+)\]\(\?([^)]+)\)/g;
|
|
26188
|
+
const buttons = [];
|
|
26189
|
+
const contentWithoutButtons = content
|
|
26190
|
+
.replace(buttonRegex, (match, text, query) => {
|
|
26191
|
+
const button = parseQuickButtonDefinition(text, query);
|
|
26192
|
+
if (!button) {
|
|
26193
|
+
return match;
|
|
26194
|
+
}
|
|
26195
|
+
buttons.push(button);
|
|
26196
|
+
return '';
|
|
26197
|
+
})
|
|
26198
|
+
.trim();
|
|
26199
|
+
return {
|
|
26200
|
+
contentWithoutButtons,
|
|
26201
|
+
buttons,
|
|
26202
|
+
};
|
|
26203
|
+
}
|
|
26204
|
+
|
|
25922
26205
|
/**
|
|
25923
26206
|
* Default citation identifier used for simplified citation markers without an explicit position.
|
|
25924
26207
|
*
|
|
@@ -26809,12 +27092,13 @@ function resolveCitationForToken(rawToken, bracketCitationId, citationsById) {
|
|
|
26809
27092
|
* @private utility of `<Chat/>`
|
|
26810
27093
|
*/
|
|
26811
27094
|
function normalizeParsedCitation(citation) {
|
|
26812
|
-
var _a, _b;
|
|
27095
|
+
var _a, _b, _c;
|
|
26813
27096
|
return {
|
|
26814
27097
|
id: citation.id.trim(),
|
|
26815
27098
|
source: citation.source.trim(),
|
|
26816
27099
|
url: ((_a = citation.url) === null || _a === void 0 ? void 0 : _a.trim()) || undefined,
|
|
26817
|
-
|
|
27100
|
+
title: ((_b = citation.title) === null || _b === void 0 ? void 0 : _b.trim()) || undefined,
|
|
27101
|
+
excerpt: ((_c = citation.excerpt) === null || _c === void 0 ? void 0 : _c.trim()) || undefined,
|
|
26818
27102
|
};
|
|
26819
27103
|
}
|
|
26820
27104
|
/**
|
|
@@ -26831,11 +27115,13 @@ function mergeParsedCitations(currentCitation, incomingCitation) {
|
|
|
26831
27115
|
id: currentCitation.id || incomingCitation.id,
|
|
26832
27116
|
source: resolvePreferredCitationSource(currentCitation, incomingCitation),
|
|
26833
27117
|
url: currentCitation.url || incomingCitation.url,
|
|
27118
|
+
title: currentCitation.title || incomingCitation.title,
|
|
26834
27119
|
excerpt: currentCitation.excerpt || incomingCitation.excerpt,
|
|
26835
27120
|
};
|
|
26836
27121
|
if (mergedCitation.id === currentCitation.id &&
|
|
26837
27122
|
mergedCitation.source === currentCitation.source &&
|
|
26838
27123
|
mergedCitation.url === currentCitation.url &&
|
|
27124
|
+
mergedCitation.title === currentCitation.title &&
|
|
26839
27125
|
mergedCitation.excerpt === currentCitation.excerpt) {
|
|
26840
27126
|
return currentCitation;
|
|
26841
27127
|
}
|
|
@@ -27185,6 +27471,12 @@ const CITATION_FOOTNOTE_REFERENCE_HTML_REGEX = /<sup data-citation-footnote="(\d
|
|
|
27185
27471
|
* @private Internal helper shared by HTML and PDF chat exports.
|
|
27186
27472
|
*/
|
|
27187
27473
|
const CHAT_HTML_EXPORT_RENDER_ROOT_CLASS_NAME = 'chat-html-export-render-root';
|
|
27474
|
+
/**
|
|
27475
|
+
* Roles whose messages are aligned to the right side of the exported transcript.
|
|
27476
|
+
*
|
|
27477
|
+
* @private Internal helper of `htmlSaveFormatDefinition`.
|
|
27478
|
+
*/
|
|
27479
|
+
const RIGHT_ALIGNED_SENDER_ROLES = new Set(['USER']);
|
|
27188
27480
|
/**
|
|
27189
27481
|
* Escapes HTML-sensitive text before embedding it into the export document.
|
|
27190
27482
|
*
|
|
@@ -27198,6 +27490,38 @@ function escapeHtml$1(value) {
|
|
|
27198
27490
|
.replace(/"/g, '"')
|
|
27199
27491
|
.replace(/'/g, ''');
|
|
27200
27492
|
}
|
|
27493
|
+
/**
|
|
27494
|
+
* Returns the first uppercase character of a display name, used for the fallback avatar glyph.
|
|
27495
|
+
*
|
|
27496
|
+
* @private Internal helper of `htmlSaveFormatDefinition`.
|
|
27497
|
+
*/
|
|
27498
|
+
function getAvatarInitial(displayName) {
|
|
27499
|
+
const trimmedName = displayName.trim();
|
|
27500
|
+
if (!trimmedName) {
|
|
27501
|
+
return '?';
|
|
27502
|
+
}
|
|
27503
|
+
return Array.from(trimmedName)[0].toUpperCase();
|
|
27504
|
+
}
|
|
27505
|
+
/**
|
|
27506
|
+
* Renders the avatar bubble shown next to one exported message.
|
|
27507
|
+
*
|
|
27508
|
+
* @private Internal helper of `htmlSaveFormatDefinition`.
|
|
27509
|
+
*/
|
|
27510
|
+
function buildAvatarMarkup(participant, displayName, accentColor) {
|
|
27511
|
+
const avatarStyle = `background-color:${escapeHtml$1(accentColor)};`;
|
|
27512
|
+
if (participant === null || participant === void 0 ? void 0 : participant.avatarSrc) {
|
|
27513
|
+
return spaceTrim$1(`
|
|
27514
|
+
<div class="message-avatar" aria-hidden="true" style="${avatarStyle}">
|
|
27515
|
+
<img src="${escapeHtml$1(participant.avatarSrc)}" alt="" loading="lazy" />
|
|
27516
|
+
</div>
|
|
27517
|
+
`);
|
|
27518
|
+
}
|
|
27519
|
+
return spaceTrim$1(`
|
|
27520
|
+
<div class="message-avatar message-avatar--initial" aria-hidden="true" style="${avatarStyle}">
|
|
27521
|
+
<span>${escapeHtml$1(getAvatarInitial(displayName))}</span>
|
|
27522
|
+
</div>
|
|
27523
|
+
`);
|
|
27524
|
+
}
|
|
27201
27525
|
/**
|
|
27202
27526
|
* Renders attachments for one exported message as a compact supporting section.
|
|
27203
27527
|
*
|
|
@@ -27261,13 +27585,26 @@ function buildCitationsMarkup(message) {
|
|
|
27261
27585
|
</section>
|
|
27262
27586
|
`);
|
|
27263
27587
|
}
|
|
27588
|
+
/**
|
|
27589
|
+
* Removes quick action and quick message buttons from the markdown body before rendering.
|
|
27590
|
+
*
|
|
27591
|
+
* Quick buttons are interactive UI affordances and have no meaning inside a static export.
|
|
27592
|
+
*
|
|
27593
|
+
* @private Internal helper of `htmlSaveFormatDefinition`.
|
|
27594
|
+
*/
|
|
27595
|
+
function stripQuickButtonsFromContent(content) {
|
|
27596
|
+
return parseMessageButtons(content).contentWithoutButtons;
|
|
27597
|
+
}
|
|
27264
27598
|
/**
|
|
27265
27599
|
* Converts one markdown message body to HTML with document-wide source references.
|
|
27266
27600
|
*
|
|
27267
27601
|
* @private Internal helper of `htmlSaveFormatDefinition`.
|
|
27268
27602
|
*/
|
|
27269
27603
|
function renderFootnotedMarkdown(message, citationFootnotes) {
|
|
27270
|
-
const renderModel = createChatExportCitationRenderModel(citationFootnotes,
|
|
27604
|
+
const renderModel = createChatExportCitationRenderModel(citationFootnotes, {
|
|
27605
|
+
...message,
|
|
27606
|
+
content: stripQuickButtonsFromContent(message.content),
|
|
27607
|
+
});
|
|
27271
27608
|
const html = linkCitationFootnoteReferences(renderMarkdown(renderModel.content));
|
|
27272
27609
|
return {
|
|
27273
27610
|
html,
|
|
@@ -27305,34 +27642,74 @@ function buildReplyingToMarkup(message, citationFootnotes) {
|
|
|
27305
27642
|
`);
|
|
27306
27643
|
}
|
|
27307
27644
|
/**
|
|
27308
|
-
*
|
|
27645
|
+
* Determines whether a message bubble should sit on the right side of the transcript.
|
|
27646
|
+
*
|
|
27647
|
+
* @private Internal helper of `htmlSaveFormatDefinition`.
|
|
27648
|
+
*/
|
|
27649
|
+
function isRightAlignedMessage(participant, sender) {
|
|
27650
|
+
if ((participant === null || participant === void 0 ? void 0 : participant.isMe) === true) {
|
|
27651
|
+
return true;
|
|
27652
|
+
}
|
|
27653
|
+
return RIGHT_ALIGNED_SENDER_ROLES.has(sender.toUpperCase());
|
|
27654
|
+
}
|
|
27655
|
+
/**
|
|
27656
|
+
* Detects whether a message would render with no body, attachments, or supporting metadata after sanitization.
|
|
27657
|
+
*
|
|
27658
|
+
* Such messages exist only to carry quick buttons in the live chat UI and add no value to a printed transcript.
|
|
27659
|
+
*
|
|
27660
|
+
* @private Internal helper of `htmlSaveFormatDefinition`.
|
|
27661
|
+
*/
|
|
27662
|
+
function isMessageEmptyForExport(message) {
|
|
27663
|
+
const trimmedContent = stripQuickButtonsFromContent(message.content).trim();
|
|
27664
|
+
if (trimmedContent.length > 0) {
|
|
27665
|
+
return false;
|
|
27666
|
+
}
|
|
27667
|
+
if (message.attachments && message.attachments.length > 0) {
|
|
27668
|
+
return false;
|
|
27669
|
+
}
|
|
27670
|
+
if (message.citations && message.citations.length > 0) {
|
|
27671
|
+
return false;
|
|
27672
|
+
}
|
|
27673
|
+
if (message.replyingTo) {
|
|
27674
|
+
return false;
|
|
27675
|
+
}
|
|
27676
|
+
return true;
|
|
27677
|
+
}
|
|
27678
|
+
/**
|
|
27679
|
+
* Renders one message bubble for the standalone HTML export.
|
|
27309
27680
|
*
|
|
27310
27681
|
* @private Internal helper of `htmlSaveFormatDefinition`.
|
|
27311
27682
|
*/
|
|
27312
27683
|
function renderMessageBlock(message, participants, citationFootnotes) {
|
|
27684
|
+
var _a;
|
|
27313
27685
|
const sender = String(message.sender || 'SYSTEM');
|
|
27314
|
-
const
|
|
27686
|
+
const participant = (_a = participants.get(sender)) !== null && _a !== void 0 ? _a : participants.get(sender.toUpperCase());
|
|
27315
27687
|
const visuals = resolveChatExportParticipantVisuals(participants, sender);
|
|
27316
27688
|
const timestamp = formatChatExportTimestamp(message.createdAt);
|
|
27317
27689
|
const durationLabel = typeof message.generationDurationMs === 'number' ? `${(message.generationDurationMs / 1000).toFixed(1)}s` : '';
|
|
27318
27690
|
const replyingToMarkup = buildReplyingToMarkup(message, citationFootnotes);
|
|
27319
27691
|
const { html: messageBody, renderModel } = renderFootnotedMarkdown(message, citationFootnotes);
|
|
27692
|
+
const isRightAligned = isRightAlignedMessage(participant, sender);
|
|
27693
|
+
const avatarMarkup = buildAvatarMarkup(participant, visuals.displayName, visuals.accentColor);
|
|
27694
|
+
const alignmentClass = isRightAligned ? 'message--mine' : 'message--theirs';
|
|
27320
27695
|
return spaceTrim$1(`
|
|
27321
|
-
<article class="message
|
|
27322
|
-
|
|
27323
|
-
|
|
27696
|
+
<article class="message ${alignmentClass}" style="--message-accent:${escapeHtml$1(visuals.accentColor)};">
|
|
27697
|
+
${avatarMarkup}
|
|
27698
|
+
<div class="message-body">
|
|
27699
|
+
<header class="message-meta">
|
|
27324
27700
|
<span class="message-sender">${escapeHtml$1(visuals.displayName)}</span>
|
|
27325
|
-
|
|
27701
|
+
${timestamp ? `<time class="message-time">${escapeHtml$1(timestamp)}</time>` : ''}
|
|
27702
|
+
</header>
|
|
27703
|
+
<div class="message-bubble">
|
|
27704
|
+
${replyingToMarkup}
|
|
27705
|
+
<div class="message-content markdown-content">
|
|
27706
|
+
${messageBody || '<p class="message-empty">No text provided.</p>'}
|
|
27707
|
+
</div>
|
|
27326
27708
|
</div>
|
|
27327
|
-
${
|
|
27328
|
-
|
|
27329
|
-
|
|
27330
|
-
|
|
27331
|
-
${messageBody || '<p class="message-empty">No text provided.</p>'}
|
|
27332
|
-
</section>
|
|
27333
|
-
${durationLabel ? `<p class="message-duration">Responded in ${escapeHtml$1(durationLabel)}</p>` : ''}
|
|
27334
|
-
${buildAttachmentsMarkup(message)}
|
|
27335
|
-
${renderModel.footnotes.length === 0 ? buildCitationsMarkup(message) : ''}
|
|
27709
|
+
${durationLabel ? `<p class="message-footnote">Responded in ${escapeHtml$1(durationLabel)}</p>` : ''}
|
|
27710
|
+
${buildAttachmentsMarkup(message)}
|
|
27711
|
+
${renderModel.footnotes.length === 0 ? buildCitationsMarkup(message) : ''}
|
|
27712
|
+
</div>
|
|
27336
27713
|
</article>
|
|
27337
27714
|
`);
|
|
27338
27715
|
}
|
|
@@ -27396,8 +27773,11 @@ function buildChatHtml(title, messages, participants) {
|
|
|
27396
27773
|
const participantLookup = buildChatExportParticipantMap(participants);
|
|
27397
27774
|
const citationFootnotes = createChatExportCitationFootnoteRegistry();
|
|
27398
27775
|
const exportedLabel = formatChatExportTimestamp(new Date());
|
|
27399
|
-
const
|
|
27400
|
-
|
|
27776
|
+
const messagesForExport = messages.filter((message) => !isMessageEmptyForExport(message));
|
|
27777
|
+
const messageMarkup = messagesForExport.length > 0
|
|
27778
|
+
? messagesForExport
|
|
27779
|
+
.map((message) => renderMessageBlock(message, participantLookup, citationFootnotes))
|
|
27780
|
+
.join('')
|
|
27401
27781
|
: '<div class="empty-state">No messages were available in this chat export.</div>';
|
|
27402
27782
|
const documentSourcesMarkup = buildDocumentSourcesMarkup(citationFootnotes, participants);
|
|
27403
27783
|
return spaceTrim$1(`
|
|
@@ -27411,6 +27791,17 @@ function buildChatHtml(title, messages, participants) {
|
|
|
27411
27791
|
<style>
|
|
27412
27792
|
:root {
|
|
27413
27793
|
color-scheme: light;
|
|
27794
|
+
--chat-export-background: #f4f6fb;
|
|
27795
|
+
--chat-export-surface: #ffffff;
|
|
27796
|
+
--chat-export-text: #0f172a;
|
|
27797
|
+
--chat-export-muted: #64748b;
|
|
27798
|
+
--chat-export-soft-border: #e2e8f0;
|
|
27799
|
+
--chat-export-bubble-theirs-bg: #ffffff;
|
|
27800
|
+
--chat-export-bubble-theirs-text: #0f172a;
|
|
27801
|
+
--chat-export-bubble-theirs-border: #e2e8f0;
|
|
27802
|
+
--chat-export-bubble-mine-bg: #115EB6;
|
|
27803
|
+
--chat-export-bubble-mine-text: #ffffff;
|
|
27804
|
+
--chat-export-link: #0f6cbd;
|
|
27414
27805
|
}
|
|
27415
27806
|
|
|
27416
27807
|
* {
|
|
@@ -27420,25 +27811,27 @@ function buildChatHtml(title, messages, participants) {
|
|
|
27420
27811
|
body,
|
|
27421
27812
|
.${CHAT_HTML_EXPORT_RENDER_ROOT_CLASS_NAME} {
|
|
27422
27813
|
margin: 0;
|
|
27423
|
-
background:
|
|
27424
|
-
color:
|
|
27425
|
-
font-family: Inter, "Segoe UI", Arial, sans-serif;
|
|
27814
|
+
background: var(--chat-export-background);
|
|
27815
|
+
color: var(--chat-export-text);
|
|
27816
|
+
font-family: Inter, "Segoe UI", system-ui, -apple-system, Arial, sans-serif;
|
|
27817
|
+
font-size: 15px;
|
|
27818
|
+
line-height: 1.55;
|
|
27426
27819
|
}
|
|
27427
27820
|
|
|
27428
27821
|
a {
|
|
27429
|
-
color:
|
|
27822
|
+
color: var(--chat-export-link);
|
|
27430
27823
|
}
|
|
27431
27824
|
|
|
27432
27825
|
.document {
|
|
27433
|
-
max-width:
|
|
27826
|
+
max-width: 820px;
|
|
27434
27827
|
margin: 0 auto;
|
|
27435
|
-
padding:
|
|
27828
|
+
padding: 40px 24px 56px;
|
|
27436
27829
|
}
|
|
27437
27830
|
|
|
27438
27831
|
.document-header {
|
|
27439
|
-
margin-bottom:
|
|
27440
|
-
padding-bottom:
|
|
27441
|
-
border-bottom: 1px solid
|
|
27832
|
+
margin-bottom: 28px;
|
|
27833
|
+
padding-bottom: 18px;
|
|
27834
|
+
border-bottom: 1px solid var(--chat-export-soft-border);
|
|
27442
27835
|
}
|
|
27443
27836
|
|
|
27444
27837
|
.document-eyebrow {
|
|
@@ -27446,7 +27839,7 @@ function buildChatHtml(title, messages, participants) {
|
|
|
27446
27839
|
font-size: 11px;
|
|
27447
27840
|
letter-spacing: 0.14em;
|
|
27448
27841
|
text-transform: uppercase;
|
|
27449
|
-
color:
|
|
27842
|
+
color: var(--chat-export-muted);
|
|
27450
27843
|
}
|
|
27451
27844
|
|
|
27452
27845
|
.document-title {
|
|
@@ -27457,89 +27850,174 @@ function buildChatHtml(title, messages, participants) {
|
|
|
27457
27850
|
|
|
27458
27851
|
.document-meta {
|
|
27459
27852
|
margin: 10px 0 0;
|
|
27460
|
-
color:
|
|
27461
|
-
font-size:
|
|
27853
|
+
color: var(--chat-export-muted);
|
|
27854
|
+
font-size: 13px;
|
|
27462
27855
|
}
|
|
27463
27856
|
|
|
27464
27857
|
.message-list {
|
|
27465
27858
|
display: flex;
|
|
27466
27859
|
flex-direction: column;
|
|
27467
|
-
gap:
|
|
27860
|
+
gap: 22px;
|
|
27468
27861
|
}
|
|
27469
27862
|
|
|
27470
|
-
.message
|
|
27471
|
-
background: #ffffff;
|
|
27472
|
-
border: 1px solid #dbe4f0;
|
|
27473
|
-
border-left-width: 4px;
|
|
27474
|
-
border-left-color: var(--message-accent, #64748b);
|
|
27475
|
-
border-radius: 14px;
|
|
27476
|
-
padding: 16px 18px;
|
|
27477
|
-
}
|
|
27478
|
-
|
|
27479
|
-
.message-header {
|
|
27863
|
+
.message {
|
|
27480
27864
|
display: flex;
|
|
27481
|
-
justify-content: space-between;
|
|
27482
27865
|
align-items: flex-start;
|
|
27483
27866
|
gap: 12px;
|
|
27484
|
-
margin-bottom: 12px;
|
|
27485
27867
|
}
|
|
27486
27868
|
|
|
27487
|
-
.message
|
|
27869
|
+
.message--mine {
|
|
27870
|
+
flex-direction: row-reverse;
|
|
27871
|
+
}
|
|
27872
|
+
|
|
27873
|
+
.message-avatar {
|
|
27874
|
+
flex-shrink: 0;
|
|
27875
|
+
width: 40px;
|
|
27876
|
+
height: 40px;
|
|
27877
|
+
border-radius: 50%;
|
|
27878
|
+
overflow: hidden;
|
|
27879
|
+
background-color: var(--message-accent, #64748b);
|
|
27880
|
+
color: #ffffff;
|
|
27488
27881
|
display: flex;
|
|
27489
|
-
flex-wrap: wrap;
|
|
27490
27882
|
align-items: center;
|
|
27883
|
+
justify-content: center;
|
|
27884
|
+
}
|
|
27885
|
+
|
|
27886
|
+
.message-avatar img {
|
|
27887
|
+
width: 100%;
|
|
27888
|
+
height: 100%;
|
|
27889
|
+
object-fit: cover;
|
|
27890
|
+
display: block;
|
|
27891
|
+
}
|
|
27892
|
+
|
|
27893
|
+
.message-avatar--initial span {
|
|
27894
|
+
font-size: 16px;
|
|
27895
|
+
font-weight: 600;
|
|
27896
|
+
line-height: 1;
|
|
27897
|
+
}
|
|
27898
|
+
|
|
27899
|
+
.message-body {
|
|
27900
|
+
flex: 1 1 auto;
|
|
27901
|
+
min-width: 0;
|
|
27902
|
+
max-width: 78%;
|
|
27903
|
+
display: flex;
|
|
27904
|
+
flex-direction: column;
|
|
27905
|
+
gap: 6px;
|
|
27906
|
+
}
|
|
27907
|
+
|
|
27908
|
+
.message--mine .message-body {
|
|
27909
|
+
align-items: flex-end;
|
|
27910
|
+
}
|
|
27911
|
+
|
|
27912
|
+
.message-meta {
|
|
27913
|
+
display: flex;
|
|
27914
|
+
flex-wrap: wrap;
|
|
27915
|
+
align-items: baseline;
|
|
27491
27916
|
gap: 8px;
|
|
27917
|
+
padding: 0 4px;
|
|
27918
|
+
}
|
|
27919
|
+
|
|
27920
|
+
.message--mine .message-meta {
|
|
27921
|
+
justify-content: flex-end;
|
|
27492
27922
|
}
|
|
27493
27923
|
|
|
27494
27924
|
.message-sender {
|
|
27495
|
-
font-size:
|
|
27925
|
+
font-size: 13px;
|
|
27496
27926
|
font-weight: 600;
|
|
27497
|
-
color: var(--message-accent,
|
|
27927
|
+
color: var(--message-accent, var(--chat-export-text));
|
|
27928
|
+
}
|
|
27929
|
+
|
|
27930
|
+
.message--mine .message-sender {
|
|
27931
|
+
color: var(--chat-export-text);
|
|
27498
27932
|
}
|
|
27499
27933
|
|
|
27500
|
-
.message-
|
|
27934
|
+
.message-time {
|
|
27501
27935
|
font-size: 11px;
|
|
27502
|
-
|
|
27503
|
-
text-transform: uppercase;
|
|
27504
|
-
color: #64748b;
|
|
27936
|
+
color: var(--chat-export-muted);
|
|
27505
27937
|
}
|
|
27506
27938
|
|
|
27507
|
-
.message-
|
|
27508
|
-
|
|
27509
|
-
|
|
27510
|
-
|
|
27939
|
+
.message-bubble {
|
|
27940
|
+
padding: 14px 16px;
|
|
27941
|
+
border-radius: 16px;
|
|
27942
|
+
background: var(--chat-export-bubble-theirs-bg);
|
|
27943
|
+
color: var(--chat-export-bubble-theirs-text);
|
|
27944
|
+
border: 1px solid var(--chat-export-bubble-theirs-border);
|
|
27945
|
+
border-top-left-radius: 4px;
|
|
27946
|
+
box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
|
|
27947
|
+
max-width: 100%;
|
|
27948
|
+
overflow-wrap: anywhere;
|
|
27949
|
+
}
|
|
27950
|
+
|
|
27951
|
+
.message--mine .message-bubble {
|
|
27952
|
+
background: var(--chat-export-bubble-mine-bg);
|
|
27953
|
+
color: var(--chat-export-bubble-mine-text);
|
|
27954
|
+
border-color: transparent;
|
|
27955
|
+
border-top-left-radius: 16px;
|
|
27956
|
+
border-top-right-radius: 4px;
|
|
27957
|
+
}
|
|
27958
|
+
|
|
27959
|
+
.message--mine .message-bubble a {
|
|
27960
|
+
color: #d4e8ff;
|
|
27961
|
+
}
|
|
27962
|
+
|
|
27963
|
+
.message--mine .message-bubble code {
|
|
27964
|
+
background: rgba(255, 255, 255, 0.18);
|
|
27965
|
+
color: inherit;
|
|
27511
27966
|
}
|
|
27512
27967
|
|
|
27513
|
-
.message-
|
|
27514
|
-
|
|
27968
|
+
.message--mine .message-bubble pre {
|
|
27969
|
+
background: rgba(15, 23, 42, 0.35);
|
|
27970
|
+
color: #f8fafc;
|
|
27971
|
+
}
|
|
27972
|
+
|
|
27973
|
+
.message--mine .message-bubble blockquote {
|
|
27974
|
+
color: rgba(255, 255, 255, 0.85);
|
|
27975
|
+
border-color: rgba(255, 255, 255, 0.5);
|
|
27976
|
+
}
|
|
27977
|
+
|
|
27978
|
+
.message-footnote {
|
|
27979
|
+
margin: 2px 4px 0;
|
|
27980
|
+
font-size: 11px;
|
|
27981
|
+
color: var(--chat-export-muted);
|
|
27515
27982
|
}
|
|
27516
27983
|
|
|
27517
27984
|
.message-empty {
|
|
27518
|
-
color:
|
|
27985
|
+
color: var(--chat-export-muted);
|
|
27519
27986
|
font-style: italic;
|
|
27987
|
+
margin: 0;
|
|
27520
27988
|
}
|
|
27521
27989
|
|
|
27522
27990
|
.reply-context {
|
|
27523
|
-
margin
|
|
27524
|
-
padding: 12px
|
|
27991
|
+
margin: 0 0 10px;
|
|
27992
|
+
padding: 8px 12px;
|
|
27525
27993
|
border-radius: 10px;
|
|
27526
|
-
border:
|
|
27527
|
-
background:
|
|
27994
|
+
border-left: 3px solid var(--message-accent, #cbd5e1);
|
|
27995
|
+
background: rgba(15, 23, 42, 0.04);
|
|
27996
|
+
}
|
|
27997
|
+
|
|
27998
|
+
.message--mine .reply-context {
|
|
27999
|
+
background: rgba(255, 255, 255, 0.18);
|
|
28000
|
+
border-left-color: rgba(255, 255, 255, 0.7);
|
|
27528
28001
|
}
|
|
27529
28002
|
|
|
27530
28003
|
.reply-context-title,
|
|
27531
28004
|
.message-supporting-title {
|
|
27532
|
-
margin-bottom:
|
|
28005
|
+
margin-bottom: 6px;
|
|
27533
28006
|
font-size: 11px;
|
|
27534
|
-
letter-spacing: 0.
|
|
28007
|
+
letter-spacing: 0.1em;
|
|
27535
28008
|
text-transform: uppercase;
|
|
27536
|
-
color:
|
|
28009
|
+
color: var(--chat-export-muted);
|
|
28010
|
+
}
|
|
28011
|
+
|
|
28012
|
+
.message--mine .reply-context-title {
|
|
28013
|
+
color: rgba(255, 255, 255, 0.8);
|
|
27537
28014
|
}
|
|
27538
28015
|
|
|
27539
28016
|
.message-supporting-list {
|
|
27540
|
-
margin-top:
|
|
27541
|
-
padding
|
|
27542
|
-
border-
|
|
28017
|
+
margin-top: 10px;
|
|
28018
|
+
padding: 10px 14px;
|
|
28019
|
+
border-radius: 10px;
|
|
28020
|
+
background: rgba(15, 23, 42, 0.03);
|
|
27543
28021
|
}
|
|
27544
28022
|
|
|
27545
28023
|
.message-supporting-list ul {
|
|
@@ -27549,18 +28027,14 @@ function buildChatHtml(title, messages, participants) {
|
|
|
27549
28027
|
|
|
27550
28028
|
.message-supporting-meta {
|
|
27551
28029
|
margin-right: 6px;
|
|
27552
|
-
color:
|
|
28030
|
+
color: var(--chat-export-muted);
|
|
27553
28031
|
font-size: 12px;
|
|
27554
28032
|
}
|
|
27555
28033
|
|
|
27556
28034
|
.message-supporting-excerpt {
|
|
27557
|
-
margin-top:
|
|
28035
|
+
margin-top: 4px;
|
|
27558
28036
|
color: #475569;
|
|
27559
|
-
|
|
27560
|
-
|
|
27561
|
-
.markdown-content {
|
|
27562
|
-
font-size: 15px;
|
|
27563
|
-
line-height: 1.65;
|
|
28037
|
+
font-size: 13px;
|
|
27564
28038
|
}
|
|
27565
28039
|
|
|
27566
28040
|
.markdown-content > *:first-child {
|
|
@@ -27588,7 +28062,7 @@ function buildChatHtml(title, messages, participants) {
|
|
|
27588
28062
|
.markdown-content pre,
|
|
27589
28063
|
.markdown-content table,
|
|
27590
28064
|
.markdown-content details {
|
|
27591
|
-
margin: 0 0
|
|
28065
|
+
margin: 0 0 12px;
|
|
27592
28066
|
}
|
|
27593
28067
|
|
|
27594
28068
|
.markdown-content ul,
|
|
@@ -27598,7 +28072,7 @@ function buildChatHtml(title, messages, participants) {
|
|
|
27598
28072
|
|
|
27599
28073
|
.markdown-content code {
|
|
27600
28074
|
font-family: ui-monospace, "SFMono-Regular", monospace;
|
|
27601
|
-
background:
|
|
28075
|
+
background: rgba(15, 23, 42, 0.06);
|
|
27602
28076
|
border-radius: 4px;
|
|
27603
28077
|
padding: 1px 5px;
|
|
27604
28078
|
font-size: 0.94em;
|
|
@@ -27650,7 +28124,7 @@ function buildChatHtml(title, messages, participants) {
|
|
|
27650
28124
|
|
|
27651
28125
|
.markdown-content details {
|
|
27652
28126
|
padding: 12px 14px;
|
|
27653
|
-
border: 1px solid
|
|
28127
|
+
border: 1px solid var(--chat-export-soft-border);
|
|
27654
28128
|
border-radius: 10px;
|
|
27655
28129
|
background: #f8fafc;
|
|
27656
28130
|
}
|
|
@@ -27672,7 +28146,7 @@ function buildChatHtml(title, messages, participants) {
|
|
|
27672
28146
|
}
|
|
27673
28147
|
|
|
27674
28148
|
.markdown-content sup[data-citation-footnote] a {
|
|
27675
|
-
color:
|
|
28149
|
+
color: inherit;
|
|
27676
28150
|
text-decoration: none;
|
|
27677
28151
|
}
|
|
27678
28152
|
|
|
@@ -27685,14 +28159,14 @@ function buildChatHtml(title, messages, participants) {
|
|
|
27685
28159
|
border: 1px dashed #cbd5e1;
|
|
27686
28160
|
border-radius: 14px;
|
|
27687
28161
|
text-align: center;
|
|
27688
|
-
color:
|
|
27689
|
-
background:
|
|
28162
|
+
color: var(--chat-export-muted);
|
|
28163
|
+
background: var(--chat-export-surface);
|
|
27690
28164
|
}
|
|
27691
28165
|
|
|
27692
28166
|
.document-sources {
|
|
27693
|
-
margin-top:
|
|
27694
|
-
padding-top:
|
|
27695
|
-
border-top: 1px solid
|
|
28167
|
+
margin-top: 32px;
|
|
28168
|
+
padding-top: 18px;
|
|
28169
|
+
border-top: 1px solid var(--chat-export-soft-border);
|
|
27696
28170
|
}
|
|
27697
28171
|
|
|
27698
28172
|
.document-sources-title {
|
|
@@ -27718,26 +28192,50 @@ function buildChatHtml(title, messages, participants) {
|
|
|
27718
28192
|
}
|
|
27719
28193
|
|
|
27720
28194
|
.document-footer {
|
|
27721
|
-
margin-top:
|
|
28195
|
+
margin-top: 28px;
|
|
27722
28196
|
padding-top: 16px;
|
|
27723
|
-
border-top: 1px solid
|
|
27724
|
-
color:
|
|
28197
|
+
border-top: 1px solid var(--chat-export-soft-border);
|
|
28198
|
+
color: var(--chat-export-muted);
|
|
27725
28199
|
font-size: 12px;
|
|
28200
|
+
text-align: center;
|
|
27726
28201
|
}
|
|
27727
28202
|
|
|
27728
28203
|
.document-footer strong {
|
|
27729
28204
|
color: #475569;
|
|
27730
28205
|
}
|
|
27731
28206
|
|
|
28207
|
+
@page {
|
|
28208
|
+
size: Letter;
|
|
28209
|
+
margin: 0.5in;
|
|
28210
|
+
}
|
|
28211
|
+
|
|
27732
28212
|
@media print {
|
|
27733
|
-
body
|
|
28213
|
+
body,
|
|
28214
|
+
.${CHAT_HTML_EXPORT_RENDER_ROOT_CLASS_NAME} {
|
|
27734
28215
|
background: #ffffff;
|
|
28216
|
+
font-size: 12pt;
|
|
27735
28217
|
}
|
|
27736
28218
|
|
|
27737
28219
|
.document {
|
|
27738
28220
|
max-width: none;
|
|
27739
28221
|
padding: 0;
|
|
27740
28222
|
}
|
|
28223
|
+
|
|
28224
|
+
.message {
|
|
28225
|
+
page-break-inside: avoid;
|
|
28226
|
+
break-inside: avoid;
|
|
28227
|
+
}
|
|
28228
|
+
|
|
28229
|
+
.message-bubble {
|
|
28230
|
+
box-shadow: none;
|
|
28231
|
+
}
|
|
28232
|
+
|
|
28233
|
+
.markdown-content pre,
|
|
28234
|
+
.message-supporting-list,
|
|
28235
|
+
.reply-context {
|
|
28236
|
+
page-break-inside: avoid;
|
|
28237
|
+
break-inside: avoid;
|
|
28238
|
+
}
|
|
27741
28239
|
}
|
|
27742
28240
|
</style>
|
|
27743
28241
|
</head>
|
|
@@ -28203,7 +28701,11 @@ const PROMPTBOOK_REACT_EXPORT_BRANDING_COMMENT = createPromptbookReactExportBran
|
|
|
28203
28701
|
*/
|
|
28204
28702
|
function createPromptbookReactExportBrandingComment() {
|
|
28205
28703
|
const branding = getPromptbookExportBranding();
|
|
28206
|
-
return
|
|
28704
|
+
return spaceTrim$1((block) => `
|
|
28705
|
+
/*
|
|
28706
|
+
${block(branding.commentLines.map((line) => ` * ${line}`).join('\n'))}
|
|
28707
|
+
*/
|
|
28708
|
+
`);
|
|
28207
28709
|
}
|
|
28208
28710
|
/**
|
|
28209
28711
|
* React <jsx/> export plugin (full metadata)
|
|
@@ -28746,6 +29248,54 @@ const MarkdownContent = memo(function MarkdownContent(props) {
|
|
|
28746
29248
|
} }));
|
|
28747
29249
|
});
|
|
28748
29250
|
|
|
29251
|
+
/**
|
|
29252
|
+
* Creates a stable key for one citation label lookup.
|
|
29253
|
+
*
|
|
29254
|
+
* @param citation - Citation metadata.
|
|
29255
|
+
* @returns Stable citation key.
|
|
29256
|
+
*
|
|
29257
|
+
* @private hook helper of `<Chat/>`
|
|
29258
|
+
*/
|
|
29259
|
+
function createCitationLabelLookupKey(citation) {
|
|
29260
|
+
return [citation.id, citation.source, citation.url || '', citation.title || '', citation.excerpt || ''].join('\n');
|
|
29261
|
+
}
|
|
29262
|
+
/**
|
|
29263
|
+
* Resolves the best available label for one citation.
|
|
29264
|
+
*
|
|
29265
|
+
* @param citation - Citation metadata.
|
|
29266
|
+
* @param resolveCitationLabel - Optional async host resolver.
|
|
29267
|
+
* @returns Current label, starting with a synchronous fallback and updating when the resolver finishes.
|
|
29268
|
+
*
|
|
29269
|
+
* @private hook of `<Chat/>`
|
|
29270
|
+
*/
|
|
29271
|
+
function useResolvedCitationLabel(citation, resolveCitationLabel) {
|
|
29272
|
+
const fallbackLabel = useMemo(() => getCitationLabel(citation), [citation]);
|
|
29273
|
+
const citationKey = useMemo(() => createCitationLabelLookupKey(citation), [citation]);
|
|
29274
|
+
const [resolvedLabel, setResolvedLabel] = useState(null);
|
|
29275
|
+
useEffect(() => {
|
|
29276
|
+
setResolvedLabel(null);
|
|
29277
|
+
if (!resolveCitationLabel) {
|
|
29278
|
+
return;
|
|
29279
|
+
}
|
|
29280
|
+
let isCurrent = true;
|
|
29281
|
+
Promise.resolve(resolveCitationLabel(citation))
|
|
29282
|
+
.then((label) => {
|
|
29283
|
+
if (!isCurrent) {
|
|
29284
|
+
return;
|
|
29285
|
+
}
|
|
29286
|
+
const normalizedLabel = label === null || label === void 0 ? void 0 : label.trim();
|
|
29287
|
+
if (normalizedLabel) {
|
|
29288
|
+
setResolvedLabel(normalizedLabel);
|
|
29289
|
+
}
|
|
29290
|
+
})
|
|
29291
|
+
.catch(() => undefined);
|
|
29292
|
+
return () => {
|
|
29293
|
+
isCurrent = false;
|
|
29294
|
+
};
|
|
29295
|
+
}, [citation, citationKey, resolveCitationLabel]);
|
|
29296
|
+
return resolvedLabel || fallbackLabel;
|
|
29297
|
+
}
|
|
29298
|
+
|
|
28749
29299
|
/**
|
|
28750
29300
|
* Renders a citation URL preview as an iframe when the target page allows embedding,
|
|
28751
29301
|
* or falls back to a server-side screenshot with an "Open in new tab" link when it
|
|
@@ -28786,6 +29336,15 @@ function CitationIframePreview({ src, title }) {
|
|
|
28786
29336
|
return jsx("iframe", { src: src, className: styles$7.citationIframe, title: title });
|
|
28787
29337
|
}
|
|
28788
29338
|
|
|
29339
|
+
/**
|
|
29340
|
+
* Empty citation used to keep modal hooks unconditional while the modal is closed.
|
|
29341
|
+
*
|
|
29342
|
+
* @private component constant of `<ChatCitationModal/>`
|
|
29343
|
+
*/
|
|
29344
|
+
const EMPTY_MODAL_CITATION = {
|
|
29345
|
+
id: '',
|
|
29346
|
+
source: '',
|
|
29347
|
+
};
|
|
28789
29348
|
/**
|
|
28790
29349
|
* Modal that previews a citation source or excerpt.
|
|
28791
29350
|
*
|
|
@@ -28793,7 +29352,9 @@ function CitationIframePreview({ src, title }) {
|
|
|
28793
29352
|
*/
|
|
28794
29353
|
function ChatCitationModal(props) {
|
|
28795
29354
|
var _a, _b;
|
|
28796
|
-
const { isOpen, citation, participants, soundSystem, onClose } = props;
|
|
29355
|
+
const { isOpen, citation, participants, resolveCitationLabel, soundSystem, onClose } = props;
|
|
29356
|
+
const resolvedCitation = citation || EMPTY_MODAL_CITATION;
|
|
29357
|
+
const label = useResolvedCitationLabel(resolvedCitation, resolveCitationLabel);
|
|
28797
29358
|
if (!isOpen || !citation) {
|
|
28798
29359
|
return null;
|
|
28799
29360
|
}
|
|
@@ -28804,7 +29365,6 @@ function ChatCitationModal(props) {
|
|
|
28804
29365
|
const previewSegment = previewBase.split('/').pop() || previewBase;
|
|
28805
29366
|
const extension = (_a = previewSegment.split('.').pop()) === null || _a === void 0 ? void 0 : _a.toLowerCase();
|
|
28806
29367
|
const isImage = ['jpg', 'jpeg', 'png', 'gif', 'svg', 'webp'].includes(extension || '');
|
|
28807
|
-
const label = getCitationLabel(citation);
|
|
28808
29368
|
const isTextCitation = isPlainTextCitation(citation);
|
|
28809
29369
|
const hasTextPreview = !isValidUrl && (citation.excerpt || isTextCitation);
|
|
28810
29370
|
const textPreviewContent = isTextCitation ? citation.source : (_b = citation.excerpt) !== null && _b !== void 0 ? _b : '';
|
|
@@ -30903,21 +31463,34 @@ function ChatInputArea(props) {
|
|
|
30903
31463
|
|
|
30904
31464
|
// Note: [💞] Ignore a discrepancy between file name and entity name
|
|
30905
31465
|
/**
|
|
30906
|
-
* Target frames per second for
|
|
31466
|
+
* Target frames per second for a single animated avatar.
|
|
30907
31467
|
*
|
|
30908
|
-
* Animated octopus visuals change slowly enough that 24 fps is indistinguishable
|
|
30909
|
-
* from 60 fps in practice
|
|
30910
|
-
* avatars are
|
|
31468
|
+
* Animated octopus visuals change slowly enough that ~24 fps per avatar is indistinguishable
|
|
31469
|
+
* from 60 fps in practice. Combined with `MAX_AVATAR_LISTENERS_PER_FRAME` this bounds total
|
|
31470
|
+
* rendering work even when many avatars are visible.
|
|
30911
31471
|
*
|
|
30912
31472
|
* @private utility of the avatar rendering system
|
|
30913
31473
|
*/
|
|
30914
31474
|
const AVATAR_TARGET_FPS = 24;
|
|
30915
31475
|
/**
|
|
30916
|
-
* Minimum elapsed time in milliseconds required between
|
|
31476
|
+
* Minimum elapsed time in milliseconds required between two consecutive renders of the same avatar.
|
|
30917
31477
|
*
|
|
30918
31478
|
* @private utility of the avatar rendering system
|
|
30919
31479
|
*/
|
|
30920
31480
|
const AVATAR_TARGET_FRAME_INTERVAL_MS = 1000 / AVATAR_TARGET_FPS;
|
|
31481
|
+
/**
|
|
31482
|
+
* Hard cap on how many avatar listeners can run inside the same animation frame.
|
|
31483
|
+
*
|
|
31484
|
+
* The default visual takes several milliseconds to render, so firing every visible avatar
|
|
31485
|
+
* on the same animation frame stalls the main thread for tens of milliseconds and drops the
|
|
31486
|
+
* overall page FPS to single digits. Bounding the number of listeners that fire per frame
|
|
31487
|
+
* spreads the work across animation frames and keeps the UI responsive even with many
|
|
31488
|
+
* visible avatars — each individual avatar still reaches `AVATAR_TARGET_FPS` because work
|
|
31489
|
+
* is interleaved instead of skipped.
|
|
31490
|
+
*
|
|
31491
|
+
* @private utility of the avatar rendering system
|
|
31492
|
+
*/
|
|
31493
|
+
const MAX_AVATAR_LISTENERS_PER_FRAME = 2;
|
|
30921
31494
|
/**
|
|
30922
31495
|
* Next registration id used by the shared avatar animation scheduler.
|
|
30923
31496
|
*
|
|
@@ -30936,17 +31509,13 @@ const avatarAnimationListeners = new Map();
|
|
|
30936
31509
|
* @private utility of the avatar rendering system
|
|
30937
31510
|
*/
|
|
30938
31511
|
let avatarAnimationFrameId = null;
|
|
30939
|
-
/**
|
|
30940
|
-
* Timestamp of the most recently rendered avatar frame.
|
|
30941
|
-
*
|
|
30942
|
-
* Used to throttle callbacks to `AVATAR_TARGET_FRAME_INTERVAL_MS`.
|
|
30943
|
-
*
|
|
30944
|
-
* @private utility of the avatar rendering system
|
|
30945
|
-
*/
|
|
30946
|
-
let lastAvatarFrameTime = 0;
|
|
30947
31512
|
/**
|
|
30948
31513
|
* Registers one avatar animation callback in the shared animation loop.
|
|
30949
31514
|
*
|
|
31515
|
+
* Each listener is staggered at registration time so it does not fire on the same animation
|
|
31516
|
+
* frame as the existing listeners, and the shared loop further caps how many listeners run
|
|
31517
|
+
* per frame, keeping the main thread responsive when many avatars are mounted.
|
|
31518
|
+
*
|
|
30950
31519
|
* @param avatarAnimationListener Frame callback invoked on every animation frame.
|
|
30951
31520
|
* @returns Cleanup function that unregisters the callback.
|
|
30952
31521
|
*
|
|
@@ -30957,7 +31526,14 @@ function retainAvatarAnimationListener(avatarAnimationListener) {
|
|
|
30957
31526
|
return () => undefined;
|
|
30958
31527
|
}
|
|
30959
31528
|
const listenerId = nextAvatarAnimationListenerId++;
|
|
30960
|
-
avatarAnimationListeners.
|
|
31529
|
+
const existingListenerCount = avatarAnimationListeners.size;
|
|
31530
|
+
const staggerOffsetMs = ((existingListenerCount % Math.max(1, MAX_AVATAR_LISTENERS_PER_FRAME)) * AVATAR_TARGET_FRAME_INTERVAL_MS) /
|
|
31531
|
+
Math.max(1, MAX_AVATAR_LISTENERS_PER_FRAME);
|
|
31532
|
+
avatarAnimationListeners.set(listenerId, {
|
|
31533
|
+
listener: avatarAnimationListener,
|
|
31534
|
+
// Phase the listener so multiple new listeners do not synchronize on the same frame.
|
|
31535
|
+
lastRunAtMs: performance.now() - AVATAR_TARGET_FRAME_INTERVAL_MS + staggerOffsetMs,
|
|
31536
|
+
});
|
|
30961
31537
|
ensureAvatarAnimationLoop();
|
|
30962
31538
|
return () => {
|
|
30963
31539
|
avatarAnimationListeners.delete(listenerId);
|
|
@@ -30978,12 +31554,21 @@ function ensureAvatarAnimationLoop() {
|
|
|
30978
31554
|
}
|
|
30979
31555
|
const runFrame = (now) => {
|
|
30980
31556
|
avatarAnimationFrameId = null;
|
|
30981
|
-
|
|
30982
|
-
|
|
30983
|
-
|
|
30984
|
-
|
|
31557
|
+
const dueListenerEntries = [];
|
|
31558
|
+
for (const listenerEntry of avatarAnimationListeners.values()) {
|
|
31559
|
+
if (now - listenerEntry.lastRunAtMs >= AVATAR_TARGET_FRAME_INTERVAL_MS) {
|
|
31560
|
+
dueListenerEntries.push(listenerEntry);
|
|
30985
31561
|
}
|
|
30986
31562
|
}
|
|
31563
|
+
// Run the most stale listeners first so each avatar keeps its target FPS even when
|
|
31564
|
+
// total work exceeds the per-frame budget.
|
|
31565
|
+
dueListenerEntries.sort((firstListenerEntry, secondListenerEntry) => firstListenerEntry.lastRunAtMs - secondListenerEntry.lastRunAtMs);
|
|
31566
|
+
const listenersToRunCount = Math.min(dueListenerEntries.length, MAX_AVATAR_LISTENERS_PER_FRAME);
|
|
31567
|
+
for (let listenerIndex = 0; listenerIndex < listenersToRunCount; listenerIndex++) {
|
|
31568
|
+
const listenerEntry = dueListenerEntries[listenerIndex];
|
|
31569
|
+
listenerEntry.lastRunAtMs = now;
|
|
31570
|
+
listenerEntry.listener(now);
|
|
31571
|
+
}
|
|
30987
31572
|
ensureAvatarAnimationLoop();
|
|
30988
31573
|
};
|
|
30989
31574
|
avatarAnimationFrameId = window.requestAnimationFrame(runFrame);
|
|
@@ -31687,8 +32272,8 @@ const AvatarProfileTooltip = forwardRef(function AvatarProfileTooltip({ agentSou
|
|
|
31687
32272
|
}, children: [jsx("div", { className: styles$4.arrow }), jsx(AvatarProfileFromSource, { agentSource: agentSource })] }), document.body);
|
|
31688
32273
|
});
|
|
31689
32274
|
|
|
31690
|
-
var css_248z$3 = ".SourceChip-module_sourceChip__Cqbn0{align-items:center;backdrop-filter:blur(8px);background:hsla(0,0%,100%,.24);background:color-mix(in srgb,var(--message-bg-color,#fff) 74%,hsla(0,0%,100%,.8) 26%);border:1px solid hsla(0,0%,49%,.3);border-color:color-mix(in srgb,var(--message-text-color,#0f172a) 16%,transparent);border-radius:999px;box-shadow:0 2px 8px rgba(15,23,42,.12);color:inherit;cursor:pointer;display:inline-flex;font-size:.8rem;font-weight:600;gap:6px;padding:5px 11px;transition:all .2s ease}.SourceChip-module_sourceChip__Cqbn0:hover{background:hsla(0,0%,100%,.34);background:color-mix(in srgb,var(--message-bg-color,#fff) 64%,hsla(0,0%,100%,.9) 36%);box-shadow:0 4px 12px rgba(15,23,42,.14);transform:translateY(-1px)}.SourceChip-module_icon__olwcc{flex-shrink:0;font-family:OpenMojiColor,OpenMojiBlack;font-size:1.1em}.SourceChip-module_label__yCkr-{align-items:center;display:flex;font-weight:600;gap:5px;white-space:nowrap}.SourceChip-module_citationId__W7xTo{font-size:.85em;font-weight:500;opacity:.78}.SourceChip-module_suffix__FSlC-{font-size:.85em;font-weight:500;opacity:.82;white-space:nowrap}\n/*# sourceMappingURL=data:application/json;base64,
|
|
31691
|
-
var styles$3 = {"sourceChip":"SourceChip-module_sourceChip__Cqbn0","icon":"SourceChip-module_icon__olwcc","label":"SourceChip-module_label__yCkr-","citationId":"SourceChip-module_citationId__W7xTo","suffix":"SourceChip-module_suffix__FSlC-"};
|
|
32275
|
+
var css_248z$3 = ".SourceChip-module_sourceChip__Cqbn0{align-items:center;backdrop-filter:blur(8px);background:hsla(0,0%,100%,.24);background:color-mix(in srgb,var(--message-bg-color,#fff) 74%,hsla(0,0%,100%,.8) 26%);border:1px solid hsla(0,0%,49%,.3);border-color:color-mix(in srgb,var(--message-text-color,#0f172a) 16%,transparent);border-radius:999px;box-shadow:0 2px 8px rgba(15,23,42,.12);color:inherit;cursor:pointer;display:inline-flex;font-size:.8rem;font-weight:600;gap:6px;max-width:min(100%,32rem);padding:5px 11px;transition:all .2s ease}.SourceChip-module_sourceChip__Cqbn0:hover{background:hsla(0,0%,100%,.34);background:color-mix(in srgb,var(--message-bg-color,#fff) 64%,hsla(0,0%,100%,.9) 36%);box-shadow:0 4px 12px rgba(15,23,42,.14);transform:translateY(-1px)}.SourceChip-module_icon__olwcc{flex-shrink:0;font-family:OpenMojiColor,OpenMojiBlack;font-size:1.1em}.SourceChip-module_label__yCkr-{align-items:center;display:flex;font-weight:600;gap:5px;min-width:0;white-space:nowrap}.SourceChip-module_labelText__aFt2z{min-width:0;overflow:hidden;text-overflow:ellipsis}.SourceChip-module_citationId__W7xTo{font-size:.85em;font-weight:500;opacity:.78}.SourceChip-module_suffix__FSlC-{font-size:.85em;font-weight:500;opacity:.82;white-space:nowrap}\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIlNvdXJjZUNoaXAubW9kdWxlLmNzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxxQ0FFSSxrQkFBbUIsQ0FlbkIseUJBQTBCLENBVDFCLDhCQUFxQyxDQUNyQyxxRkFBa0csQ0FDbEcsa0NBQTBDLENBQzFDLGlGQUFxRixDQUNyRixtQkFBb0IsQ0FDcEIsdUNBQTRDLENBQzVDLGFBQWMsQ0FFZCxjQUFlLENBZmYsbUJBQW9CLENBSXBCLGVBQWlCLENBQ2pCLGVBQWdCLENBSGhCLE9BQVEsQ0FDUix5QkFBMkIsQ0FHM0IsZ0JBQWlCLENBUWpCLHVCQUdKLENBRUEsMkNBQ0ksOEJBQXFDLENBQ3JDLHFGQUFrRyxDQUVsRyx3Q0FBNkMsQ0FEN0MsMEJBRUosQ0FFQSwrQkFFSSxhQUFjLENBQ2QsdUNBQTZDLENBRjdDLGVBR0osQ0FFQSxnQ0FJSSxrQkFBbUIsQ0FEbkIsWUFBYSxDQUZiLGVBQWdCLENBSWhCLE9BQVEsQ0FDUixXQUFZLENBSlosa0JBS0osQ0FFQSxvQ0FDSSxXQUFZLENBQ1osZUFBZ0IsQ0FDaEIsc0JBQ0osQ0FFQSxxQ0FDSSxlQUFpQixDQUVqQixlQUFnQixDQURoQixXQUVKLENBRUEsaUNBQ0ksZUFBaUIsQ0FFakIsZUFBZ0IsQ0FEaEIsV0FBYSxDQUViLGtCQUNKIiwiZmlsZSI6IlNvdXJjZUNoaXAubW9kdWxlLmNzcyIsInNvdXJjZXNDb250ZW50IjpbIi5zb3VyY2VDaGlwIHtcbiAgICBkaXNwbGF5OiBpbmxpbmUtZmxleDtcbiAgICBhbGlnbi1pdGVtczogY2VudGVyO1xuICAgIGdhcDogNnB4O1xuICAgIG1heC13aWR0aDogbWluKDEwMCUsIDMycmVtKTtcbiAgICBmb250LXNpemU6IDAuOHJlbTtcbiAgICBmb250LXdlaWdodDogNjAwO1xuICAgIHBhZGRpbmc6IDVweCAxMXB4O1xuICAgIGJhY2tncm91bmQ6IHJnYmEoMjU1LCAyNTUsIDI1NSwgMC4yNCk7XG4gICAgYmFja2dyb3VuZDogY29sb3ItbWl4KGluIHNyZ2IsIHZhcigtLW1lc3NhZ2UtYmctY29sb3IsICNmZmZmZmYpIDc0JSwgcmdiYSgyNTUsIDI1NSwgMjU1LCAwLjgpIDI2JSk7XG4gICAgYm9yZGVyOiAxcHggc29saWQgcmdiYSgxMjUsIDEyNSwgMTI1LCAwLjMpO1xuICAgIGJvcmRlci1jb2xvcjogY29sb3ItbWl4KGluIHNyZ2IsIHZhcigtLW1lc3NhZ2UtdGV4dC1jb2xvciwgIzBmMTcyYSkgMTYlLCB0cmFuc3BhcmVudCk7XG4gICAgYm9yZGVyLXJhZGl1czogOTk5cHg7XG4gICAgYm94LXNoYWRvdzogMCAycHggOHB4IHJnYmEoMTUsIDIzLCA0MiwgMC4xMik7XG4gICAgY29sb3I6IGluaGVyaXQ7XG4gICAgdHJhbnNpdGlvbjogYWxsIDAuMnMgZWFzZTtcbiAgICBjdXJzb3I6IHBvaW50ZXI7XG4gICAgYmFja2Ryb3AtZmlsdGVyOiBibHVyKDhweCk7XG59XG5cbi5zb3VyY2VDaGlwOmhvdmVyIHtcbiAgICBiYWNrZ3JvdW5kOiByZ2JhKDI1NSwgMjU1LCAyNTUsIDAuMzQpO1xuICAgIGJhY2tncm91bmQ6IGNvbG9yLW1peChpbiBzcmdiLCB2YXIoLS1tZXNzYWdlLWJnLWNvbG9yLCAjZmZmZmZmKSA2NCUsIHJnYmEoMjU1LCAyNTUsIDI1NSwgMC45KSAzNiUpO1xuICAgIHRyYW5zZm9ybTogdHJhbnNsYXRlWSgtMXB4KTtcbiAgICBib3gtc2hhZG93OiAwIDRweCAxMnB4IHJnYmEoMTUsIDIzLCA0MiwgMC4xNCk7XG59XG5cbi5pY29uIHtcbiAgICBmb250LXNpemU6IDEuMWVtO1xuICAgIGZsZXgtc2hyaW5rOiAwO1xuICAgIGZvbnQtZmFtaWx5OiAnT3Blbk1vamlDb2xvcicsICdPcGVuTW9qaUJsYWNrJztcbn1cblxuLmxhYmVsIHtcbiAgICBmb250LXdlaWdodDogNjAwO1xuICAgIHdoaXRlLXNwYWNlOiBub3dyYXA7XG4gICAgZGlzcGxheTogZmxleDtcbiAgICBhbGlnbi1pdGVtczogY2VudGVyO1xuICAgIGdhcDogNXB4O1xuICAgIG1pbi13aWR0aDogMDtcbn1cblxuLmxhYmVsVGV4dCB7XG4gICAgbWluLXdpZHRoOiAwO1xuICAgIG92ZXJmbG93OiBoaWRkZW47XG4gICAgdGV4dC1vdmVyZmxvdzogZWxsaXBzaXM7XG59XG5cbi5jaXRhdGlvbklkIHtcbiAgICBmb250LXNpemU6IDAuODVlbTtcbiAgICBvcGFjaXR5OiAwLjc4O1xuICAgIGZvbnQtd2VpZ2h0OiA1MDA7XG59XG5cbi5zdWZmaXgge1xuICAgIGZvbnQtc2l6ZTogMC44NWVtO1xuICAgIG9wYWNpdHk6IDAuODI7XG4gICAgZm9udC13ZWlnaHQ6IDUwMDtcbiAgICB3aGl0ZS1zcGFjZTogbm93cmFwO1xufVxuIl19 */";
|
|
32276
|
+
var styles$3 = {"sourceChip":"SourceChip-module_sourceChip__Cqbn0","icon":"SourceChip-module_icon__olwcc","label":"SourceChip-module_label__yCkr-","labelText":"SourceChip-module_labelText__aFt2z","citationId":"SourceChip-module_citationId__W7xTo","suffix":"SourceChip-module_suffix__FSlC-"};
|
|
31692
32277
|
styleInject(css_248z$3);
|
|
31693
32278
|
|
|
31694
32279
|
/**
|
|
@@ -31708,7 +32293,7 @@ styleInject(css_248z$3);
|
|
|
31708
32293
|
*
|
|
31709
32294
|
* @private utility of `ChatMessageItem` component
|
|
31710
32295
|
*/
|
|
31711
|
-
function SourceChip({ citation, onClick, className, suffix, isCitationIdVisible = true }) {
|
|
32296
|
+
function SourceChip({ citation, onClick, className, suffix, resolveCitationLabel, isCitationIdVisible = true, }) {
|
|
31712
32297
|
var _a;
|
|
31713
32298
|
const handleClick = (event) => {
|
|
31714
32299
|
event.stopPropagation();
|
|
@@ -31718,7 +32303,8 @@ function SourceChip({ citation, onClick, className, suffix, isCitationIdVisible
|
|
|
31718
32303
|
};
|
|
31719
32304
|
// Keep source chips concise and human-readable for CDN-backed knowledge files.
|
|
31720
32305
|
const normalizedSource = citation.source.trim();
|
|
31721
|
-
const displayName =
|
|
32306
|
+
const displayName = useResolvedCitationLabel(citation, resolveCitationLabel);
|
|
32307
|
+
const title = displayName === citation.source ? citation.source : `${displayName}\n${citation.source}`;
|
|
31722
32308
|
// Get file extension for icon
|
|
31723
32309
|
const fileExtension = ((_a = (normalizedSource || citation.source).split('.').pop()) === null || _a === void 0 ? void 0 : _a.toLowerCase()) || 'file';
|
|
31724
32310
|
const icon = isPlainTextCitation(citation)
|
|
@@ -31726,7 +32312,7 @@ function SourceChip({ citation, onClick, className, suffix, isCitationIdVisible
|
|
|
31726
32312
|
: isCitationUrl(normalizedSource)
|
|
31727
32313
|
? '🌐'
|
|
31728
32314
|
: getFileIcon(fileExtension);
|
|
31729
|
-
return (jsxs("button", { className: `${styles$3.sourceChip} ${className || ''}`, onClick: handleClick, title:
|
|
32315
|
+
return (jsxs("button", { className: `${styles$3.sourceChip} ${className || ''}`, onClick: handleClick, title: title, children: [jsx("span", { className: styles$3.icon, children: icon }), jsxs("span", { className: styles$3.label, children: [jsx("span", { className: styles$3.labelText, children: displayName }), isCitationIdVisible && jsxs("span", { className: styles$3.citationId, children: [" [", citation.id, "]"] })] }), suffix && jsx("span", { className: styles$3.suffix, children: suffix })] }));
|
|
31730
32316
|
}
|
|
31731
32317
|
/**
|
|
31732
32318
|
* Gets an appropriate emoji icon for a file type
|
|
@@ -31811,63 +32397,6 @@ function formatGenerationDurationLabel(durationMs) {
|
|
|
31811
32397
|
return `${minutes}m ${seconds}s`;
|
|
31812
32398
|
}
|
|
31813
32399
|
|
|
31814
|
-
/**
|
|
31815
|
-
* Extracts one quick button definition from a markdown link query string.
|
|
31816
|
-
*
|
|
31817
|
-
* @param text The visible button label.
|
|
31818
|
-
* @param query Raw query-string payload captured from markdown.
|
|
31819
|
-
* @returns Parsed quick button definition or `null` when the link is not a supported quick button.
|
|
31820
|
-
*
|
|
31821
|
-
* @private internal helper of `parseMessageButtons`
|
|
31822
|
-
*/
|
|
31823
|
-
function parseQuickButtonDefinition(text, query) {
|
|
31824
|
-
const searchParams = new URLSearchParams(query);
|
|
31825
|
-
const message = searchParams.get('message');
|
|
31826
|
-
if (message !== null) {
|
|
31827
|
-
return {
|
|
31828
|
-
type: 'message',
|
|
31829
|
-
text,
|
|
31830
|
-
message,
|
|
31831
|
-
};
|
|
31832
|
-
}
|
|
31833
|
-
const code = searchParams.get('action');
|
|
31834
|
-
if (code !== null) {
|
|
31835
|
-
return {
|
|
31836
|
-
type: 'action',
|
|
31837
|
-
text,
|
|
31838
|
-
code,
|
|
31839
|
-
};
|
|
31840
|
-
}
|
|
31841
|
-
return null;
|
|
31842
|
-
}
|
|
31843
|
-
/**
|
|
31844
|
-
* Parses markdown quick buttons in the format `[Button Text](?message=...)` or `[Button Text](?action=...)`.
|
|
31845
|
-
* Returns both the content without supported quick buttons and the extracted button definitions.
|
|
31846
|
-
*
|
|
31847
|
-
* @param content The markdown content that may contain buttons
|
|
31848
|
-
* @returns Object with contentWithoutButtons and buttons array
|
|
31849
|
-
*
|
|
31850
|
-
* @public exported from `@promptbook/components`
|
|
31851
|
-
*/
|
|
31852
|
-
function parseMessageButtons(content) {
|
|
31853
|
-
const buttonRegex = /\[([^\]]+)\]\(\?([^)]+)\)/g;
|
|
31854
|
-
const buttons = [];
|
|
31855
|
-
const contentWithoutButtons = content
|
|
31856
|
-
.replace(buttonRegex, (match, text, query) => {
|
|
31857
|
-
const button = parseQuickButtonDefinition(text, query);
|
|
31858
|
-
if (!button) {
|
|
31859
|
-
return match;
|
|
31860
|
-
}
|
|
31861
|
-
buttons.push(button);
|
|
31862
|
-
return '';
|
|
31863
|
-
})
|
|
31864
|
-
.trim();
|
|
31865
|
-
return {
|
|
31866
|
-
contentWithoutButtons,
|
|
31867
|
-
buttons,
|
|
31868
|
-
};
|
|
31869
|
-
}
|
|
31870
|
-
|
|
31871
32400
|
/**
|
|
31872
32401
|
* Searches for the last unclosed code fence using the provided delimiter.
|
|
31873
32402
|
*/
|
|
@@ -35339,7 +35868,7 @@ const ChatMessageItem = memo(
|
|
|
35339
35868
|
// <- TODO: [🧠] Should we wrap more components in `React.memo`
|
|
35340
35869
|
// Or make normal function from this?
|
|
35341
35870
|
(props) => {
|
|
35342
|
-
const { message, participant, participants, isLastMessage, onMessage, onActionButton, onQuickMessageButton, setExpandedMessageId, isExpanded, currentRating, handleRating, mode, isCopyButtonEnabled, isFeedbackEnabled, feedbackMode = 'stars', feedbackTranslations, timingTranslations, chatLocale, onCopy, onCreateAgent, toolTitles, teammates, onReplyToMessage, canReplyToMessage, teamAgentProfiles, visualMode = 'ARTICLE_MODE', onToolCallClick, onCitationClick, soundSystem, isSpeechPlaybackEnabled, elevenLabsVoiceId, chatUiTranslations, } = props;
|
|
35871
|
+
const { message, participant, participants, isLastMessage, onMessage, onActionButton, onQuickMessageButton, setExpandedMessageId, isExpanded, currentRating, handleRating, mode, isCopyButtonEnabled, isFeedbackEnabled, feedbackMode = 'stars', feedbackTranslations, timingTranslations, resolveCitationLabel, chatLocale, onCopy, onCreateAgent, toolTitles, teammates, onReplyToMessage, canReplyToMessage, teamAgentProfiles, visualMode = 'ARTICLE_MODE', onToolCallClick, onCitationClick, soundSystem, isSpeechPlaybackEnabled, elevenLabsVoiceId, chatUiTranslations, } = props;
|
|
35343
35872
|
const { isComplete = true,
|
|
35344
35873
|
// <- TODO: Destruct all `messages` properties like `isComplete`
|
|
35345
35874
|
} = message;
|
|
@@ -35387,6 +35916,10 @@ const ChatMessageItem = memo(
|
|
|
35387
35916
|
content: sanitizedContentWithoutButtons,
|
|
35388
35917
|
citations: message.citations,
|
|
35389
35918
|
}), [message.citations, sanitizedContentWithoutButtons]);
|
|
35919
|
+
const enrichCitationForRendering = useCallback((citation) => {
|
|
35920
|
+
const previewUrl = resolveCitationPreviewUrl(citation, participants !== null && participants !== void 0 ? participants : []);
|
|
35921
|
+
return previewUrl && !citation.url ? { ...citation, url: previewUrl } : citation;
|
|
35922
|
+
}, [participants]);
|
|
35390
35923
|
const contentSegments = useMemo(() => splitMessageContentIntoSegments(citationFootnoteRenderModel.content), [citationFootnoteRenderModel.content]);
|
|
35391
35924
|
const hasMapSegment = useMemo(() => contentSegments.some((segment) => segment.type === 'map'), [contentSegments]);
|
|
35392
35925
|
const [localHoveredRating, setLocalHoveredRating] = useState(0);
|
|
@@ -35658,7 +36191,7 @@ const ChatMessageItem = memo(
|
|
|
35658
36191
|
'--message-bg-color': isAgentArticleMode ? articleModeBackgroundColor : color.toHex(),
|
|
35659
36192
|
'--message-text-color': isAgentArticleMode ? articleModeTextColor : colorOfText.toHex(),
|
|
35660
36193
|
'--chat-message-swipe-offset': swipeTranslation,
|
|
35661
|
-
}, onPointerDown: handleReplyPointerDown, onPointerMove: handleReplyPointerMove, onPointerUp: handleReplyPointerEnd, onPointerCancel: resetReplySwipe, children: [isReplyActionEnabled && (jsx("div", { className: classNames(styles$7.replySwipeIndicator, isMe && styles$7.replySwipeIndicatorRight, isReplySwipeArmed && styles$7.replySwipeIndicatorActive), "aria-hidden": "true", children: jsx(Reply, { className: styles$7.replySwipeIndicatorIcon }) })), !shouldRenderArticleActionsBar && renderMessageReadAndCopyControls(), message.isVoiceCall && (jsx("div", { className: styles$7.voiceCallIndicator, children: jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "currentColor", children: jsx("path", { d: "M6.62 10.79c1.44 2.83 3.76 5.14 6.59 6.59l2.2-2.2c.27-.27.67-.36 1.02-.24 1.12.37 2.33.57 3.57.57.55 0 1 .45 1 1V20c0 .55-.45 1-1 1-9.39 0-17-7.61-17-17 0-.55.45-1 1-1h3.5c.55 0 1 .45 1 1 0 1.25.2 2.45.57 3.57.11.35.03.74-.25 1.02l-2.2 2.2z" }) }) })), replyingToMessage && replyPreviewText && replySenderLabel && (jsx(ChatReplyPreview, { label: replyPreviewLabel, senderLabel: replySenderLabel, previewText: replyPreviewText, className: styles$7.replyBubblePreview })), jsx("div", { ref: contentWithoutButtonsRef, children: jsx(ChatMessageRichContent, { content: message.content, contentSegments: contentSegments, streamingFeaturePlaceholderKind: streamingFeaturePlaceholderKind, onCreateAgent: onCreateAgent, mode: mode }) }), message.attachments && message.attachments.length > 0 && (jsx("div", { className: styles$7.attachments, children: message.attachments.map((attachment, index) => (jsxs("a", { href: attachment.url, target: "_blank", rel: "noopener noreferrer", className: styles$7.attachment, title: attachment.name, children: [jsx("span", { className: styles$7.attachmentIcon, children: "\uD83D\uDCCE" }), jsx("span", { className: styles$7.attachmentName, children: attachment.name })] }, index))) })), jsx(ChatMessageToolCallChips, { chips: toolCallChips, onToolCallClick: onToolCallClick }), citationFootnoteRenderModel.footnotes.length > 0 && (jsx("div", { className: styles$7.citationFootnotes, children: citationFootnoteRenderModel.footnotes.map((footnote) => (jsxs("div", { className: styles$7.citationFootnoteItem, children: [jsx("span", { className: styles$7.citationFootnoteNumber, children: footnote.number }), jsx(SourceChip, { citation: footnote.citation, onClick: onCitationClick, isCitationIdVisible: false })] }, `citation-footnote-${footnote.number}-${footnote.citation.source}`))) })), transitiveCitations.length > 0 && (jsx("div", { className: styles$7.sourceCitations, children: transitiveCitations.map((citation, index) => (jsx(SourceChip, { citation: citation, suffix: `by ${citation.origin.label}`, onClick: onCitationClick }, `team-source-${citation.source}-${index}`))) })), shouldShowButtons && (jsx("div", { className: styles$7.messageButtons, children: renderableButtons.map(({ button, buttonIndex }) => (jsx("button", { type: "button", className: classNames(styles$7.messageButton, button.type === 'action' && styles$7.actionMessageButton), onClick: (event) => {
|
|
36194
|
+
}, onPointerDown: handleReplyPointerDown, onPointerMove: handleReplyPointerMove, onPointerUp: handleReplyPointerEnd, onPointerCancel: resetReplySwipe, children: [isReplyActionEnabled && (jsx("div", { className: classNames(styles$7.replySwipeIndicator, isMe && styles$7.replySwipeIndicatorRight, isReplySwipeArmed && styles$7.replySwipeIndicatorActive), "aria-hidden": "true", children: jsx(Reply, { className: styles$7.replySwipeIndicatorIcon }) })), !shouldRenderArticleActionsBar && renderMessageReadAndCopyControls(), message.isVoiceCall && (jsx("div", { className: styles$7.voiceCallIndicator, children: jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "currentColor", children: jsx("path", { d: "M6.62 10.79c1.44 2.83 3.76 5.14 6.59 6.59l2.2-2.2c.27-.27.67-.36 1.02-.24 1.12.37 2.33.57 3.57.57.55 0 1 .45 1 1V20c0 .55-.45 1-1 1-9.39 0-17-7.61-17-17 0-.55.45-1 1-1h3.5c.55 0 1 .45 1 1 0 1.25.2 2.45.57 3.57.11.35.03.74-.25 1.02l-2.2 2.2z" }) }) })), replyingToMessage && replyPreviewText && replySenderLabel && (jsx(ChatReplyPreview, { label: replyPreviewLabel, senderLabel: replySenderLabel, previewText: replyPreviewText, className: styles$7.replyBubblePreview })), jsx("div", { ref: contentWithoutButtonsRef, children: jsx(ChatMessageRichContent, { content: message.content, contentSegments: contentSegments, streamingFeaturePlaceholderKind: streamingFeaturePlaceholderKind, onCreateAgent: onCreateAgent, mode: mode }) }), message.attachments && message.attachments.length > 0 && (jsx("div", { className: styles$7.attachments, children: message.attachments.map((attachment, index) => (jsxs("a", { href: attachment.url, target: "_blank", rel: "noopener noreferrer", className: styles$7.attachment, title: attachment.name, children: [jsx("span", { className: styles$7.attachmentIcon, children: "\uD83D\uDCCE" }), jsx("span", { className: styles$7.attachmentName, children: attachment.name })] }, index))) })), jsx(ChatMessageToolCallChips, { chips: toolCallChips, onToolCallClick: onToolCallClick }), citationFootnoteRenderModel.footnotes.length > 0 && (jsx("div", { className: styles$7.citationFootnotes, children: citationFootnoteRenderModel.footnotes.map((footnote) => (jsxs("div", { className: styles$7.citationFootnoteItem, children: [jsx("span", { className: styles$7.citationFootnoteNumber, children: footnote.number }), jsx(SourceChip, { citation: enrichCitationForRendering(footnote.citation), onClick: onCitationClick, resolveCitationLabel: resolveCitationLabel, isCitationIdVisible: false })] }, `citation-footnote-${footnote.number}-${footnote.citation.source}`))) })), transitiveCitations.length > 0 && (jsx("div", { className: styles$7.sourceCitations, children: transitiveCitations.map((citation, index) => (jsx(SourceChip, { citation: enrichCitationForRendering(citation), suffix: `by ${citation.origin.label}`, onClick: onCitationClick, resolveCitationLabel: resolveCitationLabel }, `team-source-${citation.source}-${index}`))) })), shouldShowButtons && (jsx("div", { className: styles$7.messageButtons, children: renderableButtons.map(({ button, buttonIndex }) => (jsx("button", { type: "button", className: classNames(styles$7.messageButton, button.type === 'action' && styles$7.actionMessageButton), onClick: (event) => {
|
|
35662
36195
|
event.stopPropagation();
|
|
35663
36196
|
if (button.type === 'message') {
|
|
35664
36197
|
const quickMessageHandler = onQuickMessageButton || onMessage;
|
|
@@ -35764,6 +36297,9 @@ const ChatMessageItem = memo(
|
|
|
35764
36297
|
if (prev.feedbackTranslations !== next.feedbackTranslations) {
|
|
35765
36298
|
return false;
|
|
35766
36299
|
}
|
|
36300
|
+
if (prev.resolveCitationLabel !== next.resolveCitationLabel) {
|
|
36301
|
+
return false;
|
|
36302
|
+
}
|
|
35767
36303
|
if (prev.handleRating !== next.handleRating) {
|
|
35768
36304
|
return false;
|
|
35769
36305
|
}
|
|
@@ -35792,7 +36328,7 @@ ChatMessageItem.displayName = 'ChatMessageItem';
|
|
|
35792
36328
|
* @private component of `<Chat/>`
|
|
35793
36329
|
*/
|
|
35794
36330
|
function ChatMessageList(props) {
|
|
35795
|
-
const { messages, participants, expandedMessageId, messageRatings, setExpandedMessageId, handleRating, mode, isCopyButtonEnabled, isFeedbackEnabled, feedbackMode, feedbackTranslations, timingTranslations, chatLocale, onCopy, onMessage, onActionButton, onQuickMessageButton, onReplyToMessage, canReplyToMessage, onCreateAgent, toolTitles, teammates, onToolCallClick, onCitationClick, visualMode, soundSystem, isSpeechPlaybackEnabled, elevenLabsVoiceId, teamAgentProfiles, setChatMessagesElement, onScroll, chatMessagesClassName, hasActions, chatUiTranslations, } = props;
|
|
36331
|
+
const { messages, participants, expandedMessageId, messageRatings, setExpandedMessageId, handleRating, mode, isCopyButtonEnabled, isFeedbackEnabled, feedbackMode, feedbackTranslations, timingTranslations, resolveCitationLabel, chatLocale, onCopy, onMessage, onActionButton, onQuickMessageButton, onReplyToMessage, canReplyToMessage, onCreateAgent, toolTitles, teammates, onToolCallClick, onCitationClick, visualMode, soundSystem, isSpeechPlaybackEnabled, elevenLabsVoiceId, teamAgentProfiles, setChatMessagesElement, onScroll, chatMessagesClassName, hasActions, chatUiTranslations, } = props;
|
|
35796
36332
|
const firstMessage = messages[0];
|
|
35797
36333
|
const firstMsgContent = (firstMessage === null || firstMessage === void 0 ? void 0 : firstMessage.content) || '';
|
|
35798
36334
|
const firstMsgLines = firstMsgContent.split(/\r?\n/).length;
|
|
@@ -35804,7 +36340,7 @@ function ChatMessageList(props) {
|
|
|
35804
36340
|
const isLastMessage = index === messages.length - 1;
|
|
35805
36341
|
const isExpanded = expandedMessageId === message.id;
|
|
35806
36342
|
const currentRating = messageRatings.get(message.id || message.content /* <-[??] */) || 0;
|
|
35807
|
-
return (jsx(ChatMessageItem, { message: message, participant: participant, participants: participants, isLastMessage: isLastMessage, onMessage: onMessage, onActionButton: onActionButton, onQuickMessageButton: onQuickMessageButton, onReplyToMessage: onReplyToMessage, canReplyToMessage: canReplyToMessage, setExpandedMessageId: setExpandedMessageId, isExpanded: isExpanded, currentRating: currentRating, handleRating: handleRating, mode: mode, isCopyButtonEnabled: isCopyButtonEnabled, isFeedbackEnabled: isFeedbackEnabled, feedbackMode: feedbackMode, feedbackTranslations: feedbackTranslations, timingTranslations: timingTranslations, chatLocale: chatLocale, onCopy: onCopy, onCreateAgent: onCreateAgent, toolTitles: toolTitles, teammates: teammates, teamAgentProfiles: teamAgentProfiles, visualMode: visualMode, onToolCallClick: onToolCallClick, onCitationClick: onCitationClick, soundSystem: soundSystem, isSpeechPlaybackEnabled: isSpeechPlaybackEnabled, elevenLabsVoiceId: elevenLabsVoiceId, chatUiTranslations: chatUiTranslations }, resolveRenderedMessageKey(message)));
|
|
36343
|
+
return (jsx(ChatMessageItem, { message: message, participant: participant, participants: participants, isLastMessage: isLastMessage, onMessage: onMessage, onActionButton: onActionButton, onQuickMessageButton: onQuickMessageButton, onReplyToMessage: onReplyToMessage, canReplyToMessage: canReplyToMessage, setExpandedMessageId: setExpandedMessageId, isExpanded: isExpanded, currentRating: currentRating, handleRating: handleRating, mode: mode, isCopyButtonEnabled: isCopyButtonEnabled, isFeedbackEnabled: isFeedbackEnabled, feedbackMode: feedbackMode, feedbackTranslations: feedbackTranslations, timingTranslations: timingTranslations, resolveCitationLabel: resolveCitationLabel, chatLocale: chatLocale, onCopy: onCopy, onCreateAgent: onCreateAgent, toolTitles: toolTitles, teammates: teammates, teamAgentProfiles: teamAgentProfiles, visualMode: visualMode, onToolCallClick: onToolCallClick, onCitationClick: onCitationClick, soundSystem: soundSystem, isSpeechPlaybackEnabled: isSpeechPlaybackEnabled, elevenLabsVoiceId: elevenLabsVoiceId, chatUiTranslations: chatUiTranslations }, resolveRenderedMessageKey(message)));
|
|
35808
36344
|
}), jsx("div", { style: { height: 100 } })] }));
|
|
35809
36345
|
}
|
|
35810
36346
|
/**
|
|
@@ -39250,11 +39786,11 @@ function TeamToolCallActionsGroup(props) {
|
|
|
39250
39786
|
* @private component of ChatToolCallModal
|
|
39251
39787
|
*/
|
|
39252
39788
|
function TeamToolCallSourcesGroup(props) {
|
|
39253
|
-
const { teamCitations } = props;
|
|
39789
|
+
const { teamCitations, resolveCitationLabel } = props;
|
|
39254
39790
|
if (teamCitations.length === 0) {
|
|
39255
39791
|
return null;
|
|
39256
39792
|
}
|
|
39257
|
-
return (jsxs("div", { className: styles$7.teamToolCallGroup, children: [jsx("div", { className: styles$7.teamToolCallHeading, children: "Sources" }), jsx("div", { className: styles$7.teamToolCallChips, children: teamCitations.map((citation, index) => (jsx(SourceChip, { citation: citation, suffix: `by ${citation.origin.label}
|
|
39793
|
+
return (jsxs("div", { className: styles$7.teamToolCallGroup, children: [jsx("div", { className: styles$7.teamToolCallHeading, children: "Sources" }), jsx("div", { className: styles$7.teamToolCallChips, children: teamCitations.map((citation, index) => (jsx(SourceChip, { citation: citation, suffix: `by ${citation.origin.label}`, resolveCitationLabel: resolveCitationLabel }, `team-source-${citation.source}-${index}`))) })] }));
|
|
39258
39794
|
}
|
|
39259
39795
|
/**
|
|
39260
39796
|
* Renders the nested action details for the selected teammate tool call.
|
|
@@ -39279,12 +39815,12 @@ function TeamToolCallDetailsPanel(props) {
|
|
|
39279
39815
|
* @private component of ChatToolCallModal
|
|
39280
39816
|
*/
|
|
39281
39817
|
function TeamToolCallSummarySection(props) {
|
|
39282
|
-
const { agentParticipant, buttonColor, onClearSelectedTeamToolCall, onSelectTeamToolCall, selectedTeamToolCall, teamToolCallSummary, toolTitles, } = props;
|
|
39818
|
+
const { agentParticipant, buttonColor, onClearSelectedTeamToolCall, onSelectTeamToolCall, selectedTeamToolCall, teamToolCallSummary, toolTitles, resolveCitationLabel, } = props;
|
|
39283
39819
|
const hasSummaryContent = teamToolCallSummary.toolCalls.length > 0 || teamToolCallSummary.citations.length > 0;
|
|
39284
39820
|
if (!hasSummaryContent) {
|
|
39285
39821
|
return null;
|
|
39286
39822
|
}
|
|
39287
|
-
return (jsxs("div", { className: styles$7.teamToolCallSection, children: [jsx(TeamToolCallActionsGroup, { teamToolCalls: teamToolCallSummary.toolCalls, onSelectTeamToolCall: onSelectTeamToolCall, toolTitles: toolTitles }), jsx(TeamToolCallSourcesGroup, { teamCitations: teamToolCallSummary.citations }), jsx(TeamToolCallDetailsPanel, { selectedTeamToolCall: selectedTeamToolCall, onClearSelectedTeamToolCall: onClearSelectedTeamToolCall, toolTitles: toolTitles, agentParticipant: agentParticipant, buttonColor: buttonColor })] }));
|
|
39823
|
+
return (jsxs("div", { className: styles$7.teamToolCallSection, children: [jsx(TeamToolCallActionsGroup, { teamToolCalls: teamToolCallSummary.toolCalls, onSelectTeamToolCall: onSelectTeamToolCall, toolTitles: toolTitles }), jsx(TeamToolCallSourcesGroup, { teamCitations: teamToolCallSummary.citations, resolveCitationLabel: resolveCitationLabel }), jsx(TeamToolCallDetailsPanel, { selectedTeamToolCall: selectedTeamToolCall, onClearSelectedTeamToolCall: onClearSelectedTeamToolCall, toolTitles: toolTitles, agentParticipant: agentParticipant, buttonColor: buttonColor })] }));
|
|
39288
39824
|
}
|
|
39289
39825
|
/**
|
|
39290
39826
|
* Renders TEAM conversation details, nested actions, and citations.
|
|
@@ -39292,7 +39828,7 @@ function TeamToolCallSummarySection(props) {
|
|
|
39292
39828
|
* @private function of ChatToolCallModal
|
|
39293
39829
|
*/
|
|
39294
39830
|
function TeamToolCallModalContent(options) {
|
|
39295
|
-
const { teamResult, toolCallDate, teamToolCallSummary, selectedTeamToolCall, onSelectTeamToolCall, onClearSelectedTeamToolCall, teamProfiles, toolTitles, agentParticipant, buttonColor, } = options;
|
|
39831
|
+
const { teamResult, toolCallDate, teamToolCallSummary, selectedTeamToolCall, onSelectTeamToolCall, onClearSelectedTeamToolCall, teamProfiles, toolTitles, resolveCitationLabel, agentParticipant, buttonColor, } = options;
|
|
39296
39832
|
const baseTime = toolCallDate ? toolCallDate.getTime() : Date.now();
|
|
39297
39833
|
const messages = createTeamConversationMessages(teamResult, baseTime);
|
|
39298
39834
|
const { agentHeader, teammateHeader, participants } = createTeamConversationViewModel({
|
|
@@ -39300,7 +39836,7 @@ function TeamToolCallModalContent(options) {
|
|
|
39300
39836
|
teamProfiles,
|
|
39301
39837
|
agentParticipant,
|
|
39302
39838
|
});
|
|
39303
|
-
return (jsxs(Fragment, { children: [jsx(TeamConversationHeader, { agentHeader: agentHeader, teammateHeader: teammateHeader }), jsxs("div", { className: styles$7.searchModalContent, children: [jsx(TeamConversationSection, { agentLabel: agentHeader.label, teammateLabel: teammateHeader.label, messages: messages, participants: participants }), jsx(TeamToolCallSummarySection, { teamToolCallSummary: teamToolCallSummary, selectedTeamToolCall: selectedTeamToolCall, onSelectTeamToolCall: onSelectTeamToolCall, onClearSelectedTeamToolCall: onClearSelectedTeamToolCall, toolTitles: toolTitles, agentParticipant: agentParticipant, buttonColor: buttonColor })] })] }));
|
|
39839
|
+
return (jsxs(Fragment, { children: [jsx(TeamConversationHeader, { agentHeader: agentHeader, teammateHeader: teammateHeader }), jsxs("div", { className: styles$7.searchModalContent, children: [jsx(TeamConversationSection, { agentLabel: agentHeader.label, teammateLabel: teammateHeader.label, messages: messages, participants: participants }), jsx(TeamToolCallSummarySection, { teamToolCallSummary: teamToolCallSummary, selectedTeamToolCall: selectedTeamToolCall, onSelectTeamToolCall: onSelectTeamToolCall, onClearSelectedTeamToolCall: onClearSelectedTeamToolCall, toolTitles: toolTitles, resolveCitationLabel: resolveCitationLabel, agentParticipant: agentParticipant, buttonColor: buttonColor })] })] }));
|
|
39304
39840
|
}
|
|
39305
39841
|
|
|
39306
39842
|
/**
|
|
@@ -39308,7 +39844,7 @@ function TeamToolCallModalContent(options) {
|
|
|
39308
39844
|
*
|
|
39309
39845
|
* @private component of `ChatToolCallModal`
|
|
39310
39846
|
*/
|
|
39311
|
-
function ChatToolCallModalContent({ agentParticipant, availableTools, buttonColor, chatUiTranslations, focusedToolCall, isAdvancedView, locale, mode, onClearSelectedTeamToolCall, onRequestAdvancedView, onSelectTeamToolCall, selectedTeamToolCall, teamProfiles, teamResult, teamToolCallSummary, toolCall, toolCallDate, toolTitles, }) {
|
|
39847
|
+
function ChatToolCallModalContent({ agentParticipant, availableTools, buttonColor, chatUiTranslations, focusedToolCall, isAdvancedView, locale, mode, resolveCitationLabel, onClearSelectedTeamToolCall, onRequestAdvancedView, onSelectTeamToolCall, selectedTeamToolCall, teamProfiles, teamResult, teamToolCallSummary, toolCall, toolCallDate, toolTitles, }) {
|
|
39312
39848
|
if (isAdvancedView) {
|
|
39313
39849
|
return renderAdvancedToolCallDetails({
|
|
39314
39850
|
toolCall: focusedToolCall,
|
|
@@ -39318,7 +39854,7 @@ function ChatToolCallModalContent({ agentParticipant, availableTools, buttonColo
|
|
|
39318
39854
|
});
|
|
39319
39855
|
}
|
|
39320
39856
|
if (teamResult === null || teamResult === void 0 ? void 0 : teamResult.teammate) {
|
|
39321
|
-
return (jsx(TeamToolCallModalContent, { teamResult: teamResult, toolCallDate: toolCallDate, teamToolCallSummary: teamToolCallSummary, selectedTeamToolCall: selectedTeamToolCall, onSelectTeamToolCall: onSelectTeamToolCall, onClearSelectedTeamToolCall: onClearSelectedTeamToolCall, teamProfiles: teamProfiles, toolTitles: toolTitles, agentParticipant: agentParticipant, buttonColor: buttonColor }));
|
|
39857
|
+
return (jsx(TeamToolCallModalContent, { teamResult: teamResult, toolCallDate: toolCallDate, teamToolCallSummary: teamToolCallSummary, selectedTeamToolCall: selectedTeamToolCall, onSelectTeamToolCall: onSelectTeamToolCall, onClearSelectedTeamToolCall: onClearSelectedTeamToolCall, teamProfiles: teamProfiles, toolTitles: toolTitles, resolveCitationLabel: resolveCitationLabel, agentParticipant: agentParticipant, buttonColor: buttonColor }));
|
|
39322
39858
|
}
|
|
39323
39859
|
return renderToolCallDetails({
|
|
39324
39860
|
toolCall,
|
|
@@ -39581,7 +40117,7 @@ function handleModalBackdropClick(event, onClose) {
|
|
|
39581
40117
|
* @private component of `<Chat/>`
|
|
39582
40118
|
*/
|
|
39583
40119
|
function ChatToolCallModal(props) {
|
|
39584
|
-
const { isOpen, toolCall, mode = 'LIGHT', toolCallIdentity, onClose, toolTitles, agentParticipant, buttonColor, teamAgentProfiles, chatUiTranslations, locale, availableTools, } = props;
|
|
40120
|
+
const { isOpen, toolCall, mode = 'LIGHT', toolCallIdentity, onClose, toolTitles, resolveCitationLabel, agentParticipant, buttonColor, teamAgentProfiles, chatUiTranslations, locale, availableTools, } = props;
|
|
39585
40121
|
const { clearSelectedTeamToolCall, exportAdvancedToolCallReport, focusedToolCall, isAdvancedView, modalDialogRef, openAdvancedView, selectTeamToolCall, selectedTeamToolCall, teamProfiles, teamResult, teamToolCallSummary, toggleViewMode, toolCallDate, } = useChatToolCallModalState({
|
|
39586
40122
|
isOpen,
|
|
39587
40123
|
toolCall,
|
|
@@ -39603,7 +40139,7 @@ function ChatToolCallModal(props) {
|
|
|
39603
40139
|
: (chatUiTranslations === null || chatUiTranslations === void 0 ? void 0 : chatUiTranslations.toolCallModalAdvancedLabel) || 'Advanced';
|
|
39604
40140
|
return (jsx("div", { className: styles$7.ratingModal, "data-chat-modal": "tool-call", "data-chat-theme": mode.toLowerCase(), onClick: (event) => {
|
|
39605
40141
|
handleModalBackdropClick(event, onClose);
|
|
39606
|
-
}, children: jsxs("div", { ref: modalDialogRef, className: classNames(styles$7.ratingModalContent, styles$7.toolCallModal), role: "dialog", "aria-modal": "true", "aria-label": modalTitle, tabIndex: -1, children: [jsx("button", { type: "button", className: styles$7.modalCloseButton, onClick: onClose, "aria-label": closeButtonLabel, children: jsx(CloseIcon, {}) }), jsx(ChatToolCallModalContent, { toolCall: toolCall, focusedToolCall: resolvedFocusedToolCall, isAdvancedView: isAdvancedView, teamResult: teamResult, toolCallDate: toolCallDate, teamToolCallSummary: teamToolCallSummary, selectedTeamToolCall: selectedTeamToolCall, onSelectTeamToolCall: selectTeamToolCall, onClearSelectedTeamToolCall: clearSelectedTeamToolCall, teamProfiles: teamProfiles, toolTitles: toolTitles, agentParticipant: agentParticipant, buttonColor: buttonColor, locale: locale, chatUiTranslations: chatUiTranslations, availableTools: availableTools, onRequestAdvancedView: openAdvancedView, mode: mode }), jsxs("div", { className: styles$7.toolCallModeFooter, children: [isAdvancedView && (jsxs(Fragment, { children: [jsx("button", { type: "button", className: styles$7.toolCallModeButton, onClick: () => {
|
|
40142
|
+
}, children: jsxs("div", { ref: modalDialogRef, className: classNames(styles$7.ratingModalContent, styles$7.toolCallModal), role: "dialog", "aria-modal": "true", "aria-label": modalTitle, tabIndex: -1, children: [jsx("button", { type: "button", className: styles$7.modalCloseButton, onClick: onClose, "aria-label": closeButtonLabel, children: jsx(CloseIcon, {}) }), jsx(ChatToolCallModalContent, { toolCall: toolCall, focusedToolCall: resolvedFocusedToolCall, isAdvancedView: isAdvancedView, teamResult: teamResult, toolCallDate: toolCallDate, teamToolCallSummary: teamToolCallSummary, selectedTeamToolCall: selectedTeamToolCall, onSelectTeamToolCall: selectTeamToolCall, onClearSelectedTeamToolCall: clearSelectedTeamToolCall, teamProfiles: teamProfiles, toolTitles: toolTitles, resolveCitationLabel: resolveCitationLabel, agentParticipant: agentParticipant, buttonColor: buttonColor, locale: locale, chatUiTranslations: chatUiTranslations, availableTools: availableTools, onRequestAdvancedView: openAdvancedView, mode: mode }), jsxs("div", { className: styles$7.toolCallModeFooter, children: [isAdvancedView && (jsxs(Fragment, { children: [jsx("button", { type: "button", className: styles$7.toolCallModeButton, onClick: () => {
|
|
39607
40143
|
void exportAdvancedToolCallReport('clipboard');
|
|
39608
40144
|
}, children: copyButtonLabel }), jsx("button", { type: "button", className: styles$7.toolCallModeButton, onClick: () => {
|
|
39609
40145
|
void exportAdvancedToolCallReport('file');
|
|
@@ -39746,6 +40282,146 @@ function promptbookifyAiText(text) {
|
|
|
39746
40282
|
}
|
|
39747
40283
|
// TODO: [🧠][✌️] Make some Promptbook-native token system
|
|
39748
40284
|
|
|
40285
|
+
/**
|
|
40286
|
+
* Pattern for detecting JSON-style Unicode escape sequences in model text.
|
|
40287
|
+
*
|
|
40288
|
+
* @private utility of chat message postprocessing
|
|
40289
|
+
*/
|
|
40290
|
+
const JSON_UNICODE_ESCAPE_DETECTION_PATTERN = /\\u[0-9a-fA-F]{4}/;
|
|
40291
|
+
/**
|
|
40292
|
+
* Pattern for decoding JSON-style Unicode escape sequences in model text.
|
|
40293
|
+
*
|
|
40294
|
+
* @private utility of chat message postprocessing
|
|
40295
|
+
*/
|
|
40296
|
+
const JSON_UNICODE_ESCAPE_PATTERN = /\\u([0-9a-fA-F]{4})/g;
|
|
40297
|
+
/**
|
|
40298
|
+
* Pattern for detecting fenced markdown code-block boundaries.
|
|
40299
|
+
*
|
|
40300
|
+
* @private utility of chat message postprocessing
|
|
40301
|
+
*/
|
|
40302
|
+
const MARKDOWN_CODE_FENCE_PATTERN = /^[ \t]{0,3}(`{3,}|~{3,})/;
|
|
40303
|
+
/**
|
|
40304
|
+
* Minimum code point decoded by the chat Unicode escape normalizer.
|
|
40305
|
+
*
|
|
40306
|
+
* ASCII escapes can be intentional in JSON and security-sensitive examples, so this
|
|
40307
|
+
* helper only decodes non-ASCII characters that were visibly broken in chat text.
|
|
40308
|
+
*
|
|
40309
|
+
* @private utility of chat message postprocessing
|
|
40310
|
+
*/
|
|
40311
|
+
const FIRST_NON_ASCII_CODE_POINT = 0x80;
|
|
40312
|
+
/**
|
|
40313
|
+
* Decodes JSON-style Unicode escape sequences in markdown prose while preserving code.
|
|
40314
|
+
*
|
|
40315
|
+
* Model/tool output can occasionally arrive as already JSON-escaped text, which makes
|
|
40316
|
+
* natural-language replies render `\u00fd` instead of the decoded character. This
|
|
40317
|
+
* keeps code examples intact by skipping fenced code blocks and inline code spans.
|
|
40318
|
+
*
|
|
40319
|
+
* @param markdown - Markdown chat content to normalize for display.
|
|
40320
|
+
* @returns Markdown chat content with non-ASCII JSON Unicode escapes decoded.
|
|
40321
|
+
*
|
|
40322
|
+
* @private internal utility of `<Chat/>`
|
|
40323
|
+
*/
|
|
40324
|
+
function decodeJsonUnicodeEscapesInMarkdownText(markdown) {
|
|
40325
|
+
var _a, _b;
|
|
40326
|
+
if (!JSON_UNICODE_ESCAPE_DETECTION_PATTERN.test(markdown)) {
|
|
40327
|
+
return markdown;
|
|
40328
|
+
}
|
|
40329
|
+
const parts = markdown.split(/(\r\n|\r|\n)/);
|
|
40330
|
+
let fenceState = null;
|
|
40331
|
+
let normalizedMarkdown = '';
|
|
40332
|
+
for (let index = 0; index < parts.length; index += 2) {
|
|
40333
|
+
const line = (_a = parts[index]) !== null && _a !== void 0 ? _a : '';
|
|
40334
|
+
const newline = (_b = parts[index + 1]) !== null && _b !== void 0 ? _b : '';
|
|
40335
|
+
const fenceBoundary = resolveMarkdownFenceBoundary(line);
|
|
40336
|
+
if (fenceState) {
|
|
40337
|
+
normalizedMarkdown += line + newline;
|
|
40338
|
+
if (fenceBoundary &&
|
|
40339
|
+
fenceBoundary.marker === fenceState.marker &&
|
|
40340
|
+
fenceBoundary.length >= fenceState.length) {
|
|
40341
|
+
fenceState = null;
|
|
40342
|
+
}
|
|
40343
|
+
continue;
|
|
40344
|
+
}
|
|
40345
|
+
if (fenceBoundary) {
|
|
40346
|
+
fenceState = fenceBoundary;
|
|
40347
|
+
normalizedMarkdown += line + newline;
|
|
40348
|
+
continue;
|
|
40349
|
+
}
|
|
40350
|
+
normalizedMarkdown += decodeJsonUnicodeEscapesOutsideInlineCode(line) + newline;
|
|
40351
|
+
}
|
|
40352
|
+
return normalizedMarkdown;
|
|
40353
|
+
}
|
|
40354
|
+
/**
|
|
40355
|
+
* Resolves one markdown code-fence boundary from a line.
|
|
40356
|
+
*
|
|
40357
|
+
* @private utility of `decodeJsonUnicodeEscapesInMarkdownText`
|
|
40358
|
+
*/
|
|
40359
|
+
function resolveMarkdownFenceBoundary(line) {
|
|
40360
|
+
const match = line.match(MARKDOWN_CODE_FENCE_PATTERN);
|
|
40361
|
+
const fenceMarker = match === null || match === void 0 ? void 0 : match[1];
|
|
40362
|
+
if (!fenceMarker) {
|
|
40363
|
+
return null;
|
|
40364
|
+
}
|
|
40365
|
+
return {
|
|
40366
|
+
marker: fenceMarker[0],
|
|
40367
|
+
length: fenceMarker.length,
|
|
40368
|
+
};
|
|
40369
|
+
}
|
|
40370
|
+
/**
|
|
40371
|
+
* Decodes Unicode escapes in one markdown line while skipping inline code spans.
|
|
40372
|
+
*
|
|
40373
|
+
* @private utility of `decodeJsonUnicodeEscapesInMarkdownText`
|
|
40374
|
+
*/
|
|
40375
|
+
function decodeJsonUnicodeEscapesOutsideInlineCode(line) {
|
|
40376
|
+
let normalizedLine = '';
|
|
40377
|
+
let cursor = 0;
|
|
40378
|
+
while (cursor < line.length) {
|
|
40379
|
+
const openingDelimiterStart = line.indexOf('`', cursor);
|
|
40380
|
+
if (openingDelimiterStart === -1) {
|
|
40381
|
+
normalizedLine += decodeJsonUnicodeEscapesInText(line.slice(cursor));
|
|
40382
|
+
break;
|
|
40383
|
+
}
|
|
40384
|
+
const openingDelimiterEnd = findBacktickRunEnd(line, openingDelimiterStart);
|
|
40385
|
+
const openingDelimiter = line.slice(openingDelimiterStart, openingDelimiterEnd);
|
|
40386
|
+
const closingDelimiterStart = line.indexOf(openingDelimiter, openingDelimiterEnd);
|
|
40387
|
+
normalizedLine += decodeJsonUnicodeEscapesInText(line.slice(cursor, openingDelimiterStart));
|
|
40388
|
+
if (closingDelimiterStart === -1) {
|
|
40389
|
+
normalizedLine += line.slice(openingDelimiterStart);
|
|
40390
|
+
break;
|
|
40391
|
+
}
|
|
40392
|
+
const closingDelimiterEnd = closingDelimiterStart + openingDelimiter.length;
|
|
40393
|
+
normalizedLine += line.slice(openingDelimiterStart, closingDelimiterEnd);
|
|
40394
|
+
cursor = closingDelimiterEnd;
|
|
40395
|
+
}
|
|
40396
|
+
return normalizedLine;
|
|
40397
|
+
}
|
|
40398
|
+
/**
|
|
40399
|
+
* Finds the first character after one contiguous run of backticks.
|
|
40400
|
+
*
|
|
40401
|
+
* @private utility of `decodeJsonUnicodeEscapesInMarkdownText`
|
|
40402
|
+
*/
|
|
40403
|
+
function findBacktickRunEnd(line, startIndex) {
|
|
40404
|
+
let cursor = startIndex;
|
|
40405
|
+
while (cursor < line.length && line[cursor] === '`') {
|
|
40406
|
+
cursor++;
|
|
40407
|
+
}
|
|
40408
|
+
return cursor;
|
|
40409
|
+
}
|
|
40410
|
+
/**
|
|
40411
|
+
* Decodes non-ASCII JSON Unicode escapes in plain text.
|
|
40412
|
+
*
|
|
40413
|
+
* @private utility of `decodeJsonUnicodeEscapesInMarkdownText`
|
|
40414
|
+
*/
|
|
40415
|
+
function decodeJsonUnicodeEscapesInText(text) {
|
|
40416
|
+
return text.replace(JSON_UNICODE_ESCAPE_PATTERN, (match, hexadecimalCodePoint) => {
|
|
40417
|
+
const codePoint = Number.parseInt(hexadecimalCodePoint, 16);
|
|
40418
|
+
if (codePoint < FIRST_NON_ASCII_CODE_POINT) {
|
|
40419
|
+
return match;
|
|
40420
|
+
}
|
|
40421
|
+
return String.fromCharCode(codePoint);
|
|
40422
|
+
});
|
|
40423
|
+
}
|
|
40424
|
+
|
|
39749
40425
|
/**
|
|
39750
40426
|
* Applies the same text normalization that Chat historically performed inline.
|
|
39751
40427
|
*
|
|
@@ -39759,15 +40435,24 @@ function postprocessChatMessage(message) {
|
|
|
39759
40435
|
const normalizedReplyingTo = messageWithCitations.replyingTo
|
|
39760
40436
|
? {
|
|
39761
40437
|
...messageWithCitations.replyingTo,
|
|
39762
|
-
content:
|
|
40438
|
+
content: postprocessChatMessageContent(messageWithCitations.replyingTo.content),
|
|
39763
40439
|
}
|
|
39764
40440
|
: undefined;
|
|
39765
40441
|
return {
|
|
39766
40442
|
...messageWithCitations,
|
|
39767
|
-
content:
|
|
40443
|
+
content: postprocessChatMessageContent(messageWithCitations.content),
|
|
39768
40444
|
...(normalizedReplyingTo ? { replyingTo: normalizedReplyingTo } : {}),
|
|
39769
40445
|
};
|
|
39770
40446
|
}
|
|
40447
|
+
/**
|
|
40448
|
+
* Applies markdown-safe text normalization to one chat message content value.
|
|
40449
|
+
*
|
|
40450
|
+
* @private utility of `useChatPostprocessedMessages`
|
|
40451
|
+
*/
|
|
40452
|
+
function postprocessChatMessageContent(content) {
|
|
40453
|
+
const decodedContent = decodeJsonUnicodeEscapesInMarkdownText(content);
|
|
40454
|
+
return promptbookifyAiText(humanizeAiText(decodedContent));
|
|
40455
|
+
}
|
|
39771
40456
|
/**
|
|
39772
40457
|
* Memoizes the render-only message normalization used by `<Chat/>`.
|
|
39773
40458
|
*
|
|
@@ -40579,7 +41264,7 @@ function hasChatActions(postprocessedMessages, { onReset, newChatButtonHref, onU
|
|
|
40579
41264
|
* @public exported from `@promptbook/components`
|
|
40580
41265
|
*/
|
|
40581
41266
|
function Chat(props) {
|
|
40582
|
-
const { title = 'Chat', messages, onChange, onMessage, onActionButton, onQuickMessageButton, onReplyToMessage, onCancelReply, onReset, resetRequiresConfirmation = true, newChatButtonHref, onFeedback, feedbackMode = 'stars', feedbackTranslations, timingTranslations, onFileUpload, chatLocale, speechRecognition, placeholderMessageContent, defaultMessage, enterBehavior, resolveEnterBehavior, children, className, style, isAiTextHumanizedAndPromptbookified = true, isVoiceCalling = false, isFocusedOnLoad, participants = [], canReplyToMessage, replyingToMessage, extraActions, actionsContainer, saveFormats, saveFormatHandlers, isSaveButtonEnabled = true, isCopyButtonEnabled = true, buttonColor: buttonColorRaw, onUseTemplate, onCreateAgent, toolTitles, teammates, teamAgentProfiles, layout, visualMode = 'ARTICLE_MODE', theme = 'LIGHT', effectConfigs, soundSystem, speechRecognitionLanguage, isSpeechPlaybackEnabled = true, elevenLabsVoiceId, chatUiTranslations, } = props;
|
|
41267
|
+
const { title = 'Chat', messages, onChange, onMessage, onActionButton, onQuickMessageButton, onReplyToMessage, onCancelReply, onReset, resetRequiresConfirmation = true, newChatButtonHref, onFeedback, feedbackMode = 'stars', feedbackTranslations, timingTranslations, resolveCitationLabel, onFileUpload, chatLocale, speechRecognition, placeholderMessageContent, defaultMessage, enterBehavior, resolveEnterBehavior, children, className, style, isAiTextHumanizedAndPromptbookified = true, isVoiceCalling = false, isFocusedOnLoad, participants = [], canReplyToMessage, replyingToMessage, extraActions, actionsContainer, saveFormats, saveFormatHandlers, isSaveButtonEnabled = true, isCopyButtonEnabled = true, buttonColor: buttonColorRaw, onUseTemplate, onCreateAgent, toolTitles, teammates, teamAgentProfiles, layout, visualMode = 'ARTICLE_MODE', theme = 'LIGHT', effectConfigs, soundSystem, speechRecognitionLanguage, isSpeechPlaybackEnabled = true, elevenLabsVoiceId, chatUiTranslations, } = props;
|
|
40583
41268
|
const buttonColor = useMemo(() => Color.from(buttonColorRaw || '#0066cc'), [buttonColorRaw]);
|
|
40584
41269
|
const agentParticipant = useMemo(() => participants.find((participant) => participant.name === 'AGENT'), [participants]);
|
|
40585
41270
|
const postprocessedMessages = useChatPostprocessedMessages({
|
|
@@ -40624,7 +41309,7 @@ function Chat(props) {
|
|
|
40624
41309
|
useChatCompleteNotification(messages, soundSystem);
|
|
40625
41310
|
return (jsxs(Fragment, { children: [feedbackStatus && (jsx("div", { className: classNames(styles$7.feedbackStatus, feedbackStatus.variant === 'success'
|
|
40626
41311
|
? styles$7.feedbackStatusSuccess
|
|
40627
|
-
: styles$7.feedbackStatusError), "aria-live": "polite", role: "status", children: feedbackStatus.message })), effectConfigs && effectConfigs.length > 0 && (jsx(ChatEffectsSystem, { messages: postprocessedMessages, effectConfigs: effectConfigs, soundSystem: soundSystem })), jsx("div", { className: classNames(className, styles$7.Chat, layout === 'STANDALONE' && styles$7.standaloneVisual, layout === 'FULL_PAGE' && styles$7.fullPageVisual, isConstrainedArticleMode && styles$7.constrainedArticleVisual, getChatCssClassName('Chat'), chatCssClassNames.chat), "data-chat-theme": mode.toLowerCase(), style, children: jsxs("div", { className: classNames(className, styles$7.chatMainFlow, getChatCssClassName('chatMainFlow'), chatCssClassNames.chatMainFlow), children: [children && jsx("div", { className: classNames(styles$7.chatChildren), children: children }), shouldShowScrollToBottom && (jsx("div", { className: styles$7.scrollToBottomContainer, children: jsxs("div", { className: styles$7.scrollToBottomWrapper, children: [jsx(SolidArrowButton, { "data-button-type": "custom", direction: "down", iconSize: 33, className: classNames(styles$7.scrollToBottom, scrollToBottomCssClassName), onClick: handleButtonClick(() => scrollToBottom()), "aria-label": ariaLabel, title: ariaLabel }), badgeLabel && (jsx("span", { className: styles$7.scrollToBottomBadge, "aria-live": "polite", role: "status", children: badgeLabel }))] }) })), isVoiceCalling && (jsx("div", { className: styles$7.voiceCallIndicatorBar, children: jsxs("div", { className: styles$7.voiceCallIndicator, children: [jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "currentColor", children: jsx("path", { d: "M6.62 10.79c1.44 2.83 3.76 5.14 6.59 6.59l2.2-2.2c.27-.27.67-.36 1.02-.24 1.12.37 2.33.57 3.57.57.55 0 1 .45 1 1V20c0 .55-.45 1-1 1-9.39 0-17-7.61-17-17 0-.55.45-1 1-1h3.5c.55 0 1 .45 1 1 0 1.25.2 2.45.57 3.57.11.35.03.74-.25 1.02l-2.2 2.2z" }) }), jsx("span", { children: "Voice call active" }), jsx("div", { className: styles$7.voiceCallPulse })] }) })), jsx(ChatActionsBar, { actionsRef: actionsRef, actionsContainer: actionsContainer, messages: postprocessedMessages, participants: participants, title: title, onReset: onReset, resetRequiresConfirmation: resetRequiresConfirmation, newChatButtonHref: newChatButtonHref, onUseTemplate: onUseTemplate, extraActions: extraActions, saveFormats: saveFormats, saveFormatHandlers: saveFormatHandlers, isSaveButtonEnabled: isSaveButtonEnabled, shouldFadeActions: shouldFadeActions, shouldDisableActions: shouldDisableActions, chatUiTranslations: chatUiTranslations, onButtonClick: handleButtonClick }), jsx(ChatMessageList, { messages: postprocessedMessages, participants: participants, expandedMessageId: expandedMessageId, messageRatings: messageRatings, setExpandedMessageId: setExpandedMessageId, handleRating: handleRating, mode: mode, isCopyButtonEnabled: isCopyButtonEnabled, isFeedbackEnabled: isFeedbackEnabled, feedbackMode: feedbackMode, feedbackTranslations: feedbackTranslations, timingTranslations: timingTranslations, chatLocale: chatLocale, onCopy: handleCopy, onMessage: onMessage, onActionButton: onActionButton, onQuickMessageButton: onQuickMessageButton, onReplyToMessage: onReplyToMessage, canReplyToMessage: canReplyToMessage, onCreateAgent: onCreateAgent, toolTitles: toolTitles, teammates: teammates, teamAgentProfiles: teamAgentProfiles, visualMode: visualMode, soundSystem: soundSystem, onToolCallClick: openToolCall, onCitationClick: openCitation, setChatMessagesElement: setChatMessagesElement, onScroll: handleChatScroll, isSpeechPlaybackEnabled: isSpeechPlaybackEnabled, elevenLabsVoiceId: elevenLabsVoiceId, chatUiTranslations: chatUiTranslations, chatMessagesClassName: classNames(isConstrainedArticleMode && styles$7.articleModeChatMessages, getChatCssClassName('chatMessages'), chatCssClassNames.chatMessages), hasActions: hasActions }), onMessage && (jsx(ChatInputArea, { onMessage: onMessage, onChange: onChange, onFileUpload: onFileUpload, speechRecognition: speechRecognition, speechRecognitionLanguage: speechRecognitionLanguage, replyingToMessage: replyingToMessage, onCancelReply: onCancelReply, defaultMessage: defaultMessage, enterBehavior: enterBehavior, resolveEnterBehavior: resolveEnterBehavior, placeholderMessageContent: placeholderMessageContent || (chatUiTranslations === null || chatUiTranslations === void 0 ? void 0 : chatUiTranslations.inputPlaceholder), isFocusedOnLoad: isFocusedOnLoad, isMobile: isMobile, isVoiceCalling: isVoiceCalling, participants: participants, buttonColor: buttonColor, soundSystem: soundSystem, onButtonClick: handleButtonClick, chatUiTranslations: chatUiTranslations, chatInputClassName: classNames(isConstrainedArticleMode && styles$7.articleModeChatInput, getChatCssClassName('chatInput'), chatCssClassNames.chatInput) }))] }) }), jsx(ChatToolCallModal, { isOpen: toolCallModalOpen, toolCall: selectedToolCall, toolCallIdentity: selectedToolCallIdentity, onClose: closeToolCallModal, toolTitles: toolTitles, agentParticipant: agentParticipant, buttonColor: buttonColor, teamAgentProfiles: teamAgentProfiles, chatUiTranslations: chatUiTranslations, locale: chatLocale, availableTools: selectedMessageAvailableTools, mode: mode }), jsx(ChatCitationModal, { isOpen: citationModalOpen, citation: selectedCitation, participants: participants, soundSystem: soundSystem, onClose: closeCitationModal }), jsx(ChatRatingModal, { isOpen: ratingModalOpen, selectedMessage: selectedMessage, postprocessedMessages: postprocessedMessages, messages: messages, hoveredRating: hoveredRating, messageRatings: messageRatings, textRating: textRating, feedbackMode: feedbackMode, feedbackTranslations: feedbackTranslations, mode: mode, isMobile: isMobile, onClose: () => setRatingModalOpen(false), setHoveredRating: setHoveredRating, setMessageRatings: setMessageRatings, setSelectedMessage: setSelectedMessage, setTextRating: setTextRating, submitRating: submitRating })] }));
|
|
41312
|
+
: styles$7.feedbackStatusError), "aria-live": "polite", role: "status", children: feedbackStatus.message })), effectConfigs && effectConfigs.length > 0 && (jsx(ChatEffectsSystem, { messages: postprocessedMessages, effectConfigs: effectConfigs, soundSystem: soundSystem })), jsx("div", { className: classNames(className, styles$7.Chat, layout === 'STANDALONE' && styles$7.standaloneVisual, layout === 'FULL_PAGE' && styles$7.fullPageVisual, isConstrainedArticleMode && styles$7.constrainedArticleVisual, getChatCssClassName('Chat'), chatCssClassNames.chat), "data-chat-theme": mode.toLowerCase(), style, children: jsxs("div", { className: classNames(className, styles$7.chatMainFlow, getChatCssClassName('chatMainFlow'), chatCssClassNames.chatMainFlow), children: [children && jsx("div", { className: classNames(styles$7.chatChildren), children: children }), shouldShowScrollToBottom && (jsx("div", { className: styles$7.scrollToBottomContainer, children: jsxs("div", { className: styles$7.scrollToBottomWrapper, children: [jsx(SolidArrowButton, { "data-button-type": "custom", direction: "down", iconSize: 33, className: classNames(styles$7.scrollToBottom, scrollToBottomCssClassName), onClick: handleButtonClick(() => scrollToBottom()), "aria-label": ariaLabel, title: ariaLabel }), badgeLabel && (jsx("span", { className: styles$7.scrollToBottomBadge, "aria-live": "polite", role: "status", children: badgeLabel }))] }) })), isVoiceCalling && (jsx("div", { className: styles$7.voiceCallIndicatorBar, children: jsxs("div", { className: styles$7.voiceCallIndicator, children: [jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "currentColor", children: jsx("path", { d: "M6.62 10.79c1.44 2.83 3.76 5.14 6.59 6.59l2.2-2.2c.27-.27.67-.36 1.02-.24 1.12.37 2.33.57 3.57.57.55 0 1 .45 1 1V20c0 .55-.45 1-1 1-9.39 0-17-7.61-17-17 0-.55.45-1 1-1h3.5c.55 0 1 .45 1 1 0 1.25.2 2.45.57 3.57.11.35.03.74-.25 1.02l-2.2 2.2z" }) }), jsx("span", { children: "Voice call active" }), jsx("div", { className: styles$7.voiceCallPulse })] }) })), jsx(ChatActionsBar, { actionsRef: actionsRef, actionsContainer: actionsContainer, messages: postprocessedMessages, participants: participants, title: title, onReset: onReset, resetRequiresConfirmation: resetRequiresConfirmation, newChatButtonHref: newChatButtonHref, onUseTemplate: onUseTemplate, extraActions: extraActions, saveFormats: saveFormats, saveFormatHandlers: saveFormatHandlers, isSaveButtonEnabled: isSaveButtonEnabled, shouldFadeActions: shouldFadeActions, shouldDisableActions: shouldDisableActions, chatUiTranslations: chatUiTranslations, onButtonClick: handleButtonClick }), jsx(ChatMessageList, { messages: postprocessedMessages, participants: participants, expandedMessageId: expandedMessageId, messageRatings: messageRatings, setExpandedMessageId: setExpandedMessageId, handleRating: handleRating, mode: mode, isCopyButtonEnabled: isCopyButtonEnabled, isFeedbackEnabled: isFeedbackEnabled, feedbackMode: feedbackMode, feedbackTranslations: feedbackTranslations, timingTranslations: timingTranslations, resolveCitationLabel: resolveCitationLabel, chatLocale: chatLocale, onCopy: handleCopy, onMessage: onMessage, onActionButton: onActionButton, onQuickMessageButton: onQuickMessageButton, onReplyToMessage: onReplyToMessage, canReplyToMessage: canReplyToMessage, onCreateAgent: onCreateAgent, toolTitles: toolTitles, teammates: teammates, teamAgentProfiles: teamAgentProfiles, visualMode: visualMode, soundSystem: soundSystem, onToolCallClick: openToolCall, onCitationClick: openCitation, setChatMessagesElement: setChatMessagesElement, onScroll: handleChatScroll, isSpeechPlaybackEnabled: isSpeechPlaybackEnabled, elevenLabsVoiceId: elevenLabsVoiceId, chatUiTranslations: chatUiTranslations, chatMessagesClassName: classNames(isConstrainedArticleMode && styles$7.articleModeChatMessages, getChatCssClassName('chatMessages'), chatCssClassNames.chatMessages), hasActions: hasActions }), onMessage && (jsx(ChatInputArea, { onMessage: onMessage, onChange: onChange, onFileUpload: onFileUpload, speechRecognition: speechRecognition, speechRecognitionLanguage: speechRecognitionLanguage, replyingToMessage: replyingToMessage, onCancelReply: onCancelReply, defaultMessage: defaultMessage, enterBehavior: enterBehavior, resolveEnterBehavior: resolveEnterBehavior, placeholderMessageContent: placeholderMessageContent || (chatUiTranslations === null || chatUiTranslations === void 0 ? void 0 : chatUiTranslations.inputPlaceholder), isFocusedOnLoad: isFocusedOnLoad, isMobile: isMobile, isVoiceCalling: isVoiceCalling, participants: participants, buttonColor: buttonColor, soundSystem: soundSystem, onButtonClick: handleButtonClick, chatUiTranslations: chatUiTranslations, chatInputClassName: classNames(isConstrainedArticleMode && styles$7.articleModeChatInput, getChatCssClassName('chatInput'), chatCssClassNames.chatInput) }))] }) }), jsx(ChatToolCallModal, { isOpen: toolCallModalOpen, toolCall: selectedToolCall, toolCallIdentity: selectedToolCallIdentity, onClose: closeToolCallModal, toolTitles: toolTitles, resolveCitationLabel: resolveCitationLabel, agentParticipant: agentParticipant, buttonColor: buttonColor, teamAgentProfiles: teamAgentProfiles, chatUiTranslations: chatUiTranslations, locale: chatLocale, availableTools: selectedMessageAvailableTools, mode: mode }), jsx(ChatCitationModal, { isOpen: citationModalOpen, citation: selectedCitation, participants: participants, resolveCitationLabel: resolveCitationLabel, soundSystem: soundSystem, onClose: closeCitationModal }), jsx(ChatRatingModal, { isOpen: ratingModalOpen, selectedMessage: selectedMessage, postprocessedMessages: postprocessedMessages, messages: messages, hoveredRating: hoveredRating, messageRatings: messageRatings, textRating: textRating, feedbackMode: feedbackMode, feedbackTranslations: feedbackTranslations, mode: mode, isMobile: isMobile, onClose: () => setRatingModalOpen(false), setHoveredRating: setHoveredRating, setMessageRatings: setMessageRatings, setSelectedMessage: setSelectedMessage, setTextRating: setTextRating, submitRating: submitRating })] }));
|
|
40628
41313
|
}
|
|
40629
41314
|
|
|
40630
41315
|
/**
|
|
@@ -48631,11 +49316,19 @@ const JsonFileImportPlugin = {
|
|
|
48631
49316
|
try {
|
|
48632
49317
|
const json = JSON.parse(content);
|
|
48633
49318
|
const formattedJson = JSON.stringify(json, null, 4);
|
|
48634
|
-
return
|
|
49319
|
+
return spaceTrim$1((block) => `
|
|
49320
|
+
\`\`\`json
|
|
49321
|
+
${block(formattedJson)}
|
|
49322
|
+
\`\`\`
|
|
49323
|
+
`);
|
|
48635
49324
|
}
|
|
48636
49325
|
catch (error) {
|
|
48637
49326
|
// If JSON is invalid, still import it but maybe not as pretty JSON
|
|
48638
|
-
return
|
|
49327
|
+
return spaceTrim$1((block) => `
|
|
49328
|
+
\`\`\`json
|
|
49329
|
+
${block(content)}
|
|
49330
|
+
\`\`\`
|
|
49331
|
+
`);
|
|
48639
49332
|
}
|
|
48640
49333
|
},
|
|
48641
49334
|
};
|
|
@@ -48659,7 +49352,11 @@ const TextFileImportPlugin = {
|
|
|
48659
49352
|
import(content, mimeType) {
|
|
48660
49353
|
const extension = mimeTypeToExtension(mimeType);
|
|
48661
49354
|
const codeBlockType = extension || 'txt';
|
|
48662
|
-
return
|
|
49355
|
+
return spaceTrim$1((block) => `
|
|
49356
|
+
\`\`\`${codeBlockType}
|
|
49357
|
+
${block(content)}
|
|
49358
|
+
\`\`\`
|
|
49359
|
+
`);
|
|
48663
49360
|
},
|
|
48664
49361
|
};
|
|
48665
49362
|
|
|
@@ -48906,11 +49603,19 @@ function collectExampleInteractionLines(parseResult, samples) {
|
|
|
48906
49603
|
const examples = [];
|
|
48907
49604
|
const initialMessage = (_a = parseResult.commitments.find((commitment) => commitment.type === 'INITIAL MESSAGE')) === null || _a === void 0 ? void 0 : _a.content;
|
|
48908
49605
|
if (initialMessage) {
|
|
48909
|
-
examples.push(
|
|
49606
|
+
examples.push(spaceTrim$1((block) => `
|
|
49607
|
+
**Agent:**
|
|
49608
|
+
${block(initialMessage)}
|
|
49609
|
+
`));
|
|
48910
49610
|
}
|
|
48911
49611
|
if (samples && samples.length > 0) {
|
|
48912
49612
|
for (const sample of samples) {
|
|
48913
|
-
examples.push(
|
|
49613
|
+
examples.push(spaceTrim$1((block) => `
|
|
49614
|
+
**User:** ${block(String(sample.question))}
|
|
49615
|
+
|
|
49616
|
+
**Agent:**
|
|
49617
|
+
${block(sample.answer)}
|
|
49618
|
+
`));
|
|
48914
49619
|
}
|
|
48915
49620
|
}
|
|
48916
49621
|
return examples;
|
|
@@ -55456,7 +56161,11 @@ function truncateAttachmentInlineText(content, maxCharacters) {
|
|
|
55456
56161
|
};
|
|
55457
56162
|
}
|
|
55458
56163
|
return {
|
|
55459
|
-
content:
|
|
56164
|
+
content: spaceTrim$1((block) => `
|
|
56165
|
+
${block(content.slice(0, Math.max(0, maxCharacters)))}
|
|
56166
|
+
|
|
56167
|
+
[...truncated...]
|
|
56168
|
+
`),
|
|
55460
56169
|
isTruncated: true,
|
|
55461
56170
|
};
|
|
55462
56171
|
}
|