obi-sdk 0.6.8 → 0.7.1

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