obi-sdk 0.3.13 → 0.4.0

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.
@@ -1,4 +1,4 @@
1
- import { O as ObiWidget } from "./chunks/obi-widget-d7e7c6bf.js";
1
+ import { O as ObiWidget } from "./chunks/obi-widget-9ef6796a.js";
2
2
  import "./chunks/types-82772f00.js";
3
3
  if (!customElements.get("obi-widget")) {
4
4
  customElements.define("obi-widget", ObiWidget);
@@ -1,6 +1,6 @@
1
1
  import { S as SDKState } from "./chunks/types-82772f00.js";
2
- import { i, n, a as i$1, x } from "./chunks/obi-widget-d7e7c6bf.js";
3
- import { A, C, c, d, D, N, b, O, S } from "./chunks/obi-widget-d7e7c6bf.js";
2
+ import { i, n, a as i$1, x } from "./chunks/obi-widget-9ef6796a.js";
3
+ import { A, C, c, d, D, N, b, O, S } from "./chunks/obi-widget-9ef6796a.js";
4
4
  var __defProp = Object.defineProperty;
5
5
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
6
  var __decorateClass = (decorators, target, key, kind) => {
@@ -85,14 +85,14 @@ if (!customElements.get("obi-status-widget")) {
85
85
  const statusWidget = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({ __proto__: null, ObiStatusWidget }, Symbol.toStringTag, { value: "Module" }));
86
86
  function defineCustomElements() {
87
87
  Promise.resolve().then(() => statusWidget);
88
- import("./chunks/obi-widget-d7e7c6bf.js").then((n2) => n2.o);
89
- import("./chunks/obi-widget-d7e7c6bf.js").then((n2) => n2.j);
90
- import("./chunks/obi-widget-d7e7c6bf.js").then((n2) => n2.k);
91
- import("./chunks/obi-widget-d7e7c6bf.js").then((n2) => n2.e);
92
- import("./chunks/obi-widget-d7e7c6bf.js").then((n2) => n2.f);
93
- import("./chunks/obi-widget-d7e7c6bf.js").then((n2) => n2.s);
94
- import("./chunks/obi-widget-d7e7c6bf.js").then((n2) => n2.g);
95
- import("./chunks/obi-widget-d7e7c6bf.js").then((n2) => n2.h);
88
+ import("./chunks/obi-widget-9ef6796a.js").then((n2) => n2.o);
89
+ import("./chunks/obi-widget-9ef6796a.js").then((n2) => n2.j);
90
+ import("./chunks/obi-widget-9ef6796a.js").then((n2) => n2.k);
91
+ import("./chunks/obi-widget-9ef6796a.js").then((n2) => n2.e);
92
+ import("./chunks/obi-widget-9ef6796a.js").then((n2) => n2.f);
93
+ import("./chunks/obi-widget-9ef6796a.js").then((n2) => n2.s);
94
+ import("./chunks/obi-widget-9ef6796a.js").then((n2) => n2.g);
95
+ import("./chunks/obi-widget-9ef6796a.js").then((n2) => n2.h);
96
96
  }
97
97
  export {
98
98
  A as AudioEqualizer,
@@ -22954,6 +22954,9 @@ class ObiSession {
22954
22954
  this._userAudioTimer = null;
22955
22955
  this.sessionId = sessionId;
22956
22956
  this.apiBaseUrl = apiBaseUrl || DEFAULT_API_BASE_URL;
22957
+ this.client = new ObiClient({
22958
+ baseUrl: this.apiBaseUrl
22959
+ });
22957
22960
  this.emitter = new EventEmitter();
22958
22961
  }
22959
22962
  emit(event, data) {
@@ -23010,7 +23013,7 @@ class ObiSession {
23010
23013
  if (this.currentState === SDKState.RESEARCHING || this.currentState === SDKState.PAUSED)
23011
23014
  return;
23012
23015
  const state = attributes["lk.agent.state"];
23013
- const newState = z$2(state).with("listening", () => SDKState.USER_SPEAKING).with("speaking", () => SDKState.AGENT_SPEAKING).with("thinking", () => SDKState.AGENT_SPEAKING).otherwise(() => void 0);
23016
+ const newState = z$2(state).with("listening", () => SDKState.USER_SPEAKING).with("speaking", () => SDKState.AGENT_SPEAKING).with("thinking", () => SDKState.THINKING).otherwise(() => void 0);
23014
23017
  if (!newState)
23015
23018
  return;
23016
23019
  this.setState(newState);
@@ -23080,10 +23083,8 @@ class ObiSession {
23080
23083
  dynacast: true
23081
23084
  });
23082
23085
  this.setupRoomEventListeners();
23083
- const params = new URLSearchParams({ token: this.sessionId, skip_intro: "true" });
23084
- const joinEndpoint = `${this.apiBaseUrl}/join-token?${params.toString()}`;
23085
- const joinToken = await fetch(joinEndpoint).then((res) => res.json());
23086
- await this.room.connect(joinToken.url, joinToken.token);
23086
+ const joinToken = await this.client.getJoinToken(this.sessionId, { skipIntro: true });
23087
+ await this.room.connect(joinToken.data.url, joinToken.data.token);
23087
23088
  if (this.microphoneStream) {
23088
23089
  const micTrack = this.microphoneStream.getAudioTracks()[0];
23089
23090
  await this.room.localParticipant.publishTrack(micTrack, {
@@ -23092,8 +23093,8 @@ class ObiSession {
23092
23093
  });
23093
23094
  }
23094
23095
  return {
23095
- url: joinToken.url,
23096
- token: joinToken.token
23096
+ url: joinToken.data.url,
23097
+ token: joinToken.data.token
23097
23098
  };
23098
23099
  } catch (error) {
23099
23100
  console.error("Failed to connect to LiveKit:", error);
@@ -23138,6 +23139,9 @@ class ObiSession {
23138
23139
  this.currentState = newState;
23139
23140
  this.emitter.emit("stateChanged", newState);
23140
23141
  }
23142
+ getCurrentState() {
23143
+ return this.currentState;
23144
+ }
23141
23145
  async requestMicrophone() {
23142
23146
  try {
23143
23147
  const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
@@ -33587,7 +33591,7 @@ SessionStartModal.styles = css`
33587
33591
  align-items: center;
33588
33592
  gap: 8px;
33589
33593
  aspect-ratio: 1/1;
33590
- border-radius: var(--border-radius-lg, 8px);
33594
+ border-radius: var(--border-radius-lg, 12px);
33591
33595
  background: var(--tailwind-colors-violet-600, #7c3aed);
33592
33596
  box-shadow:
33593
33597
  0px 0px 8px 0px rgba(168, 85, 247, 0.12),
@@ -33695,11 +33699,13 @@ var __decorateClass = (decorators, target, key, kind) => {
33695
33699
  __defProp(target, key, result);
33696
33700
  return result;
33697
33701
  };
33702
+ const WIDGET_PARAMS_KEY = "io.obi.widget-parameters";
33698
33703
  class ObiWidget extends LitElement {
33699
33704
  constructor() {
33700
33705
  super();
33701
33706
  this.apiKey = "";
33702
33707
  this.isActive = true;
33708
+ this.linkOnlyAccess = false;
33703
33709
  this.position = "bottom-right";
33704
33710
  this.user = null;
33705
33711
  this.state = SDKState.READY;
@@ -33721,6 +33727,7 @@ class ObiWidget extends LitElement {
33721
33727
  this.boundSaveSessionData = null;
33722
33728
  this.obiClient = null;
33723
33729
  this.closeNavTimeoutRef = null;
33730
+ this.researchingTimeoutRef = null;
33724
33731
  this.handleCourseSelectEvent = (event) => {
33725
33732
  const customEvent = event;
33726
33733
  this.selectedCourse = customEvent.detail;
@@ -33741,10 +33748,12 @@ class ObiWidget extends LitElement {
33741
33748
  const sessionWithPlan = matchingSession;
33742
33749
  this.selectedCourse = {
33743
33750
  id: sessionToken,
33744
- name: sessionWithPlan.onboarding_plan?.product?.name || "Session from URL",
33745
- description: sessionWithPlan.onboarding_plan?.product?.description || "Continue your session"
33751
+ name: sessionWithPlan.onboarding_plan?.name || "",
33752
+ description: sessionWithPlan.onboarding_plan?.description || ""
33746
33753
  };
33747
33754
  this.showSessionStartModal = true;
33755
+ } else {
33756
+ console.log("No session found with token:", sessionToken);
33748
33757
  }
33749
33758
  }
33750
33759
  } catch (error) {
@@ -33771,15 +33780,23 @@ class ObiWidget extends LitElement {
33771
33780
  if (window.obiWidgetConfig.isActive !== void 0) {
33772
33781
  this.isActive = window.obiWidgetConfig.isActive;
33773
33782
  }
33783
+ if (window.obiWidgetConfig.linkOnlyAccess !== void 0) {
33784
+ this.linkOnlyAccess = window.obiWidgetConfig.linkOnlyAccess;
33785
+ }
33774
33786
  this.style.setProperty("--obi-primary", window.obiWidgetConfig?.primaryColor || "#9500ff");
33775
33787
  this.style.setProperty("--obi-secondary", window.obiWidgetConfig?.secondaryColor || "#c4b5fd");
33776
33788
  }
33777
33789
  }
33778
- removeSessionFromUrl() {
33790
+ removeSessionUrlParams() {
33779
33791
  const url = new URL(window.location.href);
33780
33792
  url.searchParams.delete(SESSION_URL_PARAM);
33781
33793
  url.searchParams.delete(API_KEY_URL_PARAM);
33782
33794
  window.history.replaceState({}, "", url.toString());
33795
+ try {
33796
+ localStorage.removeItem(WIDGET_PARAMS_KEY);
33797
+ } catch (error) {
33798
+ console.warn("Failed to remove widget parameters from localStorage:", error);
33799
+ }
33783
33800
  }
33784
33801
  /**
33785
33802
  * Create a new ObiSession instance with common configuration
@@ -33805,9 +33822,27 @@ class ObiWidget extends LitElement {
33805
33822
  */
33806
33823
  setupSessionEventListeners(session, onError) {
33807
33824
  session.on("stateChanged", (newState) => {
33808
- this.state = newState;
33809
- if (newState !== SDKState.READY) {
33825
+ if (newState === SDKState.RESEARCHING) {
33826
+ if (this.researchingTimeoutRef) {
33827
+ window.clearTimeout(this.researchingTimeoutRef);
33828
+ }
33829
+ this.state = newState;
33830
+ this.researchingTimeoutRef = window.setTimeout(() => {
33831
+ this.researchingTimeoutRef = null;
33832
+ const currentSessionState = session.getCurrentState();
33833
+ this.state = currentSessionState;
33834
+ if (currentSessionState !== SDKState.READY) {
33835
+ this.storedActiveState = currentSessionState;
33836
+ }
33837
+ }, 1500);
33810
33838
  this.storedActiveState = newState;
33839
+ return;
33840
+ }
33841
+ if (this.researchingTimeoutRef === null) {
33842
+ this.state = newState;
33843
+ if (newState !== SDKState.READY) {
33844
+ this.storedActiveState = newState;
33845
+ }
33811
33846
  }
33812
33847
  });
33813
33848
  session.on("volume", ({ speaker, spectrum, volume }) => {
@@ -33840,10 +33875,10 @@ class ObiWidget extends LitElement {
33840
33875
  try {
33841
33876
  const session = this.createSession(sessionToken);
33842
33877
  if (!session) {
33843
- this.handleSessionCreationFailure(() => this.removeSessionFromUrl());
33878
+ this.handleSessionCreationFailure(() => this.removeSessionUrlParams());
33844
33879
  return;
33845
33880
  }
33846
- this.setupSessionEventListeners(session, () => this.removeSessionFromUrl());
33881
+ this.setupSessionEventListeners(session, () => this.removeSessionUrlParams());
33847
33882
  session.on("screenCaptureRequested", async () => {
33848
33883
  try {
33849
33884
  const canvas = await html2canvas(document.documentElement, {
@@ -33863,12 +33898,12 @@ class ObiWidget extends LitElement {
33863
33898
  this.sessionToken = sessionToken;
33864
33899
  this.roomToken = connectionInfo.token;
33865
33900
  this.roomUrl = connectionInfo.url;
33866
- this.removeSessionFromUrl();
33901
+ this.removeSessionUrlParams();
33867
33902
  }
33868
33903
  this.activeSession = session;
33869
33904
  } catch (error) {
33870
33905
  console.error("Failed to start session:", error);
33871
- this.handleSessionCreationFailure(() => this.removeSessionFromUrl());
33906
+ this.handleSessionCreationFailure(() => this.removeSessionUrlParams());
33872
33907
  }
33873
33908
  }
33874
33909
  async handleSessionStart(sessionToken) {
@@ -33949,9 +33984,28 @@ class ObiWidget extends LitElement {
33949
33984
  async sessionConnectionCheck() {
33950
33985
  await this.checkExistingSession();
33951
33986
  if (!this.activeSession) {
33952
- const urlParams = new URLSearchParams(window.location.search);
33953
- const sessionId = urlParams.get(SESSION_URL_PARAM);
33954
- this.apiKey = urlParams.get(API_KEY_URL_PARAM) || this.apiKey;
33987
+ let storedParams = {};
33988
+ try {
33989
+ const storedParamsJson = localStorage.getItem(WIDGET_PARAMS_KEY);
33990
+ if (storedParamsJson) {
33991
+ storedParams = JSON.parse(storedParamsJson);
33992
+ }
33993
+ } catch (error) {
33994
+ console.warn("Failed to parse stored widget parameters:", error);
33995
+ }
33996
+ if (Object.keys(storedParams).length === 0) {
33997
+ const urlParams = new URLSearchParams(window.location.search);
33998
+ urlParams.forEach((value, key) => {
33999
+ storedParams[key] = value;
34000
+ });
34001
+ }
34002
+ const sessionId = storedParams[SESSION_URL_PARAM];
34003
+ const urlApiKey = storedParams[API_KEY_URL_PARAM];
34004
+ if (urlApiKey) {
34005
+ this.apiKey = urlApiKey;
34006
+ } else if (!this.apiKey && window.obiWidgetConfig?.apiKey) {
34007
+ this.apiKey = window.obiWidgetConfig.apiKey;
34008
+ }
33955
34009
  if (sessionId && this.apiKey) {
33956
34010
  await this.handleUrlSessionEvent(sessionId);
33957
34011
  }
@@ -33970,11 +34024,15 @@ class ObiWidget extends LitElement {
33970
34024
  if (this.closeNavTimeoutRef !== null) {
33971
34025
  window.clearTimeout(this.closeNavTimeoutRef);
33972
34026
  }
34027
+ if (this.researchingTimeoutRef !== null) {
34028
+ window.clearTimeout(this.researchingTimeoutRef);
34029
+ this.researchingTimeoutRef = null;
34030
+ }
33973
34031
  if (this.boundSaveSessionData) {
33974
34032
  window.removeEventListener("beforeunload", this.boundSaveSessionData);
33975
34033
  window.removeEventListener("pagehide", this.boundSaveSessionData);
33976
34034
  }
33977
- this.removeSessionFromUrl();
34035
+ this.removeSessionUrlParams();
33978
34036
  super.disconnectedCallback();
33979
34037
  }
33980
34038
  handleMouseEnter() {
@@ -34002,6 +34060,10 @@ class ObiWidget extends LitElement {
34002
34060
  this.sessionToken = null;
34003
34061
  this.roomToken = null;
34004
34062
  this.roomUrl = null;
34063
+ if (this.researchingTimeoutRef !== null) {
34064
+ window.clearTimeout(this.researchingTimeoutRef);
34065
+ this.researchingTimeoutRef = null;
34066
+ }
34005
34067
  if (this.activeSession) {
34006
34068
  this.activeSession.disconnect();
34007
34069
  this.activeSession = null;
@@ -34026,13 +34088,26 @@ class ObiWidget extends LitElement {
34026
34088
  render() {
34027
34089
  if (!this.isActive)
34028
34090
  return nothing;
34091
+ if (this.linkOnlyAccess && this.state === SDKState.READY)
34092
+ return nothing;
34029
34093
  const stateRender = z$2(this.state).with(SDKState.LOADING, () => html`<obi-dot-loader></obi-dot-loader>`).with(SDKState.RESEARCHING, () => html`<obi-searching-loader></obi-searching-loader>`).with(
34030
34094
  N$1.union(SDKState.USER_SPEAKING, SDKState.AGENT_SPEAKING),
34031
34095
  () => html`<obi-audio-equalizer .volume=${this.volume}></obi-audio-equalizer>`
34032
- ).with(SDKState.PAUSED, () => obiIcon).otherwise(() => obiIcon);
34096
+ ).with(SDKState.THINKING, () => html`<obi-dot-loader></obi-dot-loader>`).with(SDKState.PAUSED, () => obiIcon).otherwise(() => obiIcon);
34097
+ const isPulseState = this.state === SDKState.USER_SPEAKING || this.state === SDKState.AGENT_SPEAKING;
34098
+ const isResearching = this.state === SDKState.RESEARCHING;
34099
+ const isUserSpeaking = this.state === SDKState.USER_SPEAKING;
34100
+ const isRotated = this.state !== SDKState.READY || this.navVisible;
34101
+ const containerClasses = [
34102
+ "widget-container",
34103
+ isRotated ? "rotated" : "",
34104
+ isPulseState ? "pulse" : "",
34105
+ isResearching ? "researching" : "",
34106
+ isUserSpeaking ? "user-speaking" : ""
34107
+ ].filter(Boolean).join(" ");
34033
34108
  return html`
34034
34109
  <div
34035
- class="widget-container ${this.state === SDKState.USER_SPEAKING || this.state === SDKState.AGENT_SPEAKING ? "pulse" : ""} ${this.state !== SDKState.READY || this.navVisible ? "rounded" : ""} ${this.state === SDKState.RESEARCHING ? "researching" : ""} ${this.state === SDKState.USER_SPEAKING ? "user-speaking" : ""}"
34110
+ class="${containerClasses}"
34036
34111
  @mouseenter=${this.handleMouseEnter}
34037
34112
  @mouseleave=${this.handleMouseLeave}
34038
34113
  >
@@ -34140,7 +34215,7 @@ ObiWidget.styles = css`
34140
34215
  position: fixed;
34141
34216
  width: 56px;
34142
34217
  height: 56px;
34143
- border-radius: 28px;
34218
+ border-radius: 12px;
34144
34219
  border-color: transparent;
34145
34220
  background-color: var(--obi-primary);
34146
34221
  display: flex;
@@ -34156,17 +34231,8 @@ ObiWidget.styles = css`
34156
34231
  linear-gradient(195.84deg, var(--obi-secondary) 00 11.05%, var(--obi-secondary) 117.01%);
34157
34232
  }
34158
34233
 
34159
- .widget-container:hover {
34160
- border-radius: 12px;
34161
- }
34162
-
34163
- .widget-container.rounded {
34164
- border-radius: 12px;
34165
- }
34166
-
34167
34234
  .widget-container.researching {
34168
34235
  width: 273px;
34169
- border-radius: 12px;
34170
34236
  }
34171
34237
 
34172
34238
  .widget-icon {
@@ -34175,7 +34241,7 @@ ObiWidget.styles = css`
34175
34241
  transition: transform 0.5s ease-in-out;
34176
34242
  }
34177
34243
 
34178
- .widget-container.rounded .widget-icon {
34244
+ .widget-container.rotated .widget-icon {
34179
34245
  transform: rotate(90deg);
34180
34246
  }
34181
34247
 
@@ -34201,6 +34267,9 @@ __decorateClass([
34201
34267
  __decorateClass([
34202
34268
  r$2()
34203
34269
  ], ObiWidget.prototype, "isActive", 2);
34270
+ __decorateClass([
34271
+ r$2()
34272
+ ], ObiWidget.prototype, "linkOnlyAccess", 2);
34204
34273
  __decorateClass([
34205
34274
  r$2()
34206
34275
  ], ObiWidget.prototype, "position", 2);