@spatius/avatarkit 1.3.1 → 1.3.3

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/CHANGELOG.md CHANGED
@@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.3.3] - 2026-08-08
9
+
10
+ ### Fixed
11
+ - Internal telemetry only, no change to public API or runtime behaviour: sessions driven through the companion RTC SDK are now attributed to that SDK and its version, matching how the Android and iOS SDKs already report. Previously such sessions were indistinguishable from a plain AvatarKit integration on the dashboards.
12
+
13
+ ## [1.3.2] - 2026-08-08
14
+
15
+ ### Fixed
16
+ - Internal telemetry only, no change to public API or runtime behaviour: fixed the diagnostics the SDK reports to Spatius. Connection setup is now reported as two separate steps (handshake and session confirmation) instead of a single total, steps faster than a millisecond no longer come back out of order, and cache lookups that complete instantly are no longer reported as loads.
17
+
8
18
  ## [1.3.1] - 2026-08-07
9
19
 
10
20
  Rolls up everything from the 1.3.1 beta line.
@@ -1,8 +1,8 @@
1
1
  import { n as __exportAll } from "./rolldown-runtime-B-1-B7_t.js";
2
- import { t as AvatarSDK } from "./AvatarSDK-DgPvHU4L.js";
3
- import { S as recordHttpClientDuration, c as logEvent, kt as ErrorCode, l as logMetric, t as logger, v as hostOf, xt as AvatarError, yt as generateTraceId } from "./logger-BOpQ7u0w.js";
4
- import { n as APP_CONFIG, r as getFlameCdnBase, t as errorToMessage } from "./error-utils-BogEllAd.js";
5
- import { t as PwaCacheManager } from "./pwa-cache-manager-C7NbU52Q.js";
2
+ import { t as AvatarSDK } from "./AvatarSDK-BbqaBxdV.js";
3
+ import { Mt as ErrorCode, S as recordHttpClientDuration, St as generateTraceId, c as logEvent, l as logMetric, t as logger, v as hostOf, wt as AvatarError } from "./logger-pANhsT4J.js";
4
+ import { n as APP_CONFIG, r as getFlameCdnBase, t as errorToMessage } from "./error-utils-DAqUlC0I.js";
5
+ import { t as PwaCacheManager } from "./pwa-cache-manager-M3XsMhvz.js";
6
6
  //#region core/AvatarDownloader.ts
7
7
  var AvatarDownloader_exports = /* @__PURE__ */ __exportAll({ AvatarDownloader: () => AvatarDownloader });
8
8
  /**
@@ -1,6 +1,6 @@
1
1
  import { n as __exportAll } from "./rolldown-runtime-B-1-B7_t.js";
2
- import { Mt as LogLevel, Ot as DrivingServiceMode, _ as fetchBootstrap, a as clientContextFields, b as cleanupOtelMetrics, c as logEvent, d as cleanupOtel, dt as OTEL_LOGS_ENDPOINT, f as initializeOtel, ft as OTEL_PASSWORD, g as clockSync, gt as OTEL_USERNAME, i as cleanupPostHog, n as setLogLevel, o as getLogsFeatureFlag, pt as OTEL_STREAM_NAME, r as logSink, s as initializePostHog, t as logger, u as updatePostHogPersonPropertiesForFlags, vt as idManager, x as initializeOtelMetrics } from "./logger-BOpQ7u0w.js";
3
- import { n as initializeOtelTrace, r as startInitTrace, t as cleanupOtelTrace } from "./otel-trace-Ct4T48nC.js";
2
+ import { Ft as LogLevel, T as resolveSdkVersion, _ as fetchBootstrap, a as clientContextFields, b as cleanupOtelMetrics, c as logEvent, d as cleanupOtel, f as initializeOtel, g as clockSync, gt as OTEL_STREAM_NAME, ht as OTEL_PASSWORD, i as cleanupPostHog, jt as DrivingServiceMode, mt as OTEL_LOGS_ENDPOINT, n as setLogLevel, o as getLogsFeatureFlag, r as logSink, s as initializePostHog, t as logger, u as updatePostHogPersonPropertiesForFlags, w as getSdkPackage, x as initializeOtelMetrics, xt as idManager, yt as OTEL_USERNAME } from "./logger-pANhsT4J.js";
3
+ import { i as startInitTrace, n as initializeOtelTrace, t as cleanupOtelTrace } from "./otel-trace-DBN8K91J.js";
4
4
  //#region node_modules/.pnpm/@bufbuild+protobuf@2.10.1/node_modules/@bufbuild/protobuf/dist/esm/wire/varint.js
5
5
  /**
6
6
  * Read a 64 bit varint as two JS numbers.
@@ -2526,9 +2526,9 @@ function emitInitErrorLog(params) {
2526
2526
  const nowNanos = String(Math.round(performance.timeOrigin + performance.now()) * 1e6);
2527
2527
  const resourceAttrs = [
2528
2528
  kv("service.name", "avatarkit"),
2529
- kv("sdk.version", sdkVersion),
2529
+ kv("sdk.version", resolveSdkVersion(sdkVersion)),
2530
2530
  kv("sdk.platform", "web"),
2531
- kv("sdk.package", "spatius-web-sdk"),
2531
+ kv("sdk.package", getSdkPackage()),
2532
2532
  kv("app_id", appId),
2533
2533
  kv("region", region),
2534
2534
  kv("dsm", dsm)
@@ -3900,7 +3900,7 @@ var AvatarSDK = class {
3900
3900
  static _initializationState = "uninitialized";
3901
3901
  static _initializingPromise = null;
3902
3902
  static _configuration = null;
3903
- static _version = "1.3.1";
3903
+ static _version = "1.3.3";
3904
3904
  static _avatarCore = null;
3905
3905
  static _cachedDeviceScore = null;
3906
3906
  static _rendererBackend = null;
@@ -4089,7 +4089,7 @@ var AvatarSDK = class {
4089
4089
  logger.log("[AvatarSDK] Loading template resources...");
4090
4090
  logEvent("template_init_start", "info", { stage: "sdk_init" });
4091
4091
  try {
4092
- const { AvatarDownloader } = await import("./AvatarDownloader-DyhenPKd.js").then((n) => n.n);
4092
+ const { AvatarDownloader } = await import("./AvatarDownloader-DNeU2n5w.js").then((n) => n.n);
4093
4093
  const templateResources = await new AvatarDownloader().loadUnifiedTemplate();
4094
4094
  if (await this._avatarCore.loadTemplateResourcesFromBuffers(templateResources)) logger.log("[AvatarSDK] Template resources initialized successfully");
4095
4095
  else logger.log("[AvatarSDK] Template resources already initialized, skipping...");
@@ -1,5 +1,5 @@
1
1
  import { n as __exportAll, r as __toESM, t as __commonJSMin } from "./rolldown-runtime-B-1-B7_t.js";
2
- import { t as logger } from "./logger-BOpQ7u0w.js";
2
+ import { t as logger } from "./logger-pANhsT4J.js";
3
3
  /** Opus granule positions are always in 48 kHz samples, regardless of input rate. */
4
4
  var OPUS_GRANULE_RATE = 48e3;
5
5
  /**
@@ -1,4 +1,4 @@
1
- import { t as logger } from "./logger-BOpQ7u0w.js";
1
+ import { t as logger } from "./logger-pANhsT4J.js";
2
2
  //#region audio/OpusDecoderProxy.ts
3
3
  var OpusDecoderProxy = class OpusDecoderProxy {
4
4
  worker = null;
@@ -21,7 +21,7 @@ var OpusDecoderProxy = class OpusDecoderProxy {
21
21
  } catch (err) {
22
22
  logger.warn("[Opus][DecoderProxy] Worker unavailable, falling back to main-thread decode:", err instanceof Error ? err.message : String(err));
23
23
  }
24
- const { OggOpusDecoder } = await import("./OpusCodec-CXU7ysrU.js").then((n) => n.n);
24
+ const { OggOpusDecoder } = await import("./OpusCodec-TzsHzMqb.js").then((n) => n.n);
25
25
  proxy.fallbackDecoder = new OggOpusDecoder();
26
26
  proxy.backend = "main-thread";
27
27
  return proxy;
@@ -32,7 +32,7 @@ var OpusDecoderProxy = class OpusDecoderProxy {
32
32
  try {
33
33
  worker = new Worker(new URL(
34
34
  /* @vite-ignore */
