@absolutejs/voice 0.0.22-beta.505 → 0.0.22-beta.507

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/vue/index.js CHANGED
@@ -12082,8 +12082,350 @@ var VoiceWidget = defineComponent18({
12082
12082
  };
12083
12083
  }
12084
12084
  });
12085
+ // src/vue/VoiceCallPlayer.ts
12086
+ import {
12087
+ defineComponent as defineComponent19,
12088
+ h as h19,
12089
+ onMounted as onMounted10,
12090
+ onUnmounted as onUnmounted23,
12091
+ ref as ref18,
12092
+ shallowRef as shallowRef22,
12093
+ watch
12094
+ } from "vue";
12095
+
12096
+ // src/client/callPlayer.ts
12097
+ var cloneState = (state) => ({
12098
+ ...state
12099
+ });
12100
+ var normalizeTranscriptTimes = (transcripts, baseEpoch) => {
12101
+ if (typeof baseEpoch !== "number") {
12102
+ return transcripts;
12103
+ }
12104
+ return transcripts.map((transcript) => {
12105
+ const adjusted = { ...transcript };
12106
+ if (typeof adjusted.startedAtMs === "number" && adjusted.startedAtMs >= baseEpoch) {
12107
+ adjusted.startedAtMs = adjusted.startedAtMs - baseEpoch;
12108
+ }
12109
+ if (typeof adjusted.endedAtMs === "number" && adjusted.endedAtMs >= baseEpoch) {
12110
+ adjusted.endedAtMs = adjusted.endedAtMs - baseEpoch;
12111
+ }
12112
+ return adjusted;
12113
+ });
12114
+ };
12115
+ var findActiveTranscript = (transcripts, positionMs) => {
12116
+ let candidate;
12117
+ for (let index = 0;index < transcripts.length; index += 1) {
12118
+ const transcript = transcripts[index];
12119
+ if (typeof transcript.startedAtMs !== "number")
12120
+ continue;
12121
+ if (transcript.startedAtMs > positionMs)
12122
+ break;
12123
+ if (typeof transcript.endedAtMs === "number" && transcript.endedAtMs < positionMs) {
12124
+ continue;
12125
+ }
12126
+ candidate = { id: transcript.id, index };
12127
+ }
12128
+ return candidate ?? {};
12129
+ };
12130
+ var createVoiceCallPlayer = (options = {}) => {
12131
+ let transcripts = normalizeTranscriptTimes(options.transcripts ?? [], options.recordingStartedAtEpochMs);
12132
+ let state = {
12133
+ audioUrl: options.audioUrl,
12134
+ buffered: 0,
12135
+ currentTimeMs: 0,
12136
+ durationMs: 0,
12137
+ isPlaying: false,
12138
+ isReady: false,
12139
+ playbackRate: options.initialPlaybackRate ?? 1
12140
+ };
12141
+ const listeners = new Set;
12142
+ const notify = () => {
12143
+ for (const listener of listeners)
12144
+ listener();
12145
+ };
12146
+ const update = (next) => {
12147
+ state = { ...state, ...next };
12148
+ notify();
12149
+ };
12150
+ const refreshActive = () => {
12151
+ const { id, index } = findActiveTranscript(transcripts, state.currentTimeMs);
12152
+ if (id !== state.activeTranscriptId || index !== state.activeTranscriptIndex) {
12153
+ state = {
12154
+ ...state,
12155
+ activeTranscriptId: id,
12156
+ activeTranscriptIndex: index
12157
+ };
12158
+ notify();
12159
+ }
12160
+ };
12161
+ return {
12162
+ getState: () => cloneState(state),
12163
+ pause: () => {
12164
+ if (!state.isPlaying)
12165
+ return;
12166
+ update({ isPlaying: false });
12167
+ },
12168
+ play: async () => {
12169
+ update({ isPlaying: true });
12170
+ },
12171
+ reset: () => {
12172
+ state = {
12173
+ audioUrl: state.audioUrl,
12174
+ buffered: 0,
12175
+ currentTimeMs: 0,
12176
+ durationMs: 0,
12177
+ isPlaying: false,
12178
+ isReady: false,
12179
+ playbackRate: 1
12180
+ };
12181
+ notify();
12182
+ },
12183
+ seekMs: (positionMs) => {
12184
+ const clamped = Math.max(0, Math.min(state.durationMs || Number.POSITIVE_INFINITY, positionMs));
12185
+ update({ currentTimeMs: clamped });
12186
+ refreshActive();
12187
+ },
12188
+ seekToTranscript: (transcriptId) => {
12189
+ const found = transcripts.find((t) => t.id === transcriptId);
12190
+ if (!found || typeof found.startedAtMs !== "number") {
12191
+ return;
12192
+ }
12193
+ update({ currentTimeMs: Math.max(0, found.startedAtMs) });
12194
+ refreshActive();
12195
+ },
12196
+ setAudioUrl: (url) => {
12197
+ update({ audioUrl: url, isReady: false });
12198
+ },
12199
+ setBuffered: (seconds) => {
12200
+ update({ buffered: Math.max(0, seconds) });
12201
+ },
12202
+ setDuration: (durationMs) => {
12203
+ update({ durationMs: Math.max(0, durationMs) });
12204
+ },
12205
+ setError: (error) => {
12206
+ update({ error });
12207
+ },
12208
+ setPlaybackRate: (rate) => {
12209
+ update({ playbackRate: Math.max(0.25, Math.min(4, rate)) });
12210
+ },
12211
+ setPlaying: (playing) => {
12212
+ if (playing === state.isPlaying)
12213
+ return;
12214
+ update({ isPlaying: playing });
12215
+ },
12216
+ setReady: (ready) => {
12217
+ update({ isReady: ready });
12218
+ },
12219
+ setTime: (positionMs) => {
12220
+ const next = Math.max(0, positionMs);
12221
+ if (next === state.currentTimeMs)
12222
+ return;
12223
+ update({ currentTimeMs: next });
12224
+ refreshActive();
12225
+ },
12226
+ setTranscripts: (next) => {
12227
+ transcripts = normalizeTranscriptTimes(next, options.recordingStartedAtEpochMs);
12228
+ refreshActive();
12229
+ },
12230
+ subscribe: (listener) => {
12231
+ listeners.add(listener);
12232
+ return () => {
12233
+ listeners.delete(listener);
12234
+ };
12235
+ },
12236
+ transcripts: () => transcripts
12237
+ };
12238
+ };
12239
+ var formatVoiceCallPlayerTimestamp = (ms) => {
12240
+ const seconds = Math.max(0, Math.floor(ms / 1000));
12241
+ const minutes = Math.floor(seconds / 60);
12242
+ const remaining = seconds % 60;
12243
+ return `${String(minutes).padStart(2, "0")}:${String(remaining).padStart(2, "0")}`;
12244
+ };
12245
+
12246
+ // src/vue/VoiceCallPlayer.ts
12247
+ var VoiceCallPlayer = defineComponent19({
12248
+ name: "VoiceCallPlayer",
12249
+ props: {
12250
+ audioUrl: String,
12251
+ player: {
12252
+ default: undefined,
12253
+ type: Object
12254
+ },
12255
+ recordingStartedAtEpochMs: Number,
12256
+ title: { default: "Call replay", type: String },
12257
+ transcripts: {
12258
+ default: () => [],
12259
+ type: Array
12260
+ }
12261
+ },
12262
+ setup(props) {
12263
+ const player = props.player ?? createVoiceCallPlayer({
12264
+ audioUrl: props.audioUrl,
12265
+ recordingStartedAtEpochMs: props.recordingStartedAtEpochMs,
12266
+ transcripts: props.transcripts
12267
+ });
12268
+ const state = shallowRef22(player.getState());
12269
+ const audioRef = ref18(null);
12270
+ const unsubscribe = player.subscribe(() => {
12271
+ state.value = player.getState();
12272
+ });
12273
+ onUnmounted23(() => {
12274
+ unsubscribe();
12275
+ });
12276
+ watch(() => props.audioUrl, (next) => {
12277
+ player.setAudioUrl(next);
12278
+ });
12279
+ watch(() => props.transcripts, (next) => {
12280
+ if (next)
12281
+ player.setTranscripts(next);
12282
+ }, { deep: false });
12283
+ const syncAudio = () => {
12284
+ const el = audioRef.value;
12285
+ if (!el)
12286
+ return;
12287
+ if (state.value.isPlaying && el.paused) {
12288
+ el.play().catch((err) => {
12289
+ player.setError(err instanceof Error ? err.message : String(err));
12290
+ player.setPlaying(false);
12291
+ });
12292
+ } else if (!state.value.isPlaying && !el.paused) {
12293
+ el.pause();
12294
+ }
12295
+ if (Math.abs(el.currentTime * 1000 - state.value.currentTimeMs) > 250) {
12296
+ el.currentTime = state.value.currentTimeMs / 1000;
12297
+ }
12298
+ el.playbackRate = state.value.playbackRate;
12299
+ };
12300
+ onMounted10(syncAudio);
12301
+ watch(state, syncAudio, { deep: false });
12302
+ return () => {
12303
+ const s = state.value;
12304
+ return h19("section", {
12305
+ "aria-label": "voice-call-player",
12306
+ class: "absolute-voice-call-player",
12307
+ style: {
12308
+ background: "#0f172a",
12309
+ borderRadius: "16px",
12310
+ color: "#f8fafc",
12311
+ fontFamily: 'ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',
12312
+ padding: "20px"
12313
+ }
12314
+ }, [
12315
+ h19("header", {
12316
+ style: {
12317
+ alignItems: "center",
12318
+ display: "flex",
12319
+ gap: "12px",
12320
+ marginBottom: "12px"
12321
+ }
12322
+ }, [
12323
+ h19("strong", { style: { fontSize: "16px" } }, props.title),
12324
+ h19("span", {
12325
+ style: {
12326
+ fontSize: "13px",
12327
+ marginLeft: "auto",
12328
+ opacity: "0.7"
12329
+ }
12330
+ }, `${formatVoiceCallPlayerTimestamp(s.currentTimeMs)} / ${formatVoiceCallPlayerTimestamp(s.durationMs)}`)
12331
+ ]),
12332
+ h19("audio", {
12333
+ onEnded: () => player.setPlaying(false),
12334
+ onError: () => player.setError("Audio playback error"),
12335
+ onLoadedmetadata: () => {
12336
+ const el = audioRef.value;
12337
+ if (!el)
12338
+ return;
12339
+ player.setDuration(el.duration * 1000);
12340
+ player.setReady(true);
12341
+ },
12342
+ onPause: () => player.setPlaying(false),
12343
+ onPlay: () => player.setPlaying(true),
12344
+ onTimeupdate: () => {
12345
+ const el = audioRef.value;
12346
+ if (!el)
12347
+ return;
12348
+ player.setTime(el.currentTime * 1000);
12349
+ },
12350
+ preload: "metadata",
12351
+ ref: audioRef,
12352
+ src: s.audioUrl,
12353
+ style: { display: "none" }
12354
+ }),
12355
+ h19("div", {
12356
+ style: {
12357
+ alignItems: "center",
12358
+ display: "flex",
12359
+ gap: "12px",
12360
+ marginBottom: "14px"
12361
+ }
12362
+ }, [
12363
+ h19("button", {
12364
+ "aria-label": s.isPlaying ? "Pause" : "Play",
12365
+ onClick: () => {
12366
+ if (s.isPlaying) {
12367
+ player.pause();
12368
+ } else {
12369
+ player.play();
12370
+ }
12371
+ },
12372
+ style: {
12373
+ background: "#3b82f6",
12374
+ border: "none",
12375
+ borderRadius: "12px",
12376
+ color: "#f8fafc",
12377
+ cursor: "pointer",
12378
+ fontSize: "14px",
12379
+ fontWeight: "500",
12380
+ padding: "8px 14px"
12381
+ },
12382
+ type: "button"
12383
+ }, s.isPlaying ? "Pause" : "Play"),
12384
+ h19("input", {
12385
+ "aria-label": "seek",
12386
+ max: 1,
12387
+ min: 0,
12388
+ onInput: (event) => {
12389
+ const target = event.target;
12390
+ player.seekMs(s.durationMs * Number(target.value));
12391
+ },
12392
+ step: 0.001,
12393
+ style: { flex: "1" },
12394
+ type: "range",
12395
+ value: s.durationMs > 0 ? s.currentTimeMs / s.durationMs : 0
12396
+ })
12397
+ ]),
12398
+ h19("ol", {
12399
+ style: {
12400
+ display: "flex",
12401
+ flexDirection: "column",
12402
+ gap: "6px",
12403
+ listStyle: "none",
12404
+ margin: "0",
12405
+ maxHeight: "280px",
12406
+ overflowY: "auto",
12407
+ padding: "0"
12408
+ }
12409
+ }, player.transcripts().map((transcript) => h19("li", {
12410
+ key: transcript.id,
12411
+ onClick: () => player.seekToTranscript(transcript.id),
12412
+ style: {
12413
+ background: transcript.id === s.activeTranscriptId ? "rgba(59,130,246,0.18)" : "transparent",
12414
+ borderRadius: "8px",
12415
+ cursor: "pointer",
12416
+ fontSize: "13px",
12417
+ padding: "8px 12px"
12418
+ }
12419
+ }, [
12420
+ h19("div", { style: { color: "#cbd5e1", fontSize: "12px" } }, formatVoiceCallPlayerTimestamp(transcript.startedAtMs ?? 0)),
12421
+ h19("div", transcript.text)
12422
+ ])))
12423
+ ]);
12424
+ };
12425
+ }
12426
+ });
12085
12427
  // src/vue/VoiceCostDashboard.ts
