obi-sdk 0.6.8 → 0.7.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.
package/dist/loader.d.ts CHANGED
@@ -14,6 +14,7 @@ interface ObiWidgetConfig {
14
14
  } | null;
15
15
  isActive?: boolean;
16
16
  linkOnlyAccess?: boolean;
17
+ showMenu?: boolean;
17
18
  primaryColor?: string;
18
19
  }
19
20
  declare class ObiWidgetLoader {
@@ -0,0 +1,6 @@
1
+ import { O } from "./obi-widget-6550377d.js";
2
+ import "./types-e0297e7b.js";
3
+ export {
4
+ O as ObiWidget
5
+ };
6
+ //# sourceMappingURL=index-f31a59cc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-f31a59cc.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;"}
@@ -15815,13 +15815,11 @@ function getDefaultIntegrations(_options) {
15815
15815
  ];
15816
15816
  }
15817
15817
  function createSentryScope() {
15818
- const integrations = getDefaultIntegrations().filter(
15819
- (defaultIntegration) => {
15820
- return !["BrowserApiErrors", "Breadcrumbs", "GlobalHandlers", "HttpContext"].includes(
15821
- defaultIntegration.name
15822
- );
15823
- }
15824
- );
15818
+ const integrations = getDefaultIntegrations().filter((defaultIntegration) => {
15819
+ return !["BrowserApiErrors", "Breadcrumbs", "GlobalHandlers", "HttpContext"].includes(
15820
+ defaultIntegration.name
15821
+ );
15822
+ });
15825
15823
  const client = new BrowserClient({
15826
15824
  dsn: "https://ac54bd10eac67be2dafbc346e704e4d4@o4507251798835200.ingest.us.sentry.io/4509409566392320",
15827
15825
  environment: "production",
@@ -16593,13 +16591,24 @@ class CourseModal extends i$1 {
16593
16591
  composed: true
16594
16592
  })
16595
16593
  );
16596
- this.onClose?.();
16597
16594
  }
16598
16595
  }
