@tutti-os/agent-gui 0.0.91 → 0.0.93

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/dist/index.js CHANGED
@@ -16874,6 +16874,9 @@ var styles = {
16874
16874
  emptyHeroCarousel: "agent-gui-node__empty-hero-carousel",
16875
16875
  emptyHeroCarouselCanvas: "agent-gui-node__empty-hero-carousel-canvas",
16876
16876
  emptyHeroCarouselItem: "agent-gui-node__empty-hero-carousel-item",
16877
+ emptyHeroCarouselLayer: "agent-gui-node__empty-hero-carousel-layer",
16878
+ emptyHeroCarouselPlaceholder: "agent-gui-node__empty-hero-carousel-placeholder",
16879
+ emptyHeroCarouselStage: "agent-gui-node__empty-hero-carousel-stage",
16877
16880
  emptyHeroIconEffect: "agent-gui-node__empty-hero-icon-effect",
16878
16881
  emptyHeroIconRail: "agent-gui-node__empty-hero-icon-rail",
16879
16882
  emptyHeroIconRailItem: "agent-gui-node__empty-hero-icon-rail-item",
@@ -17155,19 +17158,35 @@ import {
17155
17158
  import * as THREE from "three";
17156
17159
  var CAMERA_FOV_DEG = 14;
17157
17160
  var CAMERA_Z = 7.5;
17158
- var WHEEL_TARGET_SLOTS = 21;
17159
- var TILE_SPACING = 1.35;
17160
- var UNFOCUSED_OPACITY = 0.55;
17161
- var SPRING_STIFFNESS = 90;
17162
- var SPRING_DAMPING_RATIO = 0.62;
17161
+ var WHEEL_TARGET_SLOTS = 40;
17162
+ var TILE_SPACING = 1.55;
17163
+ var VISIBLE_ARC_CURVATURE = 0.9;
17164
+ var MIN_RECORD_OPACITY = 0.22;
17165
+ var RECORD_FADE_RANGE_SLOTS = 4.5;
17166
+ var RECORD_FADE_CURVE = 1.45;
17167
+ var SPRING_STIFFNESS = 120;
17168
+ var SPRING_DAMPING_RATIO = 0.78;
17169
+ var SPRING_MIN_LAUNCH_VELOCITY = 2.6;
17163
17170
  var SPRING_SETTLE_EPSILON = 1e-3;
17164
17171
  var SPRING_SETTLE_VELOCITY = 0.02;
17172
+ var MAX_FRAME_DELTA_SECONDS = 0.032;
17165
17173
  var TEXTURE_SIZE = 256;
17166
- var TEXTURE_CORNER_RADIUS = 0.05;
17167
17174
  var BADGE_CORNER_RADIUS = 0.5;
17168
17175
  var BADGE_DIAMETER = 0.36;
17169
17176
  var BADGE_OFFSET = 0.4;
17170
17177
  var MAX_PIXEL_RATIO = 2;
17178
+ var RECORD_RADIUS_RATIO = 0.47;
17179
+ var RECORD_LABEL_RADIUS_RATIO = 0.41;
17180
+ var RECORD_SPINDLE_RADIUS_RATIO = 0.035;
17181
+ var RECORD_SPIN_SECONDS = 7;
17182
+ var RECORD_MODEL_SCALE = 1.3;
17183
+ var RECORD_MODEL_RADIUS = 0.475;
17184
+ var RECORD_MODEL_THICKNESS = 0.065;
17185
+ var RECORD_MODEL_TILT_X = -0.11;
17186
+ var RECORD_MODEL_SIDE_TILT_FACTOR = 0.18;
17187
+ var RECORD_MODEL_MAX_SIDE_TILT = 0.16;
17188
+ var RECORD_RENDER_RANGE_SLOTS = 3.4;
17189
+ var RECORD_EDGE_SEGMENTS = 48;
17171
17190
  function ringOffset(index, scroll, count) {
17172
17191
  if (count <= 1) {
17173
17192
  return index - scroll;
@@ -17181,7 +17200,114 @@ function ringOffset(index, scroll, count) {
17181
17200
  }
17182
17201
  return offset;
17183
17202
  }
17184
- function roundedIconTexture(image, onReadyRender, cornerRadius = TEXTURE_CORNER_RADIUS) {
17203
+ function vinylRecordTexture(image, onReadyRender) {
17204
+ const canvas = document.createElement("canvas");
17205
+ canvas.width = TEXTURE_SIZE;
17206
+ canvas.height = TEXTURE_SIZE;
17207
+ const context = canvas.getContext("2d");
17208
+ if (context) {
17209
+ const center = TEXTURE_SIZE / 2;
17210
+ const recordRadius = TEXTURE_SIZE * RECORD_RADIUS_RATIO;
17211
+ const labelRadius = recordRadius * RECORD_LABEL_RADIUS_RATIO;
17212
+ context.clearRect(0, 0, TEXTURE_SIZE, TEXTURE_SIZE);
17213
+ context.save();
17214
+ context.beginPath();
17215
+ context.arc(center, center, recordRadius, 0, Math.PI * 2);
17216
+ context.clip();
17217
+ const recordFill = context.createRadialGradient(
17218
+ center * 0.92,
17219
+ center * 0.88,
17220
+ labelRadius,
17221
+ center,
17222
+ center,
17223
+ recordRadius
17224
+ );
17225
+ recordFill.addColorStop(0, "rgb(26 26 27)");
17226
+ recordFill.addColorStop(0.54, "rgb(5 5 6)");
17227
+ recordFill.addColorStop(0.82, "rgb(18 18 19)");
17228
+ recordFill.addColorStop(1, "rgb(3 3 4)");
17229
+ context.fillStyle = recordFill;
17230
+ context.fillRect(0, 0, TEXTURE_SIZE, TEXTURE_SIZE);
17231
+ for (let radius = labelRadius + 4; radius < recordRadius - 3; radius += 3.5) {
17232
+ const grooveIndex = Math.round((radius - labelRadius) / 3.5);
17233
+ context.beginPath();
17234
+ context.arc(center, center, radius, 0, Math.PI * 2);
17235
+ context.strokeStyle = grooveIndex % 3 === 0 ? "rgb(255 255 255 / 0.12)" : "rgb(255 255 255 / 0.055)";
17236
+ context.lineWidth = grooveIndex % 3 === 0 ? 0.7 : 0.45;
17237
+ context.stroke();
17238
+ }
17239
+ context.save();
17240
+ context.translate(center, center);
17241
+ context.rotate(-Math.PI / 4);
17242
+ const sheen = context.createLinearGradient(
17243
+ -recordRadius,
17244
+ 0,
17245
+ recordRadius,
17246
+ 0
17247
+ );
17248
+ sheen.addColorStop(0, "rgb(255 255 255 / 0)");
17249
+ sheen.addColorStop(0.42, "rgb(255 255 255 / 0.02)");
17250
+ sheen.addColorStop(0.5, "rgb(255 255 255 / 0.18)");
17251
+ sheen.addColorStop(0.58, "rgb(255 255 255 / 0.02)");
17252
+ sheen.addColorStop(1, "rgb(255 255 255 / 0)");
17253
+ context.fillStyle = sheen;
17254
+ context.fillRect(
17255
+ -recordRadius,
17256
+ -recordRadius,
17257
+ recordRadius * 2,
17258
+ recordRadius * 2
17259
+ );
17260
+ context.restore();
17261
+ context.restore();
17262
+ context.save();
17263
+ context.beginPath();
17264
+ context.arc(center, center, labelRadius, 0, Math.PI * 2);
17265
+ context.clip();
17266
+ const scale = Math.max(
17267
+ labelRadius * 2 / image.width,
17268
+ labelRadius * 2 / image.height
17269
+ );
17270
+ const width = image.width * scale;
17271
+ const height = image.height * scale;
17272
+ context.drawImage(
17273
+ image,
17274
+ center - width / 2,
17275
+ center - height / 2,
17276
+ width,
17277
+ height
17278
+ );
17279
+ context.restore();
17280
+ context.beginPath();
17281
+ context.arc(center, center, labelRadius, 0, Math.PI * 2);
17282
+ context.strokeStyle = "rgb(255 255 255 / 0.2)";
17283
+ context.lineWidth = 1;
17284
+ context.stroke();
17285
+ context.beginPath();
17286
+ context.arc(
17287
+ center,
17288
+ center,
17289
+ recordRadius * RECORD_SPINDLE_RADIUS_RATIO,
17290
+ 0,
17291
+ Math.PI * 2
17292
+ );
17293
+ context.fillStyle = "rgb(5 5 6)";
17294
+ context.fill();
17295
+ context.strokeStyle = "rgb(255 255 255 / 0.18)";
17296
+ context.lineWidth = 0.75;
17297
+ context.stroke();
17298
+ context.beginPath();
17299
+ context.arc(center, center, recordRadius - 0.75, 0, Math.PI * 2);
17300
+ context.strokeStyle = "rgb(255 255 255 / 0.32)";
17301
+ context.lineWidth = 1.25;
17302
+ context.stroke();
17303
+ }
17304
+ const texture = new THREE.CanvasTexture(canvas);
17305
+ texture.colorSpace = THREE.SRGBColorSpace;
17306
+ texture.anisotropy = 4;
17307
+ onReadyRender();
17308
+ return texture;
17309
+ }
17310
+ function roundedIconTexture(image, onReadyRender, cornerRadius) {
17185
17311
  const canvas = document.createElement("canvas");
17186
17312
  canvas.width = TEXTURE_SIZE;
17187
17313
  canvas.height = TEXTURE_SIZE;
@@ -17224,8 +17350,11 @@ var AgentGuiHeroCarouselScene = class _AgentGuiHeroCarouselScene {
17224
17350
  renderer;
17225
17351
  scene;
17226
17352
  camera;
17353
+ edgeGeometry;
17354
+ faceGeometry;
17227
17355
  raycaster = new THREE.Raycaster();
17228
17356
  tiles = [];
17357
+ textures = /* @__PURE__ */ new Set();
17229
17358
  // Number of distinct agents; the wheel holds agentCount * repeats tiles
17230
17359
  // (the icon sequence repeated), and scroll/target count TILE slots.
17231
17360
  agentCount;
@@ -17237,8 +17366,12 @@ var AgentGuiHeroCarouselScene = class _AgentGuiHeroCarouselScene {
17237
17366
  scroll = 0;
17238
17367
  target = 0;
17239
17368
  velocity = 0;
17240
- frameHandle = null;
17369
+ renderFrameHandle = null;
17370
+ springFrameHandle = null;
17371
+ recordSpinFrameHandle = null;
17241
17372
  lastFrameAt = null;
17373
+ lastRecordSpinFrameAt = null;
17374
+ hoveredTile = null;
17242
17375
  disposed = false;
17243
17376
  constructor(options) {
17244
17377
  this.agentCount = options.items.length;
@@ -17258,29 +17391,78 @@ var AgentGuiHeroCarouselScene = class _AgentGuiHeroCarouselScene {
17258
17391
  this.scene = new THREE.Scene();
17259
17392
  this.camera = new THREE.PerspectiveCamera(CAMERA_FOV_DEG, 1, 0.1, 50);
17260
17393
  this.camera.position.set(0, 0, CAMERA_Z);
17394
+ this.scene.add(new THREE.AmbientLight(16777215, 1.25));
17395
+ const keyLight = new THREE.DirectionalLight(16777215, 2.4);
17396
+ keyLight.position.set(-2.5, 3.5, 5);
17397
+ this.scene.add(keyLight);
17398
+ const rimLight = new THREE.DirectionalLight(10467327, 0.9);
17399
+ rimLight.position.set(4, -1.5, 2.5);
17400
+ this.scene.add(rimLight);
17401
+ this.faceGeometry = new THREE.PlaneGeometry(1, 1);
17402
+ this.edgeGeometry = new THREE.CylinderGeometry(
17403
+ RECORD_MODEL_RADIUS,
17404
+ RECORD_MODEL_RADIUS,
17405
+ RECORD_MODEL_THICKNESS,
17406
+ RECORD_EDGE_SEGMENTS,
17407
+ 1,
17408
+ true
17409
+ );
17261
17410
  for (let slot = 0; slot < this.tileCount; slot++) {
17262
- const geometry = new THREE.PlaneGeometry(1, 1);
17263
- const material = new THREE.MeshBasicMaterial({
17411
+ const agentIndex = slot % this.agentCount;
17412
+ const poseGroup = new THREE.Group();
17413
+ const recordGroup = new THREE.Group();
17414
+ recordGroup.scale.setScalar(RECORD_MODEL_SCALE);
17415
+ const faceMaterial = new THREE.MeshBasicMaterial({
17264
17416
  transparent: true,
17265
17417
  depthWrite: false,
17266
17418
  visible: false
17267
17419
  });
17268
- const mesh = new THREE.Mesh(geometry, material);
17269
- mesh.userData.agentIndex = slot % this.agentCount;
17420
+ const faceMesh = new THREE.Mesh(this.faceGeometry, faceMaterial);
17421
+ faceMesh.position.z = RECORD_MODEL_THICKNESS / 2 + 2e-3;
17422
+ faceMesh.userData.agentIndex = agentIndex;
17423
+ const edgeMaterial = new THREE.MeshStandardMaterial({
17424
+ color: 460552,
17425
+ metalness: 0.42,
17426
+ roughness: 0.28,
17427
+ transparent: true,
17428
+ depthWrite: false
17429
+ });
17430
+ const edgeMesh = new THREE.Mesh(this.edgeGeometry, edgeMaterial);
17431
+ edgeMesh.rotation.x = Math.PI / 2;
17270
17432
  const badgeMaterial = new THREE.MeshBasicMaterial({
17271
17433
  transparent: true,
17272
17434
  depthWrite: false,
17273
- visible: false
17435
+ // The solid circle is the owner marker's asset-independent fallback.
17436
+ // Keep it visible while the optional remote avatar is loading or when
17437
+ // that avatar cannot safely become a WebGL texture.
17438
+ visible: options.items[slot % this.agentCount]?.badge != null
17274
17439
  });
17275
17440
  const badgeMesh = new THREE.Mesh(
17276
17441
  new THREE.CircleGeometry(BADGE_DIAMETER / 2, 32),
17277
17442
  badgeMaterial
17278
17443
  );
17279
- badgeMesh.position.set(BADGE_OFFSET, -BADGE_OFFSET, 0.01);
17280
- badgeMesh.userData.agentIndex = slot % this.agentCount;
17281
- mesh.add(badgeMesh);
17282
- this.scene.add(mesh);
17283
- this.tiles.push({ badgeMesh, mesh });
17444
+ badgeMesh.position.set(
17445
+ BADGE_OFFSET,
17446
+ -BADGE_OFFSET,
17447
+ RECORD_MODEL_THICKNESS / 2 + 0.01
17448
+ );
17449
+ badgeMesh.userData.agentIndex = agentIndex;
17450
+ recordGroup.add(edgeMesh, faceMesh);
17451
+ poseGroup.add(recordGroup, badgeMesh);
17452
+ poseGroup.visible = false;
17453
+ poseGroup.userData.agentIndex = agentIndex;
17454
+ this.scene.add(poseGroup);
17455
+ this.tiles.push({
17456
+ badgeMesh,
17457
+ edgeMaterial,
17458
+ edgeMesh,
17459
+ faceMaterial,
17460
+ faceMesh,
17461
+ poseGroup,
17462
+ ready: false,
17463
+ recordGroup,
17464
+ rotation: 0
17465
+ });
17284
17466
  }
17285
17467
  options.items.forEach((item, agentIndex) => {
17286
17468
  const loadedImage = options.loadedImages?.[agentIndex] ?? null;
@@ -17308,6 +17490,7 @@ var AgentGuiHeroCarouselScene = class _AgentGuiHeroCarouselScene {
17308
17490
  }
17309
17491
  });
17310
17492
  this.applyPoses();
17493
+ this.startRecordSpin();
17311
17494
  }
17312
17495
  setSize(width, height) {
17313
17496
  if (this.disposed || width <= 0 || height <= 0) {
@@ -17330,6 +17513,7 @@ var AgentGuiHeroCarouselScene = class _AgentGuiHeroCarouselScene {
17330
17513
  // icon sequence repeats); returns the normalized agent index.
17331
17514
  stepBy(direction) {
17332
17515
  this.target += direction;
17516
+ this.primeSpringMotion();
17333
17517
  this.animate();
17334
17518
  return this.targetIndex();
17335
17519
  }
@@ -17358,6 +17542,7 @@ var AgentGuiHeroCarouselScene = class _AgentGuiHeroCarouselScene {
17358
17542
  }
17359
17543
  this.target += best ?? 0;
17360
17544
  if (animateMove) {
17545
+ this.primeSpringMotion();
17361
17546
  this.animate();
17362
17547
  return;
17363
17548
  }
@@ -17368,6 +17553,26 @@ var AgentGuiHeroCarouselScene = class _AgentGuiHeroCarouselScene {
17368
17553
  }
17369
17554
  // Canvas-relative pointer coordinates -> agent index, or null.
17370
17555
  pick(x, y, width, height) {
17556
+ const tile = this.pickTile(x, y, width, height);
17557
+ const index = tile?.poseGroup.userData.agentIndex;
17558
+ return typeof index === "number" ? index : null;
17559
+ }
17560
+ // Gives playback to the record beneath the pointer. When no record is
17561
+ // hovered, playback returns to the record nearest the center.
17562
+ hover(x, y, width, height) {
17563
+ const tile = this.pickTile(x, y, width, height);
17564
+ if (tile !== this.hoveredTile) {
17565
+ this.hoveredTile = tile;
17566
+ this.startRecordSpin();
17567
+ }
17568
+ const index = tile?.poseGroup.userData.agentIndex;
17569
+ return typeof index === "number" ? index : null;
17570
+ }
17571
+ clearHover() {
17572
+ this.hoveredTile = null;
17573
+ this.startRecordSpin();
17574
+ }
17575
+ pickTile(x, y, width, height) {
17371
17576
  if (this.disposed || width <= 0 || height <= 0) {
17372
17577
  return null;
17373
17578
  }
@@ -17377,35 +17582,52 @@ var AgentGuiHeroCarouselScene = class _AgentGuiHeroCarouselScene {
17377
17582
  );
17378
17583
  this.raycaster.setFromCamera(pointer, this.camera);
17379
17584
  const meshes = this.tiles.filter(
17380
- (tile) => tile.mesh.material.visible && tile.mesh.material.opacity > 0.05
17585
+ (tile) => tile.poseGroup.visible && tile.faceMaterial.visible && tile.faceMaterial.opacity > 0.05
17381
17586
  ).flatMap(
17382
- (tile) => tile.badgeMesh.material.visible ? [tile.mesh, tile.badgeMesh] : [tile.mesh]
17587
+ (tile) => tile.badgeMesh.material.visible ? [tile.faceMesh, tile.badgeMesh] : [tile.faceMesh]
17383
17588
  );
17384
17589
  const hit = this.raycaster.intersectObjects(meshes, false)[0];
17385
- const index = hit?.object.userData.agentIndex;
17386
- return typeof index === "number" ? index : null;
17590
+ if (!hit) {
17591
+ return null;
17592
+ }
17593
+ return this.tiles.find(
17594
+ (tile) => tile.faceMesh === hit.object || tile.badgeMesh === hit.object
17595
+ ) ?? null;
17387
17596
  }
17388
17597
  dispose() {
17389
17598
  this.disposed = true;
17390
- if (this.frameHandle !== null) {
17391
- cancelAnimationFrame(this.frameHandle);
17392
- this.frameHandle = null;
17599
+ if (this.renderFrameHandle !== null) {
17600
+ cancelAnimationFrame(this.renderFrameHandle);
17601
+ this.renderFrameHandle = null;
17602
+ }
17603
+ if (this.springFrameHandle !== null) {
17604
+ cancelAnimationFrame(this.springFrameHandle);
17605
+ this.springFrameHandle = null;
17606
+ }
17607
+ if (this.recordSpinFrameHandle !== null) {
17608
+ cancelAnimationFrame(this.recordSpinFrameHandle);
17609
+ this.recordSpinFrameHandle = null;
17393
17610
  }
17394
17611
  for (const image of this.images) {
17395
17612
  image.onload = null;
17613
+ image.onerror = null;
17396
17614
  if (this.ownedImages.has(image)) {
17397
17615
  image.src = "";
17398
17616
  }
17399
17617
  }
17400
17618
  this.ownedImages.clear();
17401
17619
  for (const tile of this.tiles) {
17402
- tile.mesh.geometry.dispose();
17403
- tile.mesh.material.map?.dispose();
17404
- tile.mesh.material.dispose();
17405
17620
  tile.badgeMesh.geometry.dispose();
17406
- tile.badgeMesh.material.map?.dispose();
17407
17621
  tile.badgeMesh.material.dispose();
17622
+ tile.faceMaterial.dispose();
17623
+ tile.edgeMaterial.dispose();
17624
+ }
17625
+ for (const texture of this.textures) {
17626
+ texture.dispose();
17408
17627
  }
17628
+ this.textures.clear();
17629
+ this.faceGeometry.dispose();
17630
+ this.edgeGeometry.dispose();
17409
17631
  this.renderer.dispose();
17410
17632
  }
17411
17633
  prefersReducedMotion() {
@@ -17423,17 +17645,31 @@ var AgentGuiHeroCarouselScene = class _AgentGuiHeroCarouselScene {
17423
17645
  this.onSettle(this.targetIndex());
17424
17646
  return;
17425
17647
  }
17426
- if (this.frameHandle === null) {
17648
+ if (this.springFrameHandle === null) {
17649
+ if (this.renderFrameHandle !== null) {
17650
+ cancelAnimationFrame(this.renderFrameHandle);
17651
+ this.renderFrameHandle = null;
17652
+ }
17427
17653
  this.lastFrameAt = null;
17428
- this.frameHandle = requestAnimationFrame(this.frame);
17654
+ this.springFrameHandle = requestAnimationFrame(this.frame);
17655
+ }
17656
+ }
17657
+ primeSpringMotion() {
17658
+ const delta = this.target - this.scroll;
17659
+ const direction = Math.sign(delta);
17660
+ if (direction === 0) {
17661
+ return;
17662
+ }
17663
+ if (this.velocity * direction < SPRING_MIN_LAUNCH_VELOCITY) {
17664
+ this.velocity = direction * SPRING_MIN_LAUNCH_VELOCITY;
17429
17665
  }
17430
17666
  }
17431
17667
  frame = (now) => {
17432
- this.frameHandle = null;
17668
+ this.springFrameHandle = null;
17433
17669
  if (this.disposed) {
17434
17670
  return;
17435
17671
  }
17436
- const dt = this.lastFrameAt === null ? 1 / 60 : Math.min((now - this.lastFrameAt) / 1e3, 0.05);
17672
+ const dt = this.lastFrameAt === null ? 1 / 60 : Math.min((now - this.lastFrameAt) / 1e3, MAX_FRAME_DELTA_SECONDS);
17437
17673
  this.lastFrameAt = now;
17438
17674
  const delta = this.target - this.scroll;
17439
17675
  if (Math.abs(delta) <= SPRING_SETTLE_EPSILON && Math.abs(this.velocity) <= SPRING_SETTLE_VELOCITY) {
@@ -17449,14 +17685,54 @@ var AgentGuiHeroCarouselScene = class _AgentGuiHeroCarouselScene {
17449
17685
  this.scroll += this.velocity * dt;
17450
17686
  this.applyPoses();
17451
17687
  this.renderer.render(this.scene, this.camera);
17452
- this.frameHandle = requestAnimationFrame(this.frame);
17688
+ this.springFrameHandle = requestAnimationFrame(this.frame);
17689
+ };
17690
+ startRecordSpin() {
17691
+ if (this.disposed || this.prefersReducedMotion() || this.recordSpinFrameHandle !== null) {
17692
+ return;
17693
+ }
17694
+ this.lastRecordSpinFrameAt = null;
17695
+ this.recordSpinFrameHandle = requestAnimationFrame(this.recordSpinFrame);
17696
+ }
17697
+ recordSpinFrame = (now) => {
17698
+ this.recordSpinFrameHandle = null;
17699
+ const spinningTile = this.hoveredTile ?? this.centerTile();
17700
+ if (this.disposed || !spinningTile || this.prefersReducedMotion()) {
17701
+ return;
17702
+ }
17703
+ const dt = this.lastRecordSpinFrameAt === null ? 1 / 60 : Math.min(
17704
+ (now - this.lastRecordSpinFrameAt) / 1e3,
17705
+ MAX_FRAME_DELTA_SECONDS
17706
+ );
17707
+ this.lastRecordSpinFrameAt = now;
17708
+ spinningTile.rotation = (spinningTile.rotation + Math.PI * 2 * dt / RECORD_SPIN_SECONDS) % (Math.PI * 2);
17709
+ if (this.springFrameHandle === null) {
17710
+ this.applyPoses();
17711
+ this.renderer.render(this.scene, this.camera);
17712
+ }
17713
+ this.recordSpinFrameHandle = requestAnimationFrame(this.recordSpinFrame);
17453
17714
  };
17715
+ centerTile() {
17716
+ let centeredTile = null;
17717
+ let centeredOffset = Number.POSITIVE_INFINITY;
17718
+ this.tiles.forEach((tile, index) => {
17719
+ if (!tile.ready) {
17720
+ return;
17721
+ }
17722
+ const offset = Math.abs(ringOffset(index, this.scroll, this.tileCount));
17723
+ if (offset < centeredOffset) {
17724
+ centeredTile = tile;
17725
+ centeredOffset = offset;
17726
+ }
17727
+ });
17728
+ return centeredTile;
17729
+ }
17454
17730
  requestRender() {
17455
- if (this.disposed || this.frameHandle !== null) {
17731
+ if (this.disposed || this.renderFrameHandle !== null || this.springFrameHandle !== null) {
17456
17732
  return;
17457
17733
  }
17458
- this.frameHandle = requestAnimationFrame(() => {
17459
- this.frameHandle = null;
17734
+ this.renderFrameHandle = requestAnimationFrame(() => {
17735
+ this.renderFrameHandle = null;
17460
17736
  if (!this.disposed) {
17461
17737
  this.renderer.render(this.scene, this.camera);
17462
17738
  }
@@ -17466,53 +17742,124 @@ var AgentGuiHeroCarouselScene = class _AgentGuiHeroCarouselScene {
17466
17742
  if (this.disposed) {
17467
17743
  return;
17468
17744
  }
17469
- const texture = roundedIconTexture(image, () => this.requestRender());
17745
+ const texture = vinylRecordTexture(image, () => this.requestRender());
17746
+ this.textures.add(texture);
17470
17747
  for (const tile of this.tiles) {
17471
- if (tile.mesh.userData.agentIndex === agentIndex) {
17472
- tile.mesh.material.map = texture;
17473
- tile.mesh.material.visible = true;
17474
- tile.mesh.material.needsUpdate = true;
17748
+ if (tile.poseGroup.userData.agentIndex === agentIndex) {
17749
+ tile.faceMaterial.map = texture;
17750
+ tile.faceMaterial.visible = true;
17751
+ tile.faceMaterial.needsUpdate = true;
17752
+ tile.ready = true;
17475
17753
  }
17476
17754
  }
17755
+ this.applyPoses();
17756
+ this.startRecordSpin();
17477
17757
  }
17478
17758
  loadBadgeImage(badgeUrl, agentIndex) {
17479
17759
  const image = new Image();
17760
+ image.crossOrigin = "anonymous";
17480
17761
  image.decoding = "async";
17481
17762
  image.loading = "eager";
17482
17763
  this.ownedImages.add(image);
17483
17764
  this.images.push(image);
17765
+ let settled = false;
17766
+ const keepFallback = () => {
17767
+ if (settled) {
17768
+ return;
17769
+ }
17770
+ settled = true;
17771
+ this.requestRender();
17772
+ };
17773
+ const applyDecodedImage = () => {
17774
+ if (settled) {
17775
+ return;
17776
+ }
17777
+ settled = true;
17778
+ this.applyBadgeImageTexture(image, agentIndex);
17779
+ };
17484
17780
  image.onload = () => {
17485
17781
  if (this.disposed) {
17486
17782
  return;
17487
17783
  }
17488
- const texture = roundedIconTexture(
17784
+ let decode;
17785
+ try {
17786
+ decode = image.decode?.();
17787
+ } catch {
17788
+ keepFallback();
17789
+ return;
17790
+ }
17791
+ if (decode) {
17792
+ void decode.then(applyDecodedImage).catch(keepFallback);
17793
+ return;
17794
+ }
17795
+ applyDecodedImage();
17796
+ };
17797
+ image.onerror = keepFallback;
17798
+ image.src = badgeUrl;
17799
+ }
17800
+ applyBadgeImageTexture(image, agentIndex) {
17801
+ if (this.disposed) {
17802
+ return;
17803
+ }
17804
+ let texture = null;
17805
+ try {
17806
+ texture = roundedIconTexture(
17489
17807
  image,
17490
17808
  () => this.requestRender(),
17491
17809
  BADGE_CORNER_RADIUS
17492
17810
  );
17493
- for (const tile of this.tiles) {
17494
- if (tile.mesh.userData.agentIndex === agentIndex) {
17495
- tile.badgeMesh.material.map = texture;
17496
- tile.badgeMesh.material.visible = true;
17497
- tile.badgeMesh.material.needsUpdate = true;
17498
- }
17499
- }
17811
+ this.renderer.initTexture(texture);
17812
+ } catch {
17813
+ texture?.dispose();
17500
17814
  this.requestRender();
17501
- };
17502
- image.src = badgeUrl;
17815
+ return;
17816
+ }
17817
+ this.textures.add(texture);
17818
+ for (const tile of this.tiles) {
17819
+ if (tile.poseGroup.userData.agentIndex === agentIndex) {
17820
+ tile.badgeMesh.material.map = texture;
17821
+ tile.badgeMesh.material.visible = true;
17822
+ tile.badgeMesh.material.needsUpdate = true;
17823
+ }
17824
+ }
17825
+ this.requestRender();
17503
17826
  }
17504
17827
  applyPoses() {
17505
17828
  const step = Math.PI * 2 / Math.max(this.tileCount, 1);
17506
17829
  this.tiles.forEach((tile, index) => {
17507
17830
  const offset = ringOffset(index, this.scroll, this.tileCount);
17831
+ const visible = tile.ready && Math.abs(offset) <= RECORD_RENDER_RANGE_SLOTS;
17832
+ tile.poseGroup.visible = visible;
17833
+ if (!visible) {
17834
+ return;
17835
+ }
17508
17836
  const angle = offset * step;
17509
17837
  const x = this.wheelRadius * Math.sin(angle);
17510
- const y = this.wheelRadius * (Math.cos(angle) - 1);
17511
- tile.mesh.position.set(x, y, 0);
17512
- tile.mesh.rotation.z = -angle;
17513
- const focus = THREE.MathUtils.clamp(1 - Math.abs(offset), 0, 1);
17514
- tile.mesh.material.opacity = UNFOCUSED_OPACITY + (1 - UNFOCUSED_OPACITY) * focus;
17515
- tile.badgeMesh.material.opacity = tile.mesh.material.opacity;
17838
+ const y = this.wheelRadius * (Math.cos(angle) - 1) * VISIBLE_ARC_CURVATURE;
17839
+ tile.poseGroup.position.set(x, y, 0);
17840
+ const fadeProgress = THREE.MathUtils.clamp(
17841
+ 1 - Math.abs(offset) / RECORD_FADE_RANGE_SLOTS,
17842
+ 0,
17843
+ 1
17844
+ );
17845
+ const rangeOpacity = Math.pow(
17846
+ THREE.MathUtils.smoothstep(fadeProgress, 0, 1),
17847
+ RECORD_FADE_CURVE
17848
+ );
17849
+ tile.poseGroup.rotation.set(
17850
+ RECORD_MODEL_TILT_X,
17851
+ THREE.MathUtils.clamp(
17852
+ -angle * RECORD_MODEL_SIDE_TILT_FACTOR,
17853
+ -RECORD_MODEL_MAX_SIDE_TILT,
17854
+ RECORD_MODEL_MAX_SIDE_TILT
17855
+ ),
17856
+ -angle * VISIBLE_ARC_CURVATURE
17857
+ );
17858
+ tile.recordGroup.rotation.z = -tile.rotation;
17859
+ const opacity = MIN_RECORD_OPACITY + (1 - MIN_RECORD_OPACITY) * rangeOpacity;
17860
+ tile.faceMaterial.opacity = opacity;
17861
+ tile.edgeMaterial.opacity = opacity;
17862
+ tile.badgeMesh.material.opacity = opacity;
17516
17863
  });
17517
17864
  }
17518
17865
  };
@@ -17719,6 +18066,7 @@ var AgentGUIHeroAgentCarousel = memo2(
17719
18066
  null
17720
18067
  );
17721
18068
  const suppressClickRef = useRef5(false);
18069
+ const pointerActivatedIndexRef = useRef5(null);
17722
18070
  const handlePointerDown = (event) => {
17723
18071
  if (!interactive || event.button !== 0) {
17724
18072
  return;
@@ -17740,6 +18088,7 @@ var AgentGUIHeroAgentCarousel = memo2(
17740
18088
  }
17741
18089
  drag.anchorX = event.clientX;
17742
18090
  suppressClickRef.current = true;
18091
+ pointerActivatedIndexRef.current = null;
17743
18092
  stepBy(deltaX < 0 ? 1 : -1);
17744
18093
  };
17745
18094
  const handlePointerEnd = (event) => {
@@ -17752,6 +18101,7 @@ var AgentGUIHeroAgentCarousel = memo2(
17752
18101
  return;
17753
18102
  }
17754
18103
  suppressClickRef.current = false;
18104
+ pointerActivatedIndexRef.current = null;
17755
18105
  event.preventDefault();
17756
18106
  event.stopPropagation();
17757
18107
  };
@@ -17782,18 +18132,53 @@ var AgentGUIHeroAgentCarousel = memo2(
17782
18132
  rect.height
17783
18133
  );
17784
18134
  };
18135
+ const activateOnPointerDown = (index, event) => {
18136
+ if (event.button !== 0) {
18137
+ return;
18138
+ }
18139
+ pointerActivatedIndexRef.current = index;
18140
+ handleItemClick(index);
18141
+ };
18142
+ const activateOnClick = (index) => {
18143
+ if (pointerActivatedIndexRef.current === index) {
18144
+ pointerActivatedIndexRef.current = null;
18145
+ return;
18146
+ }
18147
+ pointerActivatedIndexRef.current = null;
18148
+ handleItemClick(index);
18149
+ };
18150
+ const handleCanvasPointerDown = (event) => {
18151
+ const index = pickAt(event);
18152
+ if (index !== null) {
18153
+ activateOnPointerDown(index, event);
18154
+ }
18155
+ };
17785
18156
  const handleCanvasClick = (event) => {
17786
18157
  const index = pickAt(event);
17787
18158
  if (index !== null) {
17788
- handleItemClick(index);
18159
+ activateOnClick(index);
17789
18160
  }
17790
18161
  };
17791
18162
  const handleCanvasHover = (event) => {
18163
+ const scene = sceneRef.current;
17792
18164
  const canvas = canvasRef.current;
17793
- if (!canvas) {
18165
+ if (!scene || !canvas) {
17794
18166
  return;
17795
18167
  }
17796
- canvas.style.cursor = pickAt(event) !== null ? "pointer" : "";
18168
+ const rect = canvas.getBoundingClientRect();
18169
+ const hoveredIndex = scene.hover(
18170
+ event.clientX - rect.left,
18171
+ event.clientY - rect.top,
18172
+ rect.width,
18173
+ rect.height
18174
+ );
18175
+ canvas.style.cursor = hoveredIndex !== null ? "pointer" : "";
18176
+ };
18177
+ const handleCanvasLeave = () => {
18178
+ sceneRef.current?.clearHover();
18179
+ if (canvasRef.current) {
18180
+ canvasRef.current.style.cursor = "";
18181
+ }
17797
18182
  };
17798
18183
  return /* @__PURE__ */ jsxs9(
17799
18184
  "div",
@@ -17818,7 +18203,9 @@ var AgentGUIHeroAgentCarousel = memo2(
17818
18203
  "aria-hidden": "true",
17819
18204
  className: AgentGUINode_styles_default.emptyHeroCarouselCanvas,
17820
18205
  onClick: interactive ? handleCanvasClick : void 0,
17821
- onPointerMove: interactive ? handleCanvasHover : void 0
18206
+ onPointerDown: interactive ? handleCanvasPointerDown : void 0,
18207
+ onPointerMove: interactive ? handleCanvasHover : void 0,
18208
+ onPointerLeave: interactive ? handleCanvasLeave : void 0
17822
18209
  }
17823
18210
  ),
17824
18211
  items.map((item, index) => {
@@ -17838,7 +18225,8 @@ var AgentGUIHeroAgentCarousel = memo2(
17838
18225
  "aria-label": label,
17839
18226
  "aria-pressed": isCenter,
17840
18227
  title: item.label,
17841
- onClick: () => handleItemClick(index),
18228
+ onPointerDown: (event) => activateOnPointerDown(index, event),
18229
+ onClick: () => activateOnClick(index),
17842
18230
  children: item.label
17843
18231
  },
17844
18232
  key
@@ -27161,7 +27549,7 @@ function buildAgentConversationHandoffPrompt(input) {
27161
27549
  input.labels,
27162
27550
  input.uiLanguage
27163
27551
  );
27164
- const mentionLabel = `${sourceAgentLabel}${title ? ` ${title}` : ""}`.trim();
27552
+ const mentionLabel = title || sourceAgentLabel;
27165
27553
  const href = createAgentSessionMentionHref({
27166
27554
  agentTargetId: conversation.agentTargetId,
27167
27555
  agentSessionId: conversation.id,
@@ -27746,7 +28134,6 @@ function AgentGUINodeView({
27746
28134
  labels,
27747
28135
  previewMode,
27748
28136
  workspaceId: viewModel.workspaceId,
27749
- selectedAgentTarget: viewModel.selectedAgentTarget,
27750
28137
  agentTargets: viewModel.agentTargets,
27751
28138
  agentTargetsLoading: viewModel.agentTargetsLoading,
27752
28139
  renderProviderRailEmpty,
@@ -28924,7 +29311,7 @@ var AgentGUIDetailPane = memo3(function AgentGUIDetailPane2({
28924
29311
  emptyHeroProviderLabel
28925
29312
  ) : emptyHeroBaseLabel;
28926
29313
  const emptyHeroAvatarPresentations = useMemo11(
28927
- () => viewModel.conversationFilter.kind === "all" ? viewModel.agentTargets.map(projectAgentGUIAgentTargetAvatar) : viewModel.selectedAgentTarget ? [projectAgentGUIAgentTargetAvatar(viewModel.selectedAgentTarget)] : [
29314
+ () => viewModel.agentTargets.length > 0 ? viewModel.agentTargets.map(projectAgentGUIAgentTargetAvatar) : viewModel.selectedAgentTarget ? [projectAgentGUIAgentTargetAvatar(viewModel.selectedAgentTarget)] : [
28928
29315
  createFallbackAgentGUIAgentAvatar({
28929
29316
  provider: emptyHeroProvider,
28930
29317
  label: emptyHeroProviderLabel,
@@ -28934,7 +29321,6 @@ var AgentGUIDetailPane = memo3(function AgentGUIDetailPane2({
28934
29321
  [
28935
29322
  emptyHeroProvider,
28936
29323
  emptyHeroProviderLabel,
28937
- viewModel.conversationFilter.kind,
28938
29324
  viewModel.agentTargets,
28939
29325
  viewModel.selectedAgentTarget
28940
29326
  ]
@@ -29355,7 +29741,7 @@ var AgentGUIDetailPane = memo3(function AgentGUIDetailPane2({
29355
29741
  disabledAgentTarget.provider
29356
29742
  ),
29357
29743
  unavailableReason: disabledAgentTarget.unavailableReason ?? null
29358
- }) }) : emptyProviderReadinessGate ? shouldRenderProviderReadinessGateState ? /* @__PURE__ */ jsx35(Fragment9, { children: renderProviderReadinessGateState?.({
29744
+ }) }) : emptyProviderReadinessGate && shouldRenderProviderReadinessGateState ? /* @__PURE__ */ jsx35(Fragment9, { children: renderProviderReadinessGateState?.({
29359
29745
  provider: emptyHeroProvider,
29360
29746
  providerLabel: emptyHeroProviderLabel || resolveAgentGuiWorkbenchProviderLabel(emptyHeroProvider),
29361
29747
  target: viewModel.selectedAgentTarget ?? null,
@@ -29363,42 +29749,53 @@ var AgentGUIDetailPane = memo3(function AgentGUIDetailPane2({
29363
29749
  gate: emptyProviderReadinessGate,
29364
29750
  showAllProviders: viewModel.conversationFilter.kind === "all"
29365
29751
  }) }) : /* @__PURE__ */ jsx35(
29366
- AgentGUIProviderReadinessGatePane,
29367
- {
29368
- provider: emptyHeroProvider,
29369
- gate: emptyProviderReadinessGate,
29370
- showAllProviders: viewModel.conversationFilter.kind === "all",
29371
- emptyLabel: emptyHeroLabel,
29372
- emptyProvider: emptyHeroProviderLabel,
29373
- agentTargets: composerAgentTargets,
29374
- selectedAgentTarget: viewModel.selectedAgentTarget,
29375
- onProviderSelect: canSwitchComposerProvider && viewModel.activeConversationId === null ? selectHomeComposerAgentTargetAndFocus : void 0,
29376
- providerSelectLabel: labels.providerSwitchLabel,
29377
- labels
29378
- }
29379
- ) : /* @__PURE__ */ jsx35(
29380
- AgentGUIEmptyHeroPane,
29752
+ AgentGUIEmptyHeroCarouselStage,
29381
29753
  {
29382
- provider: emptyHeroProvider,
29383
- emptyLabel: emptyHeroLabel,
29384
- emptyProvider: emptyHeroProviderLabel,
29385
- avatarPresentations: emptyHeroAvatarPresentations,
29386
- inlineNoticeChrome,
29387
- isRespondingApproval: viewModel.isRespondingApproval,
29388
- onSubmitApprovalOption: submitApprovalOption,
29389
- onRetryActivation: retryActivation,
29390
- onAuthLogin: authLogin,
29391
- onContinueInNewConversation: continueInNewConversation,
29754
+ activeAgentTargetId: viewModel.selectedAgentTarget?.agentTargetId ?? viewModel.selectedAgentTarget?.targetId,
29755
+ items: emptyHeroAvatarPresentations,
29392
29756
  onProviderSelect: canSwitchComposerProvider && viewModel.activeConversationId === null ? selectHomeComposerAgentTargetAndFocus : void 0,
29393
- agentTargets: composerAgentTargets,
29394
- selectedAgentTarget: viewModel.selectedAgentTarget,
29395
- chromeLabels,
29396
- composerProps: emptyHeroComposerProps,
29397
29757
  providerSelectLabel: labels.providerSwitchLabel,
29398
- suggestions: labels.homeSuggestions ?? EMPTY_HOME_SUGGESTIONS,
29399
- suggestionsCloseLabel: labels.homeSuggestionsClose,
29400
- onSelectSuggestion: handleSelectHomeSuggestion,
29401
- onSelectSuggestionAction: handleHomeSuggestionAction
29758
+ children: emptyProviderReadinessGate ? /* @__PURE__ */ jsx35(
29759
+ AgentGUIProviderReadinessGatePane,
29760
+ {
29761
+ provider: emptyHeroProvider,
29762
+ gate: emptyProviderReadinessGate,
29763
+ showAllProviders: viewModel.conversationFilter.kind === "all",
29764
+ carouselMountedExternally: emptyHeroAvatarPresentations.length > 1,
29765
+ emptyLabel: emptyHeroLabel,
29766
+ emptyProvider: emptyHeroProviderLabel,
29767
+ agentTargets: composerAgentTargets,
29768
+ selectedAgentTarget: viewModel.selectedAgentTarget,
29769
+ onProviderSelect: canSwitchComposerProvider && viewModel.activeConversationId === null ? selectHomeComposerAgentTargetAndFocus : void 0,
29770
+ providerSelectLabel: labels.providerSwitchLabel,
29771
+ labels
29772
+ }
29773
+ ) : /* @__PURE__ */ jsx35(
29774
+ AgentGUIEmptyHeroPane,
29775
+ {
29776
+ provider: emptyHeroProvider,
29777
+ emptyLabel: emptyHeroLabel,
29778
+ emptyProvider: emptyHeroProviderLabel,
29779
+ avatarPresentations: emptyHeroAvatarPresentations,
29780
+ carouselMountedExternally: emptyHeroAvatarPresentations.length > 1,
29781
+ inlineNoticeChrome,
29782
+ isRespondingApproval: viewModel.isRespondingApproval,
29783
+ onSubmitApprovalOption: submitApprovalOption,
29784
+ onRetryActivation: retryActivation,
29785
+ onAuthLogin: authLogin,
29786
+ onContinueInNewConversation: continueInNewConversation,
29787
+ onProviderSelect: canSwitchComposerProvider && viewModel.activeConversationId === null ? selectHomeComposerAgentTargetAndFocus : void 0,
29788
+ agentTargets: composerAgentTargets,
29789
+ selectedAgentTarget: viewModel.selectedAgentTarget,
29790
+ chromeLabels,
29791
+ composerProps: emptyHeroComposerProps,
29792
+ providerSelectLabel: labels.providerSwitchLabel,
29793
+ suggestions: labels.homeSuggestions ?? EMPTY_HOME_SUGGESTIONS,
29794
+ suggestionsCloseLabel: labels.homeSuggestionsClose,
29795
+ onSelectSuggestion: handleSelectHomeSuggestion,
29796
+ onSelectSuggestionAction: handleHomeSuggestionAction
29797
+ }
29798
+ )
29402
29799
  }
29403
29800
  ) : /* @__PURE__ */ jsx35(
29404
29801
  AgentGUIConversationTimelinePane,
@@ -29538,11 +29935,35 @@ function useOptionalStableEventCallback(callback) {
29538
29935
  }, [callback != null]);
29539
29936
  }
29540
29937
  var EMPTY_HOME_SUGGESTIONS = Object.freeze([]);
29938
+ var AgentGUIEmptyHeroCarouselStage = memo3(
29939
+ function AgentGUIEmptyHeroCarouselStage2({
29940
+ activeAgentTargetId,
29941
+ children,
29942
+ items,
29943
+ onProviderSelect,
29944
+ providerSelectLabel
29945
+ }) {
29946
+ "use memo";
29947
+ return /* @__PURE__ */ jsxs22("div", { className: AgentGUINode_styles_default.emptyHeroCarouselStage, children: [
29948
+ items.length > 1 ? /* @__PURE__ */ jsx35("div", { className: AgentGUINode_styles_default.emptyHeroCarouselLayer, children: /* @__PURE__ */ jsx35(
29949
+ AgentGUIHeroAgentCarousel,
29950
+ {
29951
+ activeAgentTargetId,
29952
+ items,
29953
+ onProviderSelect,
29954
+ providerSelectLabel
29955
+ }
29956
+ ) }) : null,
29957
+ children
29958
+ ] });
29959
+ }
29960
+ );
29541
29961
  var AgentGUIEmptyHeroPane = memo3(function AgentGUIEmptyHeroPane2({
29542
29962
  provider,
29543
29963
  emptyLabel,
29544
29964
  emptyProvider,
29545
29965
  avatarPresentations,
29966
+ carouselMountedExternally = false,
29546
29967
  inlineNoticeChrome,
29547
29968
  isRespondingApproval,
29548
29969
  onSubmitApprovalOption,
@@ -29571,23 +29992,29 @@ var AgentGUIEmptyHeroPane = memo3(function AgentGUIEmptyHeroPane2({
29571
29992
  (avatar) => `${avatar.agentTargetId}:${avatar.iconUrl}:${avatar.badge?.iconUrl ?? ""}`
29572
29993
  ).join("|");
29573
29994
  return /* @__PURE__ */ jsx35("div", { className: AgentGUINode_styles_default.emptyHero, children: /* @__PURE__ */ jsxs22("div", { className: AgentGUINode_styles_default.emptyHeroBody, children: [
29574
- /* @__PURE__ */ jsx35("div", { className: AgentGUINode_styles_default.emptyHeroIconSlot, children: heroAvatarPresentations.length > 1 ? /* @__PURE__ */ jsx35(
29575
- AgentGUIHeroAgentCarousel,
29576
- {
29577
- activeAgentTargetId: selectedAgentTarget?.agentTargetId ?? selectedAgentTarget?.targetId,
29578
- items: heroAvatarPresentations,
29579
- onProviderSelect,
29580
- providerSelectLabel
29581
- },
29582
- heroIconAnimationKey
29583
- ) : /* @__PURE__ */ jsx35(
29584
- AgentGUIAgentAvatarVisual,
29995
+ /* @__PURE__ */ jsx35(
29996
+ "div",
29585
29997
  {
29586
- className: AgentGUINode_styles_default.emptyHeroIconEffect,
29587
- presentation: heroAvatarPresentations[0]
29588
- },
29589
- heroIconAnimationKey
29590
- ) }),
29998
+ className: AgentGUINode_styles_default.emptyHeroIconSlot,
29999
+ "data-carousel-placeholder": carouselMountedExternally || void 0,
30000
+ children: carouselMountedExternally ? null : heroAvatarPresentations.length > 1 ? /* @__PURE__ */ jsx35(
30001
+ AgentGUIHeroAgentCarousel,
30002
+ {
30003
+ activeAgentTargetId: selectedAgentTarget?.agentTargetId ?? selectedAgentTarget?.targetId,
30004
+ items: heroAvatarPresentations,
30005
+ onProviderSelect,
30006
+ providerSelectLabel
30007
+ }
30008
+ ) : /* @__PURE__ */ jsx35(
30009
+ AgentGUIAgentAvatarVisual,
30010
+ {
30011
+ className: AgentGUINode_styles_default.emptyHeroIconEffect,
30012
+ presentation: heroAvatarPresentations[0]
30013
+ },
30014
+ heroIconAnimationKey
30015
+ )
30016
+ }
30017
+ ),
29591
30018
  /* @__PURE__ */ jsx35("h2", { className: AgentGUINode_styles_default.emptyHeroTitle, children: /* @__PURE__ */ jsx35(
29592
30019
  EmptyHeroTitle,
29593
30020
  {
@@ -29634,6 +30061,7 @@ var AgentGUIProviderReadinessGatePane = memo3(
29634
30061
  selectedAgentTarget,
29635
30062
  onProviderSelect,
29636
30063
  providerSelectLabel,
30064
+ carouselMountedExternally = false,
29637
30065
  labels
29638
30066
  }) {
29639
30067
  "use memo";
@@ -29657,7 +30085,13 @@ var AgentGUIProviderReadinessGatePane = memo3(
29657
30085
  "data-testid": "agent-gui-provider-readiness-gate",
29658
30086
  role: "status",
29659
30087
  children: [
29660
- showAllProviders ? /* @__PURE__ */ jsx35(
30088
+ carouselMountedExternally ? /* @__PURE__ */ jsx35(
30089
+ "div",
30090
+ {
30091
+ "aria-hidden": "true",
30092
+ className: AgentGUINode_styles_default.emptyHeroCarouselPlaceholder
30093
+ }
30094
+ ) : showAllProviders ? /* @__PURE__ */ jsx35(
29661
30095
  AgentGUIHeroAgentCarousel,
29662
30096
  {
29663
30097
  activeAgentTargetId: selectedAgentTarget?.agentTargetId ?? selectedAgentTarget?.targetId,
@@ -30499,7 +30933,6 @@ var AgentGUIProviderRail = memo3(function AgentGUIProviderRail2({
30499
30933
  labels,
30500
30934
  previewMode,
30501
30935
  workspaceId,
30502
- selectedAgentTarget,
30503
30936
  agentTargets,
30504
30937
  agentTargetsLoading,
30505
30938
  renderProviderRailEmpty,
@@ -30552,27 +30985,11 @@ var AgentGUIProviderRail = memo3(function AgentGUIProviderRail2({
30552
30985
  return applyAgentGUIProviderRailOrder(railAgentTargets, providerRailOrder);
30553
30986
  }, [providerRailOrder, railAgentTargets]);
30554
30987
  const visibleProviderTiles = providerTiles;
30555
- const selectedAgentTargetIsPlaceholder = selectedAgentTarget?.disabled === true;
30556
- const allTileSelected = conversationFilter.kind === "all" && !selectedAgentTargetIsPlaceholder;
30988
+ const allTileSelected = conversationFilter.kind === "all";
30557
30989
  const selectAllProviders = useCallback11(() => {
30558
30990
  onUpdateConversationFilter({ kind: "all" });
30559
- if (selectedAgentTargetIsPlaceholder) {
30560
- const fallbackTarget = railAgentTargets.find((target) => target.disabled !== true) ?? null;
30561
- if (fallbackTarget) {
30562
- onSelectConversationFilterTarget({
30563
- provider: fallbackTarget.provider,
30564
- agentTargetId: fallbackTarget.targetId
30565
- });
30566
- }
30567
- }
30568
30991
  onRequestComposerFocus();
30569
- }, [
30570
- onSelectConversationFilterTarget,
30571
- onRequestComposerFocus,
30572
- onUpdateConversationFilter,
30573
- railAgentTargets,
30574
- selectedAgentTargetIsPlaceholder
30575
- ]);
30992
+ }, [onRequestComposerFocus, onUpdateConversationFilter]);
30576
30993
  const selectAgentTargetTile = useCallback11(
30577
30994
  (target) => {
30578
30995
  onSelectConversationFilterTarget({
@@ -30818,7 +31235,7 @@ var AgentGUIProviderRail = memo3(function AgentGUIProviderRail2({
30818
31235
  `provider-target-loading-${index}`
30819
31236
  )) : null,
30820
31237
  visibleProviderTiles.map((target) => {
30821
- const providerSelected = visibleProviderTiles.length === 1 ? true : target.disabled === true ? selectedAgentTarget?.provider === target.provider && selectedAgentTarget?.targetId === target.targetId : agentGUIAgentTargetMatchesConversationFilter(
31238
+ const providerSelected = visibleProviderTiles.length === 1 ? true : agentGUIAgentTargetMatchesConversationFilter(
30822
31239
  target,
30823
31240
  conversationFilter
30824
31241
  );