@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/umd/index.umd.js
CHANGED
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
* @generated
|
|
35
35
|
* @see https://github.com/webgptorg/promptbook
|
|
36
36
|
*/
|
|
37
|
-
const PROMPTBOOK_ENGINE_VERSION = '0.112.0-
|
|
37
|
+
const PROMPTBOOK_ENGINE_VERSION = '0.112.0-128';
|
|
38
38
|
/**
|
|
39
39
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
|
40
40
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -5269,41 +5269,91 @@
|
|
|
5269
5269
|
context.fill();
|
|
5270
5270
|
context.restore();
|
|
5271
5271
|
}
|
|
5272
|
+
/**
|
|
5273
|
+
* Number of latitude segments used by the single blobby octopus mesh.
|
|
5274
|
+
*
|
|
5275
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
5276
|
+
*/
|
|
5277
|
+
const LATITUDE_PATCH_COUNT$1 = 12;
|
|
5278
|
+
/**
|
|
5279
|
+
* Number of longitude segments used by the single blobby octopus mesh.
|
|
5280
|
+
*
|
|
5281
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
5282
|
+
*/
|
|
5283
|
+
const LONGITUDE_PATCH_COUNT$1 = 24;
|
|
5272
5284
|
/**
|
|
5273
5285
|
* Resolves all visible projected patches for the single blobby octopus mesh.
|
|
5274
5286
|
*
|
|
5287
|
+
* Within a single frame, mesh corner samples and longitude-only lobe-wave values are
|
|
5288
|
+
* quantized to the patch grid and computed once each rather than re-evaluated for every
|
|
5289
|
+
* patch corner — the patch loop alone would call `sampleBlobbyOctopusSurfacePoint`
|
|
5290
|
+
* `latitudePatchCount * longitudePatchCount * 4` times without caching, even though most
|
|
5291
|
+
* corners are shared between neighboring patches.
|
|
5292
|
+
*
|
|
5275
5293
|
* @private helper of `octopus3d2AvatarVisual`
|
|
5276
5294
|
*/
|
|
5277
5295
|
function resolveVisibleBlobbyOctopusPatches(options) {
|
|
5278
5296
|
const { center, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, morphologyProfile, animationPhase, timeMs, } = options;
|
|
5279
|
-
const latitudePatchCount =
|
|
5280
|
-
const longitudePatchCount =
|
|
5297
|
+
const latitudePatchCount = LATITUDE_PATCH_COUNT$1;
|
|
5298
|
+
const longitudePatchCount = LONGITUDE_PATCH_COUNT$1;
|
|
5281
5299
|
const surfacePatches = [];
|
|
5300
|
+
const latitudeBoundaries = new Float64Array(latitudePatchCount + 1);
|
|
5301
|
+
const longitudeBoundaries = new Float64Array(longitudePatchCount + 1);
|
|
5302
|
+
for (let boundaryIndex = 0; boundaryIndex <= latitudePatchCount; boundaryIndex++) {
|
|
5303
|
+
latitudeBoundaries[boundaryIndex] = -Math.PI / 2 + (boundaryIndex / latitudePatchCount) * Math.PI;
|
|
5304
|
+
}
|
|
5305
|
+
for (let boundaryIndex = 0; boundaryIndex <= longitudePatchCount; boundaryIndex++) {
|
|
5306
|
+
longitudeBoundaries[boundaryIndex] = -Math.PI + (boundaryIndex / longitudePatchCount) * Math.PI * 2;
|
|
5307
|
+
}
|
|
5308
|
+
const cachedLobeWavesByCornerLongitude = new Float64Array(longitudePatchCount + 1);
|
|
5309
|
+
for (let boundaryIndex = 0; boundaryIndex <= longitudePatchCount; boundaryIndex++) {
|
|
5310
|
+
cachedLobeWavesByCornerLongitude[boundaryIndex] = resolveLowerLobeWave(longitudeBoundaries[boundaryIndex], morphologyProfile, animationPhase, timeMs);
|
|
5311
|
+
}
|
|
5312
|
+
const cornerCount = (latitudePatchCount + 1) * (longitudePatchCount + 1);
|
|
5313
|
+
const transformedCornerSamples = new Array(cornerCount);
|
|
5314
|
+
for (let latitudeBoundaryIndex = 0; latitudeBoundaryIndex <= latitudePatchCount; latitudeBoundaryIndex++) {
|
|
5315
|
+
const cornerLatitude = latitudeBoundaries[latitudeBoundaryIndex];
|
|
5316
|
+
for (let longitudeBoundaryIndex = 0; longitudeBoundaryIndex <= longitudePatchCount; longitudeBoundaryIndex++) {
|
|
5317
|
+
const cornerLongitude = longitudeBoundaries[longitudeBoundaryIndex];
|
|
5318
|
+
const cornerIndex = latitudeBoundaryIndex * (longitudePatchCount + 1) + longitudeBoundaryIndex;
|
|
5319
|
+
const cornerSample = sampleBlobbyOctopusSurfacePointWithLongitudeCache(options, cornerLatitude, cornerLongitude, cachedLobeWavesByCornerLongitude[longitudeBoundaryIndex]);
|
|
5320
|
+
transformedCornerSamples[cornerIndex] = transformScenePoint(cornerSample, center, rotationX, rotationY);
|
|
5321
|
+
}
|
|
5322
|
+
}
|
|
5282
5323
|
for (let latitudeIndex = 0; latitudeIndex < latitudePatchCount; latitudeIndex++) {
|
|
5283
|
-
const startLatitude =
|
|
5284
|
-
const endLatitude =
|
|
5324
|
+
const startLatitude = latitudeBoundaries[latitudeIndex];
|
|
5325
|
+
const endLatitude = latitudeBoundaries[latitudeIndex + 1];
|
|
5285
5326
|
const centerLatitude = (startLatitude + endLatitude) / 2;
|
|
5286
5327
|
const verticalProgress = (Math.sin(centerLatitude) + 1) / 2;
|
|
5328
|
+
const startCornerRowOffset = latitudeIndex * (longitudePatchCount + 1);
|
|
5329
|
+
const endCornerRowOffset = (latitudeIndex + 1) * (longitudePatchCount + 1);
|
|
5287
5330
|
for (let longitudeIndex = 0; longitudeIndex < longitudePatchCount; longitudeIndex++) {
|
|
5288
|
-
const startLongitude =
|
|
5289
|
-
const endLongitude =
|
|
5331
|
+
const startLongitude = longitudeBoundaries[longitudeIndex];
|
|
5332
|
+
const endLongitude = longitudeBoundaries[longitudeIndex + 1];
|
|
5290
5333
|
const centerLongitude = (startLongitude + endLongitude) / 2;
|
|
5291
|
-
const
|
|
5292
|
-
|
|
5293
|
-
|
|
5294
|
-
|
|
5295
|
-
|
|
5334
|
+
const transformedCorners = [
|
|
5335
|
+
transformedCornerSamples[startCornerRowOffset + longitudeIndex],
|
|
5336
|
+
transformedCornerSamples[startCornerRowOffset + longitudeIndex + 1],
|
|
5337
|
+
transformedCornerSamples[endCornerRowOffset + longitudeIndex + 1],
|
|
5338
|
+
transformedCornerSamples[endCornerRowOffset + longitudeIndex],
|
|
5296
5339
|
];
|
|
5297
|
-
const transformedCorners = localCorners.map((localCorner) => transformScenePoint(localCorner, center, rotationX, rotationY));
|
|
5298
5340
|
const surfaceNormal = normalizeVector3(crossProduct3D(subtractPoint3D(transformedCorners[1], transformedCorners[0]), subtractPoint3D(transformedCorners[2], transformedCorners[0])));
|
|
5299
5341
|
if (surfaceNormal.z <= 0.01) {
|
|
5300
5342
|
continue;
|
|
5301
5343
|
}
|
|
5302
|
-
const projectedCorners =
|
|
5344
|
+
const projectedCorners = [
|
|
5345
|
+
projectScenePoint(transformedCorners[0], size, sceneCenterX, sceneCenterY),
|
|
5346
|
+
projectScenePoint(transformedCorners[1], size, sceneCenterX, sceneCenterY),
|
|
5347
|
+
projectScenePoint(transformedCorners[2], size, sceneCenterX, sceneCenterY),
|
|
5348
|
+
projectScenePoint(transformedCorners[3], size, sceneCenterX, sceneCenterY),
|
|
5349
|
+
];
|
|
5303
5350
|
surfacePatches.push({
|
|
5304
5351
|
corners: projectedCorners,
|
|
5305
|
-
averageDepth: transformedCorners.
|
|
5306
|
-
transformedCorners.
|
|
5352
|
+
averageDepth: (transformedCorners[0].z +
|
|
5353
|
+
transformedCorners[1].z +
|
|
5354
|
+
transformedCorners[2].z +
|
|
5355
|
+
transformedCorners[3].z) /
|
|
5356
|
+
4,
|
|
5307
5357
|
lightIntensity: clampNumber$1(dotProduct3D(surfaceNormal, LIGHT_DIRECTION$1), -1, 1),
|
|
5308
5358
|
fillStyle: resolveBlobbySurfacePatchFillStyle(palette, verticalProgress, Math.max(0, Math.cos(centerLongitude)), resolveLowerLobeWave(centerLongitude, morphologyProfile, animationPhase, timeMs)),
|
|
5309
5359
|
outlineColor: verticalProgress < 0.58 ? `${palette.highlight}73` : `${palette.shadow}8a`,
|
|
@@ -5321,12 +5371,21 @@
|
|
|
5321
5371
|
* @private helper of `octopus3d2AvatarVisual`
|
|
5322
5372
|
*/
|
|
5323
5373
|
function sampleBlobbyOctopusSurfacePoint(options, latitude, longitude) {
|
|
5374
|
+
const { morphologyProfile, animationPhase, timeMs } = options;
|
|
5375
|
+
return sampleBlobbyOctopusSurfacePointWithLongitudeCache(options, latitude, longitude, resolveLowerLobeWave(longitude, morphologyProfile, animationPhase, timeMs));
|
|
5376
|
+
}
|
|
5377
|
+
/**
|
|
5378
|
+
* Samples one point on the continuous Octopus 3D 2 surface using a precomputed lower-lobe wave
|
|
5379
|
+
* to skip the per-call trig evaluation for `latitudePatchCount + 1` longitude-shared corners.
|
|
5380
|
+
*
|
|
5381
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
5382
|
+
*/
|
|
5383
|
+
function sampleBlobbyOctopusSurfacePointWithLongitudeCache(options, latitude, longitude, lowerLobeWave) {
|
|
5324
5384
|
const { radiusX, radiusY, radiusZ, morphologyProfile, timeMs, animationPhase } = options;
|
|
5325
5385
|
const cosineLatitude = Math.max(0, Math.cos(latitude));
|
|
5326
5386
|
const verticalProgress = (Math.sin(latitude) + 1) / 2;
|
|
5327
5387
|
const upperBlend = Math.pow(1 - verticalProgress, 1.2);
|
|
5328
5388
|
const lowerBlend = Math.pow(verticalProgress, 1.42);
|
|
5329
|
-
const lowerLobeWave = resolveLowerLobeWave(longitude, morphologyProfile, animationPhase, timeMs);
|
|
5330
5389
|
const skirtEnvelope = Math.pow(cosineLatitude, 0.5) * lowerBlend;
|
|
5331
5390
|
const horizontalScale = 1.02 +
|
|
5332
5391
|
skirtEnvelope * (0.34 + (morphologyProfile.tentacles.rootSpreadScale - 1) * 0.22 + lowerLobeWave * 0.22) -
|
|
@@ -5623,45 +5682,102 @@
|
|
|
5623
5682
|
context.fill();
|
|
5624
5683
|
context.restore();
|
|
5625
5684
|
}
|
|
5685
|
+
/**
|
|
5686
|
+
* Number of latitude segments used by the continuous Octopus 3D 3 mesh.
|
|
5687
|
+
*
|
|
5688
|
+
* @private helper of `octopus3d3AvatarVisual`
|
|
5689
|
+
*/
|
|
5690
|
+
const LATITUDE_PATCH_COUNT = 16;
|
|
5691
|
+
/**
|
|
5692
|
+
* Number of longitude segments used by the continuous Octopus 3D 3 mesh.
|
|
5693
|
+
*
|
|
5694
|
+
* @private helper of `octopus3d3AvatarVisual`
|
|
5695
|
+
*/
|
|
5696
|
+
const LONGITUDE_PATCH_COUNT = 40;
|
|
5626
5697
|
/**
|
|
5627
5698
|
* Resolves visible projected patches for the continuous octopus mesh.
|
|
5628
5699
|
*
|
|
5700
|
+
* Within a single frame, mesh corner samples and longitude-only computations (tentacle
|
|
5701
|
+
* influence and lobe wave) are quantized to the patch grid and computed once each rather
|
|
5702
|
+
* than re-evaluated for every patch corner — the patch loop alone calls `sampleContinuousOctopusSurfacePoint`
|
|
5703
|
+
* for `latitudePatchCount * longitudePatchCount * 4` corners without caching, and each call
|
|
5704
|
+
* triggers an inner 8-iteration `Math.exp` loop, which dominates the per-frame cost.
|
|
5705
|
+
*
|
|
5629
5706
|
* @private helper of `octopus3d3AvatarVisual`
|
|
5630
5707
|
*/
|
|
5631
5708
|
function resolveVisibleContinuousOctopusPatches(options) {
|
|
5632
5709
|
const { center, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette } = options;
|
|
5633
|
-
const latitudePatchCount =
|
|
5634
|
-
const longitudePatchCount =
|
|
5710
|
+
const latitudePatchCount = LATITUDE_PATCH_COUNT;
|
|
5711
|
+
const longitudePatchCount = LONGITUDE_PATCH_COUNT;
|
|
5635
5712
|
const surfacePatches = [];
|
|
5713
|
+
const latitudeBoundaries = new Float64Array(latitudePatchCount + 1);
|
|
5714
|
+
const longitudeBoundaries = new Float64Array(longitudePatchCount + 1);
|
|
5715
|
+
for (let boundaryIndex = 0; boundaryIndex <= latitudePatchCount; boundaryIndex++) {
|
|
5716
|
+
latitudeBoundaries[boundaryIndex] = -Math.PI / 2 + (boundaryIndex / latitudePatchCount) * Math.PI;
|
|
5717
|
+
}
|
|
5718
|
+
for (let boundaryIndex = 0; boundaryIndex <= longitudePatchCount; boundaryIndex++) {
|
|
5719
|
+
longitudeBoundaries[boundaryIndex] = -Math.PI + (boundaryIndex / longitudePatchCount) * Math.PI * 2;
|
|
5720
|
+
}
|
|
5721
|
+
const cachedTentacleInfluencesByCornerLongitude = new Array(longitudePatchCount + 1);
|
|
5722
|
+
const cachedLobeWavesByCornerLongitude = new Float64Array(longitudePatchCount + 1);
|
|
5723
|
+
const cachedTentacleInfluencesByPatchCenterLongitude = new Array(longitudePatchCount);
|
|
5724
|
+
const cachedLobeWavesByPatchCenterLongitude = new Float64Array(longitudePatchCount);
|
|
5725
|
+
const cachedCosByPatchCenterLongitude = new Float64Array(longitudePatchCount);
|
|
5726
|
+
for (let boundaryIndex = 0; boundaryIndex <= longitudePatchCount; boundaryIndex++) {
|
|
5727
|
+
const cornerLongitude = longitudeBoundaries[boundaryIndex];
|
|
5728
|
+
cachedTentacleInfluencesByCornerLongitude[boundaryIndex] = resolveContinuousTentacleInfluence(options, cornerLongitude);
|
|
5729
|
+
cachedLobeWavesByCornerLongitude[boundaryIndex] = resolveContinuousLobeWave(options, cornerLongitude);
|
|
5730
|
+
}
|
|
5731
|
+
for (let longitudeIndex = 0; longitudeIndex < longitudePatchCount; longitudeIndex++) {
|
|
5732
|
+
const patchCenterLongitude = (longitudeBoundaries[longitudeIndex] + longitudeBoundaries[longitudeIndex + 1]) / 2;
|
|
5733
|
+
cachedTentacleInfluencesByPatchCenterLongitude[longitudeIndex] = resolveContinuousTentacleInfluence(options, patchCenterLongitude);
|
|
5734
|
+
cachedLobeWavesByPatchCenterLongitude[longitudeIndex] = resolveContinuousLobeWave(options, patchCenterLongitude);
|
|
5735
|
+
cachedCosByPatchCenterLongitude[longitudeIndex] = Math.max(0, Math.cos(patchCenterLongitude));
|
|
5736
|
+
}
|
|
5737
|
+
const cornerCount = (latitudePatchCount + 1) * (longitudePatchCount + 1);
|
|
5738
|
+
const transformedCornerSamples = new Array(cornerCount);
|
|
5739
|
+
for (let latitudeBoundaryIndex = 0; latitudeBoundaryIndex <= latitudePatchCount; latitudeBoundaryIndex++) {
|
|
5740
|
+
const cornerLatitude = latitudeBoundaries[latitudeBoundaryIndex];
|
|
5741
|
+
for (let longitudeBoundaryIndex = 0; longitudeBoundaryIndex <= longitudePatchCount; longitudeBoundaryIndex++) {
|
|
5742
|
+
const cornerLongitude = longitudeBoundaries[longitudeBoundaryIndex];
|
|
5743
|
+
const cornerIndex = latitudeBoundaryIndex * (longitudePatchCount + 1) + longitudeBoundaryIndex;
|
|
5744
|
+
const cornerSample = sampleContinuousOctopusSurfacePointWithLongitudeCache(options, cornerLatitude, cornerLongitude, cachedTentacleInfluencesByCornerLongitude[longitudeBoundaryIndex], cachedLobeWavesByCornerLongitude[longitudeBoundaryIndex]);
|
|
5745
|
+
transformedCornerSamples[cornerIndex] = transformScenePoint(cornerSample, center, rotationX, rotationY);
|
|
5746
|
+
}
|
|
5747
|
+
}
|
|
5636
5748
|
for (let latitudeIndex = 0; latitudeIndex < latitudePatchCount; latitudeIndex++) {
|
|
5637
|
-
const startLatitude =
|
|
5638
|
-
const endLatitude =
|
|
5749
|
+
const startLatitude = latitudeBoundaries[latitudeIndex];
|
|
5750
|
+
const endLatitude = latitudeBoundaries[latitudeIndex + 1];
|
|
5639
5751
|
const centerLatitude = (startLatitude + endLatitude) / 2;
|
|
5640
5752
|
const verticalProgress = (Math.sin(centerLatitude) + 1) / 2;
|
|
5753
|
+
const startCornerRowOffset = latitudeIndex * (longitudePatchCount + 1);
|
|
5754
|
+
const endCornerRowOffset = (latitudeIndex + 1) * (longitudePatchCount + 1);
|
|
5641
5755
|
for (let longitudeIndex = 0; longitudeIndex < longitudePatchCount; longitudeIndex++) {
|
|
5642
|
-
const
|
|
5643
|
-
|
|
5644
|
-
|
|
5645
|
-
|
|
5646
|
-
|
|
5647
|
-
sampleContinuousOctopusSurfacePoint(options, startLatitude, endLongitude),
|
|
5648
|
-
sampleContinuousOctopusSurfacePoint(options, endLatitude, endLongitude),
|
|
5649
|
-
sampleContinuousOctopusSurfacePoint(options, endLatitude, startLongitude),
|
|
5756
|
+
const transformedCorners = [
|
|
5757
|
+
transformedCornerSamples[startCornerRowOffset + longitudeIndex],
|
|
5758
|
+
transformedCornerSamples[startCornerRowOffset + longitudeIndex + 1],
|
|
5759
|
+
transformedCornerSamples[endCornerRowOffset + longitudeIndex + 1],
|
|
5760
|
+
transformedCornerSamples[endCornerRowOffset + longitudeIndex],
|
|
5650
5761
|
];
|
|
5651
|
-
const transformedCorners = localCorners.map((localCorner) => transformScenePoint(localCorner, center, rotationX, rotationY));
|
|
5652
5762
|
const surfaceNormal = normalizeVector3(crossProduct3D(subtractPoint3D(transformedCorners[1], transformedCorners[0]), subtractPoint3D(transformedCorners[2], transformedCorners[0])));
|
|
5653
5763
|
if (surfaceNormal.z <= 0.008) {
|
|
5654
5764
|
continue;
|
|
5655
5765
|
}
|
|
5656
|
-
const projectedCorners =
|
|
5657
|
-
|
|
5658
|
-
|
|
5766
|
+
const projectedCorners = [
|
|
5767
|
+
projectScenePoint(transformedCorners[0], size, sceneCenterX, sceneCenterY),
|
|
5768
|
+
projectScenePoint(transformedCorners[1], size, sceneCenterX, sceneCenterY),
|
|
5769
|
+
projectScenePoint(transformedCorners[2], size, sceneCenterX, sceneCenterY),
|
|
5770
|
+
projectScenePoint(transformedCorners[3], size, sceneCenterX, sceneCenterY),
|
|
5771
|
+
];
|
|
5659
5772
|
surfacePatches.push({
|
|
5660
5773
|
corners: projectedCorners,
|
|
5661
|
-
averageDepth: transformedCorners.
|
|
5662
|
-
transformedCorners.
|
|
5774
|
+
averageDepth: (transformedCorners[0].z +
|
|
5775
|
+
transformedCorners[1].z +
|
|
5776
|
+
transformedCorners[2].z +
|
|
5777
|
+
transformedCorners[3].z) /
|
|
5778
|
+
4,
|
|
5663
5779
|
lightIntensity: clampNumber$1(dotProduct3D(surfaceNormal, LIGHT_DIRECTION), -1, 1),
|
|
5664
|
-
fillStyle: resolveContinuousSurfacePatchFillStyle(palette, verticalProgress,
|
|
5780
|
+
fillStyle: resolveContinuousSurfacePatchFillStyle(palette, verticalProgress, cachedCosByPatchCenterLongitude[longitudeIndex], cachedTentacleInfluencesByPatchCenterLongitude[longitudeIndex].core, cachedLobeWavesByPatchCenterLongitude[longitudeIndex]),
|
|
5665
5781
|
outlineColor: verticalProgress < 0.54 ? `${palette.highlight}69` : `${palette.shadow}78`,
|
|
5666
5782
|
});
|
|
5667
5783
|
}
|
|
@@ -5677,16 +5793,27 @@
|
|
|
5677
5793
|
* @private helper of `octopus3d3AvatarVisual`
|
|
5678
5794
|
*/
|
|
5679
5795
|
function sampleContinuousOctopusSurfacePoint(options, latitude, longitude) {
|
|
5796
|
+
return sampleContinuousOctopusSurfacePointWithLongitudeCache(options, latitude, longitude, resolveContinuousTentacleInfluence(options, longitude), resolveContinuousLobeWave(options, longitude));
|
|
5797
|
+
}
|
|
5798
|
+
/**
|
|
5799
|
+
* Samples one point on the continuous Octopus 3D 3 surface using precomputed longitude-only
|
|
5800
|
+
* values to skip the per-call `Math.exp` tentacle-influence loop and the lobe-wave trig call.
|
|
5801
|
+
*
|
|
5802
|
+
* The patch loop quantizes the mesh into a fixed `(latitudePatchCount + 1) * (longitudePatchCount + 1)`
|
|
5803
|
+
* corner grid, so the same longitude is reused across every latitude row and each
|
|
5804
|
+
* tentacle/lobe value can be computed once per frame instead of `latitudePatchCount * 4` times.
|
|
5805
|
+
*
|
|
5806
|
+
* @private helper of `octopus3d3AvatarVisual`
|
|
5807
|
+
*/
|
|
5808
|
+
function sampleContinuousOctopusSurfacePointWithLongitudeCache(options, latitude, longitude, tentacleInfluence, lowerLobeWave) {
|
|
5680
5809
|
const { radiusX, radiusY, radiusZ, morphologyProfile, timeMs, animationPhase } = options;
|
|
5681
5810
|
const cosineLatitude = Math.max(0, Math.cos(latitude));
|
|
5682
5811
|
const verticalProgress = (Math.sin(latitude) + 1) / 2;
|
|
5683
5812
|
const upperBlend = Math.pow(1 - verticalProgress, 1.28);
|
|
5684
5813
|
const lowerBlend = smoothStep(0.38, 1, verticalProgress);
|
|
5685
5814
|
const tipBlend = smoothStep(0.68, 1, verticalProgress);
|
|
5686
|
-
const tentacleInfluence = resolveContinuousTentacleInfluence(options, longitude);
|
|
5687
5815
|
const centerPull = resolveSignedAngularDistance(longitude, tentacleInfluence.centerLongitude);
|
|
5688
5816
|
const effectiveLongitude = longitude + centerPull * lowerBlend * tentacleInfluence.core * (0.24 + tipBlend * 0.2);
|
|
5689
|
-
const lowerLobeWave = resolveContinuousLobeWave(options, longitude);
|
|
5690
5817
|
const mantleRipple = Math.sin(longitude * morphologyProfile.body.lobeCount +
|
|
5691
5818
|
animationPhase * 0.6 +
|
|
5692
5819
|
timeMs / (1750 + morphologyProfile.body.lobeCount * 30)) *
|
|
@@ -9375,8 +9502,11 @@
|
|
|
9375
9502
|
if (!trimmedContent) {
|
|
9376
9503
|
return requirements;
|
|
9377
9504
|
}
|
|
9378
|
-
|
|
9379
|
-
|
|
9505
|
+
const goalSection = spacetrim.spaceTrim((block) => `
|
|
9506
|
+
## Goal
|
|
9507
|
+
|
|
9508
|
+
${block(trimmedContent)}
|
|
9509
|
+
`);
|
|
9380
9510
|
const requirementsWithGoal = this.appendToSystemMessage(requirements, goalSection, '\n\n');
|
|
9381
9511
|
return this.appendToPromptSuffix(requirementsWithGoal, trimmedContent);
|
|
9382
9512
|
}
|
|
@@ -9898,8 +10028,11 @@
|
|
|
9898
10028
|
if (!trimmedContent) {
|
|
9899
10029
|
return requirements;
|
|
9900
10030
|
}
|
|
9901
|
-
|
|
9902
|
-
|
|
10031
|
+
const languageSection = spacetrim.spaceTrim((block) => `
|
|
10032
|
+
## Language
|
|
10033
|
+
|
|
10034
|
+
- Your language is ${block(trimmedContent)}
|
|
10035
|
+
`);
|
|
9903
10036
|
return this.appendToSystemMessage(requirements, languageSection, '\n\n');
|
|
9904
10037
|
}
|
|
9905
10038
|
}
|
|
@@ -13479,7 +13612,15 @@
|
|
|
13479
13612
|
* Builds the teammate request text, optionally including context.
|
|
13480
13613
|
*/
|
|
13481
13614
|
function buildTeammateRequest(message, context) {
|
|
13482
|
-
|
|
13615
|
+
if (!context) {
|
|
13616
|
+
return message;
|
|
13617
|
+
}
|
|
13618
|
+
return spacetrim.spaceTrim((block) => `
|
|
13619
|
+
${block(message)}
|
|
13620
|
+
|
|
13621
|
+
Context:
|
|
13622
|
+
${block(context)}
|
|
13623
|
+
`);
|
|
13483
13624
|
}
|
|
13484
13625
|
/**
|
|
13485
13626
|
* Builds a minimal chat prompt for teammate calls.
|
|
@@ -17502,7 +17643,11 @@
|
|
|
17502
17643
|
const lineRangedContent = applyOptionalLineRange(decodedContent, args.startLine, args.endLine);
|
|
17503
17644
|
const wasCharacterTruncated = lineRangedContent.length > MAX_PROJECT_FILE_CONTENT_CHARACTERS;
|
|
17504
17645
|
const contentToReturn = wasCharacterTruncated
|
|
17505
|
-
?
|
|
17646
|
+
? spacetrim.spaceTrim((block) => `
|
|
17647
|
+
${block(lineRangedContent.slice(0, MAX_PROJECT_FILE_CONTENT_CHARACTERS))}
|
|
17648
|
+
|
|
17649
|
+
[...truncated...]
|
|
17650
|
+
`)
|
|
17506
17651
|
: lineRangedContent;
|
|
17507
17652
|
const wasTruncated = decoded.isTruncated || wasCharacterTruncated;
|
|
17508
17653
|
if (wasCharacterTruncated) {
|
|
@@ -25804,11 +25949,19 @@
|
|
|
25804
25949
|
* Pattern matching punctuation that should be trimmed from citation tails.
|
|
25805
25950
|
*/
|
|
25806
25951
|
const TRAILING_PUNCTUATION_REGEX = /[.,;:!?)+\]]+$/;
|
|
25952
|
+
/**
|
|
25953
|
+
* Pattern matching filename separators that should become spaces in source labels.
|
|
25954
|
+
*/
|
|
25955
|
+
const FILENAME_SEPARATOR_REGEX = /[-_]+/g;
|
|
25956
|
+
/**
|
|
25957
|
+
* Pattern matching consecutive whitespace in display labels.
|
|
25958
|
+
*/
|
|
25959
|
+
const WHITESPACE_REGEX = /\s+/g;
|
|
25807
25960
|
/**
|
|
25808
25961
|
* Collapses consecutive whitespace into single spaces.
|
|
25809
25962
|
*/
|
|
25810
25963
|
function collapseWhitespace(value) {
|
|
25811
|
-
return value.replace(
|
|
25964
|
+
return value.replace(WHITESPACE_REGEX, ' ');
|
|
25812
25965
|
}
|
|
25813
25966
|
/**
|
|
25814
25967
|
* Trims a value before further citation normalization.
|
|
@@ -25881,6 +26034,10 @@
|
|
|
25881
26034
|
* @private utility of `<Chat/>` citation rendering
|
|
25882
26035
|
*/
|
|
25883
26036
|
function getCitationLabel(citation) {
|
|
26037
|
+
const title = normalizeCitationDisplayLabel(citation.title);
|
|
26038
|
+
if (title) {
|
|
26039
|
+
return title;
|
|
26040
|
+
}
|
|
25884
26041
|
const trimmed = trimToNormalized(citation.source);
|
|
25885
26042
|
if (!trimmed) {
|
|
25886
26043
|
return citation.source;
|
|
@@ -25892,7 +26049,7 @@
|
|
|
25892
26049
|
}
|
|
25893
26050
|
return collapsed.slice(0, TEXT_LABEL_LENGTH) + LABEL_ELLIPSIS;
|
|
25894
26051
|
}
|
|
25895
|
-
return
|
|
26052
|
+
return createReadableCitationSourceLabel(trimmed);
|
|
25896
26053
|
}
|
|
25897
26054
|
/**
|
|
25898
26055
|
* Resolves the preview URL used inside the citation modal iframe.
|
|
@@ -25911,8 +26068,134 @@
|
|
|
25911
26068
|
const knowledgeUrl = resolveCitationUrl(trimmed, participants);
|
|
25912
26069
|
return explicitUrl || literalUrl || knowledgeUrl || null;
|
|
25913
26070
|
}
|
|
26071
|
+
/**
|
|
26072
|
+
* Creates a readable fallback label from a citation source when no title metadata is available.
|
|
26073
|
+
*
|
|
26074
|
+
* @param source - Raw citation source value.
|
|
26075
|
+
* @returns Human-friendly source label.
|
|
26076
|
+
*
|
|
26077
|
+
* @private utility of `<Chat/>` citation rendering
|
|
26078
|
+
*/
|
|
26079
|
+
function createReadableCitationSourceLabel(source) {
|
|
26080
|
+
const trimmed = trimToNormalized(source);
|
|
26081
|
+
if (!trimmed) {
|
|
26082
|
+
return source;
|
|
26083
|
+
}
|
|
26084
|
+
const parsedUrl = parseCitationUrl(trimmed);
|
|
26085
|
+
const filenameCandidate = parsedUrl
|
|
26086
|
+
? getUrlLabelCandidate(parsedUrl) || parsedUrl.hostname.replace(/^www\./i, '')
|
|
26087
|
+
: simplifyKnowledgeLabel(trimmed);
|
|
26088
|
+
return normalizeCitationDisplayLabel(filenameCandidate) || simplifyKnowledgeLabel(trimmed);
|
|
26089
|
+
}
|
|
26090
|
+
/**
|
|
26091
|
+
* Normalizes a citation label candidate for display.
|
|
26092
|
+
*
|
|
26093
|
+
* @param label - Raw candidate label.
|
|
26094
|
+
* @returns Cleaned label or `null` when empty.
|
|
26095
|
+
*
|
|
26096
|
+
* @private utility of `<Chat/>` citation rendering
|
|
26097
|
+
*/
|
|
26098
|
+
function normalizeCitationDisplayLabel(label) {
|
|
26099
|
+
const normalized = collapseWhitespace((label || '').replace(FILENAME_SEPARATOR_REGEX, ' ')).trim();
|
|
26100
|
+
return normalized || null;
|
|
26101
|
+
}
|
|
26102
|
+
/**
|
|
26103
|
+
* Parses one HTTP(S) citation URL, returning null for non-URL values.
|
|
26104
|
+
*
|
|
26105
|
+
* @param value - Candidate URL value.
|
|
26106
|
+
* @returns Parsed URL or null.
|
|
26107
|
+
*
|
|
26108
|
+
* @private utility of `<Chat/>` citation rendering
|
|
26109
|
+
*/
|
|
26110
|
+
function parseCitationUrl(value) {
|
|
26111
|
+
try {
|
|
26112
|
+
const url = new URL(value);
|
|
26113
|
+
return url.protocol === 'http:' || url.protocol === 'https:' ? url : null;
|
|
26114
|
+
}
|
|
26115
|
+
catch (_a) {
|
|
26116
|
+
return null;
|
|
26117
|
+
}
|
|
26118
|
+
}
|
|
26119
|
+
/**
|
|
26120
|
+
* Extracts a readable candidate from a URL path.
|
|
26121
|
+
*
|
|
26122
|
+
* @param url - Parsed citation URL.
|
|
26123
|
+
* @returns URL path label candidate or null.
|
|
26124
|
+
*
|
|
26125
|
+
* @private utility of `<Chat/>` citation rendering
|
|
26126
|
+
*/
|
|
26127
|
+
function getUrlLabelCandidate(url) {
|
|
26128
|
+
const pathSegments = url.pathname.split('/').filter(Boolean);
|
|
26129
|
+
const lastPathSegment = pathSegments[pathSegments.length - 1];
|
|
26130
|
+
if (!lastPathSegment) {
|
|
26131
|
+
return null;
|
|
26132
|
+
}
|
|
26133
|
+
try {
|
|
26134
|
+
return simplifyKnowledgeLabel(decodeURIComponent(lastPathSegment));
|
|
26135
|
+
}
|
|
26136
|
+
catch (_a) {
|
|
26137
|
+
return simplifyKnowledgeLabel(lastPathSegment);
|
|
26138
|
+
}
|
|
26139
|
+
}
|
|
25914
26140
|
// TODO: [💞] Spread into multiple files
|
|
25915
26141
|
|
|
26142
|
+
/**
|
|
26143
|
+
* Extracts one quick button definition from a markdown link query string.
|
|
26144
|
+
*
|
|
26145
|
+
* @param text The visible button label.
|
|
26146
|
+
* @param query Raw query-string payload captured from markdown.
|
|
26147
|
+
* @returns Parsed quick button definition or `null` when the link is not a supported quick button.
|
|
26148
|
+
*
|
|
26149
|
+
* @private internal helper of `parseMessageButtons`
|
|
26150
|
+
*/
|
|
26151
|
+
function parseQuickButtonDefinition(text, query) {
|
|
26152
|
+
const searchParams = new URLSearchParams(query);
|
|
26153
|
+
const message = searchParams.get('message');
|
|
26154
|
+
if (message !== null) {
|
|
26155
|
+
return {
|
|
26156
|
+
type: 'message',
|
|
26157
|
+
text,
|
|
26158
|
+
message,
|
|
26159
|
+
};
|
|
26160
|
+
}
|
|
26161
|
+
const code = searchParams.get('action');
|
|
26162
|
+
if (code !== null) {
|
|
26163
|
+
return {
|
|
26164
|
+
type: 'action',
|
|
26165
|
+
text,
|
|
26166
|
+
code,
|
|
26167
|
+
};
|
|
26168
|
+
}
|
|
26169
|
+
return null;
|
|
26170
|
+
}
|
|
26171
|
+
/**
|
|
26172
|
+
* Parses markdown quick buttons in the format `[Button Text](?message=...)` or `[Button Text](?action=...)`.
|
|
26173
|
+
* Returns both the content without supported quick buttons and the extracted button definitions.
|
|
26174
|
+
*
|
|
26175
|
+
* @param content The markdown content that may contain buttons
|
|
26176
|
+
* @returns Object with contentWithoutButtons and buttons array
|
|
26177
|
+
*
|
|
26178
|
+
* @public exported from `@promptbook/components`
|
|
26179
|
+
*/
|
|
26180
|
+
function parseMessageButtons(content) {
|
|
26181
|
+
const buttonRegex = /\[([^\]]+)\]\(\?([^)]+)\)/g;
|
|
26182
|
+
const buttons = [];
|
|
26183
|
+
const contentWithoutButtons = content
|
|
26184
|
+
.replace(buttonRegex, (match, text, query) => {
|
|
26185
|
+
const button = parseQuickButtonDefinition(text, query);
|
|
26186
|
+
if (!button) {
|
|
26187
|
+
return match;
|
|
26188
|
+
}
|
|
26189
|
+
buttons.push(button);
|
|
26190
|
+
return '';
|
|
26191
|
+
})
|
|
26192
|
+
.trim();
|
|
26193
|
+
return {
|
|
26194
|
+
contentWithoutButtons,
|
|
26195
|
+
buttons,
|
|
26196
|
+
};
|
|
26197
|
+
}
|
|
26198
|
+
|
|
25916
26199
|
/**
|
|
25917
26200
|
* Default citation identifier used for simplified citation markers without an explicit position.
|
|
25918
26201
|
*
|
|
@@ -26803,12 +27086,13 @@
|
|
|
26803
27086
|
* @private utility of `<Chat/>`
|
|
26804
27087
|
*/
|
|
26805
27088
|
function normalizeParsedCitation(citation) {
|
|
26806
|
-
var _a, _b;
|
|
27089
|
+
var _a, _b, _c;
|
|
26807
27090
|
return {
|
|
26808
27091
|
id: citation.id.trim(),
|
|
26809
27092
|
source: citation.source.trim(),
|
|
26810
27093
|
url: ((_a = citation.url) === null || _a === void 0 ? void 0 : _a.trim()) || undefined,
|
|
26811
|
-
|
|
27094
|
+
title: ((_b = citation.title) === null || _b === void 0 ? void 0 : _b.trim()) || undefined,
|
|
27095
|
+
excerpt: ((_c = citation.excerpt) === null || _c === void 0 ? void 0 : _c.trim()) || undefined,
|
|
26812
27096
|
};
|
|
26813
27097
|
}
|
|
26814
27098
|
/**
|
|
@@ -26825,11 +27109,13 @@
|
|
|
26825
27109
|
id: currentCitation.id || incomingCitation.id,
|
|
26826
27110
|
source: resolvePreferredCitationSource(currentCitation, incomingCitation),
|
|
26827
27111
|
url: currentCitation.url || incomingCitation.url,
|
|
27112
|
+
title: currentCitation.title || incomingCitation.title,
|
|
26828
27113
|
excerpt: currentCitation.excerpt || incomingCitation.excerpt,
|
|
26829
27114
|
};
|
|
26830
27115
|
if (mergedCitation.id === currentCitation.id &&
|
|
26831
27116
|
mergedCitation.source === currentCitation.source &&
|
|
26832
27117
|
mergedCitation.url === currentCitation.url &&
|
|
27118
|
+
mergedCitation.title === currentCitation.title &&
|
|
26833
27119
|
mergedCitation.excerpt === currentCitation.excerpt) {
|
|
26834
27120
|
return currentCitation;
|
|
26835
27121
|
}
|
|
@@ -27179,6 +27465,12 @@
|
|
|
27179
27465
|
* @private Internal helper shared by HTML and PDF chat exports.
|
|
27180
27466
|
*/
|
|
27181
27467
|
const CHAT_HTML_EXPORT_RENDER_ROOT_CLASS_NAME = 'chat-html-export-render-root';
|
|
27468
|
+
/**
|
|
27469
|
+
* Roles whose messages are aligned to the right side of the exported transcript.
|
|
27470
|
+
*
|
|
27471
|
+
* @private Internal helper of `htmlSaveFormatDefinition`.
|
|
27472
|
+
*/
|
|
27473
|
+
const RIGHT_ALIGNED_SENDER_ROLES = new Set(['USER']);
|
|
27182
27474
|
/**
|
|
27183
27475
|
* Escapes HTML-sensitive text before embedding it into the export document.
|
|
27184
27476
|
*
|
|
@@ -27192,6 +27484,38 @@
|
|
|
27192
27484
|
.replace(/"/g, '"')
|
|
27193
27485
|
.replace(/'/g, ''');
|
|
27194
27486
|
}
|
|
27487
|
+
/**
|
|
27488
|
+
* Returns the first uppercase character of a display name, used for the fallback avatar glyph.
|
|
27489
|
+
*
|
|
27490
|
+
* @private Internal helper of `htmlSaveFormatDefinition`.
|
|
27491
|
+
*/
|
|
27492
|
+
function getAvatarInitial(displayName) {
|
|
27493
|
+
const trimmedName = displayName.trim();
|
|
27494
|
+
if (!trimmedName) {
|
|
27495
|
+
return '?';
|
|
27496
|
+
}
|
|
27497
|
+
return Array.from(trimmedName)[0].toUpperCase();
|
|
27498
|
+
}
|
|
27499
|
+
/**
|
|
27500
|
+
* Renders the avatar bubble shown next to one exported message.
|
|
27501
|
+
*
|
|
27502
|
+
* @private Internal helper of `htmlSaveFormatDefinition`.
|
|
27503
|
+
*/
|
|
27504
|
+
function buildAvatarMarkup(participant, displayName, accentColor) {
|
|
27505
|
+
const avatarStyle = `background-color:${escapeHtml$1(accentColor)};`;
|
|
27506
|
+
if (participant === null || participant === void 0 ? void 0 : participant.avatarSrc) {
|
|
27507
|
+
return spacetrim.spaceTrim(`
|
|
27508
|
+
<div class="message-avatar" aria-hidden="true" style="${avatarStyle}">
|
|
27509
|
+
<img src="${escapeHtml$1(participant.avatarSrc)}" alt="" loading="lazy" />
|
|
27510
|
+
</div>
|
|
27511
|
+
`);
|
|
27512
|
+
}
|
|
27513
|
+
return spacetrim.spaceTrim(`
|
|
27514
|
+
<div class="message-avatar message-avatar--initial" aria-hidden="true" style="${avatarStyle}">
|
|
27515
|
+
<span>${escapeHtml$1(getAvatarInitial(displayName))}</span>
|
|
27516
|
+
</div>
|
|
27517
|
+
`);
|
|
27518
|
+
}
|
|
27195
27519
|
/**
|
|
27196
27520
|
* Renders attachments for one exported message as a compact supporting section.
|
|
27197
27521
|
*
|
|
@@ -27255,13 +27579,26 @@
|
|
|
27255
27579
|
</section>
|
|
27256
27580
|
`);
|
|
27257
27581
|
}
|
|
27582
|
+
/**
|
|
27583
|
+
* Removes quick action and quick message buttons from the markdown body before rendering.
|
|
27584
|
+
*
|
|
27585
|
+
* Quick buttons are interactive UI affordances and have no meaning inside a static export.
|
|
27586
|
+
*
|
|
27587
|
+
* @private Internal helper of `htmlSaveFormatDefinition`.
|
|
27588
|
+
*/
|
|
27589
|
+
function stripQuickButtonsFromContent(content) {
|
|
27590
|
+
return parseMessageButtons(content).contentWithoutButtons;
|
|
27591
|
+
}
|
|
27258
27592
|
/**
|
|
27259
27593
|
* Converts one markdown message body to HTML with document-wide source references.
|
|
27260
27594
|
*
|
|
27261
27595
|
* @private Internal helper of `htmlSaveFormatDefinition`.
|
|
27262
27596
|
*/
|
|
27263
27597
|
function renderFootnotedMarkdown(message, citationFootnotes) {
|
|
27264
|
-
const renderModel = createChatExportCitationRenderModel(citationFootnotes,
|
|
27598
|
+
const renderModel = createChatExportCitationRenderModel(citationFootnotes, {
|
|
27599
|
+
...message,
|
|
27600
|
+
content: stripQuickButtonsFromContent(message.content),
|
|
27601
|
+
});
|
|
27265
27602
|
const html = linkCitationFootnoteReferences(renderMarkdown(renderModel.content));
|
|
27266
27603
|
return {
|
|
27267
27604
|
html,
|
|
@@ -27299,34 +27636,74 @@
|
|
|
27299
27636
|
`);
|
|
27300
27637
|
}
|
|
27301
27638
|
/**
|
|
27302
|
-
*
|
|
27639
|
+
* Determines whether a message bubble should sit on the right side of the transcript.
|
|
27640
|
+
*
|
|
27641
|
+
* @private Internal helper of `htmlSaveFormatDefinition`.
|
|
27642
|
+
*/
|
|
27643
|
+
function isRightAlignedMessage(participant, sender) {
|
|
27644
|
+
if ((participant === null || participant === void 0 ? void 0 : participant.isMe) === true) {
|
|
27645
|
+
return true;
|
|
27646
|
+
}
|
|
27647
|
+
return RIGHT_ALIGNED_SENDER_ROLES.has(sender.toUpperCase());
|
|
27648
|
+
}
|
|
27649
|
+
/**
|
|
27650
|
+
* Detects whether a message would render with no body, attachments, or supporting metadata after sanitization.
|
|
27651
|
+
*
|
|
27652
|
+
* Such messages exist only to carry quick buttons in the live chat UI and add no value to a printed transcript.
|
|
27653
|
+
*
|
|
27654
|
+
* @private Internal helper of `htmlSaveFormatDefinition`.
|
|
27655
|
+
*/
|
|
27656
|
+
function isMessageEmptyForExport(message) {
|
|
27657
|
+
const trimmedContent = stripQuickButtonsFromContent(message.content).trim();
|
|
27658
|
+
if (trimmedContent.length > 0) {
|
|
27659
|
+
return false;
|
|
27660
|
+
}
|
|
27661
|
+
if (message.attachments && message.attachments.length > 0) {
|
|
27662
|
+
return false;
|
|
27663
|
+
}
|
|
27664
|
+
if (message.citations && message.citations.length > 0) {
|
|
27665
|
+
return false;
|
|
27666
|
+
}
|
|
27667
|
+
if (message.replyingTo) {
|
|
27668
|
+
return false;
|
|
27669
|
+
}
|
|
27670
|
+
return true;
|
|
27671
|
+
}
|
|
27672
|
+
/**
|
|
27673
|
+
* Renders one message bubble for the standalone HTML export.
|
|
27303
27674
|
*
|
|
27304
27675
|
* @private Internal helper of `htmlSaveFormatDefinition`.
|
|
27305
27676
|
*/
|
|
27306
27677
|
function renderMessageBlock(message, participants, citationFootnotes) {
|
|
27678
|
+
var _a;
|
|
27307
27679
|
const sender = String(message.sender || 'SYSTEM');
|
|
27308
|
-
const
|
|
27680
|
+
const participant = (_a = participants.get(sender)) !== null && _a !== void 0 ? _a : participants.get(sender.toUpperCase());
|
|
27309
27681
|
const visuals = resolveChatExportParticipantVisuals(participants, sender);
|
|
27310
27682
|
const timestamp = formatChatExportTimestamp(message.createdAt);
|
|
27311
27683
|
const durationLabel = typeof message.generationDurationMs === 'number' ? `${(message.generationDurationMs / 1000).toFixed(1)}s` : '';
|
|
27312
27684
|
const replyingToMarkup = buildReplyingToMarkup(message, citationFootnotes);
|
|
27313
27685
|
const { html: messageBody, renderModel } = renderFootnotedMarkdown(message, citationFootnotes);
|
|
27686
|
+
const isRightAligned = isRightAlignedMessage(participant, sender);
|
|
27687
|
+
const avatarMarkup = buildAvatarMarkup(participant, visuals.displayName, visuals.accentColor);
|
|
27688
|
+
const alignmentClass = isRightAligned ? 'message--mine' : 'message--theirs';
|
|
27314
27689
|
return spacetrim.spaceTrim(`
|
|
27315
|
-
<article class="message
|
|
27316
|
-
|
|
27317
|
-
|
|
27690
|
+
<article class="message ${alignmentClass}" style="--message-accent:${escapeHtml$1(visuals.accentColor)};">
|
|
27691
|
+
${avatarMarkup}
|
|
27692
|
+
<div class="message-body">
|
|
27693
|
+
<header class="message-meta">
|
|
27318
27694
|
<span class="message-sender">${escapeHtml$1(visuals.displayName)}</span>
|
|
27319
|
-
|
|
27695
|
+
${timestamp ? `<time class="message-time">${escapeHtml$1(timestamp)}</time>` : ''}
|
|
27696
|
+
</header>
|
|
27697
|
+
<div class="message-bubble">
|
|
27698
|
+
${replyingToMarkup}
|
|
27699
|
+
<div class="message-content markdown-content">
|
|
27700
|
+
${messageBody || '<p class="message-empty">No text provided.</p>'}
|
|
27701
|
+
</div>
|
|
27320
27702
|
</div>
|
|
27321
|
-
${
|
|
27322
|
-
|
|
27323
|
-
|
|
27324
|
-
|
|
27325
|
-
${messageBody || '<p class="message-empty">No text provided.</p>'}
|
|
27326
|
-
</section>
|
|
27327
|
-
${durationLabel ? `<p class="message-duration">Responded in ${escapeHtml$1(durationLabel)}</p>` : ''}
|
|
27328
|
-
${buildAttachmentsMarkup(message)}
|
|
27329
|
-
${renderModel.footnotes.length === 0 ? buildCitationsMarkup(message) : ''}
|
|
27703
|
+
${durationLabel ? `<p class="message-footnote">Responded in ${escapeHtml$1(durationLabel)}</p>` : ''}
|
|
27704
|
+
${buildAttachmentsMarkup(message)}
|
|
27705
|
+
${renderModel.footnotes.length === 0 ? buildCitationsMarkup(message) : ''}
|
|
27706
|
+
</div>
|
|
27330
27707
|
</article>
|
|
27331
27708
|
`);
|
|
27332
27709
|
}
|
|
@@ -27390,8 +27767,11 @@
|
|
|
27390
27767
|
const participantLookup = buildChatExportParticipantMap(participants);
|
|
27391
27768
|
const citationFootnotes = createChatExportCitationFootnoteRegistry();
|
|
27392
27769
|
const exportedLabel = formatChatExportTimestamp(new Date());
|
|
27393
|
-
const
|
|
27394
|
-
|
|
27770
|
+
const messagesForExport = messages.filter((message) => !isMessageEmptyForExport(message));
|
|
27771
|
+
const messageMarkup = messagesForExport.length > 0
|
|
27772
|
+
? messagesForExport
|
|
27773
|
+
.map((message) => renderMessageBlock(message, participantLookup, citationFootnotes))
|
|
27774
|
+
.join('')
|
|
27395
27775
|
: '<div class="empty-state">No messages were available in this chat export.</div>';
|
|
27396
27776
|
const documentSourcesMarkup = buildDocumentSourcesMarkup(citationFootnotes, participants);
|
|
27397
27777
|
return spacetrim.spaceTrim(`
|
|
@@ -27405,6 +27785,17 @@
|
|
|
27405
27785
|
<style>
|
|
27406
27786
|
:root {
|
|
27407
27787
|
color-scheme: light;
|
|
27788
|
+
--chat-export-background: #f4f6fb;
|
|
27789
|
+
--chat-export-surface: #ffffff;
|
|
27790
|
+
--chat-export-text: #0f172a;
|
|
27791
|
+
--chat-export-muted: #64748b;
|
|
27792
|
+
--chat-export-soft-border: #e2e8f0;
|
|
27793
|
+
--chat-export-bubble-theirs-bg: #ffffff;
|
|
27794
|
+
--chat-export-bubble-theirs-text: #0f172a;
|
|
27795
|
+
--chat-export-bubble-theirs-border: #e2e8f0;
|
|
27796
|
+
--chat-export-bubble-mine-bg: #115EB6;
|
|
27797
|
+
--chat-export-bubble-mine-text: #ffffff;
|
|
27798
|
+
--chat-export-link: #0f6cbd;
|
|
27408
27799
|
}
|
|
27409
27800
|
|
|
27410
27801
|
* {
|
|
@@ -27414,25 +27805,27 @@
|
|
|
27414
27805
|
body,
|
|
27415
27806
|
.${CHAT_HTML_EXPORT_RENDER_ROOT_CLASS_NAME} {
|
|
27416
27807
|
margin: 0;
|
|
27417
|
-
background:
|
|
27418
|
-
color:
|
|
27419
|
-
font-family: Inter, "Segoe UI", Arial, sans-serif;
|
|
27808
|
+
background: var(--chat-export-background);
|
|
27809
|
+
color: var(--chat-export-text);
|
|
27810
|
+
font-family: Inter, "Segoe UI", system-ui, -apple-system, Arial, sans-serif;
|
|
27811
|
+
font-size: 15px;
|
|
27812
|
+
line-height: 1.55;
|
|
27420
27813
|
}
|
|
27421
27814
|
|
|
27422
27815
|
a {
|
|
27423
|
-
color:
|
|
27816
|
+
color: var(--chat-export-link);
|
|
27424
27817
|
}
|
|
27425
27818
|
|
|
27426
27819
|
.document {
|
|
27427
|
-
max-width:
|
|
27820
|
+
max-width: 820px;
|
|
27428
27821
|
margin: 0 auto;
|
|
27429
|
-
padding:
|
|
27822
|
+
padding: 40px 24px 56px;
|
|
27430
27823
|
}
|
|
27431
27824
|
|
|
27432
27825
|
.document-header {
|
|
27433
|
-
margin-bottom:
|
|
27434
|
-
padding-bottom:
|
|
27435
|
-
border-bottom: 1px solid
|
|
27826
|
+
margin-bottom: 28px;
|
|
27827
|
+
padding-bottom: 18px;
|
|
27828
|
+
border-bottom: 1px solid var(--chat-export-soft-border);
|
|
27436
27829
|
}
|
|
27437
27830
|
|
|
27438
27831
|
.document-eyebrow {
|
|
@@ -27440,7 +27833,7 @@
|
|
|
27440
27833
|
font-size: 11px;
|
|
27441
27834
|
letter-spacing: 0.14em;
|
|
27442
27835
|
text-transform: uppercase;
|
|
27443
|
-
color:
|
|
27836
|
+
color: var(--chat-export-muted);
|
|
27444
27837
|
}
|
|
27445
27838
|
|
|
27446
27839
|
.document-title {
|
|
@@ -27451,89 +27844,174 @@
|
|
|
27451
27844
|
|
|
27452
27845
|
.document-meta {
|
|
27453
27846
|
margin: 10px 0 0;
|
|
27454
|
-
color:
|
|
27455
|
-
font-size:
|
|
27847
|
+
color: var(--chat-export-muted);
|
|
27848
|
+
font-size: 13px;
|
|
27456
27849
|
}
|
|
27457
27850
|
|
|
27458
27851
|
.message-list {
|
|
27459
27852
|
display: flex;
|
|
27460
27853
|
flex-direction: column;
|
|
27461
|
-
gap:
|
|
27854
|
+
gap: 22px;
|
|
27462
27855
|
}
|
|
27463
27856
|
|
|
27464
|
-
.message
|
|
27465
|
-
background: #ffffff;
|
|
27466
|
-
border: 1px solid #dbe4f0;
|
|
27467
|
-
border-left-width: 4px;
|
|
27468
|
-
border-left-color: var(--message-accent, #64748b);
|
|
27469
|
-
border-radius: 14px;
|
|
27470
|
-
padding: 16px 18px;
|
|
27471
|
-
}
|
|
27472
|
-
|
|
27473
|
-
.message-header {
|
|
27857
|
+
.message {
|
|
27474
27858
|
display: flex;
|
|
27475
|
-
justify-content: space-between;
|
|
27476
27859
|
align-items: flex-start;
|
|
27477
27860
|
gap: 12px;
|
|
27478
|
-
margin-bottom: 12px;
|
|
27479
27861
|
}
|
|
27480
27862
|
|
|
27481
|
-
.message
|
|
27863
|
+
.message--mine {
|
|
27864
|
+
flex-direction: row-reverse;
|
|
27865
|
+
}
|
|
27866
|
+
|
|
27867
|
+
.message-avatar {
|
|
27868
|
+
flex-shrink: 0;
|
|
27869
|
+
width: 40px;
|
|
27870
|
+
height: 40px;
|
|
27871
|
+
border-radius: 50%;
|
|
27872
|
+
overflow: hidden;
|
|
27873
|
+
background-color: var(--message-accent, #64748b);
|
|
27874
|
+
color: #ffffff;
|
|
27482
27875
|
display: flex;
|
|
27483
|
-
flex-wrap: wrap;
|
|
27484
27876
|
align-items: center;
|
|
27877
|
+
justify-content: center;
|
|
27878
|
+
}
|
|
27879
|
+
|
|
27880
|
+
.message-avatar img {
|
|
27881
|
+
width: 100%;
|
|
27882
|
+
height: 100%;
|
|
27883
|
+
object-fit: cover;
|
|
27884
|
+
display: block;
|
|
27885
|
+
}
|
|
27886
|
+
|
|
27887
|
+
.message-avatar--initial span {
|
|
27888
|
+
font-size: 16px;
|
|
27889
|
+
font-weight: 600;
|
|
27890
|
+
line-height: 1;
|
|
27891
|
+
}
|
|
27892
|
+
|
|
27893
|
+
.message-body {
|
|
27894
|
+
flex: 1 1 auto;
|
|
27895
|
+
min-width: 0;
|
|
27896
|
+
max-width: 78%;
|
|
27897
|
+
display: flex;
|
|
27898
|
+
flex-direction: column;
|
|
27899
|
+
gap: 6px;
|
|
27900
|
+
}
|
|
27901
|
+
|
|
27902
|
+
.message--mine .message-body {
|
|
27903
|
+
align-items: flex-end;
|
|
27904
|
+
}
|
|
27905
|
+
|
|
27906
|
+
.message-meta {
|
|
27907
|
+
display: flex;
|
|
27908
|
+
flex-wrap: wrap;
|
|
27909
|
+
align-items: baseline;
|
|
27485
27910
|
gap: 8px;
|
|
27911
|
+
padding: 0 4px;
|
|
27912
|
+
}
|
|
27913
|
+
|
|
27914
|
+
.message--mine .message-meta {
|
|
27915
|
+
justify-content: flex-end;
|
|
27486
27916
|
}
|
|
27487
27917
|
|
|
27488
27918
|
.message-sender {
|
|
27489
|
-
font-size:
|
|
27919
|
+
font-size: 13px;
|
|
27490
27920
|
font-weight: 600;
|
|
27491
|
-
color: var(--message-accent,
|
|
27921
|
+
color: var(--message-accent, var(--chat-export-text));
|
|
27922
|
+
}
|
|
27923
|
+
|
|
27924
|
+
.message--mine .message-sender {
|
|
27925
|
+
color: var(--chat-export-text);
|
|
27492
27926
|
}
|
|
27493
27927
|
|
|
27494
|
-
.message-
|
|
27928
|
+
.message-time {
|
|
27495
27929
|
font-size: 11px;
|
|
27496
|
-
|
|
27497
|
-
text-transform: uppercase;
|
|
27498
|
-
color: #64748b;
|
|
27930
|
+
color: var(--chat-export-muted);
|
|
27499
27931
|
}
|
|
27500
27932
|
|
|
27501
|
-
.message-
|
|
27502
|
-
|
|
27503
|
-
|
|
27504
|
-
|
|
27933
|
+
.message-bubble {
|
|
27934
|
+
padding: 14px 16px;
|
|
27935
|
+
border-radius: 16px;
|
|
27936
|
+
background: var(--chat-export-bubble-theirs-bg);
|
|
27937
|
+
color: var(--chat-export-bubble-theirs-text);
|
|
27938
|
+
border: 1px solid var(--chat-export-bubble-theirs-border);
|
|
27939
|
+
border-top-left-radius: 4px;
|
|
27940
|
+
box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
|
|
27941
|
+
max-width: 100%;
|
|
27942
|
+
overflow-wrap: anywhere;
|
|
27943
|
+
}
|
|
27944
|
+
|
|
27945
|
+
.message--mine .message-bubble {
|
|
27946
|
+
background: var(--chat-export-bubble-mine-bg);
|
|
27947
|
+
color: var(--chat-export-bubble-mine-text);
|
|
27948
|
+
border-color: transparent;
|
|
27949
|
+
border-top-left-radius: 16px;
|
|
27950
|
+
border-top-right-radius: 4px;
|
|
27951
|
+
}
|
|
27952
|
+
|
|
27953
|
+
.message--mine .message-bubble a {
|
|
27954
|
+
color: #d4e8ff;
|
|
27955
|
+
}
|
|
27956
|
+
|
|
27957
|
+
.message--mine .message-bubble code {
|
|
27958
|
+
background: rgba(255, 255, 255, 0.18);
|
|
27959
|
+
color: inherit;
|
|
27505
27960
|
}
|
|
27506
27961
|
|
|
27507
|
-
.message-
|
|
27508
|
-
|
|
27962
|
+
.message--mine .message-bubble pre {
|
|
27963
|
+
background: rgba(15, 23, 42, 0.35);
|
|
27964
|
+
color: #f8fafc;
|
|
27965
|
+
}
|
|
27966
|
+
|
|
27967
|
+
.message--mine .message-bubble blockquote {
|
|
27968
|
+
color: rgba(255, 255, 255, 0.85);
|
|
27969
|
+
border-color: rgba(255, 255, 255, 0.5);
|
|
27970
|
+
}
|
|
27971
|
+
|
|
27972
|
+
.message-footnote {
|
|
27973
|
+
margin: 2px 4px 0;
|
|
27974
|
+
font-size: 11px;
|
|
27975
|
+
color: var(--chat-export-muted);
|
|
27509
27976
|
}
|
|
27510
27977
|
|
|
27511
27978
|
.message-empty {
|
|
27512
|
-
color:
|
|
27979
|
+
color: var(--chat-export-muted);
|
|
27513
27980
|
font-style: italic;
|
|
27981
|
+
margin: 0;
|
|
27514
27982
|
}
|
|
27515
27983
|
|
|
27516
27984
|
.reply-context {
|
|
27517
|
-
margin
|
|
27518
|
-
padding: 12px
|
|
27985
|
+
margin: 0 0 10px;
|
|
27986
|
+
padding: 8px 12px;
|
|
27519
27987
|
border-radius: 10px;
|
|
27520
|
-
border:
|
|
27521
|
-
background:
|
|
27988
|
+
border-left: 3px solid var(--message-accent, #cbd5e1);
|
|
27989
|
+
background: rgba(15, 23, 42, 0.04);
|
|
27990
|
+
}
|
|
27991
|
+
|
|
27992
|
+
.message--mine .reply-context {
|
|
27993
|
+
background: rgba(255, 255, 255, 0.18);
|
|
27994
|
+
border-left-color: rgba(255, 255, 255, 0.7);
|
|
27522
27995
|
}
|
|
27523
27996
|
|
|
27524
27997
|
.reply-context-title,
|
|
27525
27998
|
.message-supporting-title {
|
|
27526
|
-
margin-bottom:
|
|
27999
|
+
margin-bottom: 6px;
|
|
27527
28000
|
font-size: 11px;
|
|
27528
|
-
letter-spacing: 0.
|
|
28001
|
+
letter-spacing: 0.1em;
|
|
27529
28002
|
text-transform: uppercase;
|
|
27530
|
-
color:
|
|
28003
|
+
color: var(--chat-export-muted);
|
|
28004
|
+
}
|
|
28005
|
+
|
|
28006
|
+
.message--mine .reply-context-title {
|
|
28007
|
+
color: rgba(255, 255, 255, 0.8);
|
|
27531
28008
|
}
|
|
27532
28009
|
|
|
27533
28010
|
.message-supporting-list {
|
|
27534
|
-
margin-top:
|
|
27535
|
-
padding
|
|
27536
|
-
border-
|
|
28011
|
+
margin-top: 10px;
|
|
28012
|
+
padding: 10px 14px;
|
|
28013
|
+
border-radius: 10px;
|
|
28014
|
+
background: rgba(15, 23, 42, 0.03);
|
|
27537
28015
|
}
|
|
27538
28016
|
|
|
27539
28017
|
.message-supporting-list ul {
|
|
@@ -27543,18 +28021,14 @@
|
|
|
27543
28021
|
|
|
27544
28022
|
.message-supporting-meta {
|
|
27545
28023
|
margin-right: 6px;
|
|
27546
|
-
color:
|
|
28024
|
+
color: var(--chat-export-muted);
|
|
27547
28025
|
font-size: 12px;
|
|
27548
28026
|
}
|
|
27549
28027
|
|
|
27550
28028
|
.message-supporting-excerpt {
|
|
27551
|
-
margin-top:
|
|
28029
|
+
margin-top: 4px;
|
|
27552
28030
|
color: #475569;
|
|
27553
|
-
|
|
27554
|
-
|
|
27555
|
-
.markdown-content {
|
|
27556
|
-
font-size: 15px;
|
|
27557
|
-
line-height: 1.65;
|
|
28031
|
+
font-size: 13px;
|
|
27558
28032
|
}
|
|
27559
28033
|
|
|
27560
28034
|
.markdown-content > *:first-child {
|
|
@@ -27582,7 +28056,7 @@
|
|
|
27582
28056
|
.markdown-content pre,
|
|
27583
28057
|
.markdown-content table,
|
|
27584
28058
|
.markdown-content details {
|
|
27585
|
-
margin: 0 0
|
|
28059
|
+
margin: 0 0 12px;
|
|
27586
28060
|
}
|
|
27587
28061
|
|
|
27588
28062
|
.markdown-content ul,
|
|
@@ -27592,7 +28066,7 @@
|
|
|
27592
28066
|
|
|
27593
28067
|
.markdown-content code {
|
|
27594
28068
|
font-family: ui-monospace, "SFMono-Regular", monospace;
|
|
27595
|
-
background:
|
|
28069
|
+
background: rgba(15, 23, 42, 0.06);
|
|
27596
28070
|
border-radius: 4px;
|
|
27597
28071
|
padding: 1px 5px;
|
|
27598
28072
|
font-size: 0.94em;
|
|
@@ -27644,7 +28118,7 @@
|
|
|
27644
28118
|
|
|
27645
28119
|
.markdown-content details {
|
|
27646
28120
|
padding: 12px 14px;
|
|
27647
|
-
border: 1px solid
|
|
28121
|
+
border: 1px solid var(--chat-export-soft-border);
|
|
27648
28122
|
border-radius: 10px;
|
|
27649
28123
|
background: #f8fafc;
|
|
27650
28124
|
}
|
|
@@ -27666,7 +28140,7 @@
|
|
|
27666
28140
|
}
|
|
27667
28141
|
|
|
27668
28142
|
.markdown-content sup[data-citation-footnote] a {
|
|
27669
|
-
color:
|
|
28143
|
+
color: inherit;
|
|
27670
28144
|
text-decoration: none;
|
|
27671
28145
|
}
|
|
27672
28146
|
|
|
@@ -27679,14 +28153,14 @@
|
|
|
27679
28153
|
border: 1px dashed #cbd5e1;
|
|
27680
28154
|
border-radius: 14px;
|
|
27681
28155
|
text-align: center;
|
|
27682
|
-
color:
|
|
27683
|
-
background:
|
|
28156
|
+
color: var(--chat-export-muted);
|
|
28157
|
+
background: var(--chat-export-surface);
|
|
27684
28158
|
}
|
|
27685
28159
|
|
|
27686
28160
|
.document-sources {
|
|
27687
|
-
margin-top:
|
|
27688
|
-
padding-top:
|
|
27689
|
-
border-top: 1px solid
|
|
28161
|
+
margin-top: 32px;
|
|
28162
|
+
padding-top: 18px;
|
|
28163
|
+
border-top: 1px solid var(--chat-export-soft-border);
|
|
27690
28164
|
}
|
|
27691
28165
|
|
|
27692
28166
|
.document-sources-title {
|
|
@@ -27712,26 +28186,50 @@
|
|
|
27712
28186
|
}
|
|
27713
28187
|
|
|
27714
28188
|
.document-footer {
|
|
27715
|
-
margin-top:
|
|
28189
|
+
margin-top: 28px;
|
|
27716
28190
|
padding-top: 16px;
|
|
27717
|
-
border-top: 1px solid
|
|
27718
|
-
color:
|
|
28191
|
+
border-top: 1px solid var(--chat-export-soft-border);
|
|
28192
|
+
color: var(--chat-export-muted);
|
|
27719
28193
|
font-size: 12px;
|
|
28194
|
+
text-align: center;
|
|
27720
28195
|
}
|
|
27721
28196
|
|
|
27722
28197
|
.document-footer strong {
|
|
27723
28198
|
color: #475569;
|
|
27724
28199
|
}
|
|
27725
28200
|
|
|
28201
|
+
@page {
|
|
28202
|
+
size: Letter;
|
|
28203
|
+
margin: 0.5in;
|
|
28204
|
+
}
|
|
28205
|
+
|
|
27726
28206
|
@media print {
|
|
27727
|
-
body
|
|
28207
|
+
body,
|
|
28208
|
+
.${CHAT_HTML_EXPORT_RENDER_ROOT_CLASS_NAME} {
|
|
27728
28209
|
background: #ffffff;
|
|
28210
|
+
font-size: 12pt;
|
|
27729
28211
|
}
|
|
27730
28212
|
|
|
27731
28213
|
.document {
|
|
27732
28214
|
max-width: none;
|
|
27733
28215
|
padding: 0;
|
|
27734
28216
|
}
|
|
28217
|
+
|
|
28218
|
+
.message {
|
|
28219
|
+
page-break-inside: avoid;
|
|
28220
|
+
break-inside: avoid;
|
|
28221
|
+
}
|
|
28222
|
+
|
|
28223
|
+
.message-bubble {
|
|
28224
|
+
box-shadow: none;
|
|
28225
|
+
}
|
|
28226
|
+
|
|
28227
|
+
.markdown-content pre,
|
|
28228
|
+
.message-supporting-list,
|
|
28229
|
+
.reply-context {
|
|
28230
|
+
page-break-inside: avoid;
|
|
28231
|
+
break-inside: avoid;
|
|
28232
|
+
}
|
|
27735
28233
|
}
|
|
27736
28234
|
</style>
|
|
27737
28235
|
</head>
|
|
@@ -28197,7 +28695,11 @@
|
|
|
28197
28695
|
*/
|
|
28198
28696
|
function createPromptbookReactExportBrandingComment() {
|
|
28199
28697
|
const branding = getPromptbookExportBranding();
|
|
28200
|
-
return
|
|
28698
|
+
return spacetrim.spaceTrim((block) => `
|
|
28699
|
+
/*
|
|
28700
|
+
${block(branding.commentLines.map((line) => ` * ${line}`).join('\n'))}
|
|
28701
|
+
*/
|
|
28702
|
+
`);
|
|
28201
28703
|
}
|
|
28202
28704
|
/**
|
|
28203
28705
|
* React <jsx/> export plugin (full metadata)
|
|
@@ -28740,6 +29242,54 @@
|
|
|
28740
29242
|
} }));
|
|
28741
29243
|
});
|
|
28742
29244
|
|
|
29245
|
+
/**
|
|
29246
|
+
* Creates a stable key for one citation label lookup.
|
|
29247
|
+
*
|
|
29248
|
+
* @param citation - Citation metadata.
|
|
29249
|
+
* @returns Stable citation key.
|
|
29250
|
+
*
|
|
29251
|
+
* @private hook helper of `<Chat/>`
|
|
29252
|
+
*/
|
|
29253
|
+
function createCitationLabelLookupKey(citation) {
|
|
29254
|
+
return [citation.id, citation.source, citation.url || '', citation.title || '', citation.excerpt || ''].join('\n');
|
|
29255
|
+
}
|
|
29256
|
+
/**
|
|
29257
|
+
* Resolves the best available label for one citation.
|
|
29258
|
+
*
|
|
29259
|
+
* @param citation - Citation metadata.
|
|
29260
|
+
* @param resolveCitationLabel - Optional async host resolver.
|
|
29261
|
+
* @returns Current label, starting with a synchronous fallback and updating when the resolver finishes.
|
|
29262
|
+
*
|
|
29263
|
+
* @private hook of `<Chat/>`
|
|
29264
|
+
*/
|
|
29265
|
+
function useResolvedCitationLabel(citation, resolveCitationLabel) {
|
|
29266
|
+
const fallbackLabel = react.useMemo(() => getCitationLabel(citation), [citation]);
|
|
29267
|
+
const citationKey = react.useMemo(() => createCitationLabelLookupKey(citation), [citation]);
|
|
29268
|
+
const [resolvedLabel, setResolvedLabel] = react.useState(null);
|
|
29269
|
+
react.useEffect(() => {
|
|
29270
|
+
setResolvedLabel(null);
|
|
29271
|
+
if (!resolveCitationLabel) {
|
|
29272
|
+
return;
|
|
29273
|
+
}
|
|
29274
|
+
let isCurrent = true;
|
|
29275
|
+
Promise.resolve(resolveCitationLabel(citation))
|
|
29276
|
+
.then((label) => {
|
|
29277
|
+
if (!isCurrent) {
|
|
29278
|
+
return;
|
|
29279
|
+
}
|
|
29280
|
+
const normalizedLabel = label === null || label === void 0 ? void 0 : label.trim();
|
|
29281
|
+
if (normalizedLabel) {
|
|
29282
|
+
setResolvedLabel(normalizedLabel);
|
|
29283
|
+
}
|
|
29284
|
+
})
|
|
29285
|
+
.catch(() => undefined);
|
|
29286
|
+
return () => {
|
|
29287
|
+
isCurrent = false;
|
|
29288
|
+
};
|
|
29289
|
+
}, [citation, citationKey, resolveCitationLabel]);
|
|
29290
|
+
return resolvedLabel || fallbackLabel;
|
|
29291
|
+
}
|
|
29292
|
+
|
|
28743
29293
|
/**
|
|
28744
29294
|
* Renders a citation URL preview as an iframe when the target page allows embedding,
|
|
28745
29295
|
* or falls back to a server-side screenshot with an "Open in new tab" link when it
|
|
@@ -28780,6 +29330,15 @@
|
|
|
28780
29330
|
return jsxRuntime.jsx("iframe", { src: src, className: styles$7.citationIframe, title: title });
|
|
28781
29331
|
}
|
|
28782
29332
|
|
|
29333
|
+
/**
|
|
29334
|
+
* Empty citation used to keep modal hooks unconditional while the modal is closed.
|
|
29335
|
+
*
|
|
29336
|
+
* @private component constant of `<ChatCitationModal/>`
|
|
29337
|
+
*/
|
|
29338
|
+
const EMPTY_MODAL_CITATION = {
|
|
29339
|
+
id: '',
|
|
29340
|
+
source: '',
|
|
29341
|
+
};
|
|
28783
29342
|
/**
|
|
28784
29343
|
* Modal that previews a citation source or excerpt.
|
|
28785
29344
|
*
|
|
@@ -28787,7 +29346,9 @@
|
|
|
28787
29346
|
*/
|
|
28788
29347
|
function ChatCitationModal(props) {
|
|
28789
29348
|
var _a, _b;
|
|
28790
|
-
const { isOpen, citation, participants, soundSystem, onClose } = props;
|
|
29349
|
+
const { isOpen, citation, participants, resolveCitationLabel, soundSystem, onClose } = props;
|
|
29350
|
+
const resolvedCitation = citation || EMPTY_MODAL_CITATION;
|
|
29351
|
+
const label = useResolvedCitationLabel(resolvedCitation, resolveCitationLabel);
|
|
28791
29352
|
if (!isOpen || !citation) {
|
|
28792
29353
|
return null;
|
|
28793
29354
|
}
|
|
@@ -28798,7 +29359,6 @@
|
|
|
28798
29359
|
const previewSegment = previewBase.split('/').pop() || previewBase;
|
|
28799
29360
|
const extension = (_a = previewSegment.split('.').pop()) === null || _a === void 0 ? void 0 : _a.toLowerCase();
|
|
28800
29361
|
const isImage = ['jpg', 'jpeg', 'png', 'gif', 'svg', 'webp'].includes(extension || '');
|
|
28801
|
-
const label = getCitationLabel(citation);
|
|
28802
29362
|
const isTextCitation = isPlainTextCitation(citation);
|
|
28803
29363
|
const hasTextPreview = !isValidUrl && (citation.excerpt || isTextCitation);
|
|
28804
29364
|
const textPreviewContent = isTextCitation ? citation.source : (_b = citation.excerpt) !== null && _b !== void 0 ? _b : '';
|
|
@@ -30897,21 +31457,34 @@
|
|
|
30897
31457
|
|
|
30898
31458
|
// Note: [💞] Ignore a discrepancy between file name and entity name
|
|
30899
31459
|
/**
|
|
30900
|
-
* Target frames per second for
|
|
31460
|
+
* Target frames per second for a single animated avatar.
|
|
30901
31461
|
*
|
|
30902
|
-
* Animated octopus visuals change slowly enough that 24 fps is indistinguishable
|
|
30903
|
-
* from 60 fps in practice
|
|
30904
|
-
* avatars are
|
|
31462
|
+
* Animated octopus visuals change slowly enough that ~24 fps per avatar is indistinguishable
|
|
31463
|
+
* from 60 fps in practice. Combined with `MAX_AVATAR_LISTENERS_PER_FRAME` this bounds total
|
|
31464
|
+
* rendering work even when many avatars are visible.
|
|
30905
31465
|
*
|
|
30906
31466
|
* @private utility of the avatar rendering system
|
|
30907
31467
|
*/
|
|
30908
31468
|
const AVATAR_TARGET_FPS = 24;
|
|
30909
31469
|
/**
|
|
30910
|
-
* Minimum elapsed time in milliseconds required between
|
|
31470
|
+
* Minimum elapsed time in milliseconds required between two consecutive renders of the same avatar.
|
|
30911
31471
|
*
|
|
30912
31472
|
* @private utility of the avatar rendering system
|
|
30913
31473
|
*/
|
|
30914
31474
|
const AVATAR_TARGET_FRAME_INTERVAL_MS = 1000 / AVATAR_TARGET_FPS;
|
|
31475
|
+
/**
|
|
31476
|
+
* Hard cap on how many avatar listeners can run inside the same animation frame.
|
|
31477
|
+
*
|
|
31478
|
+
* The default visual takes several milliseconds to render, so firing every visible avatar
|
|
31479
|
+
* on the same animation frame stalls the main thread for tens of milliseconds and drops the
|
|
31480
|
+
* overall page FPS to single digits. Bounding the number of listeners that fire per frame
|
|
31481
|
+
* spreads the work across animation frames and keeps the UI responsive even with many
|
|
31482
|
+
* visible avatars — each individual avatar still reaches `AVATAR_TARGET_FPS` because work
|
|
31483
|
+
* is interleaved instead of skipped.
|
|
31484
|
+
*
|
|
31485
|
+
* @private utility of the avatar rendering system
|
|
31486
|
+
*/
|
|
31487
|
+
const MAX_AVATAR_LISTENERS_PER_FRAME = 2;
|
|
30915
31488
|
/**
|
|
30916
31489
|
* Next registration id used by the shared avatar animation scheduler.
|
|
30917
31490
|
*
|
|
@@ -30930,17 +31503,13 @@
|
|
|
30930
31503
|
* @private utility of the avatar rendering system
|
|
30931
31504
|
*/
|
|
30932
31505
|
let avatarAnimationFrameId = null;
|
|
30933
|
-
/**
|
|
30934
|
-
* Timestamp of the most recently rendered avatar frame.
|
|
30935
|
-
*
|
|
30936
|
-
* Used to throttle callbacks to `AVATAR_TARGET_FRAME_INTERVAL_MS`.
|
|
30937
|
-
*
|
|
30938
|
-
* @private utility of the avatar rendering system
|
|
30939
|
-
*/
|
|
30940
|
-
let lastAvatarFrameTime = 0;
|
|
30941
31506
|
/**
|
|
30942
31507
|
* Registers one avatar animation callback in the shared animation loop.
|
|
30943
31508
|
*
|
|
31509
|
+
* Each listener is staggered at registration time so it does not fire on the same animation
|
|
31510
|
+
* frame as the existing listeners, and the shared loop further caps how many listeners run
|
|
31511
|
+
* per frame, keeping the main thread responsive when many avatars are mounted.
|
|
31512
|
+
*
|
|
30944
31513
|
* @param avatarAnimationListener Frame callback invoked on every animation frame.
|
|
30945
31514
|
* @returns Cleanup function that unregisters the callback.
|
|
30946
31515
|
*
|
|
@@ -30951,7 +31520,14 @@
|
|
|
30951
31520
|
return () => undefined;
|
|
30952
31521
|
}
|
|
30953
31522
|
const listenerId = nextAvatarAnimationListenerId++;
|
|
30954
|
-
avatarAnimationListeners.
|
|
31523
|
+
const existingListenerCount = avatarAnimationListeners.size;
|
|
31524
|
+
const staggerOffsetMs = ((existingListenerCount % Math.max(1, MAX_AVATAR_LISTENERS_PER_FRAME)) * AVATAR_TARGET_FRAME_INTERVAL_MS) /
|
|
31525
|
+
Math.max(1, MAX_AVATAR_LISTENERS_PER_FRAME);
|
|
31526
|
+
avatarAnimationListeners.set(listenerId, {
|
|
31527
|
+
listener: avatarAnimationListener,
|
|
31528
|
+
// Phase the listener so multiple new listeners do not synchronize on the same frame.
|
|
31529
|
+
lastRunAtMs: performance.now() - AVATAR_TARGET_FRAME_INTERVAL_MS + staggerOffsetMs,
|
|
31530
|
+
});
|
|
30955
31531
|
ensureAvatarAnimationLoop();
|
|
30956
31532
|
return () => {
|
|
30957
31533
|
avatarAnimationListeners.delete(listenerId);
|
|
@@ -30972,12 +31548,21 @@
|
|
|
30972
31548
|
}
|
|
30973
31549
|
const runFrame = (now) => {
|
|
30974
31550
|
avatarAnimationFrameId = null;
|
|
30975
|
-
|
|
30976
|
-
|
|
30977
|
-
|
|
30978
|
-
|
|
31551
|
+
const dueListenerEntries = [];
|
|
31552
|
+
for (const listenerEntry of avatarAnimationListeners.values()) {
|
|
31553
|
+
if (now - listenerEntry.lastRunAtMs >= AVATAR_TARGET_FRAME_INTERVAL_MS) {
|
|
31554
|
+
dueListenerEntries.push(listenerEntry);
|
|
30979
31555
|
}
|
|
30980
31556
|
}
|
|
31557
|
+
// Run the most stale listeners first so each avatar keeps its target FPS even when
|
|
31558
|
+
// total work exceeds the per-frame budget.
|
|
31559
|
+
dueListenerEntries.sort((firstListenerEntry, secondListenerEntry) => firstListenerEntry.lastRunAtMs - secondListenerEntry.lastRunAtMs);
|
|
31560
|
+
const listenersToRunCount = Math.min(dueListenerEntries.length, MAX_AVATAR_LISTENERS_PER_FRAME);
|
|
31561
|
+
for (let listenerIndex = 0; listenerIndex < listenersToRunCount; listenerIndex++) {
|
|
31562
|
+
const listenerEntry = dueListenerEntries[listenerIndex];
|
|
31563
|
+
listenerEntry.lastRunAtMs = now;
|
|
31564
|
+
listenerEntry.listener(now);
|
|
31565
|
+
}
|
|
30981
31566
|
ensureAvatarAnimationLoop();
|
|
30982
31567
|
};
|
|
30983
31568
|
avatarAnimationFrameId = window.requestAnimationFrame(runFrame);
|
|
@@ -31681,8 +32266,8 @@
|
|
|
31681
32266
|
}, children: [jsxRuntime.jsx("div", { className: styles$4.arrow }), jsxRuntime.jsx(AvatarProfileFromSource, { agentSource: agentSource })] }), document.body);
|
|
31682
32267
|
});
|
|
31683
32268
|
|
|
31684
|
-
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,
|
|
31685
|
-
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-"};
|
|
32269
|
+
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 */";
|
|
32270
|
+
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-"};
|
|
31686
32271
|
styleInject(css_248z$3);
|
|
31687
32272
|
|
|
31688
32273
|
/**
|
|
@@ -31702,7 +32287,7 @@
|
|
|
31702
32287
|
*
|
|
31703
32288
|
* @private utility of `ChatMessageItem` component
|
|
31704
32289
|
*/
|
|
31705
|
-
function SourceChip({ citation, onClick, className, suffix, isCitationIdVisible = true }) {
|
|
32290
|
+
function SourceChip({ citation, onClick, className, suffix, resolveCitationLabel, isCitationIdVisible = true, }) {
|
|
31706
32291
|
var _a;
|
|
31707
32292
|
const handleClick = (event) => {
|
|
31708
32293
|
event.stopPropagation();
|
|
@@ -31712,7 +32297,8 @@
|
|
|
31712
32297
|
};
|
|
31713
32298
|
// Keep source chips concise and human-readable for CDN-backed knowledge files.
|
|
31714
32299
|
const normalizedSource = citation.source.trim();
|
|
31715
|
-
const displayName =
|
|
32300
|
+
const displayName = useResolvedCitationLabel(citation, resolveCitationLabel);
|
|
32301
|
+
const title = displayName === citation.source ? citation.source : `${displayName}\n${citation.source}`;
|
|
31716
32302
|
// Get file extension for icon
|
|
31717
32303
|
const fileExtension = ((_a = (normalizedSource || citation.source).split('.').pop()) === null || _a === void 0 ? void 0 : _a.toLowerCase()) || 'file';
|
|
31718
32304
|
const icon = isPlainTextCitation(citation)
|
|
@@ -31720,7 +32306,7 @@
|
|
|
31720
32306
|
: isCitationUrl(normalizedSource)
|
|
31721
32307
|
? '🌐'
|
|
31722
32308
|
: getFileIcon(fileExtension);
|
|
31723
|
-
return (jsxRuntime.jsxs("button", { className: `${styles$3.sourceChip} ${className || ''}`, onClick: handleClick, title:
|
|
32309
|
+
return (jsxRuntime.jsxs("button", { className: `${styles$3.sourceChip} ${className || ''}`, onClick: handleClick, title: title, children: [jsxRuntime.jsx("span", { className: styles$3.icon, children: icon }), jsxRuntime.jsxs("span", { className: styles$3.label, children: [jsxRuntime.jsx("span", { className: styles$3.labelText, children: displayName }), isCitationIdVisible && jsxRuntime.jsxs("span", { className: styles$3.citationId, children: [" [", citation.id, "]"] })] }), suffix && jsxRuntime.jsx("span", { className: styles$3.suffix, children: suffix })] }));
|
|
31724
32310
|
}
|
|
31725
32311
|
/**
|
|
31726
32312
|
* Gets an appropriate emoji icon for a file type
|
|
@@ -31805,63 +32391,6 @@
|
|
|
31805
32391
|
return `${minutes}m ${seconds}s`;
|
|
31806
32392
|
}
|
|
31807
32393
|
|
|
31808
|
-
/**
|
|
31809
|
-
* Extracts one quick button definition from a markdown link query string.
|
|
31810
|
-
*
|
|
31811
|
-
* @param text The visible button label.
|
|
31812
|
-
* @param query Raw query-string payload captured from markdown.
|
|
31813
|
-
* @returns Parsed quick button definition or `null` when the link is not a supported quick button.
|
|
31814
|
-
*
|
|
31815
|
-
* @private internal helper of `parseMessageButtons`
|
|
31816
|
-
*/
|
|
31817
|
-
function parseQuickButtonDefinition(text, query) {
|
|
31818
|
-
const searchParams = new URLSearchParams(query);
|
|
31819
|
-
const message = searchParams.get('message');
|
|
31820
|
-
if (message !== null) {
|
|
31821
|
-
return {
|
|
31822
|
-
type: 'message',
|
|
31823
|
-
text,
|
|
31824
|
-
message,
|
|
31825
|
-
};
|
|
31826
|
-
}
|
|
31827
|
-
const code = searchParams.get('action');
|
|
31828
|
-
if (code !== null) {
|
|
31829
|
-
return {
|
|
31830
|
-
type: 'action',
|
|
31831
|
-
text,
|
|
31832
|
-
code,
|
|
31833
|
-
};
|
|
31834
|
-
}
|
|
31835
|
-
return null;
|
|
31836
|
-
}
|
|
31837
|
-
/**
|
|
31838
|
-
* Parses markdown quick buttons in the format `[Button Text](?message=...)` or `[Button Text](?action=...)`.
|
|
31839
|
-
* Returns both the content without supported quick buttons and the extracted button definitions.
|
|
31840
|
-
*
|
|
31841
|
-
* @param content The markdown content that may contain buttons
|
|
31842
|
-
* @returns Object with contentWithoutButtons and buttons array
|
|
31843
|
-
*
|
|
31844
|
-
* @public exported from `@promptbook/components`
|
|
31845
|
-
*/
|
|
31846
|
-
function parseMessageButtons(content) {
|
|
31847
|
-
const buttonRegex = /\[([^\]]+)\]\(\?([^)]+)\)/g;
|
|
31848
|
-
const buttons = [];
|
|
31849
|
-
const contentWithoutButtons = content
|
|
31850
|
-
.replace(buttonRegex, (match, text, query) => {
|
|
31851
|
-
const button = parseQuickButtonDefinition(text, query);
|
|
31852
|
-
if (!button) {
|
|
31853
|
-
return match;
|
|
31854
|
-
}
|
|
31855
|
-
buttons.push(button);
|
|
31856
|
-
return '';
|
|
31857
|
-
})
|
|
31858
|
-
.trim();
|
|
31859
|
-
return {
|
|
31860
|
-
contentWithoutButtons,
|
|
31861
|
-
buttons,
|
|
31862
|
-
};
|
|
31863
|
-
}
|
|
31864
|
-
|
|
31865
32394
|
/**
|
|
31866
32395
|
* Searches for the last unclosed code fence using the provided delimiter.
|
|
31867
32396
|
*/
|
|
@@ -35333,7 +35862,7 @@
|
|
|
35333
35862
|
// <- TODO: [🧠] Should we wrap more components in `React.memo`
|
|
35334
35863
|
// Or make normal function from this?
|
|
35335
35864
|
(props) => {
|
|
35336
|
-
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;
|
|
35865
|
+
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;
|
|
35337
35866
|
const { isComplete = true,
|
|
35338
35867
|
// <- TODO: Destruct all `messages` properties like `isComplete`
|
|
35339
35868
|
} = message;
|
|
@@ -35381,6 +35910,10 @@
|
|
|
35381
35910
|
content: sanitizedContentWithoutButtons,
|
|
35382
35911
|
citations: message.citations,
|
|
35383
35912
|
}), [message.citations, sanitizedContentWithoutButtons]);
|
|
35913
|
+
const enrichCitationForRendering = react.useCallback((citation) => {
|
|
35914
|
+
const previewUrl = resolveCitationPreviewUrl(citation, participants !== null && participants !== void 0 ? participants : []);
|
|
35915
|
+
return previewUrl && !citation.url ? { ...citation, url: previewUrl } : citation;
|
|
35916
|
+
}, [participants]);
|
|
35384
35917
|
const contentSegments = react.useMemo(() => splitMessageContentIntoSegments(citationFootnoteRenderModel.content), [citationFootnoteRenderModel.content]);
|
|
35385
35918
|
const hasMapSegment = react.useMemo(() => contentSegments.some((segment) => segment.type === 'map'), [contentSegments]);
|
|
35386
35919
|
const [localHoveredRating, setLocalHoveredRating] = react.useState(0);
|
|
@@ -35652,7 +36185,7 @@
|
|
|
35652
36185
|
'--message-bg-color': isAgentArticleMode ? articleModeBackgroundColor : color.toHex(),
|
|
35653
36186
|
'--message-text-color': isAgentArticleMode ? articleModeTextColor : colorOfText.toHex(),
|
|
35654
36187
|
'--chat-message-swipe-offset': swipeTranslation,
|
|
35655
|
-
}, onPointerDown: handleReplyPointerDown, onPointerMove: handleReplyPointerMove, onPointerUp: handleReplyPointerEnd, onPointerCancel: resetReplySwipe, children: [isReplyActionEnabled && (jsxRuntime.jsx("div", { className: classNames(styles$7.replySwipeIndicator, isMe && styles$7.replySwipeIndicatorRight, isReplySwipeArmed && styles$7.replySwipeIndicatorActive), "aria-hidden": "true", children: jsxRuntime.jsx(lucideReact.Reply, { className: styles$7.replySwipeIndicatorIcon }) })), !shouldRenderArticleActionsBar && renderMessageReadAndCopyControls(), message.isVoiceCall && (jsxRuntime.jsx("div", { className: styles$7.voiceCallIndicator, children: jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "currentColor", children: jsxRuntime.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 && (jsxRuntime.jsx(ChatReplyPreview, { label: replyPreviewLabel, senderLabel: replySenderLabel, previewText: replyPreviewText, className: styles$7.replyBubblePreview })), jsxRuntime.jsx("div", { ref: contentWithoutButtonsRef, children: jsxRuntime.jsx(ChatMessageRichContent, { content: message.content, contentSegments: contentSegments, streamingFeaturePlaceholderKind: streamingFeaturePlaceholderKind, onCreateAgent: onCreateAgent, mode: mode }) }), message.attachments && message.attachments.length > 0 && (jsxRuntime.jsx("div", { className: styles$7.attachments, children: message.attachments.map((attachment, index) => (jsxRuntime.jsxs("a", { href: attachment.url, target: "_blank", rel: "noopener noreferrer", className: styles$7.attachment, title: attachment.name, children: [jsxRuntime.jsx("span", { className: styles$7.attachmentIcon, children: "\uD83D\uDCCE" }), jsxRuntime.jsx("span", { className: styles$7.attachmentName, children: attachment.name })] }, index))) })), jsxRuntime.jsx(ChatMessageToolCallChips, { chips: toolCallChips, onToolCallClick: onToolCallClick }), citationFootnoteRenderModel.footnotes.length > 0 && (jsxRuntime.jsx("div", { className: styles$7.citationFootnotes, children: citationFootnoteRenderModel.footnotes.map((footnote) => (jsxRuntime.jsxs("div", { className: styles$7.citationFootnoteItem, children: [jsxRuntime.jsx("span", { className: styles$7.citationFootnoteNumber, children: footnote.number }), jsxRuntime.jsx(SourceChip, { citation: footnote.citation, onClick: onCitationClick, isCitationIdVisible: false })] }, `citation-footnote-${footnote.number}-${footnote.citation.source}`))) })), transitiveCitations.length > 0 && (jsxRuntime.jsx("div", { className: styles$7.sourceCitations, children: transitiveCitations.map((citation, index) => (jsxRuntime.jsx(SourceChip, { citation: citation, suffix: `by ${citation.origin.label}`, onClick: onCitationClick }, `team-source-${citation.source}-${index}`))) })), shouldShowButtons && (jsxRuntime.jsx("div", { className: styles$7.messageButtons, children: renderableButtons.map(({ button, buttonIndex }) => (jsxRuntime.jsx("button", { type: "button", className: classNames(styles$7.messageButton, button.type === 'action' && styles$7.actionMessageButton), onClick: (event) => {
|
|
36188
|
+
}, onPointerDown: handleReplyPointerDown, onPointerMove: handleReplyPointerMove, onPointerUp: handleReplyPointerEnd, onPointerCancel: resetReplySwipe, children: [isReplyActionEnabled && (jsxRuntime.jsx("div", { className: classNames(styles$7.replySwipeIndicator, isMe && styles$7.replySwipeIndicatorRight, isReplySwipeArmed && styles$7.replySwipeIndicatorActive), "aria-hidden": "true", children: jsxRuntime.jsx(lucideReact.Reply, { className: styles$7.replySwipeIndicatorIcon }) })), !shouldRenderArticleActionsBar && renderMessageReadAndCopyControls(), message.isVoiceCall && (jsxRuntime.jsx("div", { className: styles$7.voiceCallIndicator, children: jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "currentColor", children: jsxRuntime.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 && (jsxRuntime.jsx(ChatReplyPreview, { label: replyPreviewLabel, senderLabel: replySenderLabel, previewText: replyPreviewText, className: styles$7.replyBubblePreview })), jsxRuntime.jsx("div", { ref: contentWithoutButtonsRef, children: jsxRuntime.jsx(ChatMessageRichContent, { content: message.content, contentSegments: contentSegments, streamingFeaturePlaceholderKind: streamingFeaturePlaceholderKind, onCreateAgent: onCreateAgent, mode: mode }) }), message.attachments && message.attachments.length > 0 && (jsxRuntime.jsx("div", { className: styles$7.attachments, children: message.attachments.map((attachment, index) => (jsxRuntime.jsxs("a", { href: attachment.url, target: "_blank", rel: "noopener noreferrer", className: styles$7.attachment, title: attachment.name, children: [jsxRuntime.jsx("span", { className: styles$7.attachmentIcon, children: "\uD83D\uDCCE" }), jsxRuntime.jsx("span", { className: styles$7.attachmentName, children: attachment.name })] }, index))) })), jsxRuntime.jsx(ChatMessageToolCallChips, { chips: toolCallChips, onToolCallClick: onToolCallClick }), citationFootnoteRenderModel.footnotes.length > 0 && (jsxRuntime.jsx("div", { className: styles$7.citationFootnotes, children: citationFootnoteRenderModel.footnotes.map((footnote) => (jsxRuntime.jsxs("div", { className: styles$7.citationFootnoteItem, children: [jsxRuntime.jsx("span", { className: styles$7.citationFootnoteNumber, children: footnote.number }), jsxRuntime.jsx(SourceChip, { citation: enrichCitationForRendering(footnote.citation), onClick: onCitationClick, resolveCitationLabel: resolveCitationLabel, isCitationIdVisible: false })] }, `citation-footnote-${footnote.number}-${footnote.citation.source}`))) })), transitiveCitations.length > 0 && (jsxRuntime.jsx("div", { className: styles$7.sourceCitations, children: transitiveCitations.map((citation, index) => (jsxRuntime.jsx(SourceChip, { citation: enrichCitationForRendering(citation), suffix: `by ${citation.origin.label}`, onClick: onCitationClick, resolveCitationLabel: resolveCitationLabel }, `team-source-${citation.source}-${index}`))) })), shouldShowButtons && (jsxRuntime.jsx("div", { className: styles$7.messageButtons, children: renderableButtons.map(({ button, buttonIndex }) => (jsxRuntime.jsx("button", { type: "button", className: classNames(styles$7.messageButton, button.type === 'action' && styles$7.actionMessageButton), onClick: (event) => {
|
|
35656
36189
|
event.stopPropagation();
|
|
35657
36190
|
if (button.type === 'message') {
|
|
35658
36191
|
const quickMessageHandler = onQuickMessageButton || onMessage;
|
|
@@ -35758,6 +36291,9 @@
|
|
|
35758
36291
|
if (prev.feedbackTranslations !== next.feedbackTranslations) {
|
|
35759
36292
|
return false;
|
|
35760
36293
|
}
|
|
36294
|
+
if (prev.resolveCitationLabel !== next.resolveCitationLabel) {
|
|
36295
|
+
return false;
|
|
36296
|
+
}
|
|
35761
36297
|
if (prev.handleRating !== next.handleRating) {
|
|
35762
36298
|
return false;
|
|
35763
36299
|
}
|
|
@@ -35786,7 +36322,7 @@
|
|
|
35786
36322
|
* @private component of `<Chat/>`
|
|
35787
36323
|
*/
|
|
35788
36324
|
function ChatMessageList(props) {
|
|
35789
|
-
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;
|
|
36325
|
+
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;
|
|
35790
36326
|
const firstMessage = messages[0];
|
|
35791
36327
|
const firstMsgContent = (firstMessage === null || firstMessage === void 0 ? void 0 : firstMessage.content) || '';
|
|
35792
36328
|
const firstMsgLines = firstMsgContent.split(/\r?\n/).length;
|
|
@@ -35798,7 +36334,7 @@
|
|
|
35798
36334
|
const isLastMessage = index === messages.length - 1;
|
|
35799
36335
|
const isExpanded = expandedMessageId === message.id;
|
|
35800
36336
|
const currentRating = messageRatings.get(message.id || message.content /* <-[??] */) || 0;
|
|
35801
|
-
return (jsxRuntime.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)));
|
|
36337
|
+
return (jsxRuntime.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)));
|
|
35802
36338
|
}), jsxRuntime.jsx("div", { style: { height: 100 } })] }));
|
|
35803
36339
|
}
|
|
35804
36340
|
/**
|
|
@@ -39244,11 +39780,11 @@
|
|
|
39244
39780
|
* @private component of ChatToolCallModal
|
|
39245
39781
|
*/
|
|
39246
39782
|
function TeamToolCallSourcesGroup(props) {
|
|
39247
|
-
const { teamCitations } = props;
|
|
39783
|
+
const { teamCitations, resolveCitationLabel } = props;
|
|
39248
39784
|
if (teamCitations.length === 0) {
|
|
39249
39785
|
return null;
|
|
39250
39786
|
}
|
|
39251
|
-
return (jsxRuntime.jsxs("div", { className: styles$7.teamToolCallGroup, children: [jsxRuntime.jsx("div", { className: styles$7.teamToolCallHeading, children: "Sources" }), jsxRuntime.jsx("div", { className: styles$7.teamToolCallChips, children: teamCitations.map((citation, index) => (jsxRuntime.jsx(SourceChip, { citation: citation, suffix: `by ${citation.origin.label}
|
|
39787
|
+
return (jsxRuntime.jsxs("div", { className: styles$7.teamToolCallGroup, children: [jsxRuntime.jsx("div", { className: styles$7.teamToolCallHeading, children: "Sources" }), jsxRuntime.jsx("div", { className: styles$7.teamToolCallChips, children: teamCitations.map((citation, index) => (jsxRuntime.jsx(SourceChip, { citation: citation, suffix: `by ${citation.origin.label}`, resolveCitationLabel: resolveCitationLabel }, `team-source-${citation.source}-${index}`))) })] }));
|
|
39252
39788
|
}
|
|
39253
39789
|
/**
|
|
39254
39790
|
* Renders the nested action details for the selected teammate tool call.
|
|
@@ -39273,12 +39809,12 @@
|
|
|
39273
39809
|
* @private component of ChatToolCallModal
|
|
39274
39810
|
*/
|
|
39275
39811
|
function TeamToolCallSummarySection(props) {
|
|
39276
|
-
const { agentParticipant, buttonColor, onClearSelectedTeamToolCall, onSelectTeamToolCall, selectedTeamToolCall, teamToolCallSummary, toolTitles, } = props;
|
|
39812
|
+
const { agentParticipant, buttonColor, onClearSelectedTeamToolCall, onSelectTeamToolCall, selectedTeamToolCall, teamToolCallSummary, toolTitles, resolveCitationLabel, } = props;
|
|
39277
39813
|
const hasSummaryContent = teamToolCallSummary.toolCalls.length > 0 || teamToolCallSummary.citations.length > 0;
|
|
39278
39814
|
if (!hasSummaryContent) {
|
|
39279
39815
|
return null;
|
|
39280
39816
|
}
|
|
39281
|
-
return (jsxRuntime.jsxs("div", { className: styles$7.teamToolCallSection, children: [jsxRuntime.jsx(TeamToolCallActionsGroup, { teamToolCalls: teamToolCallSummary.toolCalls, onSelectTeamToolCall: onSelectTeamToolCall, toolTitles: toolTitles }), jsxRuntime.jsx(TeamToolCallSourcesGroup, { teamCitations: teamToolCallSummary.citations }), jsxRuntime.jsx(TeamToolCallDetailsPanel, { selectedTeamToolCall: selectedTeamToolCall, onClearSelectedTeamToolCall: onClearSelectedTeamToolCall, toolTitles: toolTitles, agentParticipant: agentParticipant, buttonColor: buttonColor })] }));
|
|
39817
|
+
return (jsxRuntime.jsxs("div", { className: styles$7.teamToolCallSection, children: [jsxRuntime.jsx(TeamToolCallActionsGroup, { teamToolCalls: teamToolCallSummary.toolCalls, onSelectTeamToolCall: onSelectTeamToolCall, toolTitles: toolTitles }), jsxRuntime.jsx(TeamToolCallSourcesGroup, { teamCitations: teamToolCallSummary.citations, resolveCitationLabel: resolveCitationLabel }), jsxRuntime.jsx(TeamToolCallDetailsPanel, { selectedTeamToolCall: selectedTeamToolCall, onClearSelectedTeamToolCall: onClearSelectedTeamToolCall, toolTitles: toolTitles, agentParticipant: agentParticipant, buttonColor: buttonColor })] }));
|
|
39282
39818
|
}
|
|
39283
39819
|
/**
|
|
39284
39820
|
* Renders TEAM conversation details, nested actions, and citations.
|
|
@@ -39286,7 +39822,7 @@
|
|
|
39286
39822
|
* @private function of ChatToolCallModal
|
|
39287
39823
|
*/
|
|
39288
39824
|
function TeamToolCallModalContent(options) {
|
|
39289
|
-
const { teamResult, toolCallDate, teamToolCallSummary, selectedTeamToolCall, onSelectTeamToolCall, onClearSelectedTeamToolCall, teamProfiles, toolTitles, agentParticipant, buttonColor, } = options;
|
|
39825
|
+
const { teamResult, toolCallDate, teamToolCallSummary, selectedTeamToolCall, onSelectTeamToolCall, onClearSelectedTeamToolCall, teamProfiles, toolTitles, resolveCitationLabel, agentParticipant, buttonColor, } = options;
|
|
39290
39826
|
const baseTime = toolCallDate ? toolCallDate.getTime() : Date.now();
|
|
39291
39827
|
const messages = createTeamConversationMessages(teamResult, baseTime);
|
|
39292
39828
|
const { agentHeader, teammateHeader, participants } = createTeamConversationViewModel({
|
|
@@ -39294,7 +39830,7 @@
|
|
|
39294
39830
|
teamProfiles,
|
|
39295
39831
|
agentParticipant,
|
|
39296
39832
|
});
|
|
39297
|
-
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(TeamConversationHeader, { agentHeader: agentHeader, teammateHeader: teammateHeader }), jsxRuntime.jsxs("div", { className: styles$7.searchModalContent, children: [jsxRuntime.jsx(TeamConversationSection, { agentLabel: agentHeader.label, teammateLabel: teammateHeader.label, messages: messages, participants: participants }), jsxRuntime.jsx(TeamToolCallSummarySection, { teamToolCallSummary: teamToolCallSummary, selectedTeamToolCall: selectedTeamToolCall, onSelectTeamToolCall: onSelectTeamToolCall, onClearSelectedTeamToolCall: onClearSelectedTeamToolCall, toolTitles: toolTitles, agentParticipant: agentParticipant, buttonColor: buttonColor })] })] }));
|
|
39833
|
+
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(TeamConversationHeader, { agentHeader: agentHeader, teammateHeader: teammateHeader }), jsxRuntime.jsxs("div", { className: styles$7.searchModalContent, children: [jsxRuntime.jsx(TeamConversationSection, { agentLabel: agentHeader.label, teammateLabel: teammateHeader.label, messages: messages, participants: participants }), jsxRuntime.jsx(TeamToolCallSummarySection, { teamToolCallSummary: teamToolCallSummary, selectedTeamToolCall: selectedTeamToolCall, onSelectTeamToolCall: onSelectTeamToolCall, onClearSelectedTeamToolCall: onClearSelectedTeamToolCall, toolTitles: toolTitles, resolveCitationLabel: resolveCitationLabel, agentParticipant: agentParticipant, buttonColor: buttonColor })] })] }));
|
|
39298
39834
|
}
|
|
39299
39835
|
|
|
39300
39836
|
/**
|
|
@@ -39302,7 +39838,7 @@
|
|
|
39302
39838
|
*
|
|
39303
39839
|
* @private component of `ChatToolCallModal`
|
|
39304
39840
|
*/
|
|
39305
|
-
function ChatToolCallModalContent({ agentParticipant, availableTools, buttonColor, chatUiTranslations, focusedToolCall, isAdvancedView, locale, mode, onClearSelectedTeamToolCall, onRequestAdvancedView, onSelectTeamToolCall, selectedTeamToolCall, teamProfiles, teamResult, teamToolCallSummary, toolCall, toolCallDate, toolTitles, }) {
|
|
39841
|
+
function ChatToolCallModalContent({ agentParticipant, availableTools, buttonColor, chatUiTranslations, focusedToolCall, isAdvancedView, locale, mode, resolveCitationLabel, onClearSelectedTeamToolCall, onRequestAdvancedView, onSelectTeamToolCall, selectedTeamToolCall, teamProfiles, teamResult, teamToolCallSummary, toolCall, toolCallDate, toolTitles, }) {
|
|
39306
39842
|
if (isAdvancedView) {
|
|
39307
39843
|
return renderAdvancedToolCallDetails({
|
|
39308
39844
|
toolCall: focusedToolCall,
|
|
@@ -39312,7 +39848,7 @@
|
|
|
39312
39848
|
});
|
|
39313
39849
|
}
|
|
39314
39850
|
if (teamResult === null || teamResult === void 0 ? void 0 : teamResult.teammate) {
|
|
39315
|
-
return (jsxRuntime.jsx(TeamToolCallModalContent, { teamResult: teamResult, toolCallDate: toolCallDate, teamToolCallSummary: teamToolCallSummary, selectedTeamToolCall: selectedTeamToolCall, onSelectTeamToolCall: onSelectTeamToolCall, onClearSelectedTeamToolCall: onClearSelectedTeamToolCall, teamProfiles: teamProfiles, toolTitles: toolTitles, agentParticipant: agentParticipant, buttonColor: buttonColor }));
|
|
39851
|
+
return (jsxRuntime.jsx(TeamToolCallModalContent, { teamResult: teamResult, toolCallDate: toolCallDate, teamToolCallSummary: teamToolCallSummary, selectedTeamToolCall: selectedTeamToolCall, onSelectTeamToolCall: onSelectTeamToolCall, onClearSelectedTeamToolCall: onClearSelectedTeamToolCall, teamProfiles: teamProfiles, toolTitles: toolTitles, resolveCitationLabel: resolveCitationLabel, agentParticipant: agentParticipant, buttonColor: buttonColor }));
|
|
39316
39852
|
}
|
|
39317
39853
|
return renderToolCallDetails({
|
|
39318
39854
|
toolCall,
|
|
@@ -39575,7 +40111,7 @@
|
|
|
39575
40111
|
* @private component of `<Chat/>`
|
|
39576
40112
|
*/
|
|
39577
40113
|
function ChatToolCallModal(props) {
|
|
39578
|
-
const { isOpen, toolCall, mode = 'LIGHT', toolCallIdentity, onClose, toolTitles, agentParticipant, buttonColor, teamAgentProfiles, chatUiTranslations, locale, availableTools, } = props;
|
|
40114
|
+
const { isOpen, toolCall, mode = 'LIGHT', toolCallIdentity, onClose, toolTitles, resolveCitationLabel, agentParticipant, buttonColor, teamAgentProfiles, chatUiTranslations, locale, availableTools, } = props;
|
|
39579
40115
|
const { clearSelectedTeamToolCall, exportAdvancedToolCallReport, focusedToolCall, isAdvancedView, modalDialogRef, openAdvancedView, selectTeamToolCall, selectedTeamToolCall, teamProfiles, teamResult, teamToolCallSummary, toggleViewMode, toolCallDate, } = useChatToolCallModalState({
|
|
39580
40116
|
isOpen,
|
|
39581
40117
|
toolCall,
|
|
@@ -39597,7 +40133,7 @@
|
|
|
39597
40133
|
: (chatUiTranslations === null || chatUiTranslations === void 0 ? void 0 : chatUiTranslations.toolCallModalAdvancedLabel) || 'Advanced';
|
|
39598
40134
|
return (jsxRuntime.jsx("div", { className: styles$7.ratingModal, "data-chat-modal": "tool-call", "data-chat-theme": mode.toLowerCase(), onClick: (event) => {
|
|
39599
40135
|
handleModalBackdropClick(event, onClose);
|
|
39600
|
-
}, children: jsxRuntime.jsxs("div", { ref: modalDialogRef, className: classNames(styles$7.ratingModalContent, styles$7.toolCallModal), role: "dialog", "aria-modal": "true", "aria-label": modalTitle, tabIndex: -1, children: [jsxRuntime.jsx("button", { type: "button", className: styles$7.modalCloseButton, onClick: onClose, "aria-label": closeButtonLabel, children: jsxRuntime.jsx(CloseIcon, {}) }), jsxRuntime.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 }), jsxRuntime.jsxs("div", { className: styles$7.toolCallModeFooter, children: [isAdvancedView && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("button", { type: "button", className: styles$7.toolCallModeButton, onClick: () => {
|
|
40136
|
+
}, children: jsxRuntime.jsxs("div", { ref: modalDialogRef, className: classNames(styles$7.ratingModalContent, styles$7.toolCallModal), role: "dialog", "aria-modal": "true", "aria-label": modalTitle, tabIndex: -1, children: [jsxRuntime.jsx("button", { type: "button", className: styles$7.modalCloseButton, onClick: onClose, "aria-label": closeButtonLabel, children: jsxRuntime.jsx(CloseIcon, {}) }), jsxRuntime.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 }), jsxRuntime.jsxs("div", { className: styles$7.toolCallModeFooter, children: [isAdvancedView && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("button", { type: "button", className: styles$7.toolCallModeButton, onClick: () => {
|
|
39601
40137
|
void exportAdvancedToolCallReport('clipboard');
|
|
39602
40138
|
}, children: copyButtonLabel }), jsxRuntime.jsx("button", { type: "button", className: styles$7.toolCallModeButton, onClick: () => {
|
|
39603
40139
|
void exportAdvancedToolCallReport('file');
|
|
@@ -39740,6 +40276,146 @@
|
|
|
39740
40276
|
}
|
|
39741
40277
|
// TODO: [🧠][✌️] Make some Promptbook-native token system
|
|
39742
40278
|
|
|
40279
|
+
/**
|
|
40280
|
+
* Pattern for detecting JSON-style Unicode escape sequences in model text.
|
|
40281
|
+
*
|
|
40282
|
+
* @private utility of chat message postprocessing
|
|
40283
|
+
*/
|
|
40284
|
+
const JSON_UNICODE_ESCAPE_DETECTION_PATTERN = /\\u[0-9a-fA-F]{4}/;
|
|
40285
|
+
/**
|
|
40286
|
+
* Pattern for decoding JSON-style Unicode escape sequences in model text.
|
|
40287
|
+
*
|
|
40288
|
+
* @private utility of chat message postprocessing
|
|
40289
|
+
*/
|
|
40290
|
+
const JSON_UNICODE_ESCAPE_PATTERN = /\\u([0-9a-fA-F]{4})/g;
|
|
40291
|
+
/**
|
|
40292
|
+
* Pattern for detecting fenced markdown code-block boundaries.
|
|
40293
|
+
*
|
|
40294
|
+
* @private utility of chat message postprocessing
|
|
40295
|
+
*/
|
|
40296
|
+
const MARKDOWN_CODE_FENCE_PATTERN = /^[ \t]{0,3}(`{3,}|~{3,})/;
|
|
40297
|
+
/**
|
|
40298
|
+
* Minimum code point decoded by the chat Unicode escape normalizer.
|
|
40299
|
+
*
|
|
40300
|
+
* ASCII escapes can be intentional in JSON and security-sensitive examples, so this
|
|
40301
|
+
* helper only decodes non-ASCII characters that were visibly broken in chat text.
|
|
40302
|
+
*
|
|
40303
|
+
* @private utility of chat message postprocessing
|
|
40304
|
+
*/
|
|
40305
|
+
const FIRST_NON_ASCII_CODE_POINT = 0x80;
|
|
40306
|
+
/**
|
|
40307
|
+
* Decodes JSON-style Unicode escape sequences in markdown prose while preserving code.
|
|
40308
|
+
*
|
|
40309
|
+
* Model/tool output can occasionally arrive as already JSON-escaped text, which makes
|
|
40310
|
+
* natural-language replies render `\u00fd` instead of the decoded character. This
|
|
40311
|
+
* keeps code examples intact by skipping fenced code blocks and inline code spans.
|
|
40312
|
+
*
|
|
40313
|
+
* @param markdown - Markdown chat content to normalize for display.
|
|
40314
|
+
* @returns Markdown chat content with non-ASCII JSON Unicode escapes decoded.
|
|
40315
|
+
*
|
|
40316
|
+
* @private internal utility of `<Chat/>`
|
|
40317
|
+
*/
|
|
40318
|
+
function decodeJsonUnicodeEscapesInMarkdownText(markdown) {
|
|
40319
|
+
var _a, _b;
|
|
40320
|
+
if (!JSON_UNICODE_ESCAPE_DETECTION_PATTERN.test(markdown)) {
|
|
40321
|
+
return markdown;
|
|
40322
|
+
}
|
|
40323
|
+
const parts = markdown.split(/(\r\n|\r|\n)/);
|
|
40324
|
+
let fenceState = null;
|
|
40325
|
+
let normalizedMarkdown = '';
|
|
40326
|
+
for (let index = 0; index < parts.length; index += 2) {
|
|
40327
|
+
const line = (_a = parts[index]) !== null && _a !== void 0 ? _a : '';
|
|
40328
|
+
const newline = (_b = parts[index + 1]) !== null && _b !== void 0 ? _b : '';
|
|
40329
|
+
const fenceBoundary = resolveMarkdownFenceBoundary(line);
|
|
40330
|
+
if (fenceState) {
|
|
40331
|
+
normalizedMarkdown += line + newline;
|
|
40332
|
+
if (fenceBoundary &&
|
|
40333
|
+
fenceBoundary.marker === fenceState.marker &&
|
|
40334
|
+
fenceBoundary.length >= fenceState.length) {
|
|
40335
|
+
fenceState = null;
|
|
40336
|
+
}
|
|
40337
|
+
continue;
|
|
40338
|
+
}
|
|
40339
|
+
if (fenceBoundary) {
|
|
40340
|
+
fenceState = fenceBoundary;
|
|
40341
|
+
normalizedMarkdown += line + newline;
|
|
40342
|
+
continue;
|
|
40343
|
+
}
|
|
40344
|
+
normalizedMarkdown += decodeJsonUnicodeEscapesOutsideInlineCode(line) + newline;
|
|
40345
|
+
}
|
|
40346
|
+
return normalizedMarkdown;
|
|
40347
|
+
}
|
|
40348
|
+
/**
|
|
40349
|
+
* Resolves one markdown code-fence boundary from a line.
|
|
40350
|
+
*
|
|
40351
|
+
* @private utility of `decodeJsonUnicodeEscapesInMarkdownText`
|
|
40352
|
+
*/
|
|
40353
|
+
function resolveMarkdownFenceBoundary(line) {
|
|
40354
|
+
const match = line.match(MARKDOWN_CODE_FENCE_PATTERN);
|
|
40355
|
+
const fenceMarker = match === null || match === void 0 ? void 0 : match[1];
|
|
40356
|
+
if (!fenceMarker) {
|
|
40357
|
+
return null;
|
|
40358
|
+
}
|
|
40359
|
+
return {
|
|
40360
|
+
marker: fenceMarker[0],
|
|
40361
|
+
length: fenceMarker.length,
|
|
40362
|
+
};
|
|
40363
|
+
}
|
|
40364
|
+
/**
|
|
40365
|
+
* Decodes Unicode escapes in one markdown line while skipping inline code spans.
|
|
40366
|
+
*
|
|
40367
|
+
* @private utility of `decodeJsonUnicodeEscapesInMarkdownText`
|
|
40368
|
+
*/
|
|
40369
|
+
function decodeJsonUnicodeEscapesOutsideInlineCode(line) {
|
|
40370
|
+
let normalizedLine = '';
|
|
40371
|
+
let cursor = 0;
|
|
40372
|
+
while (cursor < line.length) {
|
|
40373
|
+
const openingDelimiterStart = line.indexOf('`', cursor);
|
|
40374
|
+
if (openingDelimiterStart === -1) {
|
|
40375
|
+
normalizedLine += decodeJsonUnicodeEscapesInText(line.slice(cursor));
|
|
40376
|
+
break;
|
|
40377
|
+
}
|
|
40378
|
+
const openingDelimiterEnd = findBacktickRunEnd(line, openingDelimiterStart);
|
|
40379
|
+
const openingDelimiter = line.slice(openingDelimiterStart, openingDelimiterEnd);
|
|
40380
|
+
const closingDelimiterStart = line.indexOf(openingDelimiter, openingDelimiterEnd);
|
|
40381
|
+
normalizedLine += decodeJsonUnicodeEscapesInText(line.slice(cursor, openingDelimiterStart));
|
|
40382
|
+
if (closingDelimiterStart === -1) {
|
|
40383
|
+
normalizedLine += line.slice(openingDelimiterStart);
|
|
40384
|
+
break;
|
|
40385
|
+
}
|
|
40386
|
+
const closingDelimiterEnd = closingDelimiterStart + openingDelimiter.length;
|
|
40387
|
+
normalizedLine += line.slice(openingDelimiterStart, closingDelimiterEnd);
|
|
40388
|
+
cursor = closingDelimiterEnd;
|
|
40389
|
+
}
|
|
40390
|
+
return normalizedLine;
|
|
40391
|
+
}
|
|
40392
|
+
/**
|
|
40393
|
+
* Finds the first character after one contiguous run of backticks.
|
|
40394
|
+
*
|
|
40395
|
+
* @private utility of `decodeJsonUnicodeEscapesInMarkdownText`
|
|
40396
|
+
*/
|
|
40397
|
+
function findBacktickRunEnd(line, startIndex) {
|
|
40398
|
+
let cursor = startIndex;
|
|
40399
|
+
while (cursor < line.length && line[cursor] === '`') {
|
|
40400
|
+
cursor++;
|
|
40401
|
+
}
|
|
40402
|
+
return cursor;
|
|
40403
|
+
}
|
|
40404
|
+
/**
|
|
40405
|
+
* Decodes non-ASCII JSON Unicode escapes in plain text.
|
|
40406
|
+
*
|
|
40407
|
+
* @private utility of `decodeJsonUnicodeEscapesInMarkdownText`
|
|
40408
|
+
*/
|
|
40409
|
+
function decodeJsonUnicodeEscapesInText(text) {
|
|
40410
|
+
return text.replace(JSON_UNICODE_ESCAPE_PATTERN, (match, hexadecimalCodePoint) => {
|
|
40411
|
+
const codePoint = Number.parseInt(hexadecimalCodePoint, 16);
|
|
40412
|
+
if (codePoint < FIRST_NON_ASCII_CODE_POINT) {
|
|
40413
|
+
return match;
|
|
40414
|
+
}
|
|
40415
|
+
return String.fromCharCode(codePoint);
|
|
40416
|
+
});
|
|
40417
|
+
}
|
|
40418
|
+
|
|
39743
40419
|
/**
|
|
39744
40420
|
* Applies the same text normalization that Chat historically performed inline.
|
|
39745
40421
|
*
|
|
@@ -39753,15 +40429,24 @@
|
|
|
39753
40429
|
const normalizedReplyingTo = messageWithCitations.replyingTo
|
|
39754
40430
|
? {
|
|
39755
40431
|
...messageWithCitations.replyingTo,
|
|
39756
|
-
content:
|
|
40432
|
+
content: postprocessChatMessageContent(messageWithCitations.replyingTo.content),
|
|
39757
40433
|
}
|
|
39758
40434
|
: undefined;
|
|
39759
40435
|
return {
|
|
39760
40436
|
...messageWithCitations,
|
|
39761
|
-
content:
|
|
40437
|
+
content: postprocessChatMessageContent(messageWithCitations.content),
|
|
39762
40438
|
...(normalizedReplyingTo ? { replyingTo: normalizedReplyingTo } : {}),
|
|
39763
40439
|
};
|
|
39764
40440
|
}
|
|
40441
|
+
/**
|
|
40442
|
+
* Applies markdown-safe text normalization to one chat message content value.
|
|
40443
|
+
*
|
|
40444
|
+
* @private utility of `useChatPostprocessedMessages`
|
|
40445
|
+
*/
|
|
40446
|
+
function postprocessChatMessageContent(content) {
|
|
40447
|
+
const decodedContent = decodeJsonUnicodeEscapesInMarkdownText(content);
|
|
40448
|
+
return promptbookifyAiText(humanizeAiText(decodedContent));
|
|
40449
|
+
}
|
|
39765
40450
|
/**
|
|
39766
40451
|
* Memoizes the render-only message normalization used by `<Chat/>`.
|
|
39767
40452
|
*
|
|
@@ -40573,7 +41258,7 @@
|
|
|
40573
41258
|
* @public exported from `@promptbook/components`
|
|
40574
41259
|
*/
|
|
40575
41260
|
function Chat(props) {
|
|
40576
|
-
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;
|
|
41261
|
+
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;
|
|
40577
41262
|
const buttonColor = react.useMemo(() => Color.from(buttonColorRaw || '#0066cc'), [buttonColorRaw]);
|
|
40578
41263
|
const agentParticipant = react.useMemo(() => participants.find((participant) => participant.name === 'AGENT'), [participants]);
|
|
40579
41264
|
const postprocessedMessages = useChatPostprocessedMessages({
|
|
@@ -40618,7 +41303,7 @@
|
|
|
40618
41303
|
useChatCompleteNotification(messages, soundSystem);
|
|
40619
41304
|
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [feedbackStatus && (jsxRuntime.jsx("div", { className: classNames(styles$7.feedbackStatus, feedbackStatus.variant === 'success'
|
|
40620
41305
|
? styles$7.feedbackStatusSuccess
|
|
40621
|
-
: styles$7.feedbackStatusError), "aria-live": "polite", role: "status", children: feedbackStatus.message })), effectConfigs && effectConfigs.length > 0 && (jsxRuntime.jsx(ChatEffectsSystem, { messages: postprocessedMessages, effectConfigs: effectConfigs, soundSystem: soundSystem })), jsxRuntime.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: jsxRuntime.jsxs("div", { className: classNames(className, styles$7.chatMainFlow, getChatCssClassName('chatMainFlow'), chatCssClassNames.chatMainFlow), children: [children && jsxRuntime.jsx("div", { className: classNames(styles$7.chatChildren), children: children }), shouldShowScrollToBottom && (jsxRuntime.jsx("div", { className: styles$7.scrollToBottomContainer, children: jsxRuntime.jsxs("div", { className: styles$7.scrollToBottomWrapper, children: [jsxRuntime.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 && (jsxRuntime.jsx("span", { className: styles$7.scrollToBottomBadge, "aria-live": "polite", role: "status", children: badgeLabel }))] }) })), isVoiceCalling && (jsxRuntime.jsx("div", { className: styles$7.voiceCallIndicatorBar, children: jsxRuntime.jsxs("div", { className: styles$7.voiceCallIndicator, children: [jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "currentColor", children: jsxRuntime.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" }) }), jsxRuntime.jsx("span", { children: "Voice call active" }), jsxRuntime.jsx("div", { className: styles$7.voiceCallPulse })] }) })), jsxRuntime.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 }), jsxRuntime.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 && (jsxRuntime.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) }))] }) }), jsxRuntime.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 }), jsxRuntime.jsx(ChatCitationModal, { isOpen: citationModalOpen, citation: selectedCitation, participants: participants, soundSystem: soundSystem, onClose: closeCitationModal }), jsxRuntime.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 })] }));
|
|
41306
|
+
: styles$7.feedbackStatusError), "aria-live": "polite", role: "status", children: feedbackStatus.message })), effectConfigs && effectConfigs.length > 0 && (jsxRuntime.jsx(ChatEffectsSystem, { messages: postprocessedMessages, effectConfigs: effectConfigs, soundSystem: soundSystem })), jsxRuntime.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: jsxRuntime.jsxs("div", { className: classNames(className, styles$7.chatMainFlow, getChatCssClassName('chatMainFlow'), chatCssClassNames.chatMainFlow), children: [children && jsxRuntime.jsx("div", { className: classNames(styles$7.chatChildren), children: children }), shouldShowScrollToBottom && (jsxRuntime.jsx("div", { className: styles$7.scrollToBottomContainer, children: jsxRuntime.jsxs("div", { className: styles$7.scrollToBottomWrapper, children: [jsxRuntime.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 && (jsxRuntime.jsx("span", { className: styles$7.scrollToBottomBadge, "aria-live": "polite", role: "status", children: badgeLabel }))] }) })), isVoiceCalling && (jsxRuntime.jsx("div", { className: styles$7.voiceCallIndicatorBar, children: jsxRuntime.jsxs("div", { className: styles$7.voiceCallIndicator, children: [jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "currentColor", children: jsxRuntime.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" }) }), jsxRuntime.jsx("span", { children: "Voice call active" }), jsxRuntime.jsx("div", { className: styles$7.voiceCallPulse })] }) })), jsxRuntime.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 }), jsxRuntime.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 && (jsxRuntime.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) }))] }) }), jsxRuntime.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 }), jsxRuntime.jsx(ChatCitationModal, { isOpen: citationModalOpen, citation: selectedCitation, participants: participants, resolveCitationLabel: resolveCitationLabel, soundSystem: soundSystem, onClose: closeCitationModal }), jsxRuntime.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 })] }));
|
|
40622
41307
|
}
|
|
40623
41308
|
|
|
40624
41309
|
/**
|
|
@@ -48625,11 +49310,19 @@
|
|
|
48625
49310
|
try {
|
|
48626
49311
|
const json = JSON.parse(content);
|
|
48627
49312
|
const formattedJson = JSON.stringify(json, null, 4);
|
|
48628
|
-
return
|
|
49313
|
+
return spacetrim.spaceTrim((block) => `
|
|
49314
|
+
\`\`\`json
|
|
49315
|
+
${block(formattedJson)}
|
|
49316
|
+
\`\`\`
|
|
49317
|
+
`);
|
|
48629
49318
|
}
|
|
48630
49319
|
catch (error) {
|
|
48631
49320
|
// If JSON is invalid, still import it but maybe not as pretty JSON
|
|
48632
|
-
return
|
|
49321
|
+
return spacetrim.spaceTrim((block) => `
|
|
49322
|
+
\`\`\`json
|
|
49323
|
+
${block(content)}
|
|
49324
|
+
\`\`\`
|
|
49325
|
+
`);
|
|
48633
49326
|
}
|
|
48634
49327
|
},
|
|
48635
49328
|
};
|
|
@@ -48653,7 +49346,11 @@
|
|
|
48653
49346
|
import(content, mimeType) {
|
|
48654
49347
|
const extension = mimeTypeToExtension(mimeType);
|
|
48655
49348
|
const codeBlockType = extension || 'txt';
|
|
48656
|
-
return
|
|
49349
|
+
return spacetrim.spaceTrim((block) => `
|
|
49350
|
+
\`\`\`${codeBlockType}
|
|
49351
|
+
${block(content)}
|
|
49352
|
+
\`\`\`
|
|
49353
|
+
`);
|
|
48657
49354
|
},
|
|
48658
49355
|
};
|
|
48659
49356
|
|
|
@@ -48900,11 +49597,19 @@
|
|
|
48900
49597
|
const examples = [];
|
|
48901
49598
|
const initialMessage = (_a = parseResult.commitments.find((commitment) => commitment.type === 'INITIAL MESSAGE')) === null || _a === void 0 ? void 0 : _a.content;
|
|
48902
49599
|
if (initialMessage) {
|
|
48903
|
-
examples.push(
|
|
49600
|
+
examples.push(spacetrim.spaceTrim((block) => `
|
|
49601
|
+
**Agent:**
|
|
49602
|
+
${block(initialMessage)}
|
|
49603
|
+
`));
|
|
48904
49604
|
}
|
|
48905
49605
|
if (samples && samples.length > 0) {
|
|
48906
49606
|
for (const sample of samples) {
|
|
48907
|
-
examples.push(
|
|
49607
|
+
examples.push(spacetrim.spaceTrim((block) => `
|
|
49608
|
+
**User:** ${block(String(sample.question))}
|
|
49609
|
+
|
|
49610
|
+
**Agent:**
|
|
49611
|
+
${block(sample.answer)}
|
|
49612
|
+
`));
|
|
48908
49613
|
}
|
|
48909
49614
|
}
|
|
48910
49615
|
return examples;
|
|
@@ -55450,7 +56155,11 @@
|
|
|
55450
56155
|
};
|
|
55451
56156
|
}
|
|
55452
56157
|
return {
|
|
55453
|
-
content:
|
|
56158
|
+
content: spacetrim.spaceTrim((block) => `
|
|
56159
|
+
${block(content.slice(0, Math.max(0, maxCharacters)))}
|
|
56160
|
+
|
|
56161
|
+
[...truncated...]
|
|
56162
|
+
`),
|
|
55454
56163
|
isTruncated: true,
|
|
55455
56164
|
};
|
|
55456
56165
|
}
|