12086
- import { computed as computed11, defineComponent as defineComponent19, h as h19 } from "vue";
12428
+ import { computed as computed11, defineComponent as defineComponent20, h as h20 } from "vue";
12087
12429
 
12088
12430
  // src/client/costDashboard.ts
12089
12431
  var padTwo = (value) => String(value).padStart(2, "0");
@@ -12092,12 +12434,12 @@ var formatBucketKey = (epochMs, bucketBy) => {
12092
12434
  const y = date.getUTCFullYear();
12093
12435
  const m = padTwo(date.getUTCMonth() + 1);
12094
12436
  const d = padTwo(date.getUTCDate());
12095
- const h19 = padTwo(date.getUTCHours());
12437
+ const h20 = padTwo(date.getUTCHours());
12096
12438
  if (bucketBy === "month")
12097
12439
  return `${y}-${m}`;
12098
12440
  if (bucketBy === "day")
12099
12441
  return `${y}-${m}-${d}`;
12100
- return `${y}-${m}-${d}T${h19}`;
12442
+ return `${y}-${m}-${d}T${h20}`;
12101
12443
  };
12102
12444
  var isCostBreakdown = (value) => Boolean(value) && typeof value === "object" && typeof value.totalUsd === "number";
12103
12445
  var emptyBucket = (bucketKey) => ({
@@ -12173,22 +12515,22 @@ var formatUsd = (value, currency = "USD") => new Intl.NumberFormat("en-US", {
12173
12515
  style: "currency"
12174
12516
  }).format(value);
12175
12517
  var formatInteger = (value) => new Intl.NumberFormat("en-US").format(value);
12176
- var renderRow = (bucket, currency, isTotal) => h19("tr", {
12518
+ var renderRow = (bucket, currency, isTotal) => h20("tr", {
12177
12519
  "data-bucket-key": bucket.bucketKey,
12178
12520
  style: {
12179
12521
  borderTop: isTotal ? "2px solid rgba(255,255,255,0.15)" : undefined,
12180
12522
  fontWeight: isTotal ? 600 : undefined
12181
12523
  }
12182
12524
  }, [
12183
- h19("td", { style: { padding: "8px 12px" } }, bucket.bucketKey),
12184
- h19("td", { style: { padding: "8px 12px", textAlign: "right" } }, formatInteger(bucket.callCount)),
12185
- h19("td", { style: { padding: "8px 12px", textAlign: "right" } }, formatUsd(bucket.llmUsd, currency)),
12186
- h19("td", { style: { padding: "8px 12px", textAlign: "right" } }, formatUsd(bucket.ttsUsd, currency)),
12187
- h19("td", { style: { padding: "8px 12px", textAlign: "right" } }, formatUsd(bucket.sttUsd, currency)),
12188
- h19("td", { style: { padding: "8px 12px", textAlign: "right" } }, formatUsd(bucket.telephonyUsd, currency)),
12189
- h19("td", { style: { padding: "8px 12px", textAlign: "right" } }, formatUsd(bucket.totalUsd, currency))
12525
+ h20("td", { style: { padding: "8px 12px" } }, bucket.bucketKey),
12526
+ h20("td", { style: { padding: "8px 12px", textAlign: "right" } }, formatInteger(bucket.callCount)),
12527
+ h20("td", { style: { padding: "8px 12px", textAlign: "right" } }, formatUsd(bucket.llmUsd, currency)),
12528
+ h20("td", { style: { padding: "8px 12px", textAlign: "right" } }, formatUsd(bucket.ttsUsd, currency)),
12529
+ h20("td", { style: { padding: "8px 12px", textAlign: "right" } }, formatUsd(bucket.sttUsd, currency)),
12530
+ h20("td", { style: { padding: "8px 12px", textAlign: "right" } }, formatUsd(bucket.telephonyUsd, currency)),
12531
+ h20("td", { style: { padding: "8px 12px", textAlign: "right" } }, formatUsd(bucket.totalUsd, currency))
12190
12532
  ]);
12191
- var VoiceCostDashboard = defineComponent19({
12533
+ var VoiceCostDashboard = defineComponent20({
12192
12534
  name: "VoiceCostDashboard",
12193
12535
  props: {
12194
12536
  bucketBy: {
@@ -12216,7 +12558,7 @@ var VoiceCostDashboard = defineComponent19({
12216
12558
  const r = report.value;
12217
12559
  const rows = r.buckets.map((bucket) => renderRow(bucket, props.currency, false));
12218
12560
  rows.push(renderRow(r.grandTotal, props.currency, true));
12219
- return h19("section", {
12561
+ return h20("section", {
12220
12562
  "aria-label": "voice-cost-dashboard",
12221
12563
  class: "absolute-voice-cost-dashboard",
12222
12564
  style: {
@@ -12227,7 +12569,7 @@ var VoiceCostDashboard = defineComponent19({
12227
12569
  padding: "20px"
12228
12570
  }
12229
12571
  }, [
12230
- h19("header", {
12572
+ h20("header", {
12231
12573
  style: {
12232
12574
  alignItems: "baseline",
12233
12575
  display: "flex",
@@ -12235,28 +12577,28 @@ var VoiceCostDashboard = defineComponent19({
12235
12577
  marginBottom: "12px"
12236
12578
  }
12237
12579
  }, [
12238
- h19("strong", { style: { fontSize: "16px" } }, props.title),
12239
- h19("span", { style: { fontSize: "13px", opacity: "0.7" } }, `${r.buckets.length} buckets \xB7 grand total ${formatUsd(r.grandTotal.totalUsd, props.currency)}`)
12580
+ h20("strong", { style: { fontSize: "16px" } }, props.title),
12581
+ h20("span", { style: { fontSize: "13px", opacity: "0.7" } }, `${r.buckets.length} buckets \xB7 grand total ${formatUsd(r.grandTotal.totalUsd, props.currency)}`)
12240
12582
  ]),
12241
- r.buckets.length === 0 ? h19("p", { style: { fontSize: "13px", opacity: "0.7" } }, props.emptyMessage) : h19("table", {
12583
+ r.buckets.length === 0 ? h20("p", { style: { fontSize: "13px", opacity: "0.7" } }, props.emptyMessage) : h20("table", {
12242
12584
  style: {
12243
12585
  borderCollapse: "collapse",
12244
12586
  fontSize: "13px",
12245
12587
  width: "100%"
12246
12588
  }
12247
12589
  }, [
12248
- h19("thead", [
12249
- h19("tr", { style: { opacity: "0.7", textAlign: "left" } }, [
12250
- h19("th", { style: { padding: "8px 12px" } }, "Bucket"),
12251
- h19("th", { style: { padding: "8px 12px", textAlign: "right" } }, "Calls"),
12252
- h19("th", { style: { padding: "8px 12px", textAlign: "right" } }, "LLM"),
12253
- h19("th", { style: { padding: "8px 12px", textAlign: "right" } }, "TTS"),
12254
- h19("th", { style: { padding: "8px 12px", textAlign: "right" } }, "STT"),
12255
- h19("th", { style: { padding: "8px 12px", textAlign: "right" } }, "Tel."),
12256
- h19("th", { style: { padding: "8px 12px", textAlign: "right" } }, "Total")
12590
+ h20("thead", [
12591
+ h20("tr", { style: { opacity: "0.7", textAlign: "left" } }, [
12592
+ h20("th", { style: { padding: "8px 12px" } }, "Bucket"),
12593
+ h20("th", { style: { padding: "8px 12px", textAlign: "right" } }, "Calls"),
12594
+ h20("th", { style: { padding: "8px 12px", textAlign: "right" } }, "LLM"),
12595
+ h20("th", { style: { padding: "8px 12px", textAlign: "right" } }, "TTS"),
12596
+ h20("th", { style: { padding: "8px 12px", textAlign: "right" } }, "STT"),
12597
+ h20("th", { style: { padding: "8px 12px", textAlign: "right" } }, "Tel."),
12598
+ h20("th", { style: { padding: "8px 12px", textAlign: "right" } }, "Total")
12257
12599
  ])
12258
12600
  ]),
12259
- h19("tbody", rows)
12601
+ h20("tbody", rows)
12260
12602
  ])
12261
12603
  ]);
12262
12604
  };
@@ -12264,10 +12606,10 @@ var VoiceCostDashboard = defineComponent19({
12264
12606
  });
12265
12607
  // src/vue/VoiceLiveCallViewer.ts
12266
12608
  import {
12267
- defineComponent as defineComponent20,
12268
- h as h20,
12269
- onUnmounted as onUnmounted23,
12270
- shallowRef as shallowRef22
12609
+ defineComponent as defineComponent21,
12610
+ h as h21,
12611
+ onUnmounted as onUnmounted24,
12612
+ shallowRef as shallowRef23
12271
12613
  } from "vue";
12272
12614
 
12273
12615
  // src/client/liveCallViewer.ts
@@ -12392,7 +12734,7 @@ var formatRelative = (ms) => {
12392
12734
  const remaining = seconds % 60;
12393
12735
  return `${String(minutes).padStart(2, "0")}:${String(remaining).padStart(2, "0")}`;
12394
12736
  };
12395
- var VoiceLiveCallViewer = defineComponent20({
12737
+ var VoiceLiveCallViewer = defineComponent21({
12396
12738
  name: "VoiceLiveCallViewer",
12397
12739
  props: {
12398
12740
  sessionId: { default: "live", type: String },
@@ -12405,17 +12747,17 @@ var VoiceLiveCallViewer = defineComponent20({
12405
12747
  setup(props) {
12406
12748
  const owned = !props.viewer;
12407
12749
  const viewer = props.viewer ?? createLiveCallViewer({ sessionId: props.sessionId });
12408
- const state = shallowRef22(viewer.getState());
12750
+ const state = shallowRef23(viewer.getState());
12409
12751
  const unsubscribe = viewer.subscribe(() => {
12410
12752
  state.value = viewer.getState();
12411
12753
  });
12412
- onUnmounted23(() => {
12754
+ onUnmounted24(() => {
12413
12755
  unsubscribe();
12414
12756
  });
12415
12757
  return () => {
12416
12758
  const s = state.value;
12417
12759
  const firstAt = s.events[0]?.at ?? Date.now();
12418
- return h20("section", {
12760
+ return h21("section", {
12419
12761
  "aria-label": "voice-live-call-viewer",
12420
12762
  class: "absolute-voice-live-call-viewer",
12421
12763
  "data-agent-state": s.agentState,
@@ -12427,7 +12769,7 @@ var VoiceLiveCallViewer = defineComponent20({
12427
12769
  padding: "20px"
12428
12770
  }
12429
12771
  }, [
12430
- h20("header", {
12772
+ h21("header", {
12431
12773
  style: {
12432
12774
  alignItems: "center",
12433
12775
  display: "flex",
@@ -12435,8 +12777,8 @@ var VoiceLiveCallViewer = defineComponent20({
12435
12777
  marginBottom: "12px"
12436
12778
  }
12437
12779
  }, [
12438
- h20("strong", { style: { fontSize: "16px" } }, props.title),
12439
- h20("span", {
12780
+ h21("strong", { style: { fontSize: "16px" } }, props.title),
12781
+ h21("span", {
12440
12782
  style: {
12441
12783
  background: "rgba(59,130,246,0.18)",
12442
12784
  borderRadius: "999px",
@@ -12445,7 +12787,7 @@ var VoiceLiveCallViewer = defineComponent20({
12445
12787
  textTransform: "uppercase"
12446
12788
  }
12447
12789
  }, s.agentState),
12448
- h20("span", {
12790
+ h21("span", {
12449
12791
  style: {
12450
12792
  fontSize: "13px",
12451
12793
  marginLeft: "auto",
@@ -12453,7 +12795,7 @@ var VoiceLiveCallViewer = defineComponent20({
12453
12795
  }
12454
12796
  }, `${s.sessionId} \xB7 ${formatRelative(s.callDurationMs)}`)
12455
12797
  ]),
12456
- s.partialTranscript ? h20("p", {
12798
+ s.partialTranscript ? h21("p", {
12457
12799
  style: {
12458
12800
  background: "rgba(16,185,129,0.12)",
12459
12801
  borderRadius: "12px",
@@ -12463,7 +12805,7 @@ var VoiceLiveCallViewer = defineComponent20({
12463
12805
  padding: "10px 12px"
12464
12806
  }
12465
12807
  }, `\u201C${s.partialTranscript}\u201D`) : null,
12466
- h20("ol", {
12808
+ h21("ol", {
12467
12809
  style: {
12468
12810
  display: "flex",
12469
12811
  flexDirection: "column",
@@ -12474,7 +12816,7 @@ var VoiceLiveCallViewer = defineComponent20({
12474
12816
  overflowY: "auto",
12475
12817
  padding: "0"
12476
12818
  }
12477
- }, s.events.map((event, index) => h20("li", {
12819
+ }, s.events.map((event, index) => h21("li", {
12478
12820
  key: `${event.at}-${index}`,
12479
12821
  style: {
12480
12822
  alignItems: "center",
@@ -12485,7 +12827,7 @@ var VoiceLiveCallViewer = defineComponent20({
12485
12827
  paddingLeft: "12px"
12486
12828
  }
12487
12829
  }, [
12488
- h20("span", {
12830
+ h21("span", {
12489
12831
  style: {
12490
12832
  color: "#cbd5e1",
12491
12833
  fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
@@ -12493,15 +12835,15 @@ var VoiceLiveCallViewer = defineComponent20({
12493
12835
  width: "60px"
12494
12836
  }
12495
12837
  }, formatRelative(event.at - firstAt)),
12496
- h20("strong", { style: { fontSize: "13px" } }, event.title),
12497
- event.detail ? h20("span", { style: { opacity: "0.85" } }, event.detail) : null
12838
+ h21("strong", { style: { fontSize: "13px" } }, event.title),
12839
+ event.detail ? h21("span", { style: { opacity: "0.85" } }, event.detail) : null
12498
12840
  ])))
12499
12841
  ]);
12500
12842
  };
12501
12843
  }
12502
12844
  });
12503
12845
  // src/vue/VoiceReplayTimeline.ts
12504
- import { computed as computed12, defineComponent as defineComponent21, h as h21 } from "vue";
12846
+ import { computed as computed12, defineComponent as defineComponent22, h as h22 } from "vue";
12505
12847
 
12506
12848
  // src/client/replayTimeline.ts
12507
12849
  var categorize = (entry) => {
@@ -12567,7 +12909,7 @@ var formatRelative2 = (ms) => {
12567
12909
  const remaining = seconds % 60;
12568
12910
  return `${String(minutes).padStart(2, "0")}:${String(remaining).padStart(2, "0")}`;
12569
12911
  };
12570
- var VoiceReplayTimeline = defineComponent21({
12912
+ var VoiceReplayTimeline = defineComponent22({
12571
12913
  name: "VoiceReplayTimeline",
12572
12914
  props: {
12573
12915
  artifact: {
@@ -12580,7 +12922,7 @@ var VoiceReplayTimeline = defineComponent21({
12580
12922
  const report = computed12(() => buildReplayTimelineReport({ artifact: props.artifact }));
12581
12923
  return () => {
12582
12924
  const r = report.value;
12583
- return h21("section", {
12925
+ return h22("section", {
12584
12926
  "aria-label": "voice-replay-timeline",
12585
12927
  class: "absolute-voice-replay-timeline",
12586
12928
  style: {
@@ -12591,7 +12933,7 @@ var VoiceReplayTimeline = defineComponent21({
12591
12933
  padding: "20px"
12592
12934
  }
12593
12935
  }, [
12594
- h21("header", {
12936
+ h22("header", {
12595
12937
  style: {
12596
12938
  alignItems: "baseline",
12597
12939
  display: "flex",
@@ -12599,10 +12941,10 @@ var VoiceReplayTimeline = defineComponent21({
12599
12941
  marginBottom: "12px"
12600
12942
  }
12601
12943
  }, [
12602
- h21("strong", { style: { fontSize: "16px" } }, props.title ?? r.metadata.title ?? "Replay"),
12603
- h21("span", { style: { fontSize: "13px", opacity: "0.7" } }, `${r.events.length} events \xB7 ${r.summary.userTurns} user \xB7 ${r.summary.agentTurns} agent \xB7 ${r.summary.toolCalls} tool`)
12944
+ h22("strong", { style: { fontSize: "16px" } }, props.title ?? r.metadata.title ?? "Replay"),
12945
+ h22("span", { style: { fontSize: "13px", opacity: "0.7" } }, `${r.events.length} events \xB7 ${r.summary.userTurns} user \xB7 ${r.summary.agentTurns} agent \xB7 ${r.summary.toolCalls} tool`)
12604
12946
  ]),
12605
- r.events.length === 0 ? h21("p", { style: { fontSize: "13px", opacity: "0.7" } }, "No timeline events.") : h21("ol", {
12947
+ r.events.length === 0 ? h22("p", { style: { fontSize: "13px", opacity: "0.7" } }, "No timeline events.") : h22("ol", {
12606
12948
  style: {
12607
12949
  display: "flex",
12608
12950
  flexDirection: "column",
@@ -12611,7 +12953,7 @@ var VoiceReplayTimeline = defineComponent21({
12611
12953
  margin: "0",
12612
12954
  padding: "0"
12613
12955
  }
12614
- }, r.events.map((event, index) => h21("li", {
12956
+ }, r.events.map((event, index) => h22("li", {
12615
12957
  key: `${event.at}-${index}`,
12616
12958
  style: {
12617
12959
  alignItems: "center",
@@ -12622,7 +12964,7 @@ var VoiceReplayTimeline = defineComponent21({
12622
12964
  paddingLeft: "12px"
12623
12965
  }
12624
12966
  }, [
12625
- h21("span", {
12967
+ h22("span", {
12626
12968
  style: {
12627
12969
  color: "#cbd5e1",
12628
12970
  fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
@@ -12630,21 +12972,21 @@ var VoiceReplayTimeline = defineComponent21({
12630
12972
  width: "60px"
12631
12973
  }
12632
12974
  }, formatRelative2(event.at - r.startedAt)),
12633
- h21("strong", { style: { fontSize: "13px" } }, event.label),
12634
- event.detail ? h21("span", { style: { opacity: "0.85" } }, event.detail) : null
12975
+ h22("strong", { style: { fontSize: "13px" } }, event.label),
12976
+ event.detail ? h22("span", { style: { opacity: "0.85" } }, event.detail) : null
12635
12977
  ])))
12636
12978
  ]);
12637
12979
  };
12638
12980
  }
12639
12981
  });
12640
12982
  // src/vue/useVoiceTraceTimeline.ts
12641
- import { onUnmounted as onUnmounted24, ref as ref19, shallowRef as shallowRef23 } from "vue";
12983
+ import { onUnmounted as onUnmounted25, ref as ref20, shallowRef as shallowRef24 } from "vue";
12642
12984
  function useVoiceTraceTimeline(path = "/api/voice-traces", options = {}) {
12643
12985
  const store = createVoiceTraceTimelineStore(path, options);
12644
- const error = ref19(null);
12645
- const isLoading = ref19(false);
12646
- const report = shallowRef23(null);
12647
- const updatedAt = ref19(undefined);
12986
+ const error = ref20(null);
12987
+ const isLoading = ref20(false);
12988
+ const report = shallowRef24(null);
12989
+ const updatedAt = ref20(undefined);
12648
12990
  const sync = () => {
12649
12991
  const snapshot = store.getSnapshot();
12650
12992
  error.value = snapshot.error;
@@ -12655,7 +12997,7 @@ function useVoiceTraceTimeline(path = "/api/voice-traces", options = {}) {
12655
12997
  const unsubscribe = store.subscribe(sync);
12656
12998
  sync();
12657
12999
  store.refresh().catch(() => {});
12658
- onUnmounted24(() => {
13000
+ onUnmounted25(() => {
12659
13001
  unsubscribe();
12660
13002
  store.close();
12661
13003
  });
@@ -12668,7 +13010,7 @@ function useVoiceTraceTimeline(path = "/api/voice-traces", options = {}) {
12668
13010
  };
12669
13011
  }
12670
13012
  // src/vue/useVoiceWorkflowStatus.ts
12671
- import { onMounted as onMounted10, onUnmounted as onUnmounted25, ref as ref20, shallowRef as shallowRef24 } from "vue";
13013
+ import { onMounted as onMounted11, onUnmounted as onUnmounted26, ref as ref21, shallowRef as shallowRef25 } from "vue";
12672
13014
 
12673
13015
  // src/client/workflowStatus.ts
12674
13016
  var fetchVoiceWorkflowStatus = async (path = "/evals/scenarios/json", options = {}) => {
@@ -12752,10 +13094,10 @@ var createVoiceWorkflowStatusStore = (path = "/evals/scenarios/json", options =
12752
13094
  // src/vue/useVoiceWorkflowStatus.ts
12753
13095
  function useVoiceWorkflowStatus(path = "/evals/scenarios/json", options = {}) {
12754
13096
  const store = createVoiceWorkflowStatusStore(path, options);
12755
- const error = ref20(null);
12756
- const isLoading = ref20(false);
12757
- const report = shallowRef24(undefined);
12758
- const updatedAt = ref20(undefined);
13097
+ const error = ref21(null);
13098
+ const isLoading = ref21(false);
13099
+ const report = shallowRef25(undefined);
13100
+ const updatedAt = ref21(undefined);
12759
13101
  const sync = () => {
12760
13102
  const snapshot = store.getSnapshot();
12761
13103
  error.value = snapshot.error;
@@ -12765,10 +13107,10 @@ function useVoiceWorkflowStatus(path = "/evals/scenarios/json", options = {}) {
12765
13107
  };
12766
13108
  const unsubscribe = store.subscribe(sync);
12767
13109
  sync();
12768
- onMounted10(() => {
13110
+ onMounted11(() => {
12769
13111
  store.refresh().catch(() => {});
12770
13112
  });
12771
- onUnmounted25(() => {
13113
+ onUnmounted26(() => {
12772
13114
  unsubscribe();
12773
13115
  store.close();
12774
13116
  });
@@ -12826,5 +13168,6 @@ export {
12826
13168
  VoiceLiveCallViewer,
12827
13169
  VoiceDeliveryRuntime,
12828
13170
  VoiceCostDashboard,
13171
+ VoiceCallPlayer,
12829
13172
  VoiceCallDebuggerLaunch
12830
13173
  };