16599
16596
  async fetchCourses() {
16600
16597
  try {
16601
16598
  this.loading = true;
16602
- const raw_response = await fetch(`${this.apiBaseUrl}/sessions?token=${this.apiKey}`);
16599
+ console.log("[CourseModal] Fetching sessions from API", {
16600
+ apiKey: this.apiKey ? "present" : "missing"
16601
+ });
16602
+ const raw_response = await fetch(`${this.apiBaseUrl}/sessions?token=${this.apiKey}`, {
16603
+ cache: "no-cache",
16604
+ headers: {
16605
+ "Cache-Control": "no-cache, no-store, must-revalidate",
16606
+ Pragma: "no-cache"
16607
+ }
16608
+ });
16609
+ if (!raw_response.ok) {
16610
+ throw new Error(`HTTP ${raw_response.status}: ${raw_response.statusText}`);
16611
+ }
16603
16612
  const response = await raw_response.json();
16604
16613
  let agentName = "";
16605
16614
  const mappedCourses = response.sessions?.map((session) => {
@@ -16616,10 +16625,15 @@ class CourseModal extends i$1 {
16616
16625
  const filteredCourses = mappedCourses.filter((course) => !!course.name);
16617
16626
  this.agentName = agentName || "Obi";
16618
16627
  this.courses = [...filteredCourses];
16628
+ this.error = "";
16629
+ console.log("[CourseModal] Sessions fetched successfully", {
16630
+ sessionCount: filteredCourses.length,
16631
+ sessions: filteredCourses.map((c2) => ({ id: c2.id, name: c2.name }))
16632
+ });
16619
16633
  this.requestUpdate();
16620
16634
  } catch (err) {
16621
- console.error("Fetch error:", err);
16622
- this.error = "Failed to fetch courses";
16635
+ console.error("[CourseModal] Fetch error:", err);
16636
+ this.error = `Failed to fetch courses: ${err instanceof Error ? err.message : "Unknown error"}`;
16623
16637
  } finally {
16624
16638
  this.loading = false;
16625
16639
  this.requestUpdate();
@@ -17423,12 +17437,144 @@ var __decorateClass$1 = (decorators, target, key, kind) => {
17423
17437
  return result;
17424
17438
  };
17425
17439
  class SessionStartModal extends i$1 {
17426
- handleStart() {
17427
- if (this.onStart && this.session) {
17440
+ constructor() {
17441
+ super(...arguments);
17442
+ this.isLoading = false;
17443
+ this.error = null;
17444
+ this.startAttempts = 0;
17445
+ }
17446
+ async handleStart() {
17447
+ console.log("[SessionStartModal] Start button clicked", {
17448
+ sessionId: this.session?.id,
17449
+ hasOnStartCallback: !!this.onStart,
17450
+ hasSession: !!this.session,
17451
+ isLoading: this.isLoading,
17452
+ startAttempts: this.startAttempts,
17453
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
17454
+ });
17455
+ trackEvent(
17456
+ "session_start_modal_continue_clicked",
17457
+ {
17458
+ sessionId: this.session?.id,
17459
+ sessionName: this.session?.name
17460
+ },
17461
+ "SessionStartModal"
17462
+ );
17463
+ if (this.isLoading) {
17464
+ console.warn("[SessionStartModal] Start already in progress, ignoring click");
17465
+ return;
17466
+ }
17467
+ if (!this.session) {
17468
+ const error = "Session data is missing.";
17469
+ console.error("[SessionStartModal] Validation failed:", error);
17470
+ this.showError(error);
17471
+ return;
17472
+ }
17473
+ if (!this.session.id) {
17474
+ const error = "Session ID is missing.";
17475
+ console.error("[SessionStartModal] Validation failed:", error, { session: this.session });
17476
+ this.showError(error);
17477
+ return;
17478
+ }
17479
+ if (!this.onStart) {
17480
+ const error = "Start callback is not defined.";
17481
+ console.error("[SessionStartModal] Validation failed:", error);
17482
+ captureException(error, {
17483
+ componentName: "SessionStartModal",
17484
+ handlerName: "handleStart",
17485
+ sessionData: this.session,
17486
+ hasOnStart: !!this.onStart
17487
+ });
17488
+ this.showError(error);
17489
+ return;
17490
+ }
17491
+ this.startAttempts++;
17492
+ console.log("[SessionStartModal] Starting session attempt", {
17493
+ attempt: this.startAttempts,
17494
+ sessionId: this.session.id
17495
+ });
17496
+ this.error = null;
17497
+ this.isLoading = true;
17498
+ try {
17499
+ console.log("[SessionStartModal] Calling onStart callback", {
17500
+ sessionId: this.session.id,
17501
+ attempt: this.startAttempts
17502
+ });
17503
+ trackEvent(
17504
+ "session_start_modal_calling_onStart",
17505
+ {
17506
+ sessionId: this.session.id
17507
+ },
17508
+ "SessionStartModal"
17509
+ );
17428
17510
  this.onStart(this.session.id);
17511
+ console.log("[SessionStartModal] Session start completed successfully", {
17512
+ sessionId: this.session.id,
17513
+ attempt: this.startAttempts
17514
+ });
17515
+ trackEvent(
17516
+ "session_start_modal_onStart_called",
17517
+ {
17518
+ sessionId: this.session.id
17519
+ },
17520
+ "SessionStartModal"
17521
+ );
17522
+ setTimeout(() => {
17523
+ if (this.isConnected) {
17524
+ captureException(
17525
+ new Error("Session start modal did not close after Continue was clicked"),
17526
+ {
17527
+ componentName: "SessionStartModal",
17528
+ handlerName: "handleStart_timeout",
17529
+ sessionId: this.session?.id,
17530
+ modalStillVisible: true
17531
+ }
17532
+ );
17533
+ }
17534
+ }, 2e3);
17535
+ } catch (error) {
17536
+ console.error("[SessionStartModal] Session start failed", {
17537
+ sessionId: this.session.id,
17538
+ attempt: this.startAttempts,
17539
+ error: error instanceof Error ? error.message : String(error),
17540
+ errorStack: error instanceof Error ? error.stack : void 0
17541
+ });
17542
+ captureException(error, {
17543
+ componentName: "SessionStartModal",
17544
+ handlerName: "handleStart",
17545
+ sessionId: this.session?.id
17546
+ });
17547
+ this.isLoading = false;
17548
+ if (error instanceof Error) {
17549
+ if (error.message.includes("network") || error.message.includes("fetch")) {
17550
+ this.showError(
17551
+ "Network connection failed. Please check your internet connection, refresh the page, and try again."
17552
+ );
17553
+ } else if (error.message.includes("unauthorized") || error.message.includes("403")) {
17554
+ this.showError("Session access denied.");
17555
+ } else if (error.message.includes("session") && error.message.includes("not found")) {
17556
+ this.showError("Session not found.");
17557
+ } else {
17558
+ this.showError(`Failed to start session: ${error.message}.`);
17559
+ }
17560
+ } else {
17561
+ this.showError("An unexpected error occurred while starting the session.");
17562
+ }
17429
17563
  }
17430
17564
  }
17565
+ showError(message) {
17566
+ this.error = message;
17567
+ console.error("[SessionStartModal] Displaying error to user:", message);
17568
+ }
17431
17569
  handleClose() {
17570
+ console.log("[SessionStartModal] Close button clicked", {
17571
+ sessionId: this.session?.id,
17572
+ isLoading: this.isLoading,
17573
+ startAttempts: this.startAttempts
17574
+ });
17575
+ if (this.isLoading) {
17576
+ console.warn("[SessionStartModal] Attempted to close while loading");
17577
+ }
17432
17578
  if (this.onClose) {
17433
17579
  this.onClose();
17434
17580
  }
@@ -17441,17 +17587,33 @@ class SessionStartModal extends i$1 {
17441
17587
  class="close-button"
17442
17588
  aria-label="Close session start modal"
17443
17589
  @click=${this.handleClose}
17590
+ ?disabled=${this.isLoading}
17444
17591
  >
17445
17592
  ×
17446
17593
  </button>
17447
17594
 
17448
17595
  <div class="header">
17449
17596
  <div class="logo">${obiIcon}</div>
17450
- <h1>${this.session.name}</h1>
17451
- <p class="subtitle">${this.session.description}</p>
17597
+ <h1>${this.session?.name || "Session"}</h1>
17598
+ <p class="subtitle">${this.session?.description || "Starting your session..."}</p>
17452
17599
  </div>
17453
17600
 
17454
- <button class="button button-primary" @click=${this.handleStart}>Continue</button>
17601
+ <button
17602
+ class="button button-primary"
17603
+ @click=${this.handleStart}
17604
+ ?disabled=${this.isLoading}
17605
+ aria-label=${this.isLoading ? "Starting session..." : "Start session"}
17606
+ >
17607
+ ${this.isLoading ? x`<div class="loading-spinner"></div>
17608
+ <span class="button-text">Starting...</span>` : x`<span class="button-text">Continue</span>`}
17609
+ </button>
17610
+
17611
+ ${this.error ? x`
17612
+ <div class="error-message">
17613
+ <div>${this.error}</div>
17614
+ <div>Please refresh the page and try again.</div>
17615
+ </div>
17616
+ ` : ""}
17455
17617
  </div>
17456
17618
  `;
17457
17619
  }
@@ -17583,12 +17745,80 @@ SessionStartModal.styles = i$4`
17583
17745
  background: #18181b;
17584
17746
  color: white;
17585
17747
  margin-top: 32px;
17748
+ position: relative;
17749
+ overflow: hidden;
17586
17750
  }
17587
17751
 
17588
- .button-primary:hover {
17752
+ .button-primary:hover:not(:disabled) {
17589
17753
  background: color-mix(in srgb, #18181b 90%, white);
17590
17754
  }
17591
17755
 
17756
+ .button-primary:disabled {
17757
+ background: #6b7280;
17758
+ cursor: not-allowed;
17759
+ }
17760
+
17761
+ .button-primary:disabled .button-text {
17762
+ opacity: 0.7;
17763
+ }
17764
+
17765
+ .loading-spinner {
17766
+ width: 16px;
17767
+ height: 16px;
17768
+ border: 2px solid transparent;
17769
+ border-top: 2px solid white;
17770
+ border-radius: 50%;
17771
+ animation: spin 1s linear infinite;
17772
+ margin-right: 8px;
17773
+ }
17774
+
17775
+ @keyframes spin {
17776
+ 0% {
17777
+ transform: rotate(0deg);
17778
+ }
17779
+ 100% {
17780
+ transform: rotate(360deg);
17781
+ }
17782
+ }
17783
+
17784
+ .error-message {
17785
+ margin-top: 16px;
17786
+ padding: 12px 16px;
17787
+ background: #fef2f2;
17788
+ border: 1px solid #fecaca;
17789
+ border-radius: 6px;
17790
+ color: #dc2626;
17791
+ font-size: 14px;
17792
+ line-height: 1.4;
17793
+ text-align: center;
17794
+ max-width: 100%;
17795
+ word-wrap: break-word;
17796
+ }
17797
+
17798
+ .error-actions {
17799
+ margin-top: 12px;
17800
+ display: flex;
17801
+ gap: 8px;
17802
+ justify-content: center;
17803
+ flex-wrap: wrap;
17804
+ }
17805
+
17806
+ .error-action-button {
17807
+ padding: 6px 12px;
17808
+ background: white;
17809
+ border: 1px solid #dc2626;
17810
+ color: #dc2626;
17811
+ border-radius: 4px;
17812
+ font-size: 12px;
17813
+ cursor: pointer;
17814
+ transition: all 0.2s ease;
17815
+ }
17816
+
17817
+ .error-action-button:hover {
17818
+ background: #dc2626;
17819
+ color: white;
17820
+ }
17821
+
17592
17822
  .close-button {
17593
17823
  position: absolute;
17594
17824
  top: 12px;
@@ -17605,6 +17835,11 @@ SessionStartModal.styles = i$4`
17605
17835
  align-items: center;
17606
17836
  justify-content: center;
17607
17837
  }
17838
+
17839
+ .close-button:disabled {
17840
+ opacity: 0.5;
17841
+ cursor: not-allowed;
17842
+ }
17608
17843
  `;
17609
17844
  __decorateClass$1([
17610
17845
  n$2({ type: Object })
@@ -17615,6 +17850,15 @@ __decorateClass$1([
17615
17850
  __decorateClass$1([
17616
17851
  n$2({ type: Function })
17617
17852
  ], SessionStartModal.prototype, "onClose", 2);
17853
+ __decorateClass$1([
17854
+ r$1()
17855
+ ], SessionStartModal.prototype, "isLoading", 2);
17856
+ __decorateClass$1([
17857
+ r$1()
17858
+ ], SessionStartModal.prototype, "error", 2);
17859
+ __decorateClass$1([
17860
+ r$1()
17861
+ ], SessionStartModal.prototype, "startAttempts", 2);
17618
17862
  if (!customElements.get("obi-session-start-modal")) {
17619
17863
  customElements.define("obi-session-start-modal", SessionStartModal);
17620
17864
  }
@@ -17741,6 +17985,11 @@ class ObiWidget extends i$1 {
17741
17985
  "connectObi",
17742
17986
  "ObiWidget"
17743
17987
  );
17988
+ this.handleCloseModals = () => {
17989
+ this.state = SDKState.READY;
17990
+ this.showCourseModal = false;
17991
+ this.showSessionStartModal = false;
17992
+ };
17744
17993
  this.handleCourseSelectEvent = (event) => {
17745
17994
  const customEvent = event;
17746
17995
  this.selectedCourse = customEvent.detail;
@@ -17812,8 +18061,13 @@ class ObiWidget extends i$1 {
17812
18061
  trackEvent("session_start_requested", { sessionToken }, "ObiWidget");
17813
18062
  if (this.activeSession) {
17814
18063
  trackEvent("session_start_blocked", { sessionToken }, "ObiWidget");
17815
- console.log("Connection already in progress or active session exists");
17816
- return;
18064
+ captureException(new Error("Session start blocked"), {
18065
+ componentName: "ObiWidget",
18066
+ handlerName: "handleSessionStart",
18067
+ sessionToken
18068
+ });
18069
+ this.activeSession.disconnect();
18070
+ this.activeSession = null;
17817
18071
  }
17818
18072
  this.showSessionStartModal = false;
17819
18073
  this.state = SDKState.LOADING;
@@ -17931,6 +18185,11 @@ class ObiWidget extends i$1 {
17931
18185
  if (window.obiWidgetConfig.linkOnlyAccess !== void 0) {
17932
18186
  this.linkOnlyAccess = window.obiWidgetConfig.linkOnlyAccess;
17933
18187
  }
18188
+ if (window.obiWidgetConfig.showMenu === true) {
18189
+ this.state = SDKState.LOADING;
18190
+ this.showCourseModal = true;
18191
+ window.obiWidgetConfig.showMenu = false;
18192
+ }
17934
18193
  const primaryColor = window.obiWidgetConfig?.primaryColor || OBI_PRIMARY_COLOR;
17935
18194
  this.style.setProperty("--obi-primary", primaryColor);
17936
18195
  this.generateColorVariables(primaryColor);
@@ -18218,7 +18477,7 @@ class ObiWidget extends i$1 {
18218
18477
  ` : E}
18219
18478
  </div>
18220
18479
  ${this.showCourseModal ? x`<obi-course-modal
18221
- .onClose=${() => this.showCourseModal = false}
18480
+ .onClose=${this.handleCloseModals.bind(this)}
18222
18481
  .apiKey=${this.apiKey}
18223
18482
  @course-select=${this.handleCourseSelectEvent}
18224
18483
  ></obi-course-modal>` : E}
@@ -18226,9 +18485,8 @@ class ObiWidget extends i$1 {
18226
18485
  .session=${this.selectedCourse}
18227
18486
  .onStart=${this.handleSessionStart.bind(this)}
18228
18487
  .onClose=${() => {
18229
- this.showSessionStartModal = false;
18488
+ this.handleCloseModals();
18230
18489
  this.selectedCourse = null;
18231
- this.state = SDKState.READY;
18232
18490
  this.removeSessionUrlParams();
18233
18491
  }}
18234
18492
  ></obi-session-start-modal>` : E}
@@ -18457,4 +18715,4 @@ export {
18457
18715
  withSentryAsyncHandler as w,
18458
18716
  x
18459
18717
  };
18460
- //# sourceMappingURL=obi-widget-46e82ee8.js.map
18718
+ //# sourceMappingURL=obi-widget-6550377d.js.map