35
- "/assets/OpusDecoderWorker.worker-C2T0afkj.js",
35
+ "/assets/OpusDecoderWorker.worker-ChLjIgER.js",
36
36
  "" + import.meta.url
37
37
  ), { type: "module" });
38
38
  } catch (err) {
@@ -1,5 +1,5 @@
1
1
  import { n as __exportAll } from "./rolldown-runtime-B-1-B7_t.js";
2
- import { t as logger } from "./logger-BOpQ7u0w.js";
2
+ import { t as logger } from "./logger-pANhsT4J.js";
3
3
  //#region audio/OpusEncoderProxy.ts
4
4
  var OpusEncoderProxy_exports = /* @__PURE__ */ __exportAll({
5
5
  OpusEncoderProxy: () => OpusEncoderProxy,
@@ -43,7 +43,7 @@ var OpusEncoderProxy = class OpusEncoderProxy {
43
43
  } catch (err) {
44
44
  logger.warn("[Opus][Proxy] Worker unavailable, falling back to main-thread encode:", err instanceof Error ? err.message : String(err));
45
45
  }
46
- const { OggOpusEncoder } = await import("./OpusCodec-CXU7ysrU.js").then((n) => n.n);
46
+ const { OggOpusEncoder } = await import("./OpusCodec-TzsHzMqb.js").then((n) => n.n);
47
47
  proxy.fallbackEncoder = new OggOpusEncoder(sampleRate, bitrate);
48
48
  proxy.backend = "main-thread";
49
49
  return proxy;
@@ -54,7 +54,7 @@ var OpusEncoderProxy = class OpusEncoderProxy {
54
54
  try {
55
55
  worker = new Worker(new URL(
56
56
  /* @vite-ignore */
57
- "/assets/OpusEncoderWorker.worker-DLYO9vPK.js",
57
+ "/assets/OpusEncoderWorker.worker-bjAyiJ3b.js",
58
58
  "" + import.meta.url
59
59
  ), { type: "module" });
60
60
  } catch (err) {
@@ -1,5 +1,5 @@
1
- import { c as logEvent, t as logger } from "./logger-BOpQ7u0w.js";
2
- import { n as APP_CONFIG, t as errorToMessage } from "./error-utils-BogEllAd.js";
1
+ import { c as logEvent, t as logger } from "./logger-pANhsT4J.js";
2
+ import { n as APP_CONFIG, t as errorToMessage } from "./error-utils-DAqUlC0I.js";
3
3
  //#region audio/StreamingAudioPlayer.ts
4
4
  /**
5
5
  * Streaming Audio Player
@@ -1,5 +1,5 @@
1
- import { bt as ErrorCode, c as logEvent, gt as AvatarError, h as hostOf, ht as generateTraceId, l as logMetric, pt as isDebugMode, t as logger, y as recordHttpClientDuration } from "./logger-YPooEAbA.js";
2
- import { t as AvatarSDK } from "./AvatarSDK-C_Anluwp.js";
1
+ import { St as ErrorCode, _t as generateTraceId, c as logEvent, h as hostOf, ht as isDebugMode, l as logMetric, t as logger, vt as AvatarError, y as recordHttpClientDuration } from "./logger-DI85eKqW.js";
2
+ import { t as AvatarSDK } from "./AvatarSDK-Bdz1V7pz.js";
3
3
  //#region config/app-config.ts
4
4
  const GLOBAL_FLAME_CDN_BASE = "https://cdn.spatialwalk.cloud/public";
5
5
  const CN_FLAME_CDN_BASE = "https://cdn.spatialwalk.top/public";
@@ -1,5 +1,5 @@
1
1
  import { n as __exportAll } from "./rolldown-runtime-B-1-B7_t.js";
2
- import { $ as ContextAPI, A as addHrTimes, B as ATTR_SERVICE_NAME, C as createResource, D as resourceFromAttributes, E as defaultResource, F as millisToHrTime, G as suppressTracing, H as getStringFromEnv, I as otperformance, J as context, K as trace, L as ATTR_EXCEPTION_MESSAGE, M as hrTimeDuration, N as isTimeInput, O as BindOnceFuture, P as isTimeInputHrTime, Q as TraceFlags, R as ATTR_EXCEPTION_STACKTRACE, S as createInstrumentationScope, T as OTLPExporterBase, U as globalErrorHandler, V as getNumberFromEnv, W as isTracingSuppressed, X as isValidTraceId, Y as isSpanContextValid, Z as INVALID_SPAN_CONTEXT, _ as cleanupOtelMetrics, a as clientContextFields, at as registerGlobal, b as createLegacyOtlpBrowserExportDelegate, c as logEvent, ct as OTEL_PASSWORD, d as cleanupOtel, dt as OTEL_TRACES_STREAM_NAME, et as createNoopMeter, f as initializeOtel, ft as OTEL_USERNAME, g as observeExporter, i as cleanupPostHog, it as getGlobal, j as hrTime, k as ExportResultCode, lt as OTEL_STREAM_NAME, m as fetchBootstrap, mt as idManager, n as setLogLevel, nt as createContextKey, o as getLogsFeatureFlag, ot as unregisterGlobal, p as clockSync, q as diag$1, r as logSink, rt as DiagAPI, s as initializePostHog, st as OTEL_LOGS_ENDPOINT, t as logger, tt as ROOT_CONTEXT, u as updatePostHogPersonPropertiesForFlags, ut as OTEL_TRACES_ENDPOINT, v as initializeOtelMetrics, w as toAttributes, x as JSON_ENCODER, xt as LogLevel, yt as DrivingServiceMode, z as ATTR_EXCEPTION_TYPE } from "./logger-YPooEAbA.js";
2
+ import { $ as INVALID_SPAN_CONTEXT, A as BindOnceFuture, B as ATTR_EXCEPTION_STACKTRACE, C as JSON_ENCODER, Ct as LogLevel, D as OTLPExporterBase, E as toAttributes, F as isTimeInput, G as globalErrorHandler, H as ATTR_SERVICE_NAME, I as isTimeInputHrTime, J as trace, K as isTracingSuppressed, L as millisToHrTime, M as addHrTimes, N as hrTime, O as defaultResource, P as hrTimeDuration, Q as isValidTraceId, R as otperformance, S as createLegacyOtlpBrowserExportDelegate, T as createResource, U as getNumberFromEnv, V as ATTR_EXCEPTION_TYPE, W as getStringFromEnv, X as context, Y as diag$1, Z as isSpanContextValid, _ as cleanupOtelMetrics, a as clientContextFields, at as DiagAPI, b as getSdkPackage, c as logEvent, ct as unregisterGlobal, d as cleanupOtel, dt as OTEL_STREAM_NAME, et as TraceFlags, f as initializeOtel, ft as OTEL_TRACES_ENDPOINT, g as observeExporter, gt as idManager, i as cleanupPostHog, it as createContextKey, j as ExportResultCode, k as resourceFromAttributes, lt as OTEL_LOGS_ENDPOINT, m as fetchBootstrap, mt as OTEL_USERNAME, n as setLogLevel, nt as createNoopMeter, o as getLogsFeatureFlag, ot as getGlobal, p as clockSync, pt as OTEL_TRACES_STREAM_NAME, q as suppressTracing, r as logSink, rt as ROOT_CONTEXT, s as initializePostHog, st as registerGlobal, t as logger, tt as ContextAPI, u as updatePostHogPersonPropertiesForFlags, ut as OTEL_PASSWORD, v as initializeOtelMetrics, w as createInstrumentationScope, x as resolveSdkVersion, xt as DrivingServiceMode, z as ATTR_EXCEPTION_MESSAGE } from "./logger-DI85eKqW.js";
3
3
  //#region node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/baggage/internal/baggage-impl.js
4
4
  var BaggageImpl = class BaggageImpl {
5
5
  constructor(entries) {
@@ -2382,9 +2382,9 @@ function initializeOtelTrace(version, resourceAttrs) {
2382
2382
  tracerProvider = new WebTracerProvider({
2383
2383
  resource: resourceFromAttributes({
2384
2384
  [ATTR_SERVICE_NAME]: "avatarkit",
2385
- "sdk.version": sdkVersion,
2385
+ "sdk.version": resolveSdkVersion(sdkVersion),
2386
2386
  "sdk.platform": "web",
2387
- "sdk.package": "spatius-web-sdk",
2387
+ "sdk.package": getSdkPackage(),
2388
2388
  "app_id": resourceAttrs.appId || "",
2389
2389
  "region": resourceAttrs.region,
2390
2390
  "dsm": resourceAttrs.dsm,
@@ -2460,7 +2460,7 @@ function startInitTrace(sessionId, startTimeMs, attrs = {}) {
2460
2460
  attributes: spanAttrs
2461
2461
  }, rootCtx);
2462
2462
  if (isError) sp.setStatus({ code: SpanStatusCode.ERROR });
2463
- sp.end(endMs);
2463
+ sp.end(Math.max(endMs, startMs + 1));
2464
2464
  } catch {}
2465
2465
  },
2466
2466
  group: () => NOOP_GROUP,
@@ -2535,9 +2535,9 @@ function emitInitErrorLog(params) {
2535
2535
  const nowNanos = String(Math.round(performance.timeOrigin + performance.now()) * 1e6);
2536
2536
  const resourceAttrs = [
2537
2537
  kv("service.name", "avatarkit"),
2538
- kv("sdk.version", sdkVersion),
2538
+ kv("sdk.version", resolveSdkVersion(sdkVersion)),
2539
2539
  kv("sdk.platform", "web"),
2540
- kv("sdk.package", "spatius-web-sdk"),
2540
+ kv("sdk.package", getSdkPackage()),
2541
2541
  kv("app_id", appId),
2542
2542
  kv("region", region),
2543
2543
  kv("dsm", dsm)
@@ -6223,7 +6223,7 @@ var AvatarSDK = class {
6223
6223
  static _initializationState = "uninitialized";
6224
6224
  static _initializingPromise = null;
6225
6225
  static _configuration = null;
6226
- static _version = "1.3.1";
6226
+ static _version = "1.3.3";
6227
6227
  static _avatarCore = null;
6228
6228
  static _cachedDeviceScore = null;
6229
6229
  static _rendererBackend = null;
@@ -6412,7 +6412,7 @@ var AvatarSDK = class {
6412
6412
  logger.log("[AvatarSDK] Loading template resources...");
6413
6413
  logEvent("template_init_start", "info", { stage: "sdk_init" });
6414
6414
  try {
6415
- const { AvatarDownloader } = await import("./AvatarDownloader-G5FO1bVl.js");
6415
+ const { AvatarDownloader } = await import("./AvatarDownloader-Cy2QvOfT.js");
6416
6416
  const templateResources = await new AvatarDownloader().loadUnifiedTemplate();
6417
6417
  if (await this._avatarCore.loadTemplateResourcesFromBuffers(templateResources)) logger.log("[AvatarSDK] Template resources initialized successfully");
6418
6418
  else logger.log("[AvatarSDK] Template resources already initialized, skipping...");
@@ -1,5 +1,5 @@
1
1
  import { r as __toESM, t as __commonJSMin } from "./rolldown-runtime-B-1-B7_t.js";
2
- import { t as logger } from "./logger-YPooEAbA.js";
2
+ import { t as logger } from "./logger-DI85eKqW.js";
3
3
  //#region __vite-browser-external
4
4
  var require___vite_browser_external = /* @__PURE__ */ __commonJSMin(((exports, module) => {
5
5
  module.exports = {};
@@ -1,5 +1,5 @@
1
1
  import { r as __toESM, t as __commonJSMin } from "./rolldown-runtime-B-1-B7_t.js";
2
- import { t as logger } from "./logger-YPooEAbA.js";
2
+ import { t as logger } from "./logger-DI85eKqW.js";
3
3
  //#region __vite-browser-external
4
4
  var require___vite_browser_external = /* @__PURE__ */ __commonJSMin(((exports, module) => {
5
5
  module.exports = {};
@@ -13434,6 +13434,22 @@ var OTLPMetricExporter = class extends OTLPMetricExporterBase {
13434
13434
  }
13435
13435
  };
13436
13436
  //#endregion
13437
+ //#region utils/otel-identity.ts
13438
+ let sdkPackage = "spatius-web-sdk";
13439
+ /** 当前归属包名,供各通道构建 Resource 时读取。@internal */
13440
+ function getSdkPackage() {
13441
+ return sdkPackage;
13442
+ }
13443
+ /**
13444
+ * Resource 上应上报的版本号。
13445
+ *
13446
+ * @param hostVersion - 主库自己的版本,未被上层 SDK 声明时用它。
13447
+ * @internal
13448
+ */
13449
+ function resolveSdkVersion(hostVersion) {
13450
+ return hostVersion;
13451
+ }
13452
+ //#endregion
13437
13453
  //#region utils/otel-metrics.ts
13438
13454
  /**
13439
13455
  * OpenTelemetry Metrics Tracker (Browser Version)
@@ -13812,9 +13828,9 @@ function initializeOtelMetrics(version, resourceAttrs) {
13812
13828
  meterProvider = new MeterProvider({
13813
13829
  resource: resourceFromAttributes({
13814
13830
  [ATTR_SERVICE_NAME]: "avatarkit",
13815
- "sdk.version": sdkVersion$2,
13831
+ "sdk.version": resolveSdkVersion(sdkVersion$2),
13816
13832
  "sdk.platform": "web",
13817
- "sdk.package": "spatius-web-sdk",
13833
+ "sdk.package": getSdkPackage(),
13818
13834
  "app_id": resourceAttrs.appId || "",
13819
13835
  "region": resourceAttrs.region,
13820
13836
  "dsm": resourceAttrs.dsm
@@ -14542,9 +14558,9 @@ function initializeOtel(version, resourceAttrs) {
14542
14558
  loggerProvider = new LoggerProvider({
14543
14559
  resource: resourceFromAttributes({
14544
14560
  [ATTR_SERVICE_NAME]: "avatarkit",
14545
- "sdk.version": sdkVersion$1,
14561
+ "sdk.version": resolveSdkVersion(sdkVersion$1),
14546
14562
  "sdk.platform": "web",
14547
- "sdk.package": "spatius-web-sdk",
14563
+ "sdk.package": getSdkPackage(),
14548
14564
  "app_id": resourceAttrs.appId || "",
14549
14565
  "region": resourceAttrs.region,
14550
14566
  "dsm": resourceAttrs.dsm
@@ -15434,7 +15450,7 @@ async function writeToLocalLog(message, level, extra = {}) {
15434
15450
  try {
15435
15451
  const { shouldPersist, sanitized } = sanitizeForLocalLog(message);
15436
15452
  if (!shouldPersist) return;
15437
- const { AvatarSDK } = await import("./AvatarSDK-C_Anluwp.js").then((n) => n.n);
15453
+ const { AvatarSDK } = await import("./AvatarSDK-Bdz1V7pz.js").then((n) => n.n);
15438
15454
  const version = AvatarSDK.version;
15439
15455
  const appId = idManager.getAppId();
15440
15456
  const userId = idManager.getUserId();
@@ -15524,4 +15540,4 @@ function captureErrorContext(level, error) {
15524
15540
  });
15525
15541
  }
15526
15542
  //#endregion
15527
- export { ContextAPI as $, addHrTimes as A, ATTR_SERVICE_NAME as B, createResource as C, resourceFromAttributes as D, defaultResource as E, millisToHrTime as F, suppressTracing as G, getStringFromEnv as H, otperformance as I, context as J, trace as K, ATTR_EXCEPTION_MESSAGE as L, hrTimeDuration as M, isTimeInput as N, BindOnceFuture as O, isTimeInputHrTime as P, TraceFlags as Q, ATTR_EXCEPTION_STACKTRACE as R, createInstrumentationScope as S, OTLPExporterBase as T, globalErrorHandler as U, getNumberFromEnv as V, isTracingSuppressed as W, isValidTraceId as X, isSpanContextValid as Y, INVALID_SPAN_CONTEXT as Z, cleanupOtelMetrics as _, DEFAULT_REGION as _t, clientContextFields as a, registerGlobal as at, createLegacyOtlpBrowserExportDelegate as b, ErrorCode as bt, logEvent as c, OTEL_PASSWORD as ct, cleanupOtel as d, OTEL_TRACES_STREAM_NAME as dt, createNoopMeter as et, initializeOtel as f, OTEL_USERNAME as ft, observeExporter as g, AvatarError as gt, hostOf as h, generateTraceId as ht, cleanupPostHog as i, getGlobal as it, hrTime as j, ExportResultCode as k, logMetric as l, OTEL_STREAM_NAME as lt, fetchBootstrap as m, idManager as mt, setLogLevel as n, createContextKey as nt, getLogsFeatureFlag as o, unregisterGlobal as ot, clockSync as p, isDebugMode as pt, diag as q, logSink as r, DiagAPI as rt, initializePostHog as s, OTEL_LOGS_ENDPOINT as st, logger as t, ROOT_CONTEXT as tt, updatePostHogPersonPropertiesForFlags as u, OTEL_TRACES_ENDPOINT as ut, initializeOtelMetrics as v, DEFAULT_REGION_REQUEST as vt, toAttributes$1 as w, JSON_ENCODER as x, LogLevel as xt, recordHttpClientDuration as y, DrivingServiceMode as yt, ATTR_EXCEPTION_TYPE as z };
15543
+ export { INVALID_SPAN_CONTEXT as $, BindOnceFuture as A, ATTR_EXCEPTION_STACKTRACE as B, JSON_ENCODER as C, LogLevel as Ct, OTLPExporterBase as D, toAttributes$1 as E, isTimeInput as F, globalErrorHandler as G, ATTR_SERVICE_NAME as H, isTimeInputHrTime as I, trace as J, isTracingSuppressed as K, millisToHrTime as L, addHrTimes as M, hrTime as N, defaultResource as O, hrTimeDuration as P, isValidTraceId as Q, otperformance as R, createLegacyOtlpBrowserExportDelegate as S, ErrorCode as St, createResource as T, getNumberFromEnv as U, ATTR_EXCEPTION_TYPE as V, getStringFromEnv as W, context as X, diag as Y, isSpanContextValid as Z, cleanupOtelMetrics as _, generateTraceId as _t, clientContextFields as a, DiagAPI as at, getSdkPackage as b, DEFAULT_REGION_REQUEST as bt, logEvent as c, unregisterGlobal as ct, cleanupOtel as d, OTEL_STREAM_NAME as dt, TraceFlags as et, initializeOtel as f, OTEL_TRACES_ENDPOINT as ft, observeExporter as g, idManager as gt, hostOf as h, isDebugMode as ht, cleanupPostHog as i, createContextKey as it, ExportResultCode as j, resourceFromAttributes as k, logMetric as l, OTEL_LOGS_ENDPOINT as lt, fetchBootstrap as m, OTEL_USERNAME as mt, setLogLevel as n, createNoopMeter as nt, getLogsFeatureFlag as o, getGlobal as ot, clockSync as p, OTEL_TRACES_STREAM_NAME as pt, suppressTracing as q, logSink as r, ROOT_CONTEXT as rt, initializePostHog as s, registerGlobal as st, logger as t, ContextAPI as tt, updatePostHogPersonPropertiesForFlags as u, OTEL_PASSWORD as ut, initializeOtelMetrics as v, AvatarError as vt, createInstrumentationScope as w, resolveSdkVersion as x, DrivingServiceMode as xt, recordHttpClientDuration as y, DEFAULT_REGION as yt, ATTR_EXCEPTION_MESSAGE as z };
@@ -1,4 +1,4 @@
1
- import { _t as isDebugMode } from "./logger-BOpQ7u0w.js";
1
+ import { bt as isDebugMode } from "./logger-pANhsT4J.js";
2
2
  //#region config/app-config.ts
3
3
  var GLOBAL_FLAME_CDN_BASE = "https://cdn.spatialwalk.cloud/public";
4
4
  var CN_FLAME_CDN_BASE = "https://cdn.spatialwalk.top/public";
package/dist/index.js CHANGED
@@ -1,10 +1,10 @@
1
- import { a as EgressType, c as TransportCompression, i as AudioFormat, l as BinaryReader, o as Message, r as avatarViewRegistry, s as MessageType, t as AvatarSDK, u as BinaryWriter } from "./AvatarSDK-DgPvHU4L.js";
2
- import { At as FrameStarvationMode, C as recordMetric, Ct as ConnectionState, Dt as DEFAULT_REGION_REQUEST, Et as DEFAULT_REGION, Ft as TransitionType, Mt as LogLevel, Nt as RENDER_QUALITY_PARAMS, Ot as DrivingServiceMode, Pt as RenderQuality, St as AvatarState, Tt as DEFAULT_OPUS_BITRATE, bt as AnimationType, c as logEvent, g as clockSync, h as resolveMarks, jt as LoadProgress, kt as ErrorCode, l as logMetric, m as monoTimestamp, p as monoMarkFrom, t as logger, vt as idManager, wt as ConversationState, xt as AvatarError } from "./logger-BOpQ7u0w.js";
3
- import { a as startPlaybackTrace, i as startLoadTrace, o as buildTraceparent } from "./otel-trace-Ct4T48nC.js";
4
- import { n as APP_CONFIG } from "./error-utils-BogEllAd.js";
5
- import { r as OggMuxer, t as OggPageSplitter } from "./OpusCodec-CXU7ysrU.js";
6
- import { n as setOpusEncodeFrameSink } from "./OpusEncoderProxy-CzY-VckE.js";
7
- import { t as AvatarDownloader } from "./AvatarDownloader-DyhenPKd.js";
1
+ import { a as EgressType, c as TransportCompression, i as AudioFormat, l as BinaryReader, o as Message, r as avatarViewRegistry, s as MessageType, t as AvatarSDK, u as BinaryWriter } from "./AvatarSDK-BbqaBxdV.js";
2
+ import { At as DEFAULT_REGION_REQUEST, C as recordMetric, Ct as AnimationType, Dt as ConversationState, Et as ConnectionState, Ft as LogLevel, It as RENDER_QUALITY_PARAMS, Lt as RenderQuality, Mt as ErrorCode, Nt as FrameStarvationMode, Ot as DEFAULT_OPUS_BITRATE, Pt as LoadProgress, Rt as TransitionType, Tt as AvatarState, c as logEvent, g as clockSync, h as resolveMarks, jt as DrivingServiceMode, kt as DEFAULT_REGION, l as logMetric, m as monoTimestamp, p as monoMarkFrom, t as logger, wt as AvatarError, xt as idManager } from "./logger-pANhsT4J.js";
3
+ import { a as startLoadTrace, o as startPlaybackTrace, r as startConnectTrace, s as buildTraceparent } from "./otel-trace-DBN8K91J.js";
4
+ import { n as APP_CONFIG } from "./error-utils-DAqUlC0I.js";
5
+ import { r as OggMuxer, t as OggPageSplitter } from "./OpusCodec-TzsHzMqb.js";
6
+ import { n as setOpusEncodeFrameSink } from "./OpusEncoderProxy-bLEToi2R.js";
7
+ import { t as AvatarDownloader } from "./AvatarDownloader-DNeU2n5w.js";
8
8
  //#region core/Avatar.ts
9
9
  var Avatar = class {
10
10
  id;
@@ -311,8 +311,8 @@ var AnimationPlayer = class AnimationPlayer {
311
311
  */
312
312
  async createAndInitializeStreamingPlayer() {
313
313
  if (this.streamingPlayer) return;
314
- const { StreamingAudioPlayer } = await import("./StreamingAudioPlayer-CIJmBp3z.js");
315
- const { AvatarSDK } = await import("./AvatarSDK-DgPvHU4L.js").then((n) => n.n);
314
+ const { StreamingAudioPlayer } = await import("./StreamingAudioPlayer-CCg4uoVV.js");
315
+ const { AvatarSDK } = await import("./AvatarSDK-BbqaBxdV.js").then((n) => n.n);
316
316
  const audioFormat = AvatarSDK.getAudioFormat();
317
317
  this.streamingPlayer = new StreamingAudioPlayer({
318
318
  sampleRate: audioFormat.sampleRate,
@@ -952,6 +952,15 @@ var AnimationWebSocketClient = class extends EventEmitter {
952
952
  sessionConfigured = false;
953
953
  connectionStartTime = 0;
954
954
  /**
955
+ * 连接发起时刻(`new WebSocket()` 之前)。
956
+ *
957
+ * `ws_connect_latency` 与 connect trace 都以它为起点。与 `connectionStartTime`
958
+ * 分开:那个是「连接建立成功」的时刻,用来算 session 时长,语义不同。
959
+ */
960
+ connectStartMs = 0;
961
+ /** 握手完成(onopen)时刻,用来把连接拆成握手 / 会话确认两段。 */
962
+ wsOpenMs = 0;
963
+ /**
955
964
  * Opus encoder proxy, created only when the SDK-decided uplink is Opus. Null
956
965
  * means audio is sent as raw PCM. Scoped to one connection: created
957
966
  * on connect, destroyed on disconnect. Runs the encode off the main thread via
@@ -1343,7 +1352,7 @@ var AnimationWebSocketClient = class extends EventEmitter {
1343
1352
  return;
1344
1353
  }
1345
1354
  try {
1346
- const { OpusEncoderProxy } = await import("./OpusEncoderProxy-CzY-VckE.js").then((n) => n.t);
1355
+ const { OpusEncoderProxy } = await import("./OpusEncoderProxy-bLEToi2R.js").then((n) => n.t);
1347
1356
  const bitrate = opusBitrate ?? 48e3;
1348
1357
  this.opusEncoder = await OpusEncoderProxy.create(sampleRate, bitrate);
1349
1358
  this.uplinkIsOpus = true;
@@ -1399,19 +1408,39 @@ var AnimationWebSocketClient = class extends EventEmitter {
1399
1408
  if (connectionId) url.searchParams.set("connection_id", connectionId);
1400
1409
  return url.toString();
1401
1410
  }
1411
+ /**
1412
+ * 发一条建连 trace:`connect` 下挂 `ws_handshake` / `session_confirm` 两段。
1413
+ *
1414
+ * 在会话确认时一次性回填(两段的时刻都已知),而不是实时开 span——建连全程只有
1415
+ * 两个边界点,回填式更简单,也与 init / load trace 的做法一致。
1416
+ */
1417
+ emitConnectTrace(confirmMs) {
1418
+ const start = this.connectStartMs;
1419
+ const open = this.wsOpenMs;
1420
+ if (start <= 0 || open <= 0) return;
1421
+ const t = startConnectTrace(start, {
1422
+ connection_id: idManager.getConnectionId() ?? "",
1423
+ region: AvatarSDK.configuration?.region ?? ""
1424
+ });
1425
+ t.span("ws_handshake", start, open, { dur_ms: open - start });
1426
+ t.span("session_confirm", open, confirmMs, { dur_ms: confirmMs - open });
1427
+ t.end(true, confirmMs, { dur_ms: confirmMs - start });
1428
+ this.wsOpenMs = 0;
1429
+ }
1402
1430
  connectWebSocket(url) {
1403
1431
  return new Promise((resolve, reject) => {
1404
1432
  try {
1405
1433
  const urlForLog = this.sanitizeUrlForLog(url);
1406
1434
  logger.log(`[AnimationWebSocketClient] Connecting to WebSocket: ${urlForLog}`);
1407
- const connectStartMs = Date.now();
1435
+ this.connectStartMs = Date.now();
1436
+ this.wsOpenMs = 0;
1408
1437
  this.ws = new WebSocket(url);
1409
1438
  this.ws.onopen = () => {
1410
1439
  this.isConnecting = false;
1411
1440
  this.currentRetryCount = 0;
1412
1441
  this.isManuallyDisconnected = false;
1413
1442
  this.connectionStartTime = Date.now();
1414
- logMetric("ws_connect_latency", this.connectionStartTime - connectStartMs, {}, { connection_id: idManager.getConnectionId() || "" });
1443
+ this.wsOpenMs = this.connectionStartTime;
1415
1444
  logger.log(`[AnimationWebSocketClient] WebSocket connected successfully`);
1416
1445
  this.configureSession();
1417
1446
  this.emit("connected");
@@ -1586,6 +1615,12 @@ var AnimationWebSocketClient = class extends EventEmitter {
1586
1615
  idManager.setConnectionId(connectionId);
1587
1616
  logger.log(`[AnimationWebSocketClient] Session confirmed, connection_id updated: ${connectionId}`);
1588
1617
  } else logger.log("[AnimationWebSocketClient] Session confirmed by server");
1618
+ if (this.connectStartMs > 0) {
1619
+ const confirmMs = Date.now();
1620
+ logMetric("ws_connect_latency", confirmMs - this.connectStartMs, {}, { connection_id: idManager.getConnectionId() || "" });
1621
+ this.emitConnectTrace(confirmMs);
1622
+ this.connectStartMs = 0;
1623
+ }
1589
1624
  this.flushPendingAudio();
1590
1625
  this.emit("sessionConfirmed", connectionId);
1591
1626
  return;
@@ -2759,7 +2794,7 @@ var AvatarController = class {
2759
2794
  const { inputAudioFormat } = AvatarSDK.getAudioFormat();
2760
2795
  if (inputAudioFormat !== "opus" || this.inputOpusDecoderProxy) return;
2761
2796
  try {
2762
- const { OpusDecoderProxy } = await import("./OpusDecoderProxy-Cq8Z_MZY.js");
2797
+ const { OpusDecoderProxy } = await import("./OpusDecoderProxy-D4J2CfRQ.js");
2763
2798
  this.inputOpusDecoderProxy = await OpusDecoderProxy.create();
2764
2799
  this.inputDecodeChain = Promise.resolve();
2765
2800
  } catch (error) {
@@ -4059,7 +4094,7 @@ var AvatarManager = class AvatarManager {
4059
4094
  } else {
4060
4095
  logger.log(`[AvatarManager] Avatar ${id} cache invalid: updatedAt=${cachedUpdatedAt}->${newUpdatedAt}, modelType=${cachedModelType}->${requestedModelType}, reloading...`);
4061
4096
  this.avatarCache.delete(id);
4062
- const { PwaCacheManager } = await import("./pwa-cache-manager-C7NbU52Q.js").then((n) => n.n);
4097
+ const { PwaCacheManager } = await import("./pwa-cache-manager-M3XsMhvz.js").then((n) => n.n);
4063
4098
  await PwaCacheManager.clearCharacterCache(id);
4064
4099
  }
4065
4100
  }
@@ -4138,13 +4173,7 @@ var AvatarManager = class AvatarManager {
4138
4173
  * @returns Avatar instance, or undefined if not in cache
4139
4174
  */
4140
4175
  retrieve(id) {
4141
- const trace = startLoadTrace(id, Date.now(), { source: "cache" });
4142
- const cached = this.avatarCache.get(id);
4143
- trace.end(true, Date.now(), {
4144
- result: cached ? "hit" : "miss",
4145
- cache_hit: cached !== void 0
4146
- });
4147
- return cached;
4176
+ return this.avatarCache.get(id);
4148
4177
  }
4149
4178
  /**
4150
4179
  * Clear cached avatar for specified ID
@@ -60,3 +60,30 @@ export declare function startPlaybackTrace(conversationId: string, startTimeMs?:
60
60
  * dropped before it is sent.
61
61
  */
62
62
  export declare function recordMetric(name: string, value: number, attributes?: Attributes): void;
63
+ /**
64
+ * Declare which SDK these records come from, as the `sdk.package` and
65
+ * `sdk.version` resource attributes.
66
+ *
67
+ * Without it every RTC record is attributed to the host SDK and carries the
68
+ * host's version, so the backend — which splits RTC traffic by exactly these
69
+ * fields — cannot tell an RTC session from a plain AvatarKit integration, and
70
+ * this SDK's own version is absent from the data entirely. The native SDKs
71
+ * declare the same pair, through a ContentProvider (Android) and a claim at
72
+ * construction (iOS).
73
+ *
74
+ * Each field applies independently: passing only one leaves the other as it
75
+ * was. The version overrides the Resource's `sdk.version`; instrumentation
76
+ * scope versions come from elsewhere and are unaffected.
77
+ *
78
+ * Must be called before `AvatarSDK.initialize()`: the values are read when the
79
+ * OTel Resource is built and are fixed from then on. Sharing a module graph
80
+ * with the host makes that ordering straightforward here, so unlike the native
81
+ * SDKs no rebuild of the signal providers is needed.
82
+ *
83
+ * @param identity - `sdkPackage` e.g. `spatius-web-rtc`; `sdkVersion` that
84
+ * package's own version. Empty values are ignored.
85
+ */
86
+ export declare function setSdkIdentity(identity: {
87
+ sdkPackage?: string;
88
+ sdkVersion?: string;
89
+ }): void;
@@ -1,5 +1,5 @@
1
- import { C as recordMetric$1, g as clockSync } from "./logger-BOpQ7u0w.js";
2
- import { a as startPlaybackTrace$1 } from "./otel-trace-Ct4T48nC.js";
1
+ import { C as recordMetric$1, E as setSdkIdentity$1, g as clockSync } from "./logger-pANhsT4J.js";
2
+ import { o as startPlaybackTrace$1 } from "./otel-trace-DBN8K91J.js";
3
3
  //#region internal-telemetry.ts
4
4
  /**
5
5
  * Internal telemetry surface for the companion RTC SDK.
@@ -66,5 +66,31 @@ function startPlaybackTrace(conversationId, startTimeMs, attrs = {}) {
66
66
  function recordMetric(name, value, attributes = {}) {
67
67
  recordMetric$1(name, value, attributes);
68
68
  }
69
+ /**
70
+ * Declare which SDK these records come from, as the `sdk.package` and
71
+ * `sdk.version` resource attributes.
72
+ *
73
+ * Without it every RTC record is attributed to the host SDK and carries the
74
+ * host's version, so the backend — which splits RTC traffic by exactly these
75
+ * fields — cannot tell an RTC session from a plain AvatarKit integration, and
76
+ * this SDK's own version is absent from the data entirely. The native SDKs
77
+ * declare the same pair, through a ContentProvider (Android) and a claim at
78
+ * construction (iOS).
79
+ *
80
+ * Each field applies independently: passing only one leaves the other as it
81
+ * was. The version overrides the Resource's `sdk.version`; instrumentation
82
+ * scope versions come from elsewhere and are unaffected.
83
+ *
84
+ * Must be called before `AvatarSDK.initialize()`: the values are read when the
85
+ * OTel Resource is built and are fixed from then on. Sharing a module graph
86
+ * with the host makes that ordering straightforward here, so unlike the native
87
+ * SDKs no rebuild of the signal providers is needed.
88
+ *
89
+ * @param identity - `sdkPackage` e.g. `spatius-web-rtc`; `sdkVersion` that
90
+ * package's own version. Empty values are ignored.
91
+ */
92
+ function setSdkIdentity(identity) {
93
+ setSdkIdentity$1(identity);
94
+ }
69
95
  //#endregion
70
- export { isClockCalibrated, recordMetric, resolveMonoTimestamp, startPlaybackTrace };
96
+ export { isClockCalibrated, recordMetric, resolveMonoTimestamp, setSdkIdentity, startPlaybackTrace };
@@ -13509,6 +13509,38 @@ var OTLPMetricExporter = class extends OTLPMetricExporterBase {
13509
13509
  }
13510
13510
  };
13511
13511
  //#endregion
13512
+ //#region utils/otel-identity.ts
13513
+ var sdkPackage = "spatius-web-sdk";
13514
+ var injectedSdkVersion = null;
13515
+ /**
13516
+ * 声明本次上报的归属身份。
13517
+ *
13518
+ * 与 Android `AvatarSDK.inject` 同语义:两个字段各自独立生效,只传其一时另一个
13519
+ * 保持原值。版本覆盖的是 Resource 上的 `sdk.version`(scope 上的版本号另有来源,
13520
+ * 不受影响)。
13521
+ *
13522
+ * @param identity - `sdkPackage` 形如 `spatius-web-rtc`;`sdkVersion` 为该包
13523
+ * 自身的版本。空值忽略,避免误清成空字符串后整批记录失去归属。
13524
+ * @internal
13525
+ */
13526
+ function setSdkIdentity(identity) {
13527
+ if (identity.sdkPackage) sdkPackage = identity.sdkPackage;
13528
+ if (identity.sdkVersion) injectedSdkVersion = identity.sdkVersion;
13529
+ }
13530
+ /** 当前归属包名,供各通道构建 Resource 时读取。@internal */
13531
+ function getSdkPackage() {
13532
+ return sdkPackage;
13533
+ }
13534
+ /**
13535
+ * Resource 上应上报的版本号。
13536
+ *
13537
+ * @param hostVersion - 主库自己的版本,未被上层 SDK 声明时用它。
13538
+ * @internal
13539
+ */
13540
+ function resolveSdkVersion(hostVersion) {
13541
+ return injectedSdkVersion ?? hostVersion;
13542
+ }
13543
+ //#endregion
13512
13544
  //#region utils/otel-metrics.ts
13513
13545
  /**
13514
13546
  * OpenTelemetry Metrics Tracker (Browser Version)
@@ -13888,9 +13920,9 @@ function initializeOtelMetrics(version, resourceAttrs) {
13888
13920
  meterProvider = new MeterProvider({
13889
13921
  resource: resourceFromAttributes({
13890
13922
  [ATTR_SERVICE_NAME]: "avatarkit",
13891
- "sdk.version": sdkVersion$2,
13923
+ "sdk.version": resolveSdkVersion(sdkVersion$2),
13892
13924
  "sdk.platform": "web",
13893
- "sdk.package": "spatius-web-sdk",
13925
+ "sdk.package": getSdkPackage(),
13894
13926
  "app_id": resourceAttrs.appId || "",
13895
13927
  "region": resourceAttrs.region,
13896
13928
  "dsm": resourceAttrs.dsm
@@ -14647,9 +14679,9 @@ function initializeOtel(version, resourceAttrs) {
14647
14679
  loggerProvider = new LoggerProvider({
14648
14680
  resource: resourceFromAttributes({
14649
14681
  [ATTR_SERVICE_NAME]: "avatarkit",
14650
- "sdk.version": sdkVersion$1,
14682
+ "sdk.version": resolveSdkVersion(sdkVersion$1),
14651
14683
  "sdk.platform": "web",
14652
- "sdk.package": "spatius-web-sdk",
14684
+ "sdk.package": getSdkPackage(),
14653
14685
  "app_id": resourceAttrs.appId || "",
14654
14686
  "region": resourceAttrs.region,
14655
14687
  "dsm": resourceAttrs.dsm
@@ -15539,7 +15571,7 @@ async function writeToLocalLog(message, level, extra = {}) {
15539
15571
  try {
15540
15572
  const { shouldPersist, sanitized } = sanitizeForLocalLog(message);
15541
15573
  if (!shouldPersist) return;
15542
- const { AvatarSDK } = await import("./AvatarSDK-DgPvHU4L.js").then((n) => n.n);
15574
+ const { AvatarSDK } = await import("./AvatarSDK-BbqaBxdV.js").then((n) => n.n);
15543
15575
  const version = AvatarSDK.version;
15544
15576
  const appId = idManager.getAppId();
15545
15577
  const userId = idManager.getUserId();
@@ -15627,4 +15659,4 @@ function captureErrorContext(level, error) {
15627
15659
  });
15628
15660
  }
15629
15661
  //#endregion
15630
- export { isSpanContextValid as $, defaultResource as A, FrameStarvationMode as At, otperformance as B, recordMetric as C, ConnectionState as Ct, createResource as D, DEFAULT_REGION_REQUEST as Dt, createInstrumentationScope as E, DEFAULT_REGION as Et, hrTime as F, TransitionType as Ft, getNumberFromEnv as G, ATTR_EXCEPTION_STACKTRACE as H, hrTimeDuration as I, isTracingSuppressed as J, getStringFromEnv as K, isTimeInput as L, BindOnceFuture as M, LogLevel as Mt, ExportResultCode as N, RENDER_QUALITY_PARAMS as Nt, toAttributes$1 as O, DrivingServiceMode as Ot, addHrTimes as P, RenderQuality as Pt, context as Q, isTimeInputHrTime as R, recordHttpClientDuration as S, AvatarState as St, JSON_ENCODER as T, DEFAULT_OPUS_BITRATE as Tt, ATTR_EXCEPTION_TYPE as U, ATTR_EXCEPTION_MESSAGE as V, ATTR_SERVICE_NAME as W, trace as X, suppressTracing as Y, diag as Z, fetchBootstrap as _, isDebugMode as _t, clientContextFields as a, ROOT_CONTEXT as at, cleanupOtelMetrics as b, AnimationType as bt, logEvent as c, getGlobal as ct, cleanupOtel as d, OTEL_LOGS_ENDPOINT as dt, isValidTraceId as et, initializeOtel as f, OTEL_PASSWORD as ft, clockSync as g, OTEL_USERNAME as gt, resolveMarks as h, OTEL_TRACES_STREAM_NAME as ht, cleanupPostHog as i, createNoopMeter as it, resourceFromAttributes as j, LoadProgress as jt, OTLPExporterBase as k, ErrorCode as kt, logMetric as l, registerGlobal as lt, monoTimestamp as m, OTEL_TRACES_ENDPOINT as mt, setLogLevel as n, TraceFlags as nt, getLogsFeatureFlag as o, createContextKey as ot, monoMarkFrom as p, OTEL_STREAM_NAME as pt, globalErrorHandler as q, logSink as r, ContextAPI as rt, initializePostHog as s, DiagAPI as st, logger as t, INVALID_SPAN_CONTEXT as tt, updatePostHogPersonPropertiesForFlags as u, unregisterGlobal as ut, hostOf as v, idManager as vt, createLegacyOtlpBrowserExportDelegate as w, ConversationState as wt, initializeOtelMetrics as x, AvatarError as xt, observeExporter as y, generateTraceId as yt, millisToHrTime as z };
15662
+ export { trace as $, createResource as A, DEFAULT_REGION_REQUEST as At, isTimeInput as B, recordMetric as C, AnimationType as Ct, createLegacyOtlpBrowserExportDelegate as D, ConversationState as Dt, setSdkIdentity as E, ConnectionState as Et, BindOnceFuture as F, LogLevel as Ft, ATTR_EXCEPTION_STACKTRACE as G, millisToHrTime as H, ExportResultCode as I, RENDER_QUALITY_PARAMS as It, getNumberFromEnv as J, ATTR_EXCEPTION_TYPE as K, addHrTimes as L, RenderQuality as Lt, OTLPExporterBase as M, ErrorCode as Mt, defaultResource as N, FrameStarvationMode as Nt, JSON_ENCODER as O, DEFAULT_OPUS_BITRATE as Ot, resourceFromAttributes as P, LoadProgress as Pt, suppressTracing as Q, hrTime as R, TransitionType as Rt, recordHttpClientDuration as S, generateTraceId as St, resolveSdkVersion as T, AvatarState as Tt, otperformance as U, isTimeInputHrTime as V, ATTR_EXCEPTION_MESSAGE as W, globalErrorHandler as X, getStringFromEnv as Y, isTracingSuppressed as Z, fetchBootstrap as _, OTEL_TRACES_ENDPOINT as _t, clientContextFields as a, TraceFlags as at, cleanupOtelMetrics as b, isDebugMode as bt, logEvent as c, ROOT_CONTEXT as ct, cleanupOtel as d, getGlobal as dt, diag as et, initializeOtel as f, registerGlobal as ft, clockSync as g, OTEL_STREAM_NAME as gt, resolveMarks as h, OTEL_PASSWORD as ht, cleanupPostHog as i, INVALID_SPAN_CONTEXT as it, toAttributes$1 as j, DrivingServiceMode as jt, createInstrumentationScope as k, DEFAULT_REGION as kt, logMetric as l, createContextKey as lt, monoTimestamp as m, OTEL_LOGS_ENDPOINT as mt, setLogLevel as n, isSpanContextValid as nt, getLogsFeatureFlag as o, ContextAPI as ot, monoMarkFrom as p, unregisterGlobal as pt, ATTR_SERVICE_NAME as q, logSink as r, isValidTraceId as rt, initializePostHog as s, createNoopMeter as st, logger as t, context as tt, updatePostHogPersonPropertiesForFlags as u, DiagAPI as ut, hostOf as v, OTEL_TRACES_STREAM_NAME as vt, getSdkPackage as w, AvatarError as wt, initializeOtelMetrics as x, idManager as xt, observeExporter as y, OTEL_USERNAME as yt, hrTimeDuration as z };
@@ -1,4 +1,4 @@
1
- import { $ as isSpanContextValid, A as defaultResource, B as otperformance, D as createResource, E as createInstrumentationScope, F as hrTime, G as getNumberFromEnv, H as ATTR_EXCEPTION_STACKTRACE, I as hrTimeDuration, J as isTracingSuppressed, K as getStringFromEnv, L as isTimeInput, M as BindOnceFuture, N as ExportResultCode, O as toAttributes, P as addHrTimes, Q as context, R as isTimeInputHrTime, T as JSON_ENCODER, U as ATTR_EXCEPTION_TYPE, V as ATTR_EXCEPTION_MESSAGE, W as ATTR_SERVICE_NAME, X as trace, Y as suppressTracing, Z as diag$1, a as clientContextFields, at as ROOT_CONTEXT, ct as getGlobal, et as isValidTraceId, ft as OTEL_PASSWORD, gt as OTEL_USERNAME, ht as OTEL_TRACES_STREAM_NAME, it as createNoopMeter, j as resourceFromAttributes, k as OTLPExporterBase, lt as registerGlobal, mt as OTEL_TRACES_ENDPOINT, nt as TraceFlags, ot as createContextKey, q as globalErrorHandler, rt as ContextAPI, st as DiagAPI, t as logger, tt as INVALID_SPAN_CONTEXT, ut as unregisterGlobal, vt as idManager, w as createLegacyOtlpBrowserExportDelegate, y as observeExporter, z as millisToHrTime } from "./logger-BOpQ7u0w.js";
1
+ import { $ as trace, A as createResource, B as isTimeInput, D as createLegacyOtlpBrowserExportDelegate, F as BindOnceFuture, G as ATTR_EXCEPTION_STACKTRACE, H as millisToHrTime, I as ExportResultCode, J as getNumberFromEnv, K as ATTR_EXCEPTION_TYPE, L as addHrTimes, M as OTLPExporterBase, N as defaultResource, O as JSON_ENCODER, P as resourceFromAttributes, Q as suppressTracing, R as hrTime, T as resolveSdkVersion, U as otperformance, V as isTimeInputHrTime, W as ATTR_EXCEPTION_MESSAGE, X as globalErrorHandler, Y as getStringFromEnv, Z as isTracingSuppressed, _t as OTEL_TRACES_ENDPOINT, a as clientContextFields, at as TraceFlags, ct as ROOT_CONTEXT, dt as getGlobal, et as diag$1, ft as registerGlobal, ht as OTEL_PASSWORD, it as INVALID_SPAN_CONTEXT, j as toAttributes, k as createInstrumentationScope, lt as createContextKey, nt as isSpanContextValid, ot as ContextAPI, pt as unregisterGlobal, q as ATTR_SERVICE_NAME, rt as isValidTraceId, st as createNoopMeter, t as logger, tt as context, ut as DiagAPI, vt as OTEL_TRACES_STREAM_NAME, w as getSdkPackage, xt as idManager, y as observeExporter, yt as OTEL_USERNAME, z as hrTimeDuration } from "./logger-pANhsT4J.js";
2
2
  //#region node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/baggage/internal/baggage-impl.js
3
3
  var BaggageImpl = class BaggageImpl {
4
4
  constructor(entries) {
@@ -2321,9 +2321,9 @@ function initializeOtelTrace(version, resourceAttrs) {
2321
2321
  tracerProvider = new WebTracerProvider({
2322
2322
  resource: resourceFromAttributes({
2323
2323
  [ATTR_SERVICE_NAME]: "avatarkit",
2324
- "sdk.version": sdkVersion,
2324
+ "sdk.version": resolveSdkVersion(sdkVersion),
2325
2325
  "sdk.platform": "web",
2326
- "sdk.package": "spatius-web-sdk",
2326
+ "sdk.package": getSdkPackage(),
2327
2327
  "app_id": resourceAttrs.appId || "",
2328
2328
  "region": resourceAttrs.region,
2329
2329
  "dsm": resourceAttrs.dsm,
@@ -2399,7 +2399,7 @@ function startInitTrace(sessionId, startTimeMs, attrs = {}) {
2399
2399
  attributes: spanAttrs
2400
2400
  }, rootCtx);
2401
2401
  if (isError) sp.setStatus({ code: SpanStatusCode.ERROR });
2402
- sp.end(endMs);
2402
+ sp.end(Math.max(endMs, startMs + 1));
2403
2403
  } catch {}
2404
2404
  },
2405
2405
  group: () => NOOP_GROUP,
@@ -2436,7 +2436,7 @@ function startLoadTrace(avatarId, startTimeMs, attrs = {}) {
2436
2436
  attributes: spanAttrs
2437
2437
  }, rootCtx);
2438
2438
  if (isError) s.setStatus({ code: SpanStatusCode.ERROR });
2439
- s.end(endMs);
2439
+ s.end(Math.max(endMs, startMs + 1));
2440
2440
  } catch {}
2441
2441
  },
2442
2442
  group: () => NOOP_GROUP,
@@ -2454,6 +2454,52 @@ function startLoadTrace(avatarId, startTimeMs, attrs = {}) {
2454
2454
  }
2455
2455
  }
2456
2456
  /**
2457
+ * 开一条建连 trace。root span 名 `connect`,下挂 `ws_handshake` / `session_confirm` 两段。
2458
+ *
2459
+ * 与 `ws_connect_latency` 互补:那条 metric 只给出总耗时,而慢在哪一段——TLS/网络握手,
2460
+ * 还是服务端校验 token、分配资源——只有拆开才看得出。两段的边界就是 `onopen`。
2461
+ *
2462
+ * 与 load / playback 是三条独立 trace,靠 session_id 关联。
2463
+ * @param startTimeMs root span 起点(发起连接那一刻,epoch ms)。
2464
+ * @internal
2465
+ */
2466
+ function startConnectTrace(startTimeMs, attrs = {}) {
2467
+ if (!tracer || !tracerProvider) return NOOP_TRACE;
2468
+ try {
2469
+ const root = tracer.startSpan("connect", {
2470
+ startTime: startTimeMs,
2471
+ attributes: {
2472
+ session_id: idManager.getSessionId(),
2473
+ ...attrs
2474
+ }
2475
+ }, ROOT_CONTEXT);
2476
+ const rootCtx = trace.setSpan(ROOT_CONTEXT, root);
2477
+ return {
2478
+ span(name, startMs, endMs, spanAttrs = {}, isError = false) {
2479
+ try {
2480
+ const s = tracer.startSpan(name, {
2481
+ startTime: startMs,
2482
+ attributes: spanAttrs
2483
+ }, rootCtx);
2484
+ if (isError) s.setStatus({ code: SpanStatusCode.ERROR });
2485
+ s.end(Math.max(endMs, startMs + 1));
2486
+ } catch {}
2487
+ },
2488
+ group: () => NOOP_GROUP,
2489
+ end(ok = true, endTimeMs, endAttrs = {}) {
2490
+ try {
2491
+ for (const [k, v] of Object.entries(endAttrs)) root.setAttribute(k, v);
2492
+ root.setStatus({ code: ok ? SpanStatusCode.OK : SpanStatusCode.ERROR });
2493
+ root.end(endTimeMs);
2494
+ } catch {}
2495
+ }
2496
+ };
2497
+ } catch (error) {
2498
+ logger.warn("[OTel-Trace] Failed to start connect trace:", error instanceof Error ? error.message : String(error));
2499
+ return NOOP_TRACE;
2500
+ }
2501
+ }
2502
+ /**
2457
2503
  * 开一条播放 trace。root span 名 `playback`,trace_id 由 conversation_id 确定性派生,
2458
2504
  * conversation_id 同时作为 span 属性(无论是否与后端串成一条 trace,都能按它关联查询)。
2459
2505
  * @param startTimeMs root span 起点(首包音频 tap_0 的真实时刻,epoch ms);省略则用当前时刻。
@@ -2497,7 +2543,7 @@ function startPlaybackTrace(conversationId, startTimeMs, attrs = {}) {
2497
2543
  startTime: startMs
2498
2544
  }, ctx);
2499
2545
  if (isError) s.setStatus({ code: SpanStatusCode.ERROR });
2500
- s.end(endMs);
2546
+ s.end(Math.max(endMs, startMs + 1));
2501
2547
  } catch {}
2502
2548
  };
2503
2549
  return {
@@ -2562,4 +2608,4 @@ function cleanupOtelTrace() {
2562
2608
  }
2563
2609
  }
2564
2610
  //#endregion
2565
- export { startPlaybackTrace as a, startLoadTrace as i, initializeOtelTrace as n, buildTraceparent as o, startInitTrace as r, cleanupOtelTrace as t };
2611
+ export { startLoadTrace as a, startInitTrace as i, initializeOtelTrace as n, startPlaybackTrace as o, startConnectTrace as r, buildTraceparent as s, cleanupOtelTrace as t };
@@ -1,5 +1,5 @@
1
1
  import { n as __exportAll } from "./rolldown-runtime-B-1-B7_t.js";
2
- import { t as logger } from "./logger-BOpQ7u0w.js";
2
+ import { t as logger } from "./logger-pANhsT4J.js";
3
3
  //#region utils/pwa-cache-manager.ts
4
4
  /**
5
5
  * PWA Cache Manager
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@spatius/avatarkit",
3
3
  "type": "module",
4
- "version": "1.3.1",
4
+ "version": "1.3.3",
5
5
  "packageManager": "pnpm@10.18.2",
6
6
  "description": "AvatarKit — real-time, audio-driven avatar rendering SDK for Web.",
7
7
  "homepage": "https://spatius.ai/",