cap-copilot-widget 0.1.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.
@@ -0,0 +1,665 @@
1
+ const f = class f {
2
+ static resolve(t) {
3
+ if (t) return t.replace(/^Bearer\s+/i, "");
4
+ const e = window.__BTP_COPILOT_TOKEN__;
5
+ if (e) return e.replace(/^Bearer\s+/i, "");
6
+ const n = f._fromCookie();
7
+ if (n) return n;
8
+ try {
9
+ const i = localStorage.getItem("access_token");
10
+ if (i) return i;
11
+ } catch {
12
+ }
13
+ return null;
14
+ }
15
+ static getAuthHeader(t) {
16
+ return t ? { Authorization: `Bearer ${t}` } : {};
17
+ }
18
+ static _fromCookie() {
19
+ try {
20
+ const t = document.cookie.split(";");
21
+ for (const e of t) {
22
+ const [n, ...i] = e.trim().split("=");
23
+ if (f.XSUAA_COOKIE_NAMES.includes(n.trim()))
24
+ return decodeURIComponent(i.join("=").trim());
25
+ }
26
+ } catch {
27
+ }
28
+ return null;
29
+ }
30
+ };
31
+ f.XSUAA_COOKIE_NAMES = [
32
+ "x-uaa-token",
33
+ "xsuaa_token",
34
+ "access_token",
35
+ "X-Authorization"
36
+ ];
37
+ let d = f;
38
+ class m {
39
+ static getHash() {
40
+ var t, e, n, i;
41
+ try {
42
+ const r = (n = (e = (t = sap == null ? void 0 : sap.ushell) == null ? void 0 : t.Container) == null ? void 0 : e.getService) == null ? void 0 : n.call(
43
+ e,
44
+ "CrossApplicationNavigation"
45
+ );
46
+ if (r) {
47
+ const s = (i = r.hrefForExternal) == null ? void 0 : i.call(r);
48
+ if (s) return s;
49
+ }
50
+ } catch (r) {
51
+ console.log(r);
52
+ }
53
+ return window.location.hash || "";
54
+ }
55
+ static getCurrentAppId() {
56
+ try {
57
+ const e = m.getHash().match(/^#([^&?/]+)/);
58
+ return e ? e[1] : null;
59
+ } catch {
60
+ return null;
61
+ }
62
+ }
63
+ static getUserLocale() {
64
+ var t, e, n, i, r, s;
65
+ try {
66
+ return ((s = (r = (i = (n = (e = (t = sap == null ? void 0 : sap.ui) == null ? void 0 : t.getCore) == null ? void 0 : e.call(t)) == null ? void 0 : n.getConfiguration) == null ? void 0 : i.call(n)) == null ? void 0 : r.getLanguageTag) == null ? void 0 : s.call(r)) ?? navigator.language ?? "en";
67
+ } catch {
68
+ return navigator.language ?? "en";
69
+ }
70
+ }
71
+ }
72
+ class u {
73
+ static getCurrentEntity() {
74
+ var t, e, n, i;
75
+ try {
76
+ const r = (e = (t = sap == null ? void 0 : sap.ui) == null ? void 0 : t.getCore) == null ? void 0 : e.call(t);
77
+ if (!r) return null;
78
+ let s = document.activeElement;
79
+ for (; s; ) {
80
+ const a = s.getAttribute("id") || s.getAttribute("data-sap-ui");
81
+ if (a) {
82
+ const o = r.byId(a), l = (n = o == null ? void 0 : o.getBindingContext) == null ? void 0 : n.call(o);
83
+ if (l) {
84
+ const p = (i = l.getObject) == null ? void 0 : i.call(l);
85
+ if (p && typeof p == "object")
86
+ return u._sanitize(p);
87
+ }
88
+ }
89
+ s = s.parentElement;
90
+ }
91
+ return u._scanAllControls(r);
92
+ } catch {
93
+ return null;
94
+ }
95
+ }
96
+ static _scanAllControls(t) {
97
+ var e, n;
98
+ try {
99
+ const i = t.mElements ?? {};
100
+ for (const r of Object.keys(i)) {
101
+ const s = i[r], a = (e = s == null ? void 0 : s.getBindingContext) == null ? void 0 : e.call(s);
102
+ if (a) {
103
+ const o = (n = a.getObject) == null ? void 0 : n.call(a);
104
+ if (o && typeof o == "object" && Object.keys(o).length > 0)
105
+ return u._sanitize(o);
106
+ }
107
+ }
108
+ } catch {
109
+ }
110
+ return null;
111
+ }
112
+ static getServiceUrl() {
113
+ var t, e;
114
+ try {
115
+ const n = (e = (t = sap == null ? void 0 : sap.ui) == null ? void 0 : t.getCore) == null ? void 0 : e.call(t);
116
+ if (!n) return null;
117
+ const i = n.mElements ?? {};
118
+ for (const r of Object.keys(i)) {
119
+ const s = i[r];
120
+ if (!(s != null && s.getModel)) continue;
121
+ const a = s.getModel();
122
+ if (!a) continue;
123
+ const o = a.sServiceUrl ?? a._sServiceUrl;
124
+ if (typeof o == "string" && o.length > 4)
125
+ return o.replace(/\/$/, "");
126
+ }
127
+ } catch {
128
+ }
129
+ return null;
130
+ }
131
+ static _sanitize(t) {
132
+ const e = {};
133
+ for (const [n, i] of Object.entries(t))
134
+ n.startsWith("__") || (i === null || typeof i != "object" ? e[n] = i : i.__deferred || (e[n] = i));
135
+ return e;
136
+ }
137
+ }
138
+ const c = class c {
139
+ static async fetchSchemaDocuments(t, e) {
140
+ const n = `btp-copilot-meta-${t}`;
141
+ if (c._cache.has(n))
142
+ return c._cache.get(n);
143
+ const i = sessionStorage.getItem(n);
144
+ if (i)
145
+ try {
146
+ const r = JSON.parse(i);
147
+ return c._cache.set(n, r), r;
148
+ } catch {
149
+ }
150
+ try {
151
+ const r = `${t}/$metadata`, s = { Accept: "application/xml" };
152
+ e && (s.Authorization = `Bearer ${e}`);
153
+ const a = await fetch(r, { headers: s });
154
+ if (!a.ok) return [];
155
+ const o = await a.text(), l = c._parseEDMX(o), p = c._schemasToDocuments(l, t);
156
+ return c._cache.set(n, p), sessionStorage.setItem(n, JSON.stringify(p)), p;
157
+ } catch {
158
+ return [];
159
+ }
160
+ }
161
+ static _parseEDMX(t) {
162
+ try {
163
+ const i = new DOMParser().parseFromString(t, "text/xml").querySelectorAll("EntityType");
164
+ return Array.from(i).map((r) => {
165
+ const s = r.getAttribute("Name") ?? "", a = r.querySelectorAll("Key > PropertyRef"), o = new Set(
166
+ Array.from(a).map((h) => h.getAttribute("Name") ?? "")
167
+ ), l = Array.from(
168
+ r.querySelectorAll("Property")
169
+ ).map((h) => ({
170
+ name: h.getAttribute("Name") ?? "",
171
+ type: c._shortType(h.getAttribute("Type") ?? ""),
172
+ isKey: o.has(h.getAttribute("Name") ?? ""),
173
+ nullable: h.getAttribute("Nullable") !== "false"
174
+ })), p = Array.from(
175
+ r.querySelectorAll("NavigationProperty")
176
+ ).map((h) => ({
177
+ name: h.getAttribute("Name") ?? "",
178
+ type: c._shortType(
179
+ h.getAttribute("Type") ?? h.getAttribute("ToRole") ?? ""
180
+ )
181
+ }));
182
+ return { name: s, properties: l, navProperties: p };
183
+ });
184
+ } catch {
185
+ return [];
186
+ }
187
+ }
188
+ static _shortType(t) {
189
+ return t.startsWith("Collection(") ? `${t.slice(11, -1).split(".").pop()}[]` : t.split(".").pop() ?? t;
190
+ }
191
+ static _schemasToDocuments(t, e) {
192
+ const n = [];
193
+ for (const i of t) {
194
+ if (!i.name) continue;
195
+ const r = i.properties.filter((o) => o.isKey), s = i.properties.filter((o) => !o.isKey), a = [
196
+ `Entity: ${i.name}`,
197
+ `OData service: ${e}`,
198
+ `Entity set path: ${e}/${i.name}`,
199
+ `Count path: ${e}/${i.name}/$count`
200
+ ];
201
+ r.length && a.push(
202
+ `Key fields: ${r.map((o) => `${o.name} (${o.type})`).join(", ")}`
203
+ ), s.length && a.push(
204
+ `Fields: ${s.map(
205
+ (o) => `${o.name} (${o.type}${o.nullable ? "" : ", required"})`
206
+ ).join(", ")}`
207
+ ), i.navProperties.length && a.push(
208
+ `Navigation: ${i.navProperties.map((o) => `${o.name} → ${o.type}`).join(", ")}`
209
+ ), n.push({
210
+ title: `${i.name} entity schema`,
211
+ content: a.join(`
212
+ `)
213
+ });
214
+ }
215
+ return t.length > 0 && n.push({
216
+ title: "Available OData entity sets",
217
+ content: [
218
+ `OData service: ${e}`,
219
+ `Entities: ${t.map((i) => i.name).join(", ")}`,
220
+ "GET {entity}/$count | ?$filter=field eq 'value' | ?$top=10&$skip=0 | ?$orderby=field desc"
221
+ ].join(`
222
+ `)
223
+ }), n;
224
+ }
225
+ static invalidate(t) {
226
+ const e = `btp-copilot-meta-${t}`;
227
+ c._cache.delete(e), sessionStorage.removeItem(e);
228
+ }
229
+ };
230
+ c._cache = /* @__PURE__ */ new Map();
231
+ let b = c;
232
+ class g {
233
+ static capture(t) {
234
+ const e = { ...t };
235
+ try {
236
+ const n = m.getHash();
237
+ n && (e.current_view = n);
238
+ } catch {
239
+ }
240
+ try {
241
+ const n = u.getCurrentEntity();
242
+ n && Object.keys(n).length > 0 && (e.entity_data = n);
243
+ } catch {
244
+ }
245
+ try {
246
+ e.user_locale || (e.user_locale = m.getUserLocale());
247
+ } catch {
248
+ }
249
+ try {
250
+ const n = window.__APP_CONTEXT__;
251
+ n && (n.entity_data && (e.entity_data = { ...n.entity_data, ...e.entity_data }), n.current_view && !e.current_view && (e.current_view = n.current_view), n.extra && (e.extra = { ...n.extra, ...e.extra ?? {} }), n.service_url && !e.service_url && (e.service_url = n.service_url));
252
+ } catch {
253
+ }
254
+ return e;
255
+ }
256
+ static async captureAsync(t) {
257
+ var n;
258
+ const e = g.capture(t);
259
+ if (e.service_url || (e.service_url = g._discoverServiceUrl() ?? void 0), e.service_url)
260
+ try {
261
+ const i = ((n = e.extra) == null ? void 0 : n.auth_token) ?? null, r = await b.fetchSchemaDocuments(
262
+ e.service_url,
263
+ i
264
+ );
265
+ if (r.length > 0) {
266
+ const s = r.map((a) => `## ${a.title}
267
+ ${a.content}`).join(`
268
+
269
+ `);
270
+ e.extra = { ...e.extra ?? {}, schema_hint: s };
271
+ }
272
+ } catch {
273
+ }
274
+ return e;
275
+ }
276
+ static _discoverServiceUrl() {
277
+ try {
278
+ const t = u.getServiceUrl();
279
+ if (t) return t;
280
+ } catch {
281
+ }
282
+ try {
283
+ const t = performance.getEntriesByType(
284
+ "resource"
285
+ );
286
+ for (const e of t) {
287
+ const n = e.name.match(/^(https?:\/\/[^?#]+)\/\$metadata/);
288
+ if (n) return n[1];
289
+ }
290
+ } catch {
291
+ }
292
+ try {
293
+ const t = window.location.href.match(
294
+ /(https?:\/\/[^/]+(?:\/odata\/v[24]\/[^/?#]+|\/sap\/opu\/odata\/[^/?#]+))/
295
+ );
296
+ if (t) return t[1];
297
+ } catch {
298
+ }
299
+ return null;
300
+ }
301
+ static async discoverFromManifest() {
302
+ var t;
303
+ try {
304
+ const e = await fetch("/manifest.json");
305
+ if (!e.ok) return null;
306
+ const n = await e.json(), i = ((t = n == null ? void 0 : n["sap.app"]) == null ? void 0 : t.dataSources) ?? {};
307
+ for (const r of Object.keys(i)) {
308
+ const s = i[r];
309
+ if ((s == null ? void 0 : s.type) === "ODataAnnotation") continue;
310
+ const a = s == null ? void 0 : s.uri;
311
+ if (typeof a == "string" && a.length > 0)
312
+ return new URL(a, window.location.href).toString().replace(/\/$/, "");
313
+ }
314
+ } catch {
315
+ }
316
+ return null;
317
+ }
318
+ static listenForUpdates(t, e, n, i) {
319
+ const r = (s) => {
320
+ if (!s.data || typeof s.data != "object") return;
321
+ const { type: a, payload: o, text: l } = s.data;
322
+ switch (a) {
323
+ case "btp-copilot:set-context":
324
+ o && t(o);
325
+ break;
326
+ case "btp-copilot:send-message":
327
+ l && e(l);
328
+ break;
329
+ case "btp-copilot:open":
330
+ n();
331
+ break;
332
+ case "btp-copilot:close":
333
+ i();
334
+ break;
335
+ }
336
+ };
337
+ return window.addEventListener("message", r), () => window.removeEventListener("message", r);
338
+ }
339
+ }
340
+ const v = `/* ── Host element ─────────────────────────────────────────────────────────── */
341
+ :host {
342
+ position: fixed;
343
+ z-index: 2147483647;
344
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
345
+ }
346
+
347
+ *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
348
+
349
+ /* ── Toggle (FAB) button ─────────────────────────────────────────────────── */
350
+ .toggle-btn {
351
+ position: fixed;
352
+ bottom: 1.25rem;
353
+ width: 3.25rem;
354
+ height: 3.25rem;
355
+ border-radius: 50%;
356
+ border: none;
357
+ cursor: pointer;
358
+ display: flex;
359
+ align-items: center;
360
+ justify-content: center;
361
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
362
+ color: #fff;
363
+ box-shadow: 0 4px 14px rgba(102, 126, 234, 0.45);
364
+ z-index: 2147483647;
365
+ transition: transform 0.2s ease, box-shadow 0.2s ease;
366
+ outline: none;
367
+ }
368
+
369
+ .toggle-btn.bottom-right { right: 1.25rem; }
370
+ .toggle-btn.bottom-left { left: 1.25rem; }
371
+
372
+ .toggle-btn:hover {
373
+ transform: scale(1.08);
374
+ box-shadow: 0 6px 20px rgba(102, 126, 234, 0.55);
375
+ }
376
+ .toggle-btn:active { transform: scale(0.95); }
377
+ .toggle-btn:focus-visible { outline: 3px solid #60a5fa; outline-offset: 2px; }
378
+
379
+ .toggle-btn[aria-expanded="false"] .icon-close { display: none; }
380
+ .toggle-btn[aria-expanded="true"] .icon-chat { display: none; }
381
+ .toggle-btn svg { width: 1.375rem; height: 1.375rem; pointer-events: none; }
382
+
383
+ /* Unread-message badge */
384
+ .badge {
385
+ position: absolute;
386
+ top: 0.125rem;
387
+ right: 0.125rem;
388
+ width: 0.625rem;
389
+ height: 0.625rem;
390
+ border-radius: 50%;
391
+ background: #ef4444;
392
+ border: 2px solid #fff;
393
+ opacity: 0;
394
+ transform: scale(0);
395
+ transition: opacity 0.2s ease, transform 0.2s ease;
396
+ }
397
+ .badge.visible { opacity: 1; transform: scale(1); }
398
+
399
+ /* ── Chat panel ──────────────────────────────────────────────────────────── */
400
+ .panel {
401
+ position: fixed;
402
+ bottom: 5.5rem;
403
+ width: 26rem;
404
+ height: 70vh;
405
+ min-height: 25rem;
406
+ max-height: 47.5rem;
407
+ background: transparent;
408
+ border-radius: 1rem;
409
+ box-shadow: 0 8px 40px rgba(0, 0, 0, 0.22), 0 0 0 1px rgba(0, 0, 0, 0.06);
410
+ z-index: 2147483646;
411
+ overflow: hidden;
412
+ display: flex;
413
+ flex-direction: column;
414
+ transform-origin: bottom center;
415
+ transition: opacity 0.25s ease, transform 0.25s cubic-bezier(0.34, 1.3, 0.64, 1),
416
+ width 0.3s cubic-bezier(0.4, 0, 0.2, 1), height 0.3s cubic-bezier(0.4, 0, 0.2, 1),
417
+ bottom 0.3s cubic-bezier(0.4, 0, 0.2, 1), border-radius 0.3s ease;
418
+ }
419
+
420
+ .panel.bottom-right { right: 1.25rem; }
421
+ .panel.bottom-left { left: 1.25rem; }
422
+
423
+ .panel.closed {
424
+ opacity: 0;
425
+ pointer-events: none;
426
+ transform: translateY(0.5rem) scale(0.97);
427
+ }
428
+
429
+ /* Fullscreen mode */
430
+ .panel.fullscreen {
431
+ width: 100vw !important;
432
+ height: 100vh !important;
433
+ height: 100dvh !important;
434
+ bottom: 0 !important;
435
+ right: 0 !important;
436
+ left: 0 !important;
437
+ border-radius: 0 !important;
438
+ max-height: none !important;
439
+ }
440
+
441
+ .panel.fullscreen .chat-iframe {
442
+ border-radius: 0 !important;
443
+ }
444
+
445
+ /* Iframe fills the entire panel */
446
+ .chat-iframe {
447
+ width: 100%;
448
+ height: 100%;
449
+ border: none;
450
+ border-radius: 1rem;
451
+ display: block;
452
+ background: #fff;
453
+ }
454
+
455
+ /* ── Mobile: full-screen ─────────────────────────────────────────────────── */
456
+ @media (max-width: 30rem) {
457
+ .panel {
458
+ width: 100vw;
459
+ height: 85dvh;
460
+ bottom: 0;
461
+ right: 0 !important;
462
+ left: 0 !important;
463
+ border-radius: 1rem 1rem 0 0;
464
+ }
465
+ .chat-iframe { border-radius: 1rem 1rem 0 0; }
466
+ }
467
+ `, x = [
468
+ "iframe-url",
469
+ "app-id",
470
+ "app-name",
471
+ "service-url",
472
+ "auto-context",
473
+ "position",
474
+ "theme",
475
+ "token",
476
+ "context-interval"
477
+ ], _ = class _ extends HTMLElement {
478
+ constructor() {
479
+ super(...arguments), this._open = !1, this._isFullscreen = !1, this._iframeEl = null, this._contextTimer = null;
480
+ }
481
+ connectedCallback() {
482
+ this._config = this._readConfig(), this._buildShadow(), this._startContextPolling();
483
+ const t = (e) => {
484
+ if (!e.data || typeof e.data != "object") return;
485
+ const { type: n } = e.data;
486
+ n === "btp-copilot:close" && this.close(), n === "btp-copilot:open" && this.open(), n === "btp-copilot:fullscreen" && this._toggleFullscreen(), n === "btp-copilot:minimize" && this.close();
487
+ };
488
+ window.addEventListener("message", t), this._removeMessageListener = () => window.removeEventListener("message", t);
489
+ }
490
+ disconnectedCallback() {
491
+ var t;
492
+ (t = this._removeMessageListener) == null || t.call(this), this._stopContextPolling();
493
+ }
494
+ attributeChangedCallback(t, e, n) {
495
+ e === n || !this.isConnected || (this._config = this._readConfig(), this._updateAfterAttributeChange());
496
+ }
497
+ // ── Public API ─────────────────────────────────────────────────────────────
498
+ open() {
499
+ this._open = !0, this.shadowRoot.querySelector(".panel").classList.remove("closed"), this.shadowRoot.querySelector(".toggle-btn").setAttribute("aria-expanded", "true"), this._clearBadge(), this._pushContextToIframe();
500
+ }
501
+ close() {
502
+ this._open = !1;
503
+ const t = this.shadowRoot.querySelector(".panel");
504
+ t.classList.add("closed"), t.classList.remove("fullscreen"), this._isFullscreen = !1, this.shadowRoot.querySelector(".toggle-btn").setAttribute("aria-expanded", "false");
505
+ }
506
+ _toggleFullscreen() {
507
+ this._isFullscreen = !this._isFullscreen;
508
+ const t = this.shadowRoot.querySelector(".panel"), e = this.shadowRoot.querySelector(".toggle-btn");
509
+ this._isFullscreen ? (t.classList.add("fullscreen"), e.style.display = "none") : (t.classList.remove("fullscreen"), e.style.display = "");
510
+ }
511
+ sendMessage(t) {
512
+ this._open || this.open(), setTimeout(() => {
513
+ var e, n;
514
+ (n = (e = this._iframeEl) == null ? void 0 : e.contentWindow) == null || n.postMessage(
515
+ { type: "btp-copilot:send-message", text: t },
516
+ "*"
517
+ );
518
+ }, 100);
519
+ }
520
+ // ── Shadow DOM ─────────────────────────────────────────────────────────────
521
+ _buildShadow() {
522
+ var i;
523
+ const t = this.attachShadow({ mode: "open" }), e = document.createElement("style");
524
+ e.textContent = v, t.appendChild(e);
525
+ const n = document.createElement("div");
526
+ for (n.innerHTML = this._template(); n.firstChild; ) t.appendChild(n.firstChild);
527
+ t.querySelector(".toggle-btn").addEventListener("click", () => {
528
+ this._open ? this.close() : this.open();
529
+ }), this._iframeEl = t.querySelector(".chat-iframe"), (i = this._iframeEl) == null || i.addEventListener("load", () => {
530
+ this._pushAuthToIframe(), this._pushContextToIframe();
531
+ });
532
+ }
533
+ _template() {
534
+ var n;
535
+ const t = ((n = this._config) == null ? void 0 : n.position) ?? "bottom-right", e = this._esc(this._buildIframeUrl());
536
+ return `
537
+ <button class="toggle-btn ${t}" aria-label="Open AI assistant" aria-expanded="false" aria-haspopup="dialog">
538
+ <svg class="icon-chat" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
539
+ <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/>
540
+ </svg>
541
+ <svg class="icon-close" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
542
+ <line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/>
543
+ </svg>
544
+ <span class="badge" aria-hidden="true"></span>
545
+ </button>
546
+
547
+ <div class="panel closed ${t}" role="dialog" aria-label="AI Assistant" aria-modal="true">
548
+ <iframe
549
+ class="chat-iframe"
550
+ src="${e}"
551
+ title="AI Assistant"
552
+ allow="clipboard-read; clipboard-write"
553
+ loading="lazy">
554
+ </iframe>
555
+ </div>`;
556
+ }
557
+ // ── Context + Auth ─────────────────────────────────────────────────────────
558
+ _buildBaseContext() {
559
+ const t = d.resolve(this._config.token);
560
+ return {
561
+ app_id: this._config.appId,
562
+ app_name: this._config.appName,
563
+ service_url: this._config.serviceUrl,
564
+ // Include the resolved auth token in extra so the backend can
565
+ // proxy OData calls on behalf of the user to fetch real data
566
+ ...t ? { extra: { auth_token: t } } : {}
567
+ };
568
+ }
569
+ _buildIframeUrl() {
570
+ var e;
571
+ const t = ((e = this._config) == null ? void 0 : e.iframeUrl) ?? "";
572
+ if (!t) return "";
573
+ try {
574
+ const n = new URL(t), { appId: i, appName: r, serviceUrl: s } = this._config;
575
+ i && n.searchParams.set("appId", i), r && n.searchParams.set("appName", r), s && n.searchParams.set("serviceUrl", s);
576
+ const a = d.resolve(this._config.token);
577
+ return a && n.searchParams.set("token", a), n.toString();
578
+ } catch {
579
+ return t;
580
+ }
581
+ }
582
+ /** Derive the allowed postMessage target origin from the configured iframe URL.
583
+ * Falls back to "*" only when the URL cannot be parsed (e.g. empty string). */
584
+ _iframeOrigin() {
585
+ try {
586
+ return new URL(this._config.iframeUrl).origin;
587
+ } catch {
588
+ return "*";
589
+ }
590
+ }
591
+ _pushContextToIframe() {
592
+ var e;
593
+ if (!((e = this._iframeEl) != null && e.contentWindow)) return;
594
+ const t = this._iframeOrigin();
595
+ this._config.autoContext ? g.captureAsync(this._buildBaseContext()).then((n) => {
596
+ var i, r;
597
+ (r = (i = this._iframeEl) == null ? void 0 : i.contentWindow) == null || r.postMessage(
598
+ { type: "btp-copilot:set-context", payload: n },
599
+ t
600
+ ), n.service_url && !this._config.serviceUrl && (this._config = { ...this._config, serviceUrl: n.service_url });
601
+ }).catch(() => {
602
+ var n, i;
603
+ (i = (n = this._iframeEl) == null ? void 0 : n.contentWindow) == null || i.postMessage(
604
+ { type: "btp-copilot:set-context", payload: this._buildBaseContext() },
605
+ t
606
+ );
607
+ }) : this._iframeEl.contentWindow.postMessage(
608
+ { type: "btp-copilot:set-context", payload: this._buildBaseContext() },
609
+ t
610
+ );
611
+ }
612
+ _pushAuthToIframe() {
613
+ var e;
614
+ const t = d.resolve(this._config.token);
615
+ !t || !((e = this._iframeEl) != null && e.contentWindow) || this._iframeEl.contentWindow.postMessage(
616
+ { type: "btp-copilot:auth", token: t },
617
+ this._iframeOrigin()
618
+ );
619
+ }
620
+ _startContextPolling() {
621
+ this._config.autoContext && (this._contextTimer = setInterval(() => {
622
+ this._open && this._pushContextToIframe();
623
+ }, this._config.contextInterval));
624
+ }
625
+ _stopContextPolling() {
626
+ this._contextTimer !== null && (clearInterval(this._contextTimer), this._contextTimer = null);
627
+ }
628
+ // ── Config ─────────────────────────────────────────────────────────────────
629
+ _readConfig() {
630
+ const t = (e) => this.getAttribute(e);
631
+ return {
632
+ iframeUrl: t("iframe-url") ?? "",
633
+ appId: t("app-id") ?? "default",
634
+ appName: t("app-name") ?? void 0,
635
+ serviceUrl: t("service-url") ?? void 0,
636
+ autoContext: t("auto-context") !== "false",
637
+ position: t("position") ?? "bottom-right",
638
+ theme: t("theme") ?? "auto",
639
+ token: t("token") ?? void 0,
640
+ contextInterval: Math.max(500, Number(t("context-interval")) || 3e3)
641
+ };
642
+ }
643
+ _updateAfterAttributeChange() {
644
+ var n;
645
+ const t = (n = this.shadowRoot) == null ? void 0 : n.querySelector("style");
646
+ t && (t.textContent = v);
647
+ const e = this._buildIframeUrl();
648
+ this._iframeEl && this._iframeEl.src !== e && e && (this._iframeEl.src = e), this._stopContextPolling(), this._startContextPolling();
649
+ }
650
+ _clearBadge() {
651
+ var t, e;
652
+ (e = (t = this.shadowRoot) == null ? void 0 : t.querySelector(".badge")) == null || e.classList.remove("visible");
653
+ }
654
+ _esc(t) {
655
+ return t.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
656
+ }
657
+ };
658
+ _.observedAttributes = [...x];
659
+ let y = _;
660
+ customElements.get("btp-copilot") || customElements.define("btp-copilot", y);
661
+ export {
662
+ y as BtpCopilotElement,
663
+ g as ContextBridge
664
+ };
665
+ //# sourceMappingURL=btp-copilot.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"btp-copilot.esm.js","sources":["../src/api/TokenManager.ts","../src/context/ShellProbe.ts","../src/context/UI5Probe.ts","../src/context/ODataProbe.ts","../src/context/ContextBridge.ts","../src/styles/widget.css?raw","../src/BtpCopilotElement.ts","../src/index.ts"],"sourcesContent":["export class TokenManager {\n private static readonly XSUAA_COOKIE_NAMES = [\n \"x-uaa-token\",\n \"xsuaa_token\",\n \"access_token\",\n \"X-Authorization\",\n ];\n\n static resolve(explicitToken?: string | null): string | null {\n if (explicitToken) return explicitToken.replace(/^Bearer\\s+/i, \"\");\n\n const windowToken = (window as any).__BTP_COPILOT_TOKEN__ as\n | string\n | undefined;\n if (windowToken) return windowToken.replace(/^Bearer\\s+/i, \"\");\n\n const cookieToken = TokenManager._fromCookie();\n if (cookieToken) return cookieToken;\n\n try {\n const lsToken = localStorage.getItem(\"access_token\");\n if (lsToken) return lsToken;\n } catch {}\n\n return null;\n }\n\n static getAuthHeader(token: string | null): Record<string, string> {\n return token ? { Authorization: `Bearer ${token}` } : {};\n }\n\n private static _fromCookie(): string | null {\n try {\n const cookies = document.cookie.split(\";\");\n for (const cookie of cookies) {\n const [name, ...rest] = cookie.trim().split(\"=\");\n if (TokenManager.XSUAA_COOKIE_NAMES.includes(name.trim())) {\n return decodeURIComponent(rest.join(\"=\").trim());\n }\n }\n } catch {}\n return null;\n }\n}\n","declare const sap: any;\n\nexport class ShellProbe {\n static getHash(): string {\n try {\n const nav = sap?.ushell?.Container?.getService?.(\n \"CrossApplicationNavigation\",\n );\n if (nav) {\n const href = nav.hrefForExternal?.() as string | undefined;\n if (href) return href;\n }\n } catch (err) {\n console.log(err);\n }\n return window.location.hash || \"\";\n }\n\n static getCurrentAppId(): string | null {\n try {\n const hash = ShellProbe.getHash();\n const match = hash.match(/^#([^&?/]+)/);\n return match ? match[1] : null;\n } catch {\n return null;\n }\n }\n\n static getUserLocale(): string {\n try {\n return (\n sap?.ui?.getCore?.()?.getConfiguration?.()?.getLanguageTag?.() ??\n navigator.language ??\n \"en\"\n );\n } catch {\n return navigator.language ?? \"en\";\n }\n }\n}\n","declare const sap: any;\n\nexport class UI5Probe {\n static getCurrentEntity(): Record<string, unknown> | null {\n try {\n const core = sap?.ui?.getCore?.();\n if (!core) return null;\n\n let el: Element | null = document.activeElement;\n while (el) {\n const id = el.getAttribute(\"id\") || el.getAttribute(\"data-sap-ui\");\n if (id) {\n const control = core.byId(id);\n const ctx = control?.getBindingContext?.();\n if (ctx) {\n const obj = ctx.getObject?.();\n if (obj && typeof obj === \"object\") {\n return UI5Probe._sanitize(obj as Record<string, unknown>);\n }\n }\n }\n el = el.parentElement;\n }\n return UI5Probe._scanAllControls(core);\n } catch {\n return null;\n }\n }\n\n private static _scanAllControls(core: any): Record<string, unknown> | null {\n try {\n const elements = core.mElements ?? {};\n for (const id of Object.keys(elements)) {\n const control = elements[id];\n const ctx = control?.getBindingContext?.();\n if (ctx) {\n const obj = ctx.getObject?.();\n if (obj && typeof obj === \"object\" && Object.keys(obj).length > 0) {\n return UI5Probe._sanitize(obj as Record<string, unknown>);\n }\n }\n }\n } catch {}\n return null;\n }\n\n static getServiceUrl(): string | null {\n try {\n const core = sap?.ui?.getCore?.();\n if (!core) return null;\n const elements = core.mElements ?? {};\n for (const id of Object.keys(elements)) {\n const control = elements[id];\n if (!control?.getModel) continue;\n const model = control.getModel();\n if (!model) continue;\n const url: unknown = model.sServiceUrl ?? (model as any)._sServiceUrl;\n if (typeof url === \"string\" && url.length > 4) {\n return url.replace(/\\/$/, \"\");\n }\n }\n } catch {}\n return null;\n }\n\n private static _sanitize(\n obj: Record<string, unknown>,\n ): Record<string, unknown> {\n const clean: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(obj)) {\n if (k.startsWith(\"__\")) continue;\n if (v === null || typeof v !== \"object\") {\n clean[k] = v;\n } else if ((v as any).__deferred) {\n // navigation property stub — skip\n } else {\n clean[k] = v;\n }\n }\n return clean;\n }\n}\n","import type {\n EntitySchema,\n EntityProperty,\n NavProperty,\n AppDocument,\n} from \"../types\";\n\nexport class ODataProbe {\n private static _cache = new Map<string, AppDocument[]>();\n\n static async fetchSchemaDocuments(\n serviceUrl: string,\n token?: string | null,\n ): Promise<AppDocument[]> {\n const cacheKey = `btp-copilot-meta-${serviceUrl}`;\n\n if (ODataProbe._cache.has(cacheKey)) {\n return ODataProbe._cache.get(cacheKey)!;\n }\n\n const stored = sessionStorage.getItem(cacheKey);\n if (stored) {\n try {\n const docs = JSON.parse(stored) as AppDocument[];\n ODataProbe._cache.set(cacheKey, docs);\n return docs;\n } catch {}\n }\n\n try {\n const metaUrl = `${serviceUrl}/$metadata`;\n const headers: Record<string, string> = { Accept: \"application/xml\" };\n if (token) headers[\"Authorization\"] = `Bearer ${token}`;\n\n const resp = await fetch(metaUrl, { headers });\n if (!resp.ok) return [];\n\n const xml = await resp.text();\n const schemas = ODataProbe._parseEDMX(xml);\n const docs = ODataProbe._schemasToDocuments(schemas, serviceUrl);\n\n ODataProbe._cache.set(cacheKey, docs);\n sessionStorage.setItem(cacheKey, JSON.stringify(docs));\n return docs;\n } catch {\n return [];\n }\n }\n\n private static _parseEDMX(xml: string): EntitySchema[] {\n try {\n const parser = new DOMParser();\n const doc = parser.parseFromString(xml, \"text/xml\");\n const entityTypes = doc.querySelectorAll(\"EntityType\");\n return Array.from(entityTypes).map((et) => {\n const name = et.getAttribute(\"Name\") ?? \"\";\n const keyRefs = et.querySelectorAll(\"Key > PropertyRef\");\n const keyNames = new Set(\n Array.from(keyRefs).map((k) => k.getAttribute(\"Name\") ?? \"\"),\n );\n const properties: EntityProperty[] = Array.from(\n et.querySelectorAll(\"Property\"),\n ).map((p) => ({\n name: p.getAttribute(\"Name\") ?? \"\",\n type: ODataProbe._shortType(p.getAttribute(\"Type\") ?? \"\"),\n isKey: keyNames.has(p.getAttribute(\"Name\") ?? \"\"),\n nullable: p.getAttribute(\"Nullable\") !== \"false\",\n }));\n const navProperties: NavProperty[] = Array.from(\n et.querySelectorAll(\"NavigationProperty\"),\n ).map((n) => ({\n name: n.getAttribute(\"Name\") ?? \"\",\n type: ODataProbe._shortType(\n n.getAttribute(\"Type\") ?? n.getAttribute(\"ToRole\") ?? \"\",\n ),\n }));\n return { name, properties, navProperties };\n });\n } catch {\n return [];\n }\n }\n\n private static _shortType(full: string): string {\n if (full.startsWith(\"Collection(\")) {\n const inner = full.slice(11, -1);\n return `${inner.split(\".\").pop()}[]`;\n }\n return full.split(\".\").pop() ?? full;\n }\n\n private static _schemasToDocuments(\n schemas: EntitySchema[],\n serviceUrl: string,\n ): AppDocument[] {\n const docs: AppDocument[] = [];\n\n for (const schema of schemas) {\n if (!schema.name) continue;\n const keyProps = schema.properties.filter((p) => p.isKey);\n const otherProps = schema.properties.filter((p) => !p.isKey);\n const lines = [\n `Entity: ${schema.name}`,\n `OData service: ${serviceUrl}`,\n `Entity set path: ${serviceUrl}/${schema.name}`,\n `Count path: ${serviceUrl}/${schema.name}/$count`,\n ];\n if (keyProps.length) {\n lines.push(\n `Key fields: ${keyProps.map((p) => `${p.name} (${p.type})`).join(\", \")}`,\n );\n }\n if (otherProps.length) {\n lines.push(\n `Fields: ${otherProps\n .map(\n (p) => `${p.name} (${p.type}${p.nullable ? \"\" : \", required\"})`,\n )\n .join(\", \")}`,\n );\n }\n if (schema.navProperties.length) {\n lines.push(\n `Navigation: ${schema.navProperties.map((n) => `${n.name} → ${n.type}`).join(\", \")}`,\n );\n }\n docs.push({\n title: `${schema.name} entity schema`,\n content: lines.join(\"\\n\"),\n });\n }\n\n if (schemas.length > 0) {\n docs.push({\n title: \"Available OData entity sets\",\n content: [\n `OData service: ${serviceUrl}`,\n `Entities: ${schemas.map((s) => s.name).join(\", \")}`,\n \"GET {entity}/$count | ?$filter=field eq 'value' | ?$top=10&$skip=0 | ?$orderby=field desc\",\n ].join(\"\\n\"),\n });\n }\n\n return docs;\n }\n\n static invalidate(serviceUrl: string) {\n const key = `btp-copilot-meta-${serviceUrl}`;\n ODataProbe._cache.delete(key);\n sessionStorage.removeItem(key);\n }\n}\n","import type { HostAppContext } from \"../types\";\nimport { ShellProbe } from \"./ShellProbe\";\nimport { UI5Probe } from \"./UI5Probe\";\nimport { ODataProbe } from \"./ODataProbe\";\n\nexport class ContextBridge {\n static capture(baseContext: HostAppContext): HostAppContext {\n const ctx: HostAppContext = { ...baseContext };\n\n try {\n const hash = ShellProbe.getHash();\n if (hash) ctx.current_view = hash;\n } catch {}\n\n try {\n const entity = UI5Probe.getCurrentEntity();\n if (entity && Object.keys(entity).length > 0) ctx.entity_data = entity;\n } catch {}\n\n try {\n if (!ctx.user_locale) ctx.user_locale = ShellProbe.getUserLocale();\n } catch {}\n\n // Merge any context injected by the host app\n try {\n const injected = (window as any).__APP_CONTEXT__ as\n | Partial<HostAppContext>\n | undefined;\n if (injected) {\n if (injected.entity_data)\n ctx.entity_data = { ...injected.entity_data, ...ctx.entity_data };\n if (injected.current_view && !ctx.current_view)\n ctx.current_view = injected.current_view;\n if (injected.extra)\n ctx.extra = { ...injected.extra, ...(ctx.extra ?? {}) };\n if (injected.service_url && !ctx.service_url)\n ctx.service_url = injected.service_url;\n }\n } catch {}\n\n return ctx;\n }\n\n static async captureAsync(\n baseContext: HostAppContext,\n ): Promise<HostAppContext> {\n const ctx = ContextBridge.capture(baseContext);\n\n if (!ctx.service_url) {\n ctx.service_url = ContextBridge._discoverServiceUrl() ?? undefined;\n }\n\n if (ctx.service_url) {\n try {\n const token = (ctx.extra as any)?.auth_token ?? null;\n const docs = await ODataProbe.fetchSchemaDocuments(\n ctx.service_url,\n token,\n );\n if (docs.length > 0) {\n const schemaHint = docs\n .map((d) => `## ${d.title}\\n${d.content}`)\n .join(\"\\n\\n\");\n ctx.extra = { ...(ctx.extra ?? {}), schema_hint: schemaHint };\n }\n } catch {}\n }\n\n return ctx;\n }\n\n private static _discoverServiceUrl(): string | null {\n try {\n const url = UI5Probe.getServiceUrl();\n if (url) return url;\n } catch {}\n\n try {\n const entries = performance.getEntriesByType(\n \"resource\",\n ) as PerformanceResourceTiming[];\n for (const e of entries) {\n const m = e.name.match(/^(https?:\\/\\/[^?#]+)\\/\\$metadata/);\n if (m) return m[1];\n }\n } catch {}\n\n try {\n const m = window.location.href.match(\n /(https?:\\/\\/[^/]+(?:\\/odata\\/v[24]\\/[^/?#]+|\\/sap\\/opu\\/odata\\/[^/?#]+))/,\n );\n if (m) return m[1];\n } catch {}\n\n return null;\n }\n\n static async discoverFromManifest(): Promise<string | null> {\n try {\n const resp = await fetch(\"/manifest.json\");\n if (!resp.ok) return null;\n const manifest = await resp.json();\n const sources: Record<string, any> =\n manifest?.[\"sap.app\"]?.dataSources ?? {};\n for (const key of Object.keys(sources)) {\n const src = sources[key];\n if (src?.type === \"ODataAnnotation\") continue;\n const uri: unknown = src?.uri;\n if (typeof uri === \"string\" && uri.length > 0) {\n return new URL(uri, window.location.href)\n .toString()\n .replace(/\\/$/, \"\");\n }\n }\n } catch {}\n return null;\n }\n\n static listenForUpdates(\n onContextUpdate: (ctx: Partial<HostAppContext>) => void,\n onMessage: (text: string) => void,\n onOpen: () => void,\n onClose: () => void,\n ): () => void {\n const handler = (event: MessageEvent) => {\n if (!event.data || typeof event.data !== \"object\") return;\n const { type, payload, text } = event.data as {\n type?: string;\n payload?: Partial<HostAppContext>;\n text?: string;\n };\n switch (type) {\n case \"btp-copilot:set-context\":\n if (payload) onContextUpdate(payload);\n break;\n case \"btp-copilot:send-message\":\n if (text) onMessage(text);\n break;\n case \"btp-copilot:open\":\n onOpen();\n break;\n case \"btp-copilot:close\":\n onClose();\n break;\n }\n };\n window.addEventListener(\"message\", handler);\n return () => window.removeEventListener(\"message\", handler);\n }\n}\n","export default \"/* ── Host element ─────────────────────────────────────────────────────────── */\\n:host {\\n position: fixed;\\n z-index: 2147483647;\\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\\n}\\n\\n*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }\\n\\n/* ── Toggle (FAB) button ─────────────────────────────────────────────────── */\\n.toggle-btn {\\n position: fixed;\\n bottom: 1.25rem;\\n width: 3.25rem;\\n height: 3.25rem;\\n border-radius: 50%;\\n border: none;\\n cursor: pointer;\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\\n color: #fff;\\n box-shadow: 0 4px 14px rgba(102, 126, 234, 0.45);\\n z-index: 2147483647;\\n transition: transform 0.2s ease, box-shadow 0.2s ease;\\n outline: none;\\n}\\n\\n.toggle-btn.bottom-right { right: 1.25rem; }\\n.toggle-btn.bottom-left { left: 1.25rem; }\\n\\n.toggle-btn:hover {\\n transform: scale(1.08);\\n box-shadow: 0 6px 20px rgba(102, 126, 234, 0.55);\\n}\\n.toggle-btn:active { transform: scale(0.95); }\\n.toggle-btn:focus-visible { outline: 3px solid #60a5fa; outline-offset: 2px; }\\n\\n.toggle-btn[aria-expanded=\\\"false\\\"] .icon-close { display: none; }\\n.toggle-btn[aria-expanded=\\\"true\\\"] .icon-chat { display: none; }\\n.toggle-btn svg { width: 1.375rem; height: 1.375rem; pointer-events: none; }\\n\\n/* Unread-message badge */\\n.badge {\\n position: absolute;\\n top: 0.125rem;\\n right: 0.125rem;\\n width: 0.625rem;\\n height: 0.625rem;\\n border-radius: 50%;\\n background: #ef4444;\\n border: 2px solid #fff;\\n opacity: 0;\\n transform: scale(0);\\n transition: opacity 0.2s ease, transform 0.2s ease;\\n}\\n.badge.visible { opacity: 1; transform: scale(1); }\\n\\n/* ── Chat panel ──────────────────────────────────────────────────────────── */\\n.panel {\\n position: fixed;\\n bottom: 5.5rem;\\n width: 26rem;\\n height: 70vh;\\n min-height: 25rem;\\n max-height: 47.5rem;\\n background: transparent;\\n border-radius: 1rem;\\n box-shadow: 0 8px 40px rgba(0, 0, 0, 0.22), 0 0 0 1px rgba(0, 0, 0, 0.06);\\n z-index: 2147483646;\\n overflow: hidden;\\n display: flex;\\n flex-direction: column;\\n transform-origin: bottom center;\\n transition: opacity 0.25s ease, transform 0.25s cubic-bezier(0.34, 1.3, 0.64, 1),\\n width 0.3s cubic-bezier(0.4, 0, 0.2, 1), height 0.3s cubic-bezier(0.4, 0, 0.2, 1),\\n bottom 0.3s cubic-bezier(0.4, 0, 0.2, 1), border-radius 0.3s ease;\\n}\\n\\n.panel.bottom-right { right: 1.25rem; }\\n.panel.bottom-left { left: 1.25rem; }\\n\\n.panel.closed {\\n opacity: 0;\\n pointer-events: none;\\n transform: translateY(0.5rem) scale(0.97);\\n}\\n\\n/* Fullscreen mode */\\n.panel.fullscreen {\\n width: 100vw !important;\\n height: 100vh !important;\\n height: 100dvh !important;\\n bottom: 0 !important;\\n right: 0 !important;\\n left: 0 !important;\\n border-radius: 0 !important;\\n max-height: none !important;\\n}\\n\\n.panel.fullscreen .chat-iframe {\\n border-radius: 0 !important;\\n}\\n\\n/* Iframe fills the entire panel */\\n.chat-iframe {\\n width: 100%;\\n height: 100%;\\n border: none;\\n border-radius: 1rem;\\n display: block;\\n background: #fff;\\n}\\n\\n/* ── Mobile: full-screen ─────────────────────────────────────────────────── */\\n@media (max-width: 30rem) {\\n .panel {\\n width: 100vw;\\n height: 85dvh;\\n bottom: 0;\\n right: 0 !important;\\n left: 0 !important;\\n border-radius: 1rem 1rem 0 0;\\n }\\n .chat-iframe { border-radius: 1rem 1rem 0 0; }\\n}\\n\"","/**\n * BtpCopilotElement — <btp-copilot> Custom Element.\n *\n * Renders a fixed floating FAB button. When opened, shows your deployed\n * BTP Copilot React chatbot in an iframe. Context from the host UI5/Fiori\n * app is auto-captured and forwarded into the iframe via postMessage so the\n * chatbot is always aware of what the user is looking at.\n *\n * Attributes:\n * iframe-url Full URL of the deployed React chatbot frontend (required)\n * app-id Stable identifier of the host application (required)\n * app-name Human-readable app name\n * service-url OData service URL for context auto-capture\n * auto-context \"true\"|\"false\" — auto-capture UI5/OData context (default: true)\n * position \"bottom-right\"|\"bottom-left\" (default: bottom-right)\n * theme \"auto\"|\"light\"|\"dark\" (default: auto)\n * token Bearer token forwarded to the chatbot iframe\n * context-interval Context re-capture interval in ms (default: 3000)\n *\n * postMessage protocol (outgoing → iframe):\n * { type: 'btp-copilot:set-context', payload: HostAppContext }\n * { type: 'btp-copilot:auth', token: string }\n *\n * postMessage protocol (incoming ← iframe or host page):\n * { type: 'btp-copilot:close' }\n * { type: 'btp-copilot:open' }\n */\n\nimport type { HostAppContext, WidgetConfig } from \"./types\";\nimport { TokenManager } from \"./api/TokenManager\";\nimport { ContextBridge } from \"./context/ContextBridge\";\nimport widgetCss from \"./styles/widget.css?raw\";\n\nconst OBSERVED = [\n \"iframe-url\",\n \"app-id\",\n \"app-name\",\n \"service-url\",\n \"auto-context\",\n \"position\",\n \"theme\",\n \"token\",\n \"context-interval\",\n] as const;\n\nexport class BtpCopilotElement extends HTMLElement {\n static observedAttributes = [...OBSERVED];\n\n private _config!: WidgetConfig;\n private _open = false;\n private _isFullscreen = false;\n private _iframeEl: HTMLIFrameElement | null = null;\n private _contextTimer: ReturnType<typeof setInterval> | null = null;\n private _removeMessageListener?: () => void;\n\n connectedCallback() {\n this._config = this._readConfig();\n this._buildShadow();\n this._startContextPolling();\n\n const msgHandler = (event: MessageEvent) => {\n if (!event.data || typeof event.data !== \"object\") return;\n const { type } = event.data as { type?: string };\n if (type === \"btp-copilot:close\") this.close();\n if (type === \"btp-copilot:open\") this.open();\n if (type === \"btp-copilot:fullscreen\") this._toggleFullscreen();\n if (type === \"btp-copilot:minimize\") this.close();\n };\n window.addEventListener(\"message\", msgHandler);\n this._removeMessageListener = () =>\n window.removeEventListener(\"message\", msgHandler);\n }\n\n disconnectedCallback() {\n this._removeMessageListener?.();\n this._stopContextPolling();\n }\n\n attributeChangedCallback(\n _name: string,\n old: string | null,\n next: string | null\n ) {\n if (old === next || !this.isConnected) return;\n this._config = this._readConfig();\n this._updateAfterAttributeChange();\n }\n\n // ── Public API ─────────────────────────────────────────────────────────────\n open() {\n this._open = true;\n this.shadowRoot!.querySelector(\".panel\")!.classList.remove(\"closed\");\n this.shadowRoot!\n .querySelector(\".toggle-btn\")!\n .setAttribute(\"aria-expanded\", \"true\");\n this._clearBadge();\n this._pushContextToIframe();\n }\n\n close() {\n this._open = false;\n const panel = this.shadowRoot!.querySelector(\".panel\")!;\n panel.classList.add(\"closed\");\n panel.classList.remove(\"fullscreen\");\n this._isFullscreen = false;\n this.shadowRoot!\n .querySelector(\".toggle-btn\")!\n .setAttribute(\"aria-expanded\", \"false\");\n }\n\n private _toggleFullscreen() {\n this._isFullscreen = !this._isFullscreen;\n const panel = this.shadowRoot!.querySelector(\".panel\")!;\n const fab = this.shadowRoot!.querySelector(\".toggle-btn\") as HTMLElement;\n if (this._isFullscreen) {\n panel.classList.add(\"fullscreen\");\n fab.style.display = \"none\";\n } else {\n panel.classList.remove(\"fullscreen\");\n fab.style.display = \"\";\n }\n }\n\n sendMessage(text: string) {\n if (!this._open) this.open();\n setTimeout(() => {\n this._iframeEl?.contentWindow?.postMessage(\n { type: \"btp-copilot:send-message\", text },\n \"*\"\n );\n }, 100);\n }\n\n // ── Shadow DOM ─────────────────────────────────────────────────────────────\n private _buildShadow() {\n const shadow = this.attachShadow({ mode: \"open\" });\n\n const styleEl = document.createElement(\"style\");\n styleEl.textContent = widgetCss;\n shadow.appendChild(styleEl);\n\n const wrapper = document.createElement(\"div\");\n wrapper.innerHTML = this._template();\n while (wrapper.firstChild) shadow.appendChild(wrapper.firstChild);\n\n shadow.querySelector(\".toggle-btn\")!.addEventListener(\"click\", () => {\n this._open ? this.close() : this.open();\n });\n\n this._iframeEl = shadow.querySelector(\".chat-iframe\");\n\n this._iframeEl?.addEventListener(\"load\", () => {\n this._pushAuthToIframe();\n this._pushContextToIframe();\n });\n }\n\n private _template(): string {\n const pos = this._config?.position ?? \"bottom-right\";\n const src = this._esc(this._buildIframeUrl());\n return `\n<button class=\"toggle-btn ${pos}\" aria-label=\"Open AI assistant\" aria-expanded=\"false\" aria-haspopup=\"dialog\">\n <svg class=\"icon-chat\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\"/>\n </svg>\n <svg class=\"icon-close\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/>\n </svg>\n <span class=\"badge\" aria-hidden=\"true\"></span>\n</button>\n\n<div class=\"panel closed ${pos}\" role=\"dialog\" aria-label=\"AI Assistant\" aria-modal=\"true\">\n <iframe\n class=\"chat-iframe\"\n src=\"${src}\"\n title=\"AI Assistant\"\n allow=\"clipboard-read; clipboard-write\"\n loading=\"lazy\">\n </iframe>\n</div>`;\n }\n\n // ── Context + Auth ─────────────────────────────────────────────────────────\n private _buildBaseContext(): HostAppContext {\n const token = TokenManager.resolve(this._config.token);\n return {\n app_id: this._config.appId,\n app_name: this._config.appName,\n service_url: this._config.serviceUrl,\n // Include the resolved auth token in extra so the backend can\n // proxy OData calls on behalf of the user to fetch real data\n ...(token ? { extra: { auth_token: token } } : {}),\n };\n }\n\n private _buildIframeUrl(): string {\n const base = this._config?.iframeUrl ?? \"\";\n if (!base) return \"\";\n try {\n const url = new URL(base);\n const { appId, appName, serviceUrl } = this._config;\n if (appId) url.searchParams.set(\"appId\", appId);\n if (appName) url.searchParams.set(\"appName\", appName);\n if (serviceUrl) url.searchParams.set(\"serviceUrl\", serviceUrl);\n // Pass token as URL param so the chatbot can auto-authenticate in iframe mode\n const token = TokenManager.resolve(this._config.token);\n if (token) url.searchParams.set(\"token\", token);\n return url.toString();\n } catch {\n return base;\n }\n }\n\n /** Derive the allowed postMessage target origin from the configured iframe URL.\n * Falls back to \"*\" only when the URL cannot be parsed (e.g. empty string). */\n private _iframeOrigin(): string {\n try {\n return new URL(this._config.iframeUrl).origin;\n } catch {\n return \"*\";\n }\n }\n\n private _pushContextToIframe() {\n if (!this._iframeEl?.contentWindow) return;\n const origin = this._iframeOrigin();\n\n if (this._config.autoContext) {\n ContextBridge.captureAsync(this._buildBaseContext())\n .then((ctx) => {\n this._iframeEl?.contentWindow?.postMessage(\n { type: \"btp-copilot:set-context\", payload: ctx },\n origin\n );\n if (ctx.service_url && !this._config.serviceUrl) {\n this._config = { ...this._config, serviceUrl: ctx.service_url };\n }\n })\n .catch(() => {\n this._iframeEl?.contentWindow?.postMessage(\n { type: \"btp-copilot:set-context\", payload: this._buildBaseContext() },\n origin\n );\n });\n } else {\n this._iframeEl.contentWindow.postMessage(\n { type: \"btp-copilot:set-context\", payload: this._buildBaseContext() },\n origin\n );\n }\n }\n\n private _pushAuthToIframe() {\n const token = TokenManager.resolve(this._config.token);\n if (!token || !this._iframeEl?.contentWindow) return;\n this._iframeEl.contentWindow.postMessage(\n { type: \"btp-copilot:auth\", token },\n this._iframeOrigin()\n );\n }\n\n private _startContextPolling() {\n if (!this._config.autoContext) return;\n this._contextTimer = setInterval(() => {\n if (this._open) this._pushContextToIframe();\n }, this._config.contextInterval);\n }\n\n private _stopContextPolling() {\n if (this._contextTimer !== null) {\n clearInterval(this._contextTimer);\n this._contextTimer = null;\n }\n }\n\n // ── Config ─────────────────────────────────────────────────────────────────\n private _readConfig(): WidgetConfig {\n const get = (attr: string) => this.getAttribute(attr);\n return {\n iframeUrl: get(\"iframe-url\") ?? \"\",\n appId: get(\"app-id\") ?? \"default\",\n appName: get(\"app-name\") ?? undefined,\n serviceUrl: get(\"service-url\") ?? undefined,\n autoContext: get(\"auto-context\") !== \"false\",\n position: (get(\"position\") ?? \"bottom-right\") as WidgetConfig[\"position\"],\n theme: (get(\"theme\") ?? \"auto\") as WidgetConfig[\"theme\"],\n token: get(\"token\") ?? undefined,\n contextInterval: Math.max(500, Number(get(\"context-interval\")) || 3000),\n };\n }\n\n private _updateAfterAttributeChange() {\n const style = this.shadowRoot?.querySelector(\"style\");\n if (style) style.textContent = widgetCss;\n\n const newSrc = this._buildIframeUrl();\n if (this._iframeEl && this._iframeEl.src !== newSrc && newSrc) {\n this._iframeEl.src = newSrc;\n }\n\n this._stopContextPolling();\n this._startContextPolling();\n }\n\n private _clearBadge() {\n this.shadowRoot?.querySelector(\".badge\")?.classList.remove(\"visible\");\n }\n\n private _esc(s: string): string {\n return s\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\");\n }\n}\n","import { BtpCopilotElement } from \"./BtpCopilotElement\";\n\nif (!customElements.get(\"btp-copilot\")) {\n customElements.define(\"btp-copilot\", BtpCopilotElement);\n}\n\nexport { BtpCopilotElement };\nexport type { HostAppContext, WidgetConfig, AppDocument } from \"./types\";\nexport { ContextBridge } from \"./context/ContextBridge\";\n"],"names":["_TokenManager","explicitToken","windowToken","cookieToken","lsToken","token","cookies","cookie","name","rest","TokenManager","ShellProbe","_a","_b","_c","_d","nav","href","err","match","_e","_f","UI5Probe","core","el","id","control","ctx","obj","elements","model","url","clean","k","v","_ODataProbe","serviceUrl","cacheKey","stored","docs","metaUrl","headers","resp","xml","schemas","entityTypes","et","keyRefs","keyNames","properties","p","navProperties","n","full","schema","keyProps","otherProps","lines","s","key","ODataProbe","ContextBridge","baseContext","hash","entity","injected","schemaHint","d","entries","m","manifest","sources","src","uri","onContextUpdate","onMessage","onOpen","onClose","handler","event","type","payload","text","widgetCss","OBSERVED","_BtpCopilotElement","msgHandler","_name","old","next","panel","fab","shadow","styleEl","wrapper","pos","base","appId","appName","origin","get","attr","style","newSrc","BtpCopilotElement"],"mappings":"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"}
@@ -0,0 +1,153 @@
1
+ var BtpCopilot=function(g){"use strict";const m=class m{static resolve(t){if(t)return t.replace(/^Bearer\s+/i,"");const e=window.__BTP_COPILOT_TOKEN__;if(e)return e.replace(/^Bearer\s+/i,"");const n=m._fromCookie();if(n)return n;try{const i=localStorage.getItem("access_token");if(i)return i}catch{}return null}static getAuthHeader(t){return t?{Authorization:`Bearer ${t}`}:{}}static _fromCookie(){try{const t=document.cookie.split(";");for(const e of t){const[n,...i]=e.trim().split("=");if(m.XSUAA_COOKIE_NAMES.includes(n.trim()))return decodeURIComponent(i.join("=").trim())}}catch{}return null}};m.XSUAA_COOKIE_NAMES=["x-uaa-token","xsuaa_token","access_token","X-Authorization"];let d=m;class b{static getHash(){var t,e,n,i;try{const r=(n=(e=(t=sap==null?void 0:sap.ushell)==null?void 0:t.Container)==null?void 0:e.getService)==null?void 0:n.call(e,"CrossApplicationNavigation");if(r){const o=(i=r.hrefForExternal)==null?void 0:i.call(r);if(o)return o}}catch(r){console.log(r)}return window.location.hash||""}static getCurrentAppId(){try{const e=b.getHash().match(/^#([^&?/]+)/);return e?e[1]:null}catch{return null}}static getUserLocale(){var t,e,n,i,r,o;try{return((o=(r=(i=(n=(e=(t=sap==null?void 0:sap.ui)==null?void 0:t.getCore)==null?void 0:e.call(t))==null?void 0:n.getConfiguration)==null?void 0:i.call(n))==null?void 0:r.getLanguageTag)==null?void 0:o.call(r))??navigator.language??"en"}catch{return navigator.language??"en"}}}class u{static getCurrentEntity(){var t,e,n,i;try{const r=(e=(t=sap==null?void 0:sap.ui)==null?void 0:t.getCore)==null?void 0:e.call(t);if(!r)return null;let o=document.activeElement;for(;o;){const a=o.getAttribute("id")||o.getAttribute("data-sap-ui");if(a){const s=r.byId(a),l=(n=s==null?void 0:s.getBindingContext)==null?void 0:n.call(s);if(l){const p=(i=l.getObject)==null?void 0:i.call(l);if(p&&typeof p=="object")return u._sanitize(p)}}o=o.parentElement}return u._scanAllControls(r)}catch{return null}}static _scanAllControls(t){var e,n;try{const i=t.mElements??{};for(const r of Object.keys(i)){const o=i[r],a=(e=o==null?void 0:o.getBindingContext)==null?void 0:e.call(o);if(a){const s=(n=a.getObject)==null?void 0:n.call(a);if(s&&typeof s=="object"&&Object.keys(s).length>0)return u._sanitize(s)}}}catch{}return null}static getServiceUrl(){var t,e;try{const n=(e=(t=sap==null?void 0:sap.ui)==null?void 0:t.getCore)==null?void 0:e.call(t);if(!n)return null;const i=n.mElements??{};for(const r of Object.keys(i)){const o=i[r];if(!(o!=null&&o.getModel))continue;const a=o.getModel();if(!a)continue;const s=a.sServiceUrl??a._sServiceUrl;if(typeof s=="string"&&s.length>4)return s.replace(/\/$/,"")}}catch{}return null}static _sanitize(t){const e={};for(const[n,i]of Object.entries(t))n.startsWith("__")||(i===null||typeof i!="object"?e[n]=i:i.__deferred||(e[n]=i));return e}}const c=class c{static async fetchSchemaDocuments(t,e){const n=`btp-copilot-meta-${t}`;if(c._cache.has(n))return c._cache.get(n);const i=sessionStorage.getItem(n);if(i)try{const r=JSON.parse(i);return c._cache.set(n,r),r}catch{}try{const r=`${t}/$metadata`,o={Accept:"application/xml"};e&&(o.Authorization=`Bearer ${e}`);const a=await fetch(r,{headers:o});if(!a.ok)return[];const s=await a.text(),l=c._parseEDMX(s),p=c._schemasToDocuments(l,t);return c._cache.set(n,p),sessionStorage.setItem(n,JSON.stringify(p)),p}catch{return[]}}static _parseEDMX(t){try{const i=new DOMParser().parseFromString(t,"text/xml").querySelectorAll("EntityType");return Array.from(i).map(r=>{const o=r.getAttribute("Name")??"",a=r.querySelectorAll("Key > PropertyRef"),s=new Set(Array.from(a).map(h=>h.getAttribute("Name")??"")),l=Array.from(r.querySelectorAll("Property")).map(h=>({name:h.getAttribute("Name")??"",type:c._shortType(h.getAttribute("Type")??""),isKey:s.has(h.getAttribute("Name")??""),nullable:h.getAttribute("Nullable")!=="false"})),p=Array.from(r.querySelectorAll("NavigationProperty")).map(h=>({name:h.getAttribute("Name")??"",type:c._shortType(h.getAttribute("Type")??h.getAttribute("ToRole")??"")}));return{name:o,properties:l,navProperties:p}})}catch{return[]}}static _shortType(t){return t.startsWith("Collection(")?`${t.slice(11,-1).split(".").pop()}[]`:t.split(".").pop()??t}static _schemasToDocuments(t,e){const n=[];for(const i of t){if(!i.name)continue;const r=i.properties.filter(s=>s.isKey),o=i.properties.filter(s=>!s.isKey),a=[`Entity: ${i.name}`,`OData service: ${e}`,`Entity set path: ${e}/${i.name}`,`Count path: ${e}/${i.name}/$count`];r.length&&a.push(`Key fields: ${r.map(s=>`${s.name} (${s.type})`).join(", ")}`),o.length&&a.push(`Fields: ${o.map(s=>`${s.name} (${s.type}${s.nullable?"":", required"})`).join(", ")}`),i.navProperties.length&&a.push(`Navigation: ${i.navProperties.map(s=>`${s.name} → ${s.type}`).join(", ")}`),n.push({title:`${i.name} entity schema`,content:a.join(`
2
+ `)})}return t.length>0&&n.push({title:"Available OData entity sets",content:[`OData service: ${e}`,`Entities: ${t.map(i=>i.name).join(", ")}`,"GET {entity}/$count | ?$filter=field eq 'value' | ?$top=10&$skip=0 | ?$orderby=field desc"].join(`
3
+ `)}),n}static invalidate(t){const e=`btp-copilot-meta-${t}`;c._cache.delete(e),sessionStorage.removeItem(e)}};c._cache=new Map;let _=c;class f{static capture(t){const e={...t};try{const n=b.getHash();n&&(e.current_view=n)}catch{}try{const n=u.getCurrentEntity();n&&Object.keys(n).length>0&&(e.entity_data=n)}catch{}try{e.user_locale||(e.user_locale=b.getUserLocale())}catch{}try{const n=window.__APP_CONTEXT__;n&&(n.entity_data&&(e.entity_data={...n.entity_data,...e.entity_data}),n.current_view&&!e.current_view&&(e.current_view=n.current_view),n.extra&&(e.extra={...n.extra,...e.extra??{}}),n.service_url&&!e.service_url&&(e.service_url=n.service_url))}catch{}return e}static async captureAsync(t){var n;const e=f.capture(t);if(e.service_url||(e.service_url=f._discoverServiceUrl()??void 0),e.service_url)try{const i=((n=e.extra)==null?void 0:n.auth_token)??null,r=await _.fetchSchemaDocuments(e.service_url,i);if(r.length>0){const o=r.map(a=>`## ${a.title}
4
+ ${a.content}`).join(`
5
+
6
+ `);e.extra={...e.extra??{},schema_hint:o}}}catch{}return e}static _discoverServiceUrl(){try{const t=u.getServiceUrl();if(t)return t}catch{}try{const t=performance.getEntriesByType("resource");for(const e of t){const n=e.name.match(/^(https?:\/\/[^?#]+)\/\$metadata/);if(n)return n[1]}}catch{}try{const t=window.location.href.match(/(https?:\/\/[^/]+(?:\/odata\/v[24]\/[^/?#]+|\/sap\/opu\/odata\/[^/?#]+))/);if(t)return t[1]}catch{}return null}static async discoverFromManifest(){var t;try{const e=await fetch("/manifest.json");if(!e.ok)return null;const n=await e.json(),i=((t=n==null?void 0:n["sap.app"])==null?void 0:t.dataSources)??{};for(const r of Object.keys(i)){const o=i[r];if((o==null?void 0:o.type)==="ODataAnnotation")continue;const a=o==null?void 0:o.uri;if(typeof a=="string"&&a.length>0)return new URL(a,window.location.href).toString().replace(/\/$/,"")}}catch{}return null}static listenForUpdates(t,e,n,i){const r=o=>{if(!o.data||typeof o.data!="object")return;const{type:a,payload:s,text:l}=o.data;switch(a){case"btp-copilot:set-context":s&&t(s);break;case"btp-copilot:send-message":l&&e(l);break;case"btp-copilot:open":n();break;case"btp-copilot:close":i();break}};return window.addEventListener("message",r),()=>window.removeEventListener("message",r)}}const x=`/* ── Host element ─────────────────────────────────────────────────────────── */
7
+ :host {
8
+ position: fixed;
9
+ z-index: 2147483647;
10
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
11
+ }
12
+
13
+ *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
14
+
15
+ /* ── Toggle (FAB) button ─────────────────────────────────────────────────── */
16
+ .toggle-btn {
17
+ position: fixed;
18
+ bottom: 1.25rem;
19
+ width: 3.25rem;
20
+ height: 3.25rem;
21
+ border-radius: 50%;
22
+ border: none;
23
+ cursor: pointer;
24
+ display: flex;
25
+ align-items: center;
26
+ justify-content: center;
27
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
28
+ color: #fff;
29
+ box-shadow: 0 4px 14px rgba(102, 126, 234, 0.45);
30
+ z-index: 2147483647;
31
+ transition: transform 0.2s ease, box-shadow 0.2s ease;
32
+ outline: none;
33
+ }
34
+
35
+ .toggle-btn.bottom-right { right: 1.25rem; }
36
+ .toggle-btn.bottom-left { left: 1.25rem; }
37
+
38
+ .toggle-btn:hover {
39
+ transform: scale(1.08);
40
+ box-shadow: 0 6px 20px rgba(102, 126, 234, 0.55);
41
+ }
42
+ .toggle-btn:active { transform: scale(0.95); }
43
+ .toggle-btn:focus-visible { outline: 3px solid #60a5fa; outline-offset: 2px; }
44
+
45
+ .toggle-btn[aria-expanded="false"] .icon-close { display: none; }
46
+ .toggle-btn[aria-expanded="true"] .icon-chat { display: none; }
47
+ .toggle-btn svg { width: 1.375rem; height: 1.375rem; pointer-events: none; }
48
+
49
+ /* Unread-message badge */
50
+ .badge {
51
+ position: absolute;
52
+ top: 0.125rem;
53
+ right: 0.125rem;
54
+ width: 0.625rem;
55
+ height: 0.625rem;
56
+ border-radius: 50%;
57
+ background: #ef4444;
58
+ border: 2px solid #fff;
59
+ opacity: 0;
60
+ transform: scale(0);
61
+ transition: opacity 0.2s ease, transform 0.2s ease;
62
+ }
63
+ .badge.visible { opacity: 1; transform: scale(1); }
64
+
65
+ /* ── Chat panel ──────────────────────────────────────────────────────────── */
66
+ .panel {
67
+ position: fixed;
68
+ bottom: 5.5rem;
69
+ width: 26rem;
70
+ height: 70vh;
71
+ min-height: 25rem;
72
+ max-height: 47.5rem;
73
+ background: transparent;
74
+ border-radius: 1rem;
75
+ box-shadow: 0 8px 40px rgba(0, 0, 0, 0.22), 0 0 0 1px rgba(0, 0, 0, 0.06);
76
+ z-index: 2147483646;
77
+ overflow: hidden;
78
+ display: flex;
79
+ flex-direction: column;
80
+ transform-origin: bottom center;
81
+ transition: opacity 0.25s ease, transform 0.25s cubic-bezier(0.34, 1.3, 0.64, 1),
82
+ width 0.3s cubic-bezier(0.4, 0, 0.2, 1), height 0.3s cubic-bezier(0.4, 0, 0.2, 1),
83
+ bottom 0.3s cubic-bezier(0.4, 0, 0.2, 1), border-radius 0.3s ease;
84
+ }
85
+
86
+ .panel.bottom-right { right: 1.25rem; }
87
+ .panel.bottom-left { left: 1.25rem; }
88
+
89
+ .panel.closed {
90
+ opacity: 0;
91
+ pointer-events: none;
92
+ transform: translateY(0.5rem) scale(0.97);
93
+ }
94
+
95
+ /* Fullscreen mode */
96
+ .panel.fullscreen {
97
+ width: 100vw !important;
98
+ height: 100vh !important;
99
+ height: 100dvh !important;
100
+ bottom: 0 !important;
101
+ right: 0 !important;
102
+ left: 0 !important;
103
+ border-radius: 0 !important;
104
+ max-height: none !important;
105
+ }
106
+
107
+ .panel.fullscreen .chat-iframe {
108
+ border-radius: 0 !important;
109
+ }
110
+
111
+ /* Iframe fills the entire panel */
112
+ .chat-iframe {
113
+ width: 100%;
114
+ height: 100%;
115
+ border: none;
116
+ border-radius: 1rem;
117
+ display: block;
118
+ background: #fff;
119
+ }
120
+
121
+ /* ── Mobile: full-screen ─────────────────────────────────────────────────── */
122
+ @media (max-width: 30rem) {
123
+ .panel {
124
+ width: 100vw;
125
+ height: 85dvh;
126
+ bottom: 0;
127
+ right: 0 !important;
128
+ left: 0 !important;
129
+ border-radius: 1rem 1rem 0 0;
130
+ }
131
+ .chat-iframe { border-radius: 1rem 1rem 0 0; }
132
+ }
133
+ `,w=["iframe-url","app-id","app-name","service-url","auto-context","position","theme","token","context-interval"],v=class v extends HTMLElement{constructor(){super(...arguments),this._open=!1,this._isFullscreen=!1,this._iframeEl=null,this._contextTimer=null}connectedCallback(){this._config=this._readConfig(),this._buildShadow(),this._startContextPolling();const t=e=>{if(!e.data||typeof e.data!="object")return;const{type:n}=e.data;n==="btp-copilot:close"&&this.close(),n==="btp-copilot:open"&&this.open(),n==="btp-copilot:fullscreen"&&this._toggleFullscreen(),n==="btp-copilot:minimize"&&this.close()};window.addEventListener("message",t),this._removeMessageListener=()=>window.removeEventListener("message",t)}disconnectedCallback(){var t;(t=this._removeMessageListener)==null||t.call(this),this._stopContextPolling()}attributeChangedCallback(t,e,n){e===n||!this.isConnected||(this._config=this._readConfig(),this._updateAfterAttributeChange())}open(){this._open=!0,this.shadowRoot.querySelector(".panel").classList.remove("closed"),this.shadowRoot.querySelector(".toggle-btn").setAttribute("aria-expanded","true"),this._clearBadge(),this._pushContextToIframe()}close(){this._open=!1;const t=this.shadowRoot.querySelector(".panel");t.classList.add("closed"),t.classList.remove("fullscreen"),this._isFullscreen=!1,this.shadowRoot.querySelector(".toggle-btn").setAttribute("aria-expanded","false")}_toggleFullscreen(){this._isFullscreen=!this._isFullscreen;const t=this.shadowRoot.querySelector(".panel"),e=this.shadowRoot.querySelector(".toggle-btn");this._isFullscreen?(t.classList.add("fullscreen"),e.style.display="none"):(t.classList.remove("fullscreen"),e.style.display="")}sendMessage(t){this._open||this.open(),setTimeout(()=>{var e,n;(n=(e=this._iframeEl)==null?void 0:e.contentWindow)==null||n.postMessage({type:"btp-copilot:send-message",text:t},"*")},100)}_buildShadow(){var i;const t=this.attachShadow({mode:"open"}),e=document.createElement("style");e.textContent=x,t.appendChild(e);const n=document.createElement("div");for(n.innerHTML=this._template();n.firstChild;)t.appendChild(n.firstChild);t.querySelector(".toggle-btn").addEventListener("click",()=>{this._open?this.close():this.open()}),this._iframeEl=t.querySelector(".chat-iframe"),(i=this._iframeEl)==null||i.addEventListener("load",()=>{this._pushAuthToIframe(),this._pushContextToIframe()})}_template(){var n;const t=((n=this._config)==null?void 0:n.position)??"bottom-right",e=this._esc(this._buildIframeUrl());return`
134
+ <button class="toggle-btn ${t}" aria-label="Open AI assistant" aria-expanded="false" aria-haspopup="dialog">
135
+ <svg class="icon-chat" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
136
+ <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/>
137
+ </svg>
138
+ <svg class="icon-close" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
139
+ <line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/>
140
+ </svg>
141
+ <span class="badge" aria-hidden="true"></span>
142
+ </button>
143
+
144
+ <div class="panel closed ${t}" role="dialog" aria-label="AI Assistant" aria-modal="true">
145
+ <iframe
146
+ class="chat-iframe"
147
+ src="${e}"
148
+ title="AI Assistant"
149
+ allow="clipboard-read; clipboard-write"
150
+ loading="lazy">
151
+ </iframe>
152
+ </div>`}_buildBaseContext(){const t=d.resolve(this._config.token);return{app_id:this._config.appId,app_name:this._config.appName,service_url:this._config.serviceUrl,...t?{extra:{auth_token:t}}:{}}}_buildIframeUrl(){var e;const t=((e=this._config)==null?void 0:e.iframeUrl)??"";if(!t)return"";try{const n=new URL(t),{appId:i,appName:r,serviceUrl:o}=this._config;i&&n.searchParams.set("appId",i),r&&n.searchParams.set("appName",r),o&&n.searchParams.set("serviceUrl",o);const a=d.resolve(this._config.token);return a&&n.searchParams.set("token",a),n.toString()}catch{return t}}_iframeOrigin(){try{return new URL(this._config.iframeUrl).origin}catch{return"*"}}_pushContextToIframe(){var e;if(!((e=this._iframeEl)!=null&&e.contentWindow))return;const t=this._iframeOrigin();this._config.autoContext?f.captureAsync(this._buildBaseContext()).then(n=>{var i,r;(r=(i=this._iframeEl)==null?void 0:i.contentWindow)==null||r.postMessage({type:"btp-copilot:set-context",payload:n},t),n.service_url&&!this._config.serviceUrl&&(this._config={...this._config,serviceUrl:n.service_url})}).catch(()=>{var n,i;(i=(n=this._iframeEl)==null?void 0:n.contentWindow)==null||i.postMessage({type:"btp-copilot:set-context",payload:this._buildBaseContext()},t)}):this._iframeEl.contentWindow.postMessage({type:"btp-copilot:set-context",payload:this._buildBaseContext()},t)}_pushAuthToIframe(){var e;const t=d.resolve(this._config.token);!t||!((e=this._iframeEl)!=null&&e.contentWindow)||this._iframeEl.contentWindow.postMessage({type:"btp-copilot:auth",token:t},this._iframeOrigin())}_startContextPolling(){this._config.autoContext&&(this._contextTimer=setInterval(()=>{this._open&&this._pushContextToIframe()},this._config.contextInterval))}_stopContextPolling(){this._contextTimer!==null&&(clearInterval(this._contextTimer),this._contextTimer=null)}_readConfig(){const t=e=>this.getAttribute(e);return{iframeUrl:t("iframe-url")??"",appId:t("app-id")??"default",appName:t("app-name")??void 0,serviceUrl:t("service-url")??void 0,autoContext:t("auto-context")!=="false",position:t("position")??"bottom-right",theme:t("theme")??"auto",token:t("token")??void 0,contextInterval:Math.max(500,Number(t("context-interval"))||3e3)}}_updateAfterAttributeChange(){var n;const t=(n=this.shadowRoot)==null?void 0:n.querySelector("style");t&&(t.textContent=x);const e=this._buildIframeUrl();this._iframeEl&&this._iframeEl.src!==e&&e&&(this._iframeEl.src=e),this._stopContextPolling(),this._startContextPolling()}_clearBadge(){var t,e;(e=(t=this.shadowRoot)==null?void 0:t.querySelector(".badge"))==null||e.classList.remove("visible")}_esc(t){return t.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}};v.observedAttributes=[...w];let y=v;return customElements.get("btp-copilot")||customElements.define("btp-copilot",y),g.BtpCopilotElement=y,g.ContextBridge=f,Object.defineProperty(g,Symbol.toStringTag,{value:"Module"}),g}({});
153
+ //# sourceMappingURL=btp-copilot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"btp-copilot.js","sources":["../src/api/TokenManager.ts","../src/context/ShellProbe.ts","../src/context/UI5Probe.ts","../src/context/ODataProbe.ts","../src/context/ContextBridge.ts","../src/styles/widget.css?raw","../src/BtpCopilotElement.ts","../src/index.ts"],"sourcesContent":["export class TokenManager {\n private static readonly XSUAA_COOKIE_NAMES = [\n \"x-uaa-token\",\n \"xsuaa_token\",\n \"access_token\",\n \"X-Authorization\",\n ];\n\n static resolve(explicitToken?: string | null): string | null {\n if (explicitToken) return explicitToken.replace(/^Bearer\\s+/i, \"\");\n\n const windowToken = (window as any).__BTP_COPILOT_TOKEN__ as\n | string\n | undefined;\n if (windowToken) return windowToken.replace(/^Bearer\\s+/i, \"\");\n\n const cookieToken = TokenManager._fromCookie();\n if (cookieToken) return cookieToken;\n\n try {\n const lsToken = localStorage.getItem(\"access_token\");\n if (lsToken) return lsToken;\n } catch {}\n\n return null;\n }\n\n static getAuthHeader(token: string | null): Record<string, string> {\n return token ? { Authorization: `Bearer ${token}` } : {};\n }\n\n private static _fromCookie(): string | null {\n try {\n const cookies = document.cookie.split(\";\");\n for (const cookie of cookies) {\n const [name, ...rest] = cookie.trim().split(\"=\");\n if (TokenManager.XSUAA_COOKIE_NAMES.includes(name.trim())) {\n return decodeURIComponent(rest.join(\"=\").trim());\n }\n }\n } catch {}\n return null;\n }\n}\n","declare const sap: any;\n\nexport class ShellProbe {\n static getHash(): string {\n try {\n const nav = sap?.ushell?.Container?.getService?.(\n \"CrossApplicationNavigation\",\n );\n if (nav) {\n const href = nav.hrefForExternal?.() as string | undefined;\n if (href) return href;\n }\n } catch (err) {\n console.log(err);\n }\n return window.location.hash || \"\";\n }\n\n static getCurrentAppId(): string | null {\n try {\n const hash = ShellProbe.getHash();\n const match = hash.match(/^#([^&?/]+)/);\n return match ? match[1] : null;\n } catch {\n return null;\n }\n }\n\n static getUserLocale(): string {\n try {\n return (\n sap?.ui?.getCore?.()?.getConfiguration?.()?.getLanguageTag?.() ??\n navigator.language ??\n \"en\"\n );\n } catch {\n return navigator.language ?? \"en\";\n }\n }\n}\n","declare const sap: any;\n\nexport class UI5Probe {\n static getCurrentEntity(): Record<string, unknown> | null {\n try {\n const core = sap?.ui?.getCore?.();\n if (!core) return null;\n\n let el: Element | null = document.activeElement;\n while (el) {\n const id = el.getAttribute(\"id\") || el.getAttribute(\"data-sap-ui\");\n if (id) {\n const control = core.byId(id);\n const ctx = control?.getBindingContext?.();\n if (ctx) {\n const obj = ctx.getObject?.();\n if (obj && typeof obj === \"object\") {\n return UI5Probe._sanitize(obj as Record<string, unknown>);\n }\n }\n }\n el = el.parentElement;\n }\n return UI5Probe._scanAllControls(core);\n } catch {\n return null;\n }\n }\n\n private static _scanAllControls(core: any): Record<string, unknown> | null {\n try {\n const elements = core.mElements ?? {};\n for (const id of Object.keys(elements)) {\n const control = elements[id];\n const ctx = control?.getBindingContext?.();\n if (ctx) {\n const obj = ctx.getObject?.();\n if (obj && typeof obj === \"object\" && Object.keys(obj).length > 0) {\n return UI5Probe._sanitize(obj as Record<string, unknown>);\n }\n }\n }\n } catch {}\n return null;\n }\n\n static getServiceUrl(): string | null {\n try {\n const core = sap?.ui?.getCore?.();\n if (!core) return null;\n const elements = core.mElements ?? {};\n for (const id of Object.keys(elements)) {\n const control = elements[id];\n if (!control?.getModel) continue;\n const model = control.getModel();\n if (!model) continue;\n const url: unknown = model.sServiceUrl ?? (model as any)._sServiceUrl;\n if (typeof url === \"string\" && url.length > 4) {\n return url.replace(/\\/$/, \"\");\n }\n }\n } catch {}\n return null;\n }\n\n private static _sanitize(\n obj: Record<string, unknown>,\n ): Record<string, unknown> {\n const clean: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(obj)) {\n if (k.startsWith(\"__\")) continue;\n if (v === null || typeof v !== \"object\") {\n clean[k] = v;\n } else if ((v as any).__deferred) {\n // navigation property stub — skip\n } else {\n clean[k] = v;\n }\n }\n return clean;\n }\n}\n","import type {\n EntitySchema,\n EntityProperty,\n NavProperty,\n AppDocument,\n} from \"../types\";\n\nexport class ODataProbe {\n private static _cache = new Map<string, AppDocument[]>();\n\n static async fetchSchemaDocuments(\n serviceUrl: string,\n token?: string | null,\n ): Promise<AppDocument[]> {\n const cacheKey = `btp-copilot-meta-${serviceUrl}`;\n\n if (ODataProbe._cache.has(cacheKey)) {\n return ODataProbe._cache.get(cacheKey)!;\n }\n\n const stored = sessionStorage.getItem(cacheKey);\n if (stored) {\n try {\n const docs = JSON.parse(stored) as AppDocument[];\n ODataProbe._cache.set(cacheKey, docs);\n return docs;\n } catch {}\n }\n\n try {\n const metaUrl = `${serviceUrl}/$metadata`;\n const headers: Record<string, string> = { Accept: \"application/xml\" };\n if (token) headers[\"Authorization\"] = `Bearer ${token}`;\n\n const resp = await fetch(metaUrl, { headers });\n if (!resp.ok) return [];\n\n const xml = await resp.text();\n const schemas = ODataProbe._parseEDMX(xml);\n const docs = ODataProbe._schemasToDocuments(schemas, serviceUrl);\n\n ODataProbe._cache.set(cacheKey, docs);\n sessionStorage.setItem(cacheKey, JSON.stringify(docs));\n return docs;\n } catch {\n return [];\n }\n }\n\n private static _parseEDMX(xml: string): EntitySchema[] {\n try {\n const parser = new DOMParser();\n const doc = parser.parseFromString(xml, \"text/xml\");\n const entityTypes = doc.querySelectorAll(\"EntityType\");\n return Array.from(entityTypes).map((et) => {\n const name = et.getAttribute(\"Name\") ?? \"\";\n const keyRefs = et.querySelectorAll(\"Key > PropertyRef\");\n const keyNames = new Set(\n Array.from(keyRefs).map((k) => k.getAttribute(\"Name\") ?? \"\"),\n );\n const properties: EntityProperty[] = Array.from(\n et.querySelectorAll(\"Property\"),\n ).map((p) => ({\n name: p.getAttribute(\"Name\") ?? \"\",\n type: ODataProbe._shortType(p.getAttribute(\"Type\") ?? \"\"),\n isKey: keyNames.has(p.getAttribute(\"Name\") ?? \"\"),\n nullable: p.getAttribute(\"Nullable\") !== \"false\",\n }));\n const navProperties: NavProperty[] = Array.from(\n et.querySelectorAll(\"NavigationProperty\"),\n ).map((n) => ({\n name: n.getAttribute(\"Name\") ?? \"\",\n type: ODataProbe._shortType(\n n.getAttribute(\"Type\") ?? n.getAttribute(\"ToRole\") ?? \"\",\n ),\n }));\n return { name, properties, navProperties };\n });\n } catch {\n return [];\n }\n }\n\n private static _shortType(full: string): string {\n if (full.startsWith(\"Collection(\")) {\n const inner = full.slice(11, -1);\n return `${inner.split(\".\").pop()}[]`;\n }\n return full.split(\".\").pop() ?? full;\n }\n\n private static _schemasToDocuments(\n schemas: EntitySchema[],\n serviceUrl: string,\n ): AppDocument[] {\n const docs: AppDocument[] = [];\n\n for (const schema of schemas) {\n if (!schema.name) continue;\n const keyProps = schema.properties.filter((p) => p.isKey);\n const otherProps = schema.properties.filter((p) => !p.isKey);\n const lines = [\n `Entity: ${schema.name}`,\n `OData service: ${serviceUrl}`,\n `Entity set path: ${serviceUrl}/${schema.name}`,\n `Count path: ${serviceUrl}/${schema.name}/$count`,\n ];\n if (keyProps.length) {\n lines.push(\n `Key fields: ${keyProps.map((p) => `${p.name} (${p.type})`).join(\", \")}`,\n );\n }\n if (otherProps.length) {\n lines.push(\n `Fields: ${otherProps\n .map(\n (p) => `${p.name} (${p.type}${p.nullable ? \"\" : \", required\"})`,\n )\n .join(\", \")}`,\n );\n }\n if (schema.navProperties.length) {\n lines.push(\n `Navigation: ${schema.navProperties.map((n) => `${n.name} → ${n.type}`).join(\", \")}`,\n );\n }\n docs.push({\n title: `${schema.name} entity schema`,\n content: lines.join(\"\\n\"),\n });\n }\n\n if (schemas.length > 0) {\n docs.push({\n title: \"Available OData entity sets\",\n content: [\n `OData service: ${serviceUrl}`,\n `Entities: ${schemas.map((s) => s.name).join(\", \")}`,\n \"GET {entity}/$count | ?$filter=field eq 'value' | ?$top=10&$skip=0 | ?$orderby=field desc\",\n ].join(\"\\n\"),\n });\n }\n\n return docs;\n }\n\n static invalidate(serviceUrl: string) {\n const key = `btp-copilot-meta-${serviceUrl}`;\n ODataProbe._cache.delete(key);\n sessionStorage.removeItem(key);\n }\n}\n","import type { HostAppContext } from \"../types\";\nimport { ShellProbe } from \"./ShellProbe\";\nimport { UI5Probe } from \"./UI5Probe\";\nimport { ODataProbe } from \"./ODataProbe\";\n\nexport class ContextBridge {\n static capture(baseContext: HostAppContext): HostAppContext {\n const ctx: HostAppContext = { ...baseContext };\n\n try {\n const hash = ShellProbe.getHash();\n if (hash) ctx.current_view = hash;\n } catch {}\n\n try {\n const entity = UI5Probe.getCurrentEntity();\n if (entity && Object.keys(entity).length > 0) ctx.entity_data = entity;\n } catch {}\n\n try {\n if (!ctx.user_locale) ctx.user_locale = ShellProbe.getUserLocale();\n } catch {}\n\n // Merge any context injected by the host app\n try {\n const injected = (window as any).__APP_CONTEXT__ as\n | Partial<HostAppContext>\n | undefined;\n if (injected) {\n if (injected.entity_data)\n ctx.entity_data = { ...injected.entity_data, ...ctx.entity_data };\n if (injected.current_view && !ctx.current_view)\n ctx.current_view = injected.current_view;\n if (injected.extra)\n ctx.extra = { ...injected.extra, ...(ctx.extra ?? {}) };\n if (injected.service_url && !ctx.service_url)\n ctx.service_url = injected.service_url;\n }\n } catch {}\n\n return ctx;\n }\n\n static async captureAsync(\n baseContext: HostAppContext,\n ): Promise<HostAppContext> {\n const ctx = ContextBridge.capture(baseContext);\n\n if (!ctx.service_url) {\n ctx.service_url = ContextBridge._discoverServiceUrl() ?? undefined;\n }\n\n if (ctx.service_url) {\n try {\n const token = (ctx.extra as any)?.auth_token ?? null;\n const docs = await ODataProbe.fetchSchemaDocuments(\n ctx.service_url,\n token,\n );\n if (docs.length > 0) {\n const schemaHint = docs\n .map((d) => `## ${d.title}\\n${d.content}`)\n .join(\"\\n\\n\");\n ctx.extra = { ...(ctx.extra ?? {}), schema_hint: schemaHint };\n }\n } catch {}\n }\n\n return ctx;\n }\n\n private static _discoverServiceUrl(): string | null {\n try {\n const url = UI5Probe.getServiceUrl();\n if (url) return url;\n } catch {}\n\n try {\n const entries = performance.getEntriesByType(\n \"resource\",\n ) as PerformanceResourceTiming[];\n for (const e of entries) {\n const m = e.name.match(/^(https?:\\/\\/[^?#]+)\\/\\$metadata/);\n if (m) return m[1];\n }\n } catch {}\n\n try {\n const m = window.location.href.match(\n /(https?:\\/\\/[^/]+(?:\\/odata\\/v[24]\\/[^/?#]+|\\/sap\\/opu\\/odata\\/[^/?#]+))/,\n );\n if (m) return m[1];\n } catch {}\n\n return null;\n }\n\n static async discoverFromManifest(): Promise<string | null> {\n try {\n const resp = await fetch(\"/manifest.json\");\n if (!resp.ok) return null;\n const manifest = await resp.json();\n const sources: Record<string, any> =\n manifest?.[\"sap.app\"]?.dataSources ?? {};\n for (const key of Object.keys(sources)) {\n const src = sources[key];\n if (src?.type === \"ODataAnnotation\") continue;\n const uri: unknown = src?.uri;\n if (typeof uri === \"string\" && uri.length > 0) {\n return new URL(uri, window.location.href)\n .toString()\n .replace(/\\/$/, \"\");\n }\n }\n } catch {}\n return null;\n }\n\n static listenForUpdates(\n onContextUpdate: (ctx: Partial<HostAppContext>) => void,\n onMessage: (text: string) => void,\n onOpen: () => void,\n onClose: () => void,\n ): () => void {\n const handler = (event: MessageEvent) => {\n if (!event.data || typeof event.data !== \"object\") return;\n const { type, payload, text } = event.data as {\n type?: string;\n payload?: Partial<HostAppContext>;\n text?: string;\n };\n switch (type) {\n case \"btp-copilot:set-context\":\n if (payload) onContextUpdate(payload);\n break;\n case \"btp-copilot:send-message\":\n if (text) onMessage(text);\n break;\n case \"btp-copilot:open\":\n onOpen();\n break;\n case \"btp-copilot:close\":\n onClose();\n break;\n }\n };\n window.addEventListener(\"message\", handler);\n return () => window.removeEventListener(\"message\", handler);\n }\n}\n","export default \"/* ── Host element ─────────────────────────────────────────────────────────── */\\n:host {\\n position: fixed;\\n z-index: 2147483647;\\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\\n}\\n\\n*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }\\n\\n/* ── Toggle (FAB) button ─────────────────────────────────────────────────── */\\n.toggle-btn {\\n position: fixed;\\n bottom: 1.25rem;\\n width: 3.25rem;\\n height: 3.25rem;\\n border-radius: 50%;\\n border: none;\\n cursor: pointer;\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\\n color: #fff;\\n box-shadow: 0 4px 14px rgba(102, 126, 234, 0.45);\\n z-index: 2147483647;\\n transition: transform 0.2s ease, box-shadow 0.2s ease;\\n outline: none;\\n}\\n\\n.toggle-btn.bottom-right { right: 1.25rem; }\\n.toggle-btn.bottom-left { left: 1.25rem; }\\n\\n.toggle-btn:hover {\\n transform: scale(1.08);\\n box-shadow: 0 6px 20px rgba(102, 126, 234, 0.55);\\n}\\n.toggle-btn:active { transform: scale(0.95); }\\n.toggle-btn:focus-visible { outline: 3px solid #60a5fa; outline-offset: 2px; }\\n\\n.toggle-btn[aria-expanded=\\\"false\\\"] .icon-close { display: none; }\\n.toggle-btn[aria-expanded=\\\"true\\\"] .icon-chat { display: none; }\\n.toggle-btn svg { width: 1.375rem; height: 1.375rem; pointer-events: none; }\\n\\n/* Unread-message badge */\\n.badge {\\n position: absolute;\\n top: 0.125rem;\\n right: 0.125rem;\\n width: 0.625rem;\\n height: 0.625rem;\\n border-radius: 50%;\\n background: #ef4444;\\n border: 2px solid #fff;\\n opacity: 0;\\n transform: scale(0);\\n transition: opacity 0.2s ease, transform 0.2s ease;\\n}\\n.badge.visible { opacity: 1; transform: scale(1); }\\n\\n/* ── Chat panel ──────────────────────────────────────────────────────────── */\\n.panel {\\n position: fixed;\\n bottom: 5.5rem;\\n width: 26rem;\\n height: 70vh;\\n min-height: 25rem;\\n max-height: 47.5rem;\\n background: transparent;\\n border-radius: 1rem;\\n box-shadow: 0 8px 40px rgba(0, 0, 0, 0.22), 0 0 0 1px rgba(0, 0, 0, 0.06);\\n z-index: 2147483646;\\n overflow: hidden;\\n display: flex;\\n flex-direction: column;\\n transform-origin: bottom center;\\n transition: opacity 0.25s ease, transform 0.25s cubic-bezier(0.34, 1.3, 0.64, 1),\\n width 0.3s cubic-bezier(0.4, 0, 0.2, 1), height 0.3s cubic-bezier(0.4, 0, 0.2, 1),\\n bottom 0.3s cubic-bezier(0.4, 0, 0.2, 1), border-radius 0.3s ease;\\n}\\n\\n.panel.bottom-right { right: 1.25rem; }\\n.panel.bottom-left { left: 1.25rem; }\\n\\n.panel.closed {\\n opacity: 0;\\n pointer-events: none;\\n transform: translateY(0.5rem) scale(0.97);\\n}\\n\\n/* Fullscreen mode */\\n.panel.fullscreen {\\n width: 100vw !important;\\n height: 100vh !important;\\n height: 100dvh !important;\\n bottom: 0 !important;\\n right: 0 !important;\\n left: 0 !important;\\n border-radius: 0 !important;\\n max-height: none !important;\\n}\\n\\n.panel.fullscreen .chat-iframe {\\n border-radius: 0 !important;\\n}\\n\\n/* Iframe fills the entire panel */\\n.chat-iframe {\\n width: 100%;\\n height: 100%;\\n border: none;\\n border-radius: 1rem;\\n display: block;\\n background: #fff;\\n}\\n\\n/* ── Mobile: full-screen ─────────────────────────────────────────────────── */\\n@media (max-width: 30rem) {\\n .panel {\\n width: 100vw;\\n height: 85dvh;\\n bottom: 0;\\n right: 0 !important;\\n left: 0 !important;\\n border-radius: 1rem 1rem 0 0;\\n }\\n .chat-iframe { border-radius: 1rem 1rem 0 0; }\\n}\\n\"","/**\n * BtpCopilotElement — <btp-copilot> Custom Element.\n *\n * Renders a fixed floating FAB button. When opened, shows your deployed\n * BTP Copilot React chatbot in an iframe. Context from the host UI5/Fiori\n * app is auto-captured and forwarded into the iframe via postMessage so the\n * chatbot is always aware of what the user is looking at.\n *\n * Attributes:\n * iframe-url Full URL of the deployed React chatbot frontend (required)\n * app-id Stable identifier of the host application (required)\n * app-name Human-readable app name\n * service-url OData service URL for context auto-capture\n * auto-context \"true\"|\"false\" — auto-capture UI5/OData context (default: true)\n * position \"bottom-right\"|\"bottom-left\" (default: bottom-right)\n * theme \"auto\"|\"light\"|\"dark\" (default: auto)\n * token Bearer token forwarded to the chatbot iframe\n * context-interval Context re-capture interval in ms (default: 3000)\n *\n * postMessage protocol (outgoing → iframe):\n * { type: 'btp-copilot:set-context', payload: HostAppContext }\n * { type: 'btp-copilot:auth', token: string }\n *\n * postMessage protocol (incoming ← iframe or host page):\n * { type: 'btp-copilot:close' }\n * { type: 'btp-copilot:open' }\n */\n\nimport type { HostAppContext, WidgetConfig } from \"./types\";\nimport { TokenManager } from \"./api/TokenManager\";\nimport { ContextBridge } from \"./context/ContextBridge\";\nimport widgetCss from \"./styles/widget.css?raw\";\n\nconst OBSERVED = [\n \"iframe-url\",\n \"app-id\",\n \"app-name\",\n \"service-url\",\n \"auto-context\",\n \"position\",\n \"theme\",\n \"token\",\n \"context-interval\",\n] as const;\n\nexport class BtpCopilotElement extends HTMLElement {\n static observedAttributes = [...OBSERVED];\n\n private _config!: WidgetConfig;\n private _open = false;\n private _isFullscreen = false;\n private _iframeEl: HTMLIFrameElement | null = null;\n private _contextTimer: ReturnType<typeof setInterval> | null = null;\n private _removeMessageListener?: () => void;\n\n connectedCallback() {\n this._config = this._readConfig();\n this._buildShadow();\n this._startContextPolling();\n\n const msgHandler = (event: MessageEvent) => {\n if (!event.data || typeof event.data !== \"object\") return;\n const { type } = event.data as { type?: string };\n if (type === \"btp-copilot:close\") this.close();\n if (type === \"btp-copilot:open\") this.open();\n if (type === \"btp-copilot:fullscreen\") this._toggleFullscreen();\n if (type === \"btp-copilot:minimize\") this.close();\n };\n window.addEventListener(\"message\", msgHandler);\n this._removeMessageListener = () =>\n window.removeEventListener(\"message\", msgHandler);\n }\n\n disconnectedCallback() {\n this._removeMessageListener?.();\n this._stopContextPolling();\n }\n\n attributeChangedCallback(\n _name: string,\n old: string | null,\n next: string | null\n ) {\n if (old === next || !this.isConnected) return;\n this._config = this._readConfig();\n this._updateAfterAttributeChange();\n }\n\n // ── Public API ─────────────────────────────────────────────────────────────\n open() {\n this._open = true;\n this.shadowRoot!.querySelector(\".panel\")!.classList.remove(\"closed\");\n this.shadowRoot!\n .querySelector(\".toggle-btn\")!\n .setAttribute(\"aria-expanded\", \"true\");\n this._clearBadge();\n this._pushContextToIframe();\n }\n\n close() {\n this._open = false;\n const panel = this.shadowRoot!.querySelector(\".panel\")!;\n panel.classList.add(\"closed\");\n panel.classList.remove(\"fullscreen\");\n this._isFullscreen = false;\n this.shadowRoot!\n .querySelector(\".toggle-btn\")!\n .setAttribute(\"aria-expanded\", \"false\");\n }\n\n private _toggleFullscreen() {\n this._isFullscreen = !this._isFullscreen;\n const panel = this.shadowRoot!.querySelector(\".panel\")!;\n const fab = this.shadowRoot!.querySelector(\".toggle-btn\") as HTMLElement;\n if (this._isFullscreen) {\n panel.classList.add(\"fullscreen\");\n fab.style.display = \"none\";\n } else {\n panel.classList.remove(\"fullscreen\");\n fab.style.display = \"\";\n }\n }\n\n sendMessage(text: string) {\n if (!this._open) this.open();\n setTimeout(() => {\n this._iframeEl?.contentWindow?.postMessage(\n { type: \"btp-copilot:send-message\", text },\n \"*\"\n );\n }, 100);\n }\n\n // ── Shadow DOM ─────────────────────────────────────────────────────────────\n private _buildShadow() {\n const shadow = this.attachShadow({ mode: \"open\" });\n\n const styleEl = document.createElement(\"style\");\n styleEl.textContent = widgetCss;\n shadow.appendChild(styleEl);\n\n const wrapper = document.createElement(\"div\");\n wrapper.innerHTML = this._template();\n while (wrapper.firstChild) shadow.appendChild(wrapper.firstChild);\n\n shadow.querySelector(\".toggle-btn\")!.addEventListener(\"click\", () => {\n this._open ? this.close() : this.open();\n });\n\n this._iframeEl = shadow.querySelector(\".chat-iframe\");\n\n this._iframeEl?.addEventListener(\"load\", () => {\n this._pushAuthToIframe();\n this._pushContextToIframe();\n });\n }\n\n private _template(): string {\n const pos = this._config?.position ?? \"bottom-right\";\n const src = this._esc(this._buildIframeUrl());\n return `\n<button class=\"toggle-btn ${pos}\" aria-label=\"Open AI assistant\" aria-expanded=\"false\" aria-haspopup=\"dialog\">\n <svg class=\"icon-chat\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\"/>\n </svg>\n <svg class=\"icon-close\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/>\n </svg>\n <span class=\"badge\" aria-hidden=\"true\"></span>\n</button>\n\n<div class=\"panel closed ${pos}\" role=\"dialog\" aria-label=\"AI Assistant\" aria-modal=\"true\">\n <iframe\n class=\"chat-iframe\"\n src=\"${src}\"\n title=\"AI Assistant\"\n allow=\"clipboard-read; clipboard-write\"\n loading=\"lazy\">\n </iframe>\n</div>`;\n }\n\n // ── Context + Auth ─────────────────────────────────────────────────────────\n private _buildBaseContext(): HostAppContext {\n const token = TokenManager.resolve(this._config.token);\n return {\n app_id: this._config.appId,\n app_name: this._config.appName,\n service_url: this._config.serviceUrl,\n // Include the resolved auth token in extra so the backend can\n // proxy OData calls on behalf of the user to fetch real data\n ...(token ? { extra: { auth_token: token } } : {}),\n };\n }\n\n private _buildIframeUrl(): string {\n const base = this._config?.iframeUrl ?? \"\";\n if (!base) return \"\";\n try {\n const url = new URL(base);\n const { appId, appName, serviceUrl } = this._config;\n if (appId) url.searchParams.set(\"appId\", appId);\n if (appName) url.searchParams.set(\"appName\", appName);\n if (serviceUrl) url.searchParams.set(\"serviceUrl\", serviceUrl);\n // Pass token as URL param so the chatbot can auto-authenticate in iframe mode\n const token = TokenManager.resolve(this._config.token);\n if (token) url.searchParams.set(\"token\", token);\n return url.toString();\n } catch {\n return base;\n }\n }\n\n /** Derive the allowed postMessage target origin from the configured iframe URL.\n * Falls back to \"*\" only when the URL cannot be parsed (e.g. empty string). */\n private _iframeOrigin(): string {\n try {\n return new URL(this._config.iframeUrl).origin;\n } catch {\n return \"*\";\n }\n }\n\n private _pushContextToIframe() {\n if (!this._iframeEl?.contentWindow) return;\n const origin = this._iframeOrigin();\n\n if (this._config.autoContext) {\n ContextBridge.captureAsync(this._buildBaseContext())\n .then((ctx) => {\n this._iframeEl?.contentWindow?.postMessage(\n { type: \"btp-copilot:set-context\", payload: ctx },\n origin\n );\n if (ctx.service_url && !this._config.serviceUrl) {\n this._config = { ...this._config, serviceUrl: ctx.service_url };\n }\n })\n .catch(() => {\n this._iframeEl?.contentWindow?.postMessage(\n { type: \"btp-copilot:set-context\", payload: this._buildBaseContext() },\n origin\n );\n });\n } else {\n this._iframeEl.contentWindow.postMessage(\n { type: \"btp-copilot:set-context\", payload: this._buildBaseContext() },\n origin\n );\n }\n }\n\n private _pushAuthToIframe() {\n const token = TokenManager.resolve(this._config.token);\n if (!token || !this._iframeEl?.contentWindow) return;\n this._iframeEl.contentWindow.postMessage(\n { type: \"btp-copilot:auth\", token },\n this._iframeOrigin()\n );\n }\n\n private _startContextPolling() {\n if (!this._config.autoContext) return;\n this._contextTimer = setInterval(() => {\n if (this._open) this._pushContextToIframe();\n }, this._config.contextInterval);\n }\n\n private _stopContextPolling() {\n if (this._contextTimer !== null) {\n clearInterval(this._contextTimer);\n this._contextTimer = null;\n }\n }\n\n // ── Config ─────────────────────────────────────────────────────────────────\n private _readConfig(): WidgetConfig {\n const get = (attr: string) => this.getAttribute(attr);\n return {\n iframeUrl: get(\"iframe-url\") ?? \"\",\n appId: get(\"app-id\") ?? \"default\",\n appName: get(\"app-name\") ?? undefined,\n serviceUrl: get(\"service-url\") ?? undefined,\n autoContext: get(\"auto-context\") !== \"false\",\n position: (get(\"position\") ?? \"bottom-right\") as WidgetConfig[\"position\"],\n theme: (get(\"theme\") ?? \"auto\") as WidgetConfig[\"theme\"],\n token: get(\"token\") ?? undefined,\n contextInterval: Math.max(500, Number(get(\"context-interval\")) || 3000),\n };\n }\n\n private _updateAfterAttributeChange() {\n const style = this.shadowRoot?.querySelector(\"style\");\n if (style) style.textContent = widgetCss;\n\n const newSrc = this._buildIframeUrl();\n if (this._iframeEl && this._iframeEl.src !== newSrc && newSrc) {\n this._iframeEl.src = newSrc;\n }\n\n this._stopContextPolling();\n this._startContextPolling();\n }\n\n private _clearBadge() {\n this.shadowRoot?.querySelector(\".badge\")?.classList.remove(\"visible\");\n }\n\n private _esc(s: string): string {\n return s\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\");\n }\n}\n","import { BtpCopilotElement } from \"./BtpCopilotElement\";\n\nif (!customElements.get(\"btp-copilot\")) {\n customElements.define(\"btp-copilot\", BtpCopilotElement);\n}\n\nexport { BtpCopilotElement };\nexport type { HostAppContext, WidgetConfig, AppDocument } from \"./types\";\nexport { ContextBridge } from \"./context/ContextBridge\";\n"],"names":["_TokenManager","explicitToken","windowToken","cookieToken","lsToken","token","cookies","cookie","name","rest","TokenManager","ShellProbe","nav","_c","_b","_a","href","_d","err","match","_f","_e","UI5Probe","core","el","id","control","ctx","obj","elements","model","url","clean","k","v","_ODataProbe","serviceUrl","cacheKey","stored","docs","metaUrl","headers","resp","xml","schemas","entityTypes","et","keyRefs","keyNames","properties","p","navProperties","n","full","schema","keyProps","otherProps","lines","s","key","ODataProbe","ContextBridge","baseContext","hash","entity","injected","schemaHint","d","entries","m","manifest","sources","src","uri","onContextUpdate","onMessage","onOpen","onClose","handler","event","type","payload","text","widgetCss","OBSERVED","_BtpCopilotElement","msgHandler","_name","old","next","panel","fab","shadow","styleEl","wrapper","pos","base","appId","appName","origin","get","attr","style","newSrc","BtpCopilotElement"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "cap-copilot-widget",
3
+ "version": "0.1.0",
4
+ "description": "BTP Copilot floating chat widget — Web Component (iframe launcher)",
5
+ "main": "dist/btp-copilot.js",
6
+ "module": "dist/btp-copilot.esm.js",
7
+ "types": "dist/btp-copilot.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/btp-copilot.esm.js",
11
+ "require": "./dist/btp-copilot.js",
12
+ "types": "./dist/btp-copilot.d.ts"
13
+ }
14
+ },
15
+ "files": ["dist"],
16
+ "scripts": {
17
+ "dev": "vite --port 5174 --open",
18
+ "build": "tsc --noEmit && vite build",
19
+ "prepare": "tsc --noEmit && vite build",
20
+ "preview": "vite preview",
21
+ "clean": "rm -rf dist"
22
+ },
23
+ "keywords": ["sap", "fiori", "ui5", "cap", "btp", "ai", "chatbot", "web-component"],
24
+ "license": "MIT",
25
+ "devDependencies": {
26
+ "typescript": "^5.4.0",
27
+ "vite": "^5.2.0"
28
+ }
29
+ }