obi-sdk 0.3.12 → 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,529 @@
1
1
  import { S as SDKState, E as EventEmitter, R as RoomEvent, T as Track, z as z$2, a as Room, A as API_BASE_URL, N as N$1 } from "./types-82772f00.js";
2
+ const PATH_PARAM_RE = /\{[^{}]+\}/g;
3
+ function randomID() {
4
+ return Math.random().toString(36).slice(2, 11);
5
+ }
6
+ function createClient(clientOptions) {
7
+ let {
8
+ baseUrl = "",
9
+ Request: CustomRequest = globalThis.Request,
10
+ fetch: baseFetch = globalThis.fetch,
11
+ querySerializer: globalQuerySerializer,
12
+ bodySerializer: globalBodySerializer,
13
+ headers: baseHeaders,
14
+ ...baseOptions
15
+ } = { ...clientOptions };
16
+ baseUrl = removeTrailingSlash(baseUrl);
17
+ const middlewares = [];
18
+ async function coreFetch(schemaPath, fetchOptions) {
19
+ const {
20
+ baseUrl: localBaseUrl,
21
+ fetch: fetch2 = baseFetch,
22
+ Request = CustomRequest,
23
+ headers,
24
+ params = {},
25
+ parseAs = "json",
26
+ querySerializer: requestQuerySerializer,
27
+ bodySerializer = globalBodySerializer ?? defaultBodySerializer,
28
+ body,
29
+ ...init
30
+ } = fetchOptions || {};
31
+ if (localBaseUrl) {
32
+ baseUrl = removeTrailingSlash(localBaseUrl);
33
+ }
34
+ let querySerializer = typeof globalQuerySerializer === "function" ? globalQuerySerializer : createQuerySerializer(globalQuerySerializer);
35
+ if (requestQuerySerializer) {
36
+ querySerializer = typeof requestQuerySerializer === "function" ? requestQuerySerializer : createQuerySerializer({
37
+ ...typeof globalQuerySerializer === "object" ? globalQuerySerializer : {},
38
+ ...requestQuerySerializer
39
+ });
40
+ }
41
+ const serializedBody = body === void 0 ? void 0 : bodySerializer(body);
42
+ const defaultHeaders = (
43
+ // with no body, we should not to set Content-Type
44
+ serializedBody === void 0 || // if serialized body is FormData; browser will correctly set Content-Type & boundary expression
45
+ serializedBody instanceof FormData ? {} : {
46
+ "Content-Type": "application/json"
47
+ }
48
+ );
49
+ const requestInit = {
50
+ redirect: "follow",
51
+ ...baseOptions,
52
+ ...init,
53
+ body: serializedBody,
54
+ headers: mergeHeaders(defaultHeaders, baseHeaders, headers, params.header)
55
+ };
56
+ let id;
57
+ let options;
58
+ let request = new CustomRequest(createFinalURL(schemaPath, { baseUrl, params, querySerializer }), requestInit);
59
+ for (const key in init) {
60
+ if (!(key in request)) {
61
+ request[key] = init[key];
62
+ }
63
+ }
64
+ if (middlewares.length) {
65
+ id = randomID();
66
+ options = Object.freeze({
67
+ baseUrl,
68
+ fetch: fetch2,
69
+ parseAs,
70
+ querySerializer,
71
+ bodySerializer
72
+ });
73
+ for (const m2 of middlewares) {
74
+ if (m2 && typeof m2 === "object" && typeof m2.onRequest === "function") {
75
+ const result = await m2.onRequest({
76
+ request,
77
+ schemaPath,
78
+ params,
79
+ options,
80
+ id
81
+ });
82
+ if (result) {
83
+ if (!(result instanceof CustomRequest)) {
84
+ throw new Error("onRequest: must return new Request() when modifying the request");
85
+ }
86
+ request = result;
87
+ }
88
+ }
89
+ }
90
+ }
91
+ let response = await fetch2(request);
92
+ if (middlewares.length) {
93
+ for (let i3 = middlewares.length - 1; i3 >= 0; i3--) {
94
+ const m2 = middlewares[i3];
95
+ if (m2 && typeof m2 === "object" && typeof m2.onResponse === "function") {
96
+ const result = await m2.onResponse({
97
+ request,
98
+ response,
99
+ schemaPath,
100
+ params,
101
+ options,
102
+ id
103
+ });
104
+ if (result) {
105
+ if (!(result instanceof Response)) {
106
+ throw new Error("onResponse: must return new Response() when modifying the response");
107
+ }
108
+ response = result;
109
+ }
110
+ }
111
+ }
112
+ }
113
+ if (response.status === 204 || response.headers.get("Content-Length") === "0") {
114
+ return response.ok ? { data: {}, response } : { error: {}, response };
115
+ }
116
+ if (response.ok) {
117
+ if (parseAs === "stream") {
118
+ return { data: response.body, response };
119
+ }
120
+ return { data: await response[parseAs](), response };
121
+ }
122
+ let error = await response.text();
123
+ try {
124
+ error = JSON.parse(error);
125
+ } catch {
126
+ }
127
+ return { error, response };
128
+ }
129
+ return {
130
+ /** Call a GET endpoint */
131
+ GET(url, init) {
132
+ return coreFetch(url, { ...init, method: "GET" });
133
+ },
134
+ /** Call a PUT endpoint */
135
+ PUT(url, init) {
136
+ return coreFetch(url, { ...init, method: "PUT" });
137
+ },
138
+ /** Call a POST endpoint */
139
+ POST(url, init) {
140
+ return coreFetch(url, { ...init, method: "POST" });
141
+ },
142
+ /** Call a DELETE endpoint */
143
+ DELETE(url, init) {
144
+ return coreFetch(url, { ...init, method: "DELETE" });
145
+ },
146
+ /** Call a OPTIONS endpoint */
147
+ OPTIONS(url, init) {
148
+ return coreFetch(url, { ...init, method: "OPTIONS" });
149
+ },
150
+ /** Call a HEAD endpoint */
151
+ HEAD(url, init) {
152
+ return coreFetch(url, { ...init, method: "HEAD" });
153
+ },
154
+ /** Call a PATCH endpoint */
155
+ PATCH(url, init) {
156
+ return coreFetch(url, { ...init, method: "PATCH" });
157
+ },
158
+ /** Call a TRACE endpoint */
159
+ TRACE(url, init) {
160
+ return coreFetch(url, { ...init, method: "TRACE" });
161
+ },
162
+ /** Register middleware */
163
+ use(...middleware) {
164
+ for (const m2 of middleware) {
165
+ if (!m2) {
166
+ continue;
167
+ }
168
+ if (typeof m2 !== "object" || !("onRequest" in m2 || "onResponse" in m2)) {
169
+ throw new Error("Middleware must be an object with one of `onRequest()` or `onResponse()`");
170
+ }
171
+ middlewares.push(m2);
172
+ }
173
+ },
174
+ /** Unregister middleware */
175
+ eject(...middleware) {
176
+ for (const m2 of middleware) {
177
+ const i3 = middlewares.indexOf(m2);
178
+ if (i3 !== -1) {
179
+ middlewares.splice(i3, 1);
180
+ }
181
+ }
182
+ }
183
+ };
184
+ }
185
+ function serializePrimitiveParam(name, value, options) {
186
+ if (value === void 0 || value === null) {
187
+ return "";
188
+ }
189
+ if (typeof value === "object") {
190
+ throw new Error(
191
+ "Deeply-nested arrays/objects aren’t supported. Provide your own `querySerializer()` to handle these."
192
+ );
193
+ }
194
+ return `${name}=${options?.allowReserved === true ? value : encodeURIComponent(value)}`;
195
+ }
196
+ function serializeObjectParam(name, value, options) {
197
+ if (!value || typeof value !== "object") {
198
+ return "";
199
+ }
200
+ const values = [];
201
+ const joiner = {
202
+ simple: ",",
203
+ label: ".",
204
+ matrix: ";"
205
+ }[options.style] || "&";
206
+ if (options.style !== "deepObject" && options.explode === false) {
207
+ for (const k2 in value) {
208
+ values.push(k2, options.allowReserved === true ? value[k2] : encodeURIComponent(value[k2]));
209
+ }
210
+ const final2 = values.join(",");
211
+ switch (options.style) {
212
+ case "form": {
213
+ return `${name}=${final2}`;
214
+ }
215
+ case "label": {
216
+ return `.${final2}`;
217
+ }
218
+ case "matrix": {
219
+ return `;${name}=${final2}`;
220
+ }
221
+ default: {
222
+ return final2;
223
+ }
224
+ }
225
+ }
226
+ for (const k2 in value) {
227
+ const finalName = options.style === "deepObject" ? `${name}[${k2}]` : k2;
228
+ values.push(serializePrimitiveParam(finalName, value[k2], options));
229
+ }
230
+ const final = values.join(joiner);
231
+ return options.style === "label" || options.style === "matrix" ? `${joiner}${final}` : final;
232
+ }
233
+ function serializeArrayParam(name, value, options) {
234
+ if (!Array.isArray(value)) {
235
+ return "";
236
+ }
237
+ if (options.explode === false) {
238
+ const joiner2 = { form: ",", spaceDelimited: "%20", pipeDelimited: "|" }[options.style] || ",";
239
+ const final = (options.allowReserved === true ? value : value.map((v2) => encodeURIComponent(v2))).join(joiner2);
240
+ switch (options.style) {
241
+ case "simple": {
242
+ return final;
243
+ }
244
+ case "label": {
245
+ return `.${final}`;
246
+ }
247
+ case "matrix": {
248
+ return `;${name}=${final}`;
249
+ }
250
+ default: {
251
+ return `${name}=${final}`;
252
+ }
253
+ }
254
+ }
255
+ const joiner = { simple: ",", label: ".", matrix: ";" }[options.style] || "&";
256
+ const values = [];
257
+ for (const v2 of value) {
258
+ if (options.style === "simple" || options.style === "label") {
259
+ values.push(options.allowReserved === true ? v2 : encodeURIComponent(v2));
260
+ } else {
261
+ values.push(serializePrimitiveParam(name, v2, options));
262
+ }
263
+ }
264
+ return options.style === "label" || options.style === "matrix" ? `${joiner}${values.join(joiner)}` : values.join(joiner);
265
+ }
266
+ function createQuerySerializer(options) {
267
+ return function querySerializer(queryParams) {
268
+ const search = [];
269
+ if (queryParams && typeof queryParams === "object") {
270
+ for (const name in queryParams) {
271
+ const value = queryParams[name];
272
+ if (value === void 0 || value === null) {
273
+ continue;
274
+ }
275
+ if (Array.isArray(value)) {
276
+ if (value.length === 0) {
277
+ continue;
278
+ }
279
+ search.push(
280
+ serializeArrayParam(name, value, {
281
+ style: "form",
282
+ explode: true,
283
+ ...options?.array,
284
+ allowReserved: options?.allowReserved || false
285
+ })
286
+ );
287
+ continue;
288
+ }
289
+ if (typeof value === "object") {
290
+ search.push(
291
+ serializeObjectParam(name, value, {
292
+ style: "deepObject",
293
+ explode: true,
294
+ ...options?.object,
295
+ allowReserved: options?.allowReserved || false
296
+ })
297
+ );
298
+ continue;
299
+ }
300
+ search.push(serializePrimitiveParam(name, value, options));
301
+ }
302
+ }
303
+ return search.join("&");
304
+ };
305
+ }
306
+ function defaultPathSerializer(pathname, pathParams) {
307
+ let nextURL = pathname;
308
+ for (const match of pathname.match(PATH_PARAM_RE) ?? []) {
309
+ let name = match.substring(1, match.length - 1);
310
+ let explode = false;
311
+ let style = "simple";
312
+ if (name.endsWith("*")) {
313
+ explode = true;
314
+ name = name.substring(0, name.length - 1);
315
+ }
316
+ if (name.startsWith(".")) {
317
+ style = "label";
318
+ name = name.substring(1);
319
+ } else if (name.startsWith(";")) {
320
+ style = "matrix";
321
+ name = name.substring(1);
322
+ }
323
+ if (!pathParams || pathParams[name] === void 0 || pathParams[name] === null) {
324
+ continue;
325
+ }
326
+ const value = pathParams[name];
327
+ if (Array.isArray(value)) {
328
+ nextURL = nextURL.replace(match, serializeArrayParam(name, value, { style, explode }));
329
+ continue;
330
+ }
331
+ if (typeof value === "object") {
332
+ nextURL = nextURL.replace(match, serializeObjectParam(name, value, { style, explode }));
333
+ continue;
334
+ }
335
+ if (style === "matrix") {
336
+ nextURL = nextURL.replace(match, `;${serializePrimitiveParam(name, value)}`);
337
+ continue;
338
+ }
339
+ nextURL = nextURL.replace(match, style === "label" ? `.${encodeURIComponent(value)}` : encodeURIComponent(value));
340
+ }
341
+ return nextURL;
342
+ }
343
+ function defaultBodySerializer(body) {
344
+ if (body instanceof FormData) {
345
+ return body;
346
+ }
347
+ return JSON.stringify(body);
348
+ }
349
+ function createFinalURL(pathname, options) {
350
+ let finalURL = `${options.baseUrl}${pathname}`;
351
+ if (options.params?.path) {
352
+ finalURL = defaultPathSerializer(finalURL, options.params.path);
353
+ }
354
+ let search = options.querySerializer(options.params.query ?? {});
355
+ if (search.startsWith("?")) {
356
+ search = search.substring(1);
357
+ }
358
+ if (search) {
359
+ finalURL += `?${search}`;
360
+ }
361
+ return finalURL;
362
+ }
363
+ function mergeHeaders(...allHeaders) {
364
+ const finalHeaders = new Headers();
365
+ for (const h2 of allHeaders) {
366
+ if (!h2 || typeof h2 !== "object") {
367
+ continue;
368
+ }
369
+ const iterator = h2 instanceof Headers ? h2.entries() : Object.entries(h2);
370
+ for (const [k2, v2] of iterator) {
371
+ if (v2 === null) {
372
+ finalHeaders.delete(k2);
373
+ } else if (Array.isArray(v2)) {
374
+ for (const v22 of v2) {
375
+ finalHeaders.append(k2, v22);
376
+ }
377
+ } else if (v2 !== void 0) {
378
+ finalHeaders.set(k2, v2);
379
+ }
380
+ }
381
+ }
382
+ return finalHeaders;
383
+ }
384
+ function removeTrailingSlash(url) {
385
+ if (url.endsWith("/")) {
386
+ return url.substring(0, url.length - 1);
387
+ }
388
+ return url;
389
+ }
390
+ class ObiClient {
391
+ constructor(config) {
392
+ this.client = createClient({
393
+ baseUrl: config.baseUrl,
394
+ headers: config.headers,
395
+ fetch: config.fetch
396
+ });
397
+ }
398
+ /**
399
+ * Set authorization header for authenticated requests
400
+ */
401
+ setAuthToken(token) {
402
+ this.client.use({
403
+ onRequest({ request }) {
404
+ request.headers.set("Authorization", `Bearer ${token}`);
405
+ return request;
406
+ }
407
+ });
408
+ }
409
+ /**
410
+ * Set API token for tool calls and notifications
411
+ */
412
+ setApiToken(token) {
413
+ this.client.use({
414
+ onRequest({ request }) {
415
+ request.headers.set("Authorization", `Token ${token}`);
416
+ return request;
417
+ }
418
+ });
419
+ }
420
+ // Auth endpoints
421
+ async getAuthUrl(type) {
422
+ return await this.client.GET("/auth/{type}", {
423
+ params: { path: { type } }
424
+ });
425
+ }
426
+ async getConnectUrl(type) {
427
+ return await this.client.GET("/connect/{type}", {
428
+ params: { path: { type } }
429
+ });
430
+ }
431
+ async logout() {
432
+ return await this.client.POST("/logout");
433
+ }
434
+ async getCurrentUser() {
435
+ return await this.client.GET("/me");
436
+ }
437
+ // Files
438
+ async createPresignedUploadUrl(data) {
439
+ return await this.client.POST("/files", {
440
+ body: data
441
+ });
442
+ }
443
+ // Knowledge blocks
444
+ async createKnowledgeBlock(data) {
445
+ return await this.client.POST("/knowledge", {
446
+ body: data
447
+ });
448
+ }
449
+ // Onboardees
450
+ async listOnboardees() {
451
+ return await this.client.GET("/onboardees");
452
+ }
453
+ async getOnboardeeWhitelistedDomains(id) {
454
+ return await this.client.GET("/onboardees/{id}/whitelisted-domains", {
455
+ params: { path: { id } }
456
+ });
457
+ }
458
+ // Plans
459
+ async listPlans() {
460
+ return await this.client.GET("/plans");
461
+ }
462
+ async createPlan(data) {
463
+ return await this.client.POST("/plans", {
464
+ body: data
465
+ });
466
+ }
467
+ async getPlan(id) {
468
+ return await this.client.GET("/plans/{id}", {
469
+ params: { path: { id } }
470
+ });
471
+ }
472
+ async replacePlan(id, data) {
473
+ return await this.client.PUT("/plans/{id}", {
474
+ params: { path: { id } },
475
+ body: data
476
+ });
477
+ }
478
+ async updatePlan(id, data) {
479
+ return await this.client.PATCH("/plans/{id}", {
480
+ params: { path: { id } },
481
+ body: data
482
+ });
483
+ }
484
+ // Sessions
485
+ async listSessions(token) {
486
+ return await this.client.GET("/sessions", {
487
+ params: { query: token ? { token } : {} }
488
+ });
489
+ }
490
+ async createSession(data) {
491
+ return await this.client.POST("/sessions", {
492
+ body: data
493
+ });
494
+ }
495
+ async getSession(id) {
496
+ return await this.client.GET("/sessions/{id}", {
497
+ params: { path: { id } }
498
+ });
499
+ }
500
+ async getSessionRecording(id) {
501
+ return await this.client.GET("/sessions/{id}/recording", {
502
+ params: { path: { id } }
503
+ });
504
+ }
505
+ async getSessionProductUrl(id) {
506
+ return await this.client.GET("/sessions/{id}/product-url", {
507
+ params: { path: { id } }
508
+ });
509
+ }
510
+ async getJoinToken(token, { skipIntro } = {}) {
511
+ return await this.client.GET("/join-token", {
512
+ params: {
513
+ query: {
514
+ token,
515
+ ...skipIntro && { skip_intro: "true" }
516
+ }
517
+ }
518
+ });
519
+ }
520
+ /**
521
+ * Get the underlying openapi-fetch client for advanced usage
522
+ */
523
+ getClient() {
524
+ return this.client;
525
+ }
526
+ }
2
527
  const DEFAULT_API_BASE_URL = "https://obi.getcor.io/api";
3
528
  class ObiSession {
4
529
  constructor({ sessionId, apiBaseUrl }) {
@@ -9,6 +534,9 @@ class ObiSession {
9
534
  this._userAudioTimer = null;
10
535
  this.sessionId = sessionId;
11
536
  this.apiBaseUrl = apiBaseUrl || DEFAULT_API_BASE_URL;
537
+ this.client = new ObiClient({
538
+ baseUrl: this.apiBaseUrl
539
+ });
12
540
  this.emitter = new EventEmitter();
13
541
  }
14
542
  emit(event, data) {
@@ -65,7 +593,7 @@ class ObiSession {
65
593
  if (this.currentState === SDKState.RESEARCHING || this.currentState === SDKState.PAUSED)
66
594
  return;
67
595
  const state = attributes["lk.agent.state"];
68
- const newState = z$2(state).with("listening", () => SDKState.USER_SPEAKING).with("speaking", () => SDKState.AGENT_SPEAKING).with("thinking", () => SDKState.AGENT_SPEAKING).otherwise(() => void 0);
596
+ const newState = z$2(state).with("listening", () => SDKState.USER_SPEAKING).with("speaking", () => SDKState.AGENT_SPEAKING).with("thinking", () => SDKState.THINKING).otherwise(() => void 0);
69
597
  if (!newState)
70
598
  return;
71
599
  this.setState(newState);
@@ -135,10 +663,8 @@ class ObiSession {
135
663
  dynacast: true
136
664
  });
137
665
  this.setupRoomEventListeners();
138
- const params = new URLSearchParams({ token: this.sessionId, skip_intro: "true" });
139
- const joinEndpoint = `${this.apiBaseUrl}/join-token?${params.toString()}`;
140
- const joinToken = await fetch(joinEndpoint).then((res) => res.json());
141
- await this.room.connect(joinToken.url, joinToken.token);
666
+ const joinToken = await this.client.getJoinToken(this.sessionId, { skipIntro: true });
667
+ await this.room.connect(joinToken.data.url, joinToken.data.token);
142
668
  if (this.microphoneStream) {
143
669
  const micTrack = this.microphoneStream.getAudioTracks()[0];
144
670
  await this.room.localParticipant.publishTrack(micTrack, {
@@ -147,8 +673,8 @@ class ObiSession {
147
673
  });
148
674
  }
149
675
  return {
150
- url: joinToken.url,
151
- token: joinToken.token
676
+ url: joinToken.data.url,
677
+ token: joinToken.data.token
152
678
  };
153
679
  } catch (error) {
154
680
  console.error("Failed to connect to LiveKit:", error);
@@ -193,6 +719,9 @@ class ObiSession {
193
719
  this.currentState = newState;
194
720
  this.emitter.emit("stateChanged", newState);
195
721
  }
722
+ getCurrentState() {
723
+ return this.currentState;
724
+ }
196
725
  async requestMicrophone() {
197
726
  try {
198
727
  const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
@@ -348,6 +877,8 @@ class ObiSession {
348
877
  }
349
878
  }
350
879
  }
880
+ const SESSION_URL_PARAM = "49206C6F7665204F6269_session";
881
+ const API_KEY_URL_PARAM = "49206C6F7665204F6269_client";
351
882
  var extendStatics = function(d2, b2) {
352
883
  extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function(d3, b3) {
353
884
  d3.__proto__ = b3;
@@ -9515,15 +10046,15 @@ const STORAGE_KEYS = {
9515
10046
  SESSION_DATA: "session_data"
9516
10047
  };
9517
10048
  const storage = new StorageManager("io.obi.widget");
9518
- var __defProp$6 = Object.defineProperty;
9519
- var __getOwnPropDesc$6 = Object.getOwnPropertyDescriptor;
9520
- var __decorateClass$6 = (decorators, target, key, kind) => {
9521
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$6(target, key) : target;
10049
+ var __defProp$7 = Object.defineProperty;
10050
+ var __getOwnPropDesc$7 = Object.getOwnPropertyDescriptor;
10051
+ var __decorateClass$7 = (decorators, target, key, kind) => {
10052
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$7(target, key) : target;
9522
10053
  for (var i3 = decorators.length - 1, decorator; i3 >= 0; i3--)
9523
10054
  if (decorator = decorators[i3])
9524
10055
  result = (kind ? decorator(target, key, result) : decorator(result)) || result;
9525
10056
  if (kind && result)
9526
- __defProp$6(target, key, result);
10057
+ __defProp$7(target, key, result);
9527
10058
  return result;
9528
10059
  };
9529
10060
  class NavIcon extends i$1 {
@@ -9616,16 +10147,16 @@ NavIcon.styles = i$4`
9616
10147
  height: 18px;
9617
10148
  }
9618
10149
  `;
9619
- __decorateClass$6([
10150
+ __decorateClass$7([
9620
10151
  n$2({ type: String })
9621
10152
  ], NavIcon.prototype, "id", 2);
9622
- __decorateClass$6([
10153
+ __decorateClass$7([
9623
10154
  n$2({ type: Boolean })
9624
10155
  ], NavIcon.prototype, "isActive", 2);
9625
- __decorateClass$6([
10156
+ __decorateClass$7([
9626
10157
  n$2({ type: Boolean })
9627
10158
  ], NavIcon.prototype, "isSpecial", 2);
9628
- __decorateClass$6([
10159
+ __decorateClass$7([
9629
10160
  n$2({ type: Function })
9630
10161
  ], NavIcon.prototype, "onClick", 2);
9631
10162
  if (!customElements.get("obi-nav-icon")) {
@@ -9675,15 +10206,15 @@ const obiIcon = x`
9675
10206
  alt="Obi Icon"
9676
10207
  />
9677
10208
  `;
9678
- var __defProp$5 = Object.defineProperty;
9679
- var __getOwnPropDesc$5 = Object.getOwnPropertyDescriptor;
9680
- var __decorateClass$5 = (decorators, target, key, kind) => {
9681
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$5(target, key) : target;
10209
+ var __defProp$6 = Object.defineProperty;
10210
+ var __getOwnPropDesc$6 = Object.getOwnPropertyDescriptor;
10211
+ var __decorateClass$6 = (decorators, target, key, kind) => {
10212
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$6(target, key) : target;
9682
10213
  for (var i3 = decorators.length - 1, decorator; i3 >= 0; i3--)
9683
10214
  if (decorator = decorators[i3])
9684
10215
  result = (kind ? decorator(target, key, result) : decorator(result)) || result;
9685
10216
  if (kind && result)
9686
- __defProp$5(target, key, result);
10217
+ __defProp$6(target, key, result);
9687
10218
  return result;
9688
10219
  };
9689
10220
  class NavigationBar extends i$1 {
@@ -9757,37 +10288,37 @@ NavigationBar.styles = i$4`
9757
10288
  flex-direction: column;
9758
10289
  }
9759
10290
  `;
9760
- __decorateClass$5([
10291
+ __decorateClass$6([
9761
10292
  n$2({ type: Boolean })
9762
10293
  ], NavigationBar.prototype, "isActive", 2);
9763
- __decorateClass$5([
10294
+ __decorateClass$6([
9764
10295
  n$2({ type: Boolean })
9765
10296
  ], NavigationBar.prototype, "isScreenActive", 2);
9766
- __decorateClass$5([
10297
+ __decorateClass$6([
9767
10298
  n$2({ type: Object })
9768
10299
  ], NavigationBar.prototype, "position", 2);
9769
- __decorateClass$5([
10300
+ __decorateClass$6([
9770
10301
  n$2({ type: String })
9771
10302
  ], NavigationBar.prototype, "currentState", 2);
9772
- __decorateClass$5([
10303
+ __decorateClass$6([
9773
10304
  n$2({ type: String })
9774
10305
  ], NavigationBar.prototype, "direction", 2);
9775
- __decorateClass$5([
10306
+ __decorateClass$6([
9776
10307
  n$2({ type: Function })
9777
10308
  ], NavigationBar.prototype, "onItemSelect", 2);
9778
10309
  if (!customElements.get("obi-navigation-bar")) {
9779
10310
  customElements.define("obi-navigation-bar", NavigationBar);
9780
10311
  }
9781
10312
  const navigationBar = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({ __proto__: null, NavigationBar }, Symbol.toStringTag, { value: "Module" }));
9782
- var __defProp$4 = Object.defineProperty;
9783
- var __getOwnPropDesc$4 = Object.getOwnPropertyDescriptor;
9784
- var __decorateClass$4 = (decorators, target, key, kind) => {
9785
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$4(target, key) : target;
10313
+ var __defProp$5 = Object.defineProperty;
10314
+ var __getOwnPropDesc$5 = Object.getOwnPropertyDescriptor;
10315
+ var __decorateClass$5 = (decorators, target, key, kind) => {
10316
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$5(target, key) : target;
9786
10317
  for (var i3 = decorators.length - 1, decorator; i3 >= 0; i3--)
9787
10318
  if (decorator = decorators[i3])
9788
10319
  result = (kind ? decorator(target, key, result) : decorator(result)) || result;
9789
10320
  if (kind && result)
9790
- __defProp$4(target, key, result);
10321
+ __defProp$5(target, key, result);
9791
10322
  return result;
9792
10323
  };
9793
10324
  class Course extends i$1 {
@@ -9799,12 +10330,9 @@ class Course extends i$1 {
9799
10330
  this.imageSrc = "";
9800
10331
  }
9801
10332
  handleClick() {
9802
- if (this.onSelect) {
9803
- this.onSelect(this.id);
9804
- }
9805
10333
  this.dispatchEvent(
9806
10334
  new CustomEvent("course-select", {
9807
- detail: { id: this.id },
10335
+ detail: { id: this.id, name: this.name, description: this.description },
9808
10336
  bubbles: true,
9809
10337
  composed: true
9810
10338
  })
@@ -9866,21 +10394,18 @@ Course.styles = i$4`
9866
10394
  margin: 0;
9867
10395
  }
9868
10396
  `;
9869
- __decorateClass$4([
10397
+ __decorateClass$5([
9870
10398
  n$2({ type: String })
9871
10399
  ], Course.prototype, "id", 2);
9872
- __decorateClass$4([
10400
+ __decorateClass$5([
9873
10401
  n$2({ type: String })
9874
10402
  ], Course.prototype, "name", 2);
9875
- __decorateClass$4([
10403
+ __decorateClass$5([
9876
10404
  n$2({ type: String })
9877
10405
  ], Course.prototype, "description", 2);
9878
- __decorateClass$4([
10406
+ __decorateClass$5([
9879
10407
  n$2({ type: String })
9880
10408
  ], Course.prototype, "imageSrc", 2);
9881
- __decorateClass$4([
9882
- n$2({ type: Function })
9883
- ], Course.prototype, "onSelect", 2);
9884
10409
  class CourseList extends i$1 {
9885
10410
  constructor() {
9886
10411
  super(...arguments);
@@ -9888,11 +10413,6 @@ class CourseList extends i$1 {
9888
10413
  this.loading = false;
9889
10414
  this.error = "";
9890
10415
  }
9891
- handleCourseSelect(e2) {
9892
- if (this.onCourseSelect) {
9893
- this.onCourseSelect(e2.detail.id);
9894
- }
9895
- }
9896
10416
  render() {
9897
10417
  if (this.loading) {
9898
10418
  return x`<div class="loading">Loading...</div>`;
@@ -9913,7 +10433,6 @@ class CourseList extends i$1 {
9913
10433
  name=${course.name}
9914
10434
  description=${course.description || ""}
9915
10435
  imageSrc=${course.imageSrc}
9916
- @course-select=${this.handleCourseSelect}
9917
10436
  ></obi-course>
9918
10437
  `
9919
10438
  )}
@@ -9957,18 +10476,15 @@ CourseList.styles = i$4`
9957
10476
  color: #ef4444;
9958
10477
  }
9959
10478
  `;
9960
- __decorateClass$4([
10479
+ __decorateClass$5([
9961
10480
  n$2({ type: Array })
9962
10481
  ], CourseList.prototype, "courses", 2);
9963
- __decorateClass$4([
10482
+ __decorateClass$5([
9964
10483
  n$2({ type: Boolean })
9965
10484
  ], CourseList.prototype, "loading", 2);
9966
- __decorateClass$4([
10485
+ __decorateClass$5([
9967
10486
  n$2({ type: String })
9968
10487
  ], CourseList.prototype, "error", 2);
9969
- __decorateClass$4([
9970
- n$2({ type: Function })
9971
- ], CourseList.prototype, "onCourseSelect", 2);
9972
10488
  if (!customElements.get("obi-course")) {
9973
10489
  customElements.define("obi-course", Course);
9974
10490
  }
@@ -9976,15 +10492,15 @@ if (!customElements.get("obi-course-list")) {
9976
10492
  customElements.define("obi-course-list", CourseList);
9977
10493
  }
9978
10494
  const courses = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({ __proto__: null, Course, CourseList }, Symbol.toStringTag, { value: "Module" }));
9979
- var __defProp$3 = Object.defineProperty;
9980
- var __getOwnPropDesc$3 = Object.getOwnPropertyDescriptor;
9981
- var __decorateClass$3 = (decorators, target, key, kind) => {
9982
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$3(target, key) : target;
10495
+ var __defProp$4 = Object.defineProperty;
10496
+ var __getOwnPropDesc$4 = Object.getOwnPropertyDescriptor;
10497
+ var __decorateClass$4 = (decorators, target, key, kind) => {
10498
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$4(target, key) : target;
9983
10499
  for (var i3 = decorators.length - 1, decorator; i3 >= 0; i3--)
9984
10500
  if (decorator = decorators[i3])
9985
10501
  result = (kind ? decorator(target, key, result) : decorator(result)) || result;
9986
10502
  if (kind && result)
9987
- __defProp$3(target, key, result);
10503
+ __defProp$4(target, key, result);
9988
10504
  return result;
9989
10505
  };
9990
10506
  class CourseModal extends i$1 {
@@ -9996,11 +10512,6 @@ class CourseModal extends i$1 {
9996
10512
  this.apiKey = "";
9997
10513
  this.apiBaseUrl = "";
9998
10514
  }
9999
- handleCourseSelect(e2) {
10000
- if (this.onCourseSelect) {
10001
- this.onCourseSelect(e2.detail.id);
10002
- }
10003
- }
10004
10515
  handleClose() {
10005
10516
  if (this.onClose) {
10006
10517
  this.onClose();
@@ -10055,7 +10566,6 @@ class CourseModal extends i$1 {
10055
10566
  .courses=${this.courses}
10056
10567
  .loading=${this.loading}
10057
10568
  .error=${this.error}
10058
- @course-select=${this.handleCourseSelect}
10059
10569
  ></obi-course-list>
10060
10570
  </div>
10061
10571
  `;
@@ -10145,25 +10655,22 @@ CourseModal.styles = i$4`
10145
10655
  color: #6b7280;
10146
10656
  }
10147
10657
  `;
10148
- __decorateClass$3([
10658
+ __decorateClass$4([
10149
10659
  n$2({ type: Array })
10150
10660
  ], CourseModal.prototype, "courses", 2);
10151
- __decorateClass$3([
10661
+ __decorateClass$4([
10152
10662
  n$2({ type: Boolean })
10153
10663
  ], CourseModal.prototype, "loading", 2);
10154
- __decorateClass$3([
10664
+ __decorateClass$4([
10155
10665
  n$2({ type: String })
10156
10666
  ], CourseModal.prototype, "error", 2);
10157
- __decorateClass$3([
10667
+ __decorateClass$4([
10158
10668
  n$2({ type: String })
10159
10669
  ], CourseModal.prototype, "apiKey", 2);
10160
- __decorateClass$3([
10161
- n$2({ type: Function })
10162
- ], CourseModal.prototype, "onCourseSelect", 2);
10163
- __decorateClass$3([
10670
+ __decorateClass$4([
10164
10671
  n$2({ type: Function })
10165
10672
  ], CourseModal.prototype, "onClose", 2);
10166
- __decorateClass$3([
10673
+ __decorateClass$4([
10167
10674
  r$1()
10168
10675
  ], CourseModal.prototype, "apiBaseUrl", 2);
10169
10676
  if (!customElements.get("obi-course-modal")) {
@@ -10282,15 +10789,15 @@ const o = /* @__PURE__ */ new WeakMap(), n2 = e$1(class extends f {
10282
10789
  this.rt(this.ct);
10283
10790
  }
10284
10791
  });
10285
- var __defProp$2 = Object.defineProperty;
10286
- var __getOwnPropDesc$2 = Object.getOwnPropertyDescriptor;
10287
- var __decorateClass$2 = (decorators, target, key, kind) => {
10288
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$2(target, key) : target;
10792
+ var __defProp$3 = Object.defineProperty;
10793
+ var __getOwnPropDesc$3 = Object.getOwnPropertyDescriptor;
10794
+ var __decorateClass$3 = (decorators, target, key, kind) => {
10795
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$3(target, key) : target;
10289
10796
  for (var i3 = decorators.length - 1, decorator; i3 >= 0; i3--)
10290
10797
  if (decorator = decorators[i3])
10291
10798
  result = (kind ? decorator(target, key, result) : decorator(result)) || result;
10292
10799
  if (kind && result)
10293
- __defProp$2(target, key, result);
10800
+ __defProp$3(target, key, result);
10294
10801
  return result;
10295
10802
  };
10296
10803
  class AudioEqualizer extends i$1 {
@@ -10300,9 +10807,11 @@ class AudioEqualizer extends i$1 {
10300
10807
  this.canvasRef = e();
10301
10808
  this.barCount = 8;
10302
10809
  this.animationFrame = null;
10810
+ this.primaryColor = "#9500ff";
10303
10811
  }
10304
10812
  connectedCallback() {
10305
10813
  super.connectedCallback();
10814
+ this.primaryColor = getComputedStyle(this).getPropertyValue("--obi-primary").trim() || "#9500ff";
10306
10815
  this.startAnimation();
10307
10816
  }
10308
10817
  disconnectedCallback() {
@@ -10394,7 +10903,7 @@ class AudioEqualizer extends i$1 {
10394
10903
  const spectrumValue = processedSpectrum.length > 0 ? processedSpectrum[i3] !== void 0 ? processedSpectrum[i3] : currentVolume : currentVolume;
10395
10904
  if (this.volume.speaker === "USER") {
10396
10905
  const opacity2 = Math.floor((spectrumValue * 0.5 + 0.5) * 255).toString(16).padStart(2, "0");
10397
- ctx.fillStyle = `var(--obi-primary)${opacity2}`;
10906
+ ctx.fillStyle = `${this.primaryColor}${opacity2}`;
10398
10907
  } else {
10399
10908
  const opacity2 = Math.floor((spectrumValue * 0.5 + 0.5) * 255).toString(16).padStart(2, "0");
10400
10909
  ctx.fillStyle = `#FFFFFF${opacity2}`;
@@ -10459,25 +10968,25 @@ AudioEqualizer.styles = i$4`
10459
10968
  height: 100%;
10460
10969
  }
10461
10970
  `;
10462
- __decorateClass$2([
10971
+ __decorateClass$3([
10463
10972
  n$2({ type: Object })
10464
10973
  ], AudioEqualizer.prototype, "volume", 2);
10465
- __decorateClass$2([
10974
+ __decorateClass$3([
10466
10975
  r$1()
10467
10976
  ], AudioEqualizer.prototype, "canvasRef", 2);
10468
10977
  if (!customElements.get("obi-audio-equalizer")) {
10469
10978
  customElements.define("obi-audio-equalizer", AudioEqualizer);
10470
10979
  }
10471
10980
  const audioEqualizer = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({ __proto__: null, AudioEqualizer }, Symbol.toStringTag, { value: "Module" }));
10472
- var __defProp$1 = Object.defineProperty;
10473
- var __getOwnPropDesc$1 = Object.getOwnPropertyDescriptor;
10474
- var __decorateClass$1 = (decorators, target, key, kind) => {
10475
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$1(target, key) : target;
10981
+ var __defProp$2 = Object.defineProperty;
10982
+ var __getOwnPropDesc$2 = Object.getOwnPropertyDescriptor;
10983
+ var __decorateClass$2 = (decorators, target, key, kind) => {
10984
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$2(target, key) : target;
10476
10985
  for (var i3 = decorators.length - 1, decorator; i3 >= 0; i3--)
10477
10986
  if (decorator = decorators[i3])
10478
10987
  result = (kind ? decorator(target, key, result) : decorator(result)) || result;
10479
10988
  if (kind && result)
10480
- __defProp$1(target, key, result);
10989
+ __defProp$2(target, key, result);
10481
10990
  return result;
10482
10991
  };
10483
10992
  class DotLoader extends i$1 {
@@ -10578,7 +11087,7 @@ DotLoader.styles = i$4`
10578
11087
  opacity: 1;
10579
11088
  }
10580
11089
  `;
10581
- __decorateClass$1([
11090
+ __decorateClass$2([
10582
11091
  r$1()
10583
11092
  ], DotLoader.prototype, "activeDots", 2);
10584
11093
  if (!customElements.get("obi-dot-loader")) {
@@ -10613,6 +11122,205 @@ if (!customElements.get("obi-searching-loader")) {
10613
11122
  customElements.define("obi-searching-loader", SearchingLoader);
10614
11123
  }
10615
11124
  const searchingLoader = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({ __proto__: null, SearchingLoader }, Symbol.toStringTag, { value: "Module" }));
11125
+ var __defProp$1 = Object.defineProperty;
11126
+ var __getOwnPropDesc$1 = Object.getOwnPropertyDescriptor;
11127
+ var __decorateClass$1 = (decorators, target, key, kind) => {
11128
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$1(target, key) : target;
11129
+ for (var i3 = decorators.length - 1, decorator; i3 >= 0; i3--)
11130
+ if (decorator = decorators[i3])
11131
+ result = (kind ? decorator(target, key, result) : decorator(result)) || result;
11132
+ if (kind && result)
11133
+ __defProp$1(target, key, result);
11134
+ return result;
11135
+ };
11136
+ class SessionStartModal extends i$1 {
11137
+ handleStart() {
11138
+ if (this.onStart && this.session) {
11139
+ this.onStart(this.session.id);
11140
+ }
11141
+ }
11142
+ handleClose() {
11143
+ if (this.onClose) {
11144
+ this.onClose();
11145
+ }
11146
+ }
11147
+ handleBackdropClick(e2) {
11148
+ if (e2.target === e2.currentTarget) {
11149
+ this.handleClose();
11150
+ }
11151
+ }
11152
+ render() {
11153
+ return x`
11154
+ <div class="backdrop" @click=${this.handleBackdropClick}></div>
11155
+ <div class="container">
11156
+ <button class="close-button" @click=${this.handleClose}>×</button>
11157
+
11158
+ <div class="header">
11159
+ <div class="logo">${obiIcon}</div>
11160
+ <h1>${this.session.name}</h1>
11161
+ <p class="subtitle">${this.session.description}</p>
11162
+ </div>
11163
+
11164
+ <button class="button button-primary" @click=${this.handleStart}>Continue →</button>
11165
+ </div>
11166
+ `;
11167
+ }
11168
+ }
11169
+ SessionStartModal.styles = i$4`
11170
+ :host {
11171
+ display: block;
11172
+ font-family: "Inter", sans-serif;
11173
+ }
11174
+
11175
+ .backdrop {
11176
+ position: fixed;
11177
+ top: 0;
11178
+ right: 0;
11179
+ bottom: 0;
11180
+ left: 0;
11181
+ background-color: rgba(0, 0, 0, 0.5);
11182
+ z-index: 40;
11183
+ }
11184
+
11185
+ .container {
11186
+ position: fixed;
11187
+ top: 50%;
11188
+ left: 50%;
11189
+ transform: translate(-50%, -50%);
11190
+ z-index: 50;
11191
+
11192
+ /* Layout from user specifications */
11193
+ display: flex;
11194
+ width: 640px;
11195
+ height: 380px;
11196
+ padding: 48px 48px 32px 48px;
11197
+ flex-direction: column;
11198
+ justify-content: space-between;
11199
+ align-items: center;
11200
+ flex-shrink: 0;
11201
+
11202
+ /* Style from user specifications */
11203
+ border-radius: 12px;
11204
+ background: #fafafa;
11205
+ box-shadow:
11206
+ 0px 10px 15px -3px rgba(0, 0, 0, 0.1),
11207
+ 0px 4px 6px -2px rgba(0, 0, 0, 0.05);
11208
+ }
11209
+
11210
+ .header {
11211
+ display: flex;
11212
+ flex-direction: column;
11213
+ align-items: center;
11214
+ text-align: center;
11215
+ gap: 16px;
11216
+ }
11217
+
11218
+ .logo {
11219
+ display: flex;
11220
+ width: 96px;
11221
+ height: 96px;
11222
+ padding: 8px;
11223
+ justify-content: center;
11224
+ align-items: center;
11225
+ gap: 8px;
11226
+ aspect-ratio: 1/1;
11227
+ border-radius: var(--border-radius-lg, 12px);
11228
+ background: var(--tailwind-colors-violet-600, #7c3aed);
11229
+ box-shadow:
11230
+ 0px 0px 8px 0px rgba(168, 85, 247, 0.12),
11231
+ 0px 0px 8px 0px rgba(192, 132, 252, 0.24),
11232
+ 0px 0px 4px 0px rgba(192, 132, 252, 0.24),
11233
+ 0px 0px 4px 0px rgba(192, 132, 252, 0.24),
11234
+ 0px 0px 2px 0px rgba(192, 132, 252, 0.12),
11235
+ 0px 0px 1px 0px rgba(168, 85, 247, 0.24);
11236
+ }
11237
+
11238
+ .logo img {
11239
+ width: 48px;
11240
+ height: 48px;
11241
+ color: white;
11242
+ fill: #fff;
11243
+ }
11244
+
11245
+ h1 {
11246
+ font-family: "Syne", sans-serif;
11247
+ font-size: 32px;
11248
+ font-weight: 700;
11249
+ margin: 32px 0 0 0;
11250
+ color: #111827;
11251
+ }
11252
+
11253
+ .subtitle {
11254
+ font-size: 16px;
11255
+ color: #6b7280;
11256
+ margin: 16px 0 0 0;
11257
+ line-height: 1.5;
11258
+ }
11259
+
11260
+ .button {
11261
+ padding: 12px 24px;
11262
+ border-radius: 8px;
11263
+ border: none;
11264
+ font-size: 16px;
11265
+ font-weight: 500;
11266
+ cursor: pointer;
11267
+ transition: all 0.2s ease;
11268
+ display: flex;
11269
+ align-items: center;
11270
+ justify-content: center;
11271
+ gap: 8px;
11272
+ }
11273
+
11274
+ .button-primary {
11275
+ display: flex;
11276
+ width: 100%;
11277
+ height: var(--height-h-11, 44px);
11278
+ padding: var(--spacing-2, 8px) var(--spacing-4, 16px);
11279
+ justify-content: center;
11280
+ align-items: center;
11281
+ gap: var(--spacing-2, 8px);
11282
+ flex-shrink: 0;
11283
+ align-self: stretch;
11284
+ border-radius: var(--border-radius-default, 6px);
11285
+ background: var(--base-primary, #18181b);
11286
+ color: white;
11287
+ }
11288
+
11289
+ .button-primary:hover {
11290
+ background: color-mix(in srgb, var(--base-primary, #18181b) 90%, white);
11291
+ }
11292
+
11293
+ .close-button {
11294
+ position: absolute;
11295
+ top: 16px;
11296
+ right: 16px;
11297
+ background: none;
11298
+ border: none;
11299
+ cursor: pointer;
11300
+ font-size: 24px;
11301
+ color: #6b7280;
11302
+ padding: 4px;
11303
+ border-radius: 4px;
11304
+ transition: all 0.2s ease;
11305
+ }
11306
+
11307
+ .close-button:hover {
11308
+ color: #374151;
11309
+ background: #f3f4f6;
11310
+ }
11311
+ `;
11312
+ __decorateClass$1([
11313
+ n$2({ type: Object })
11314
+ ], SessionStartModal.prototype, "session", 2);
11315
+ __decorateClass$1([
11316
+ n$2({ type: Function })
11317
+ ], SessionStartModal.prototype, "onStart", 2);
11318
+ __decorateClass$1([
11319
+ n$2({ type: Function })
11320
+ ], SessionStartModal.prototype, "onClose", 2);
11321
+ if (!customElements.get("obi-session-start-modal")) {
11322
+ customElements.define("obi-session-start-modal", SessionStartModal);
11323
+ }
10616
11324
  var __defProp = Object.defineProperty;
10617
11325
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
10618
11326
  var __decorateClass = (decorators, target, key, kind) => {
@@ -10624,17 +11332,20 @@ var __decorateClass = (decorators, target, key, kind) => {
10624
11332
  __defProp(target, key, result);
10625
11333
  return result;
10626
11334
  };
10627
- const SESSION_URL_PARAM = "49206C6F7665204F6269_session";
11335
+ const WIDGET_PARAMS_KEY = "io.obi.widget-parameters";
10628
11336
  class ObiWidget extends i$1 {
10629
11337
  constructor() {
10630
11338
  super();
10631
11339
  this.apiKey = "";
10632
11340
  this.isActive = true;
11341
+ this.linkOnlyAccess = false;
10633
11342
  this.position = "bottom-right";
10634
11343
  this.user = null;
10635
11344
  this.state = SDKState.READY;
10636
11345
  this.storedActiveState = void 0;
10637
11346
  this.showCourseModal = false;
11347
+ this.showSessionStartModal = false;
11348
+ this.selectedCourse = null;
10638
11349
  this.isHovering = false;
10639
11350
  this.navVisible = false;
10640
11351
  this.activeSession = null;
@@ -10647,7 +11358,44 @@ class ObiWidget extends i$1 {
10647
11358
  this.roomToken = null;
10648
11359
  this.roomUrl = null;
10649
11360
  this.boundSaveSessionData = null;
11361
+ this.obiClient = null;
10650
11362
  this.closeNavTimeoutRef = null;
11363
+ this.researchingTimeoutRef = null;
11364
+ this.handleCourseSelectEvent = (event) => {
11365
+ const customEvent = event;
11366
+ this.selectedCourse = customEvent.detail;
11367
+ this.showCourseModal = false;
11368
+ this.showSessionStartModal = true;
11369
+ };
11370
+ this.handleUrlSessionEvent = async (sessionToken) => {
11371
+ try {
11372
+ if (!this.obiClient) {
11373
+ console.error("ObiClient not initialized");
11374
+ return;
11375
+ }
11376
+ const sessionsResponse = await this.obiClient.listSessions(this.apiKey);
11377
+ if (sessionsResponse.data) {
11378
+ const sessions = sessionsResponse.data.sessions;
11379
+ const matchingSession = sessions?.find((session) => session.uuid === sessionToken);
11380
+ if (matchingSession) {
11381
+ const sessionWithPlan = matchingSession;
11382
+ this.selectedCourse = {
11383
+ id: sessionToken,
11384
+ name: sessionWithPlan.onboarding_plan?.name || "",
11385
+ description: sessionWithPlan.onboarding_plan?.description || ""
11386
+ };
11387
+ this.showSessionStartModal = true;
11388
+ } else {
11389
+ console.log("No session found with token:", sessionToken);
11390
+ }
11391
+ }
11392
+ } catch (error) {
11393
+ console.error("Failed to fetch session details:", error);
11394
+ }
11395
+ };
11396
+ this.obiClient = new ObiClient({
11397
+ baseUrl: API_BASE_URL
11398
+ });
10651
11399
  const handleUnload = () => {
10652
11400
  if (this.activeSession && this.sessionToken && this.roomToken && this.roomUrl) {
10653
11401
  this.saveSessionData();
@@ -10665,20 +11413,28 @@ class ObiWidget extends i$1 {
10665
11413
  if (window.obiWidgetConfig.isActive !== void 0) {
10666
11414
  this.isActive = window.obiWidgetConfig.isActive;
10667
11415
  }
11416
+ if (window.obiWidgetConfig.linkOnlyAccess !== void 0) {
11417
+ this.linkOnlyAccess = window.obiWidgetConfig.linkOnlyAccess;
11418
+ }
10668
11419
  this.style.setProperty("--obi-primary", window.obiWidgetConfig?.primaryColor || "#9500ff");
10669
11420
  this.style.setProperty("--obi-secondary", window.obiWidgetConfig?.secondaryColor || "#c4b5fd");
10670
11421
  }
10671
11422
  }
10672
- removeSessionFromUrl() {
11423
+ removeSessionUrlParams() {
10673
11424
  const url = new URL(window.location.href);
10674
11425
  url.searchParams.delete(SESSION_URL_PARAM);
11426
+ url.searchParams.delete(API_KEY_URL_PARAM);
10675
11427
  window.history.replaceState({}, "", url.toString());
10676
- }
10677
- async connectObi(sessionToken) {
10678
- if (this.activeSession) {
10679
- console.log("Connection already exists");
10680
- return;
11428
+ try {
11429
+ localStorage.removeItem(WIDGET_PARAMS_KEY);
11430
+ } catch (error) {
11431
+ console.warn("Failed to remove widget parameters from localStorage:", error);
10681
11432
  }
11433
+ }
11434
+ /**
11435
+ * Create a new ObiSession instance with common configuration
11436
+ */
11437
+ createSession(sessionToken) {
10682
11438
  try {
10683
11439
  const session = new ObiSession({
10684
11440
  sessionId: sessionToken,
@@ -10686,20 +11442,76 @@ class ObiWidget extends i$1 {
10686
11442
  });
10687
11443
  if (!session) {
10688
11444
  console.error("Failed to create session");
10689
- this.state = SDKState.ERROR;
10690
- this.activeSession = null;
10691
- this.removeSessionFromUrl();
11445
+ return null;
11446
+ }
11447
+ return session;
11448
+ } catch (error) {
11449
+ console.error("Error creating session:", error);
11450
+ return null;
11451
+ }
11452
+ }
11453
+ /**
11454
+ * Set up common event listeners for a session
11455
+ */
11456
+ setupSessionEventListeners(session, onError) {
11457
+ session.on("stateChanged", (newState) => {
11458
+ if (newState === SDKState.RESEARCHING) {
11459
+ if (this.researchingTimeoutRef) {
11460
+ window.clearTimeout(this.researchingTimeoutRef);
11461
+ }
11462
+ this.state = newState;
11463
+ this.researchingTimeoutRef = window.setTimeout(() => {
11464
+ this.researchingTimeoutRef = null;
11465
+ const currentSessionState = session.getCurrentState();
11466
+ this.state = currentSessionState;
11467
+ if (currentSessionState !== SDKState.READY) {
11468
+ this.storedActiveState = currentSessionState;
11469
+ }
11470
+ }, 1500);
11471
+ this.storedActiveState = newState;
10692
11472
  return;
10693
11473
  }
10694
- session.on("stateChanged", (newState) => {
11474
+ if (this.researchingTimeoutRef === null) {
10695
11475
  this.state = newState;
10696
11476
  if (newState !== SDKState.READY) {
10697
11477
  this.storedActiveState = newState;
10698
11478
  }
10699
- });
10700
- session.on("volume", ({ speaker, spectrum, volume }) => {
10701
- this.volume = { speaker, spectrum, volume };
10702
- });
11479
+ }
11480
+ });
11481
+ session.on("volume", ({ speaker, spectrum, volume }) => {
11482
+ this.volume = { speaker, spectrum, volume };
11483
+ });
11484
+ session.on("error", (error) => {
11485
+ console.error("Session error:", error);
11486
+ this.state = SDKState.ERROR;
11487
+ this.activeSession = null;
11488
+ if (onError) {
11489
+ onError();
11490
+ }
11491
+ });
11492
+ }
11493
+ /**
11494
+ * Handle session creation failure
11495
+ */
11496
+ handleSessionCreationFailure(onFailure) {
11497
+ this.state = SDKState.ERROR;
11498
+ this.activeSession = null;
11499
+ if (onFailure) {
11500
+ onFailure();
11501
+ }
11502
+ }
11503
+ async connectObi(sessionToken) {
11504
+ if (this.activeSession) {
11505
+ console.log("Connection already exists");
11506
+ return;
11507
+ }
11508
+ try {
11509
+ const session = this.createSession(sessionToken);
11510
+ if (!session) {
11511
+ this.handleSessionCreationFailure(() => this.removeSessionUrlParams());
11512
+ return;
11513
+ }
11514
+ this.setupSessionEventListeners(session, () => this.removeSessionUrlParams());
10703
11515
  session.on("screenCaptureRequested", async () => {
10704
11516
  try {
10705
11517
  const canvas = await html2canvas(document.documentElement, {
@@ -10714,25 +11526,17 @@ class ObiWidget extends i$1 {
10714
11526
  this.activeSession.emit("screenCaptureComplete", "error");
10715
11527
  }
10716
11528
  });
10717
- session.on("error", (error) => {
10718
- console.error("Session error:", error);
10719
- this.state = SDKState.ERROR;
10720
- this.activeSession = null;
10721
- this.removeSessionFromUrl();
10722
- });
10723
11529
  const connectionInfo = await session.connect();
10724
11530
  if (connectionInfo) {
10725
11531
  this.sessionToken = sessionToken;
10726
11532
  this.roomToken = connectionInfo.token;
10727
11533
  this.roomUrl = connectionInfo.url;
10728
- this.removeSessionFromUrl();
11534
+ this.removeSessionUrlParams();
10729
11535
  }
10730
11536
  this.activeSession = session;
10731
11537
  } catch (error) {
10732
11538
  console.error("Failed to start session:", error);
10733
- this.state = SDKState.ERROR;
10734
- this.activeSession = null;
10735
- this.removeSessionFromUrl();
11539
+ this.handleSessionCreationFailure(() => this.removeSessionUrlParams());
10736
11540
  }
10737
11541
  }
10738
11542
  async handleSessionStart(sessionToken) {
@@ -10740,7 +11544,7 @@ class ObiWidget extends i$1 {
10740
11544
  console.log("Connection already in progress or active session exists");
10741
11545
  return;
10742
11546
  }
10743
- this.showCourseModal = false;
11547
+ this.showSessionStartModal = false;
10744
11548
  this.state = SDKState.LOADING;
10745
11549
  await this.connectObi(sessionToken);
10746
11550
  }
@@ -10765,31 +11569,12 @@ class ObiWidget extends i$1 {
10765
11569
  }
10766
11570
  }
10767
11571
  this.state = SDKState.LOADING;
10768
- const session = new ObiSession({
10769
- sessionId: sessionToken,
10770
- apiBaseUrl: API_BASE_URL
10771
- });
11572
+ const session = this.createSession(sessionToken);
10772
11573
  if (!session) {
10773
- console.error("Failed to create session");
10774
- this.state = SDKState.ERROR;
10775
- this.clearSessionStorage();
11574
+ this.handleSessionCreationFailure(() => this.clearSessionStorage());
10776
11575
  return;
10777
11576
  }
10778
- session.on("stateChanged", (newState) => {
10779
- this.state = newState;
10780
- if (newState !== SDKState.READY) {
10781
- this.storedActiveState = newState;
10782
- }
10783
- });
10784
- session.on("volume", ({ speaker, spectrum, volume }) => {
10785
- this.volume = { speaker, spectrum, volume };
10786
- });
10787
- session.on("error", (error) => {
10788
- console.error("Session error:", error);
10789
- this.state = SDKState.ERROR;
10790
- this.activeSession = null;
10791
- this.clearSessionStorage();
10792
- });
11577
+ this.setupSessionEventListeners(session, () => this.clearSessionStorage());
10793
11578
  const reconnected = await session.reconnect(roomUrl, roomToken, obiState);
10794
11579
  if (reconnected) {
10795
11580
  this.activeSession = session;
@@ -10803,8 +11588,7 @@ class ObiWidget extends i$1 {
10803
11588
  }
10804
11589
  } catch (error) {
10805
11590
  console.error("Error reconnecting to session:", error);
10806
- this.state = SDKState.ERROR;
10807
- this.clearSessionStorage();
11591
+ this.handleSessionCreationFailure(() => this.clearSessionStorage());
10808
11592
  }
10809
11593
  }
10810
11594
  /**
@@ -10833,10 +11617,30 @@ class ObiWidget extends i$1 {
10833
11617
  async sessionConnectionCheck() {
10834
11618
  await this.checkExistingSession();
10835
11619
  if (!this.activeSession) {
10836
- const urlParams = new URLSearchParams(window.location.search);
10837
- const sessionId = urlParams.get(SESSION_URL_PARAM);
10838
- if (sessionId) {
10839
- this.handleSessionStart(sessionId);
11620
+ let storedParams = {};
11621
+ try {
11622
+ const storedParamsJson = localStorage.getItem(WIDGET_PARAMS_KEY);
11623
+ if (storedParamsJson) {
11624
+ storedParams = JSON.parse(storedParamsJson);
11625
+ }
11626
+ } catch (error) {
11627
+ console.warn("Failed to parse stored widget parameters:", error);
11628
+ }
11629
+ if (Object.keys(storedParams).length === 0) {
11630
+ const urlParams = new URLSearchParams(window.location.search);
11631
+ urlParams.forEach((value, key) => {
11632
+ storedParams[key] = value;
11633
+ });
11634
+ }
11635
+ const sessionId = storedParams[SESSION_URL_PARAM];
11636
+ const urlApiKey = storedParams[API_KEY_URL_PARAM];
11637
+ if (urlApiKey) {
11638
+ this.apiKey = urlApiKey;
11639
+ } else if (!this.apiKey && window.obiWidgetConfig?.apiKey) {
11640
+ this.apiKey = window.obiWidgetConfig.apiKey;
11641
+ }
11642
+ if (sessionId && this.apiKey) {
11643
+ await this.handleUrlSessionEvent(sessionId);
10840
11644
  }
10841
11645
  }
10842
11646
  }
@@ -10853,11 +11657,15 @@ class ObiWidget extends i$1 {
10853
11657
  if (this.closeNavTimeoutRef !== null) {
10854
11658
  window.clearTimeout(this.closeNavTimeoutRef);
10855
11659
  }
11660
+ if (this.researchingTimeoutRef !== null) {
11661
+ window.clearTimeout(this.researchingTimeoutRef);
11662
+ this.researchingTimeoutRef = null;
11663
+ }
10856
11664
  if (this.boundSaveSessionData) {
10857
11665
  window.removeEventListener("beforeunload", this.boundSaveSessionData);
10858
11666
  window.removeEventListener("pagehide", this.boundSaveSessionData);
10859
11667
  }
10860
- this.removeSessionFromUrl();
11668
+ this.removeSessionUrlParams();
10861
11669
  super.disconnectedCallback();
10862
11670
  }
10863
11671
  handleMouseEnter() {
@@ -10885,6 +11693,10 @@ class ObiWidget extends i$1 {
10885
11693
  this.sessionToken = null;
10886
11694
  this.roomToken = null;
10887
11695
  this.roomUrl = null;
11696
+ if (this.researchingTimeoutRef !== null) {
11697
+ window.clearTimeout(this.researchingTimeoutRef);
11698
+ this.researchingTimeoutRef = null;
11699
+ }
10888
11700
  if (this.activeSession) {
10889
11701
  this.activeSession.disconnect();
10890
11702
  this.activeSession = null;
@@ -10909,13 +11721,26 @@ class ObiWidget extends i$1 {
10909
11721
  render() {
10910
11722
  if (!this.isActive)
10911
11723
  return E;
11724
+ if (this.linkOnlyAccess && this.state === SDKState.READY)
11725
+ return E;
10912
11726
  const stateRender = z$2(this.state).with(SDKState.LOADING, () => x`<obi-dot-loader></obi-dot-loader>`).with(SDKState.RESEARCHING, () => x`<obi-searching-loader></obi-searching-loader>`).with(
10913
11727
  N$1.union(SDKState.USER_SPEAKING, SDKState.AGENT_SPEAKING),
10914
11728
  () => x`<obi-audio-equalizer .volume=${this.volume}></obi-audio-equalizer>`
10915
- ).with(SDKState.PAUSED, () => obiIcon).otherwise(() => obiIcon);
11729
+ ).with(SDKState.THINKING, () => x`<obi-dot-loader></obi-dot-loader>`).with(SDKState.PAUSED, () => obiIcon).otherwise(() => obiIcon);
11730
+ const isPulseState = this.state === SDKState.USER_SPEAKING || this.state === SDKState.AGENT_SPEAKING;
11731
+ const isResearching = this.state === SDKState.RESEARCHING;
11732
+ const isUserSpeaking = this.state === SDKState.USER_SPEAKING;
11733
+ const isRotated = this.state !== SDKState.READY || this.navVisible;
11734
+ const containerClasses = [
11735
+ "widget-container",
11736
+ isRotated ? "rotated" : "",
11737
+ isPulseState ? "pulse" : "",
11738
+ isResearching ? "researching" : "",
11739
+ isUserSpeaking ? "user-speaking" : ""
11740
+ ].filter(Boolean).join(" ");
10916
11741
  return x`
10917
11742
  <div
10918
- 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" : ""}"
11743
+ class="${containerClasses}"
10919
11744
  @mouseenter=${this.handleMouseEnter}
10920
11745
  @mouseleave=${this.handleMouseLeave}
10921
11746
  >
@@ -10932,9 +11757,17 @@ class ObiWidget extends i$1 {
10932
11757
  </div>
10933
11758
  ${this.showCourseModal ? x`<obi-course-modal
10934
11759
  .onClose=${() => this.showCourseModal = false}
10935
- .onCourseSelect=${this.handleSessionStart.bind(this)}
11760
+ @course-select=${this.handleCourseSelectEvent}
10936
11761
  .apiKey=${this.apiKey}
10937
11762
  ></obi-course-modal>` : E}
11763
+ ${this.showSessionStartModal && this.selectedCourse ? x`<obi-session-start-modal
11764
+ .session=${this.selectedCourse}
11765
+ .onStart=${this.handleSessionStart.bind(this)}
11766
+ .onClose=${() => {
11767
+ this.showSessionStartModal = false;
11768
+ this.selectedCourse = null;
11769
+ }}
11770
+ ></obi-session-start-modal>` : E}
10938
11771
  `;
10939
11772
  }
10940
11773
  }
@@ -11015,7 +11848,7 @@ ObiWidget.styles = i$4`
11015
11848
  position: fixed;
11016
11849
  width: 56px;
11017
11850
  height: 56px;
11018
- border-radius: 28px;
11851
+ border-radius: 12px;
11019
11852
  border-color: transparent;
11020
11853
  background-color: var(--obi-primary);
11021
11854
  display: flex;
@@ -11031,17 +11864,8 @@ ObiWidget.styles = i$4`
11031
11864
  linear-gradient(195.84deg, var(--obi-secondary) 00 11.05%, var(--obi-secondary) 117.01%);
11032
11865
  }
11033
11866
 
11034
- .widget-container:hover {
11035
- border-radius: 12px;
11036
- }
11037
-
11038
- .widget-container.rounded {
11039
- border-radius: 12px;
11040
- }
11041
-
11042
11867
  .widget-container.researching {
11043
11868
  width: 273px;
11044
- border-radius: 12px;
11045
11869
  }
11046
11870
 
11047
11871
  .widget-icon {
@@ -11050,7 +11874,7 @@ ObiWidget.styles = i$4`
11050
11874
  transition: transform 0.5s ease-in-out;
11051
11875
  }
11052
11876
 
11053
- .widget-container.rounded .widget-icon {
11877
+ .widget-container.rotated .widget-icon {
11054
11878
  transform: rotate(90deg);
11055
11879
  }
11056
11880
 
@@ -11076,6 +11900,9 @@ __decorateClass([
11076
11900
  __decorateClass([
11077
11901
  r$1()
11078
11902
  ], ObiWidget.prototype, "isActive", 2);
11903
+ __decorateClass([
11904
+ r$1()
11905
+ ], ObiWidget.prototype, "linkOnlyAccess", 2);
11079
11906
  __decorateClass([
11080
11907
  r$1()
11081
11908
  ], ObiWidget.prototype, "position", 2);
@@ -11091,6 +11918,12 @@ __decorateClass([
11091
11918
  __decorateClass([
11092
11919
  r$1()
11093
11920
  ], ObiWidget.prototype, "showCourseModal", 2);
11921
+ __decorateClass([
11922
+ r$1()
11923
+ ], ObiWidget.prototype, "showSessionStartModal", 2);
11924
+ __decorateClass([
11925
+ r$1()
11926
+ ], ObiWidget.prototype, "selectedCourse", 2);
11094
11927
  __decorateClass([
11095
11928
  r$1()
11096
11929
  ], ObiWidget.prototype, "isHovering", 2);
@@ -11130,4 +11963,4 @@ export {
11130
11963
  searchingLoader as s,
11131
11964
  x
11132
11965
  };
11133
- //# sourceMappingURL=obi-widget-dffef845.js.map
11966
+ //# sourceMappingURL=obi-widget-9ef6796a.js.map