cap-copilot-widget 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/btp-copilot.esm.js +127 -107
- package/dist/btp-copilot.esm.js.map +1 -1
- package/dist/btp-copilot.js +6 -6
- package/dist/btp-copilot.js.map +1 -1
- package/package.json +1 -1
package/dist/btp-copilot.esm.js
CHANGED
|
@@ -6,8 +6,8 @@ const f = class f {
|
|
|
6
6
|
const n = f._fromCookie();
|
|
7
7
|
if (n) return n;
|
|
8
8
|
try {
|
|
9
|
-
const
|
|
10
|
-
if (
|
|
9
|
+
const r = localStorage.getItem("access_token");
|
|
10
|
+
if (r) return r;
|
|
11
11
|
} catch {
|
|
12
12
|
}
|
|
13
13
|
return null;
|
|
@@ -19,9 +19,9 @@ const f = class f {
|
|
|
19
19
|
try {
|
|
20
20
|
const t = document.cookie.split(";");
|
|
21
21
|
for (const e of t) {
|
|
22
|
-
const [n, ...
|
|
22
|
+
const [n, ...r] = e.trim().split("=");
|
|
23
23
|
if (f.XSUAA_COOKIE_NAMES.includes(n.trim()))
|
|
24
|
-
return decodeURIComponent(
|
|
24
|
+
return decodeURIComponent(r.join("=").trim());
|
|
25
25
|
}
|
|
26
26
|
} catch {
|
|
27
27
|
}
|
|
@@ -37,18 +37,18 @@ f.XSUAA_COOKIE_NAMES = [
|
|
|
37
37
|
let d = f;
|
|
38
38
|
class m {
|
|
39
39
|
static getHash() {
|
|
40
|
-
var t, e, n,
|
|
40
|
+
var t, e, n, r;
|
|
41
41
|
try {
|
|
42
|
-
const
|
|
42
|
+
const o = (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
43
|
e,
|
|
44
44
|
"CrossApplicationNavigation"
|
|
45
45
|
);
|
|
46
|
-
if (
|
|
47
|
-
const
|
|
48
|
-
if (
|
|
46
|
+
if (o) {
|
|
47
|
+
const i = (r = o.hrefForExternal) == null ? void 0 : r.call(o);
|
|
48
|
+
if (i) return i;
|
|
49
49
|
}
|
|
50
|
-
} catch (
|
|
51
|
-
console.log(
|
|
50
|
+
} catch (o) {
|
|
51
|
+
console.log(o);
|
|
52
52
|
}
|
|
53
53
|
return window.location.hash || "";
|
|
54
54
|
}
|
|
@@ -61,9 +61,9 @@ class m {
|
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
63
|
static getUserLocale() {
|
|
64
|
-
var t, e, n,
|
|
64
|
+
var t, e, n, r, o, i;
|
|
65
65
|
try {
|
|
66
|
-
return ((
|
|
66
|
+
return ((i = (o = (r = (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 : r.call(n)) == null ? void 0 : o.getLanguageTag) == null ? void 0 : i.call(o)) ?? navigator.language ?? "en";
|
|
67
67
|
} catch {
|
|
68
68
|
return navigator.language ?? "en";
|
|
69
69
|
}
|
|
@@ -71,24 +71,24 @@ class m {
|
|
|
71
71
|
}
|
|
72
72
|
class u {
|
|
73
73
|
static getCurrentEntity() {
|
|
74
|
-
var t, e, n,
|
|
74
|
+
var t, e, n, r;
|
|
75
75
|
try {
|
|
76
|
-
const
|
|
77
|
-
if (!
|
|
78
|
-
let
|
|
79
|
-
for (;
|
|
80
|
-
const a =
|
|
76
|
+
const o = (e = (t = sap == null ? void 0 : sap.ui) == null ? void 0 : t.getCore) == null ? void 0 : e.call(t);
|
|
77
|
+
if (!o) return null;
|
|
78
|
+
let i = document.activeElement;
|
|
79
|
+
for (; i; ) {
|
|
80
|
+
const a = i.getAttribute("id") || i.getAttribute("data-sap-ui");
|
|
81
81
|
if (a) {
|
|
82
|
-
const
|
|
82
|
+
const s = o.byId(a), l = (n = s == null ? void 0 : s.getBindingContext) == null ? void 0 : n.call(s);
|
|
83
83
|
if (l) {
|
|
84
|
-
const p = (
|
|
84
|
+
const p = (r = l.getObject) == null ? void 0 : r.call(l);
|
|
85
85
|
if (p && typeof p == "object")
|
|
86
86
|
return u._sanitize(p);
|
|
87
87
|
}
|
|
88
88
|
}
|
|
89
|
-
|
|
89
|
+
i = i.parentElement;
|
|
90
90
|
}
|
|
91
|
-
return u._scanAllControls(
|
|
91
|
+
return u._scanAllControls(o);
|
|
92
92
|
} catch {
|
|
93
93
|
return null;
|
|
94
94
|
}
|
|
@@ -96,13 +96,13 @@ class u {
|
|
|
96
96
|
static _scanAllControls(t) {
|
|
97
97
|
var e, n;
|
|
98
98
|
try {
|
|
99
|
-
const
|
|
100
|
-
for (const
|
|
101
|
-
const
|
|
99
|
+
const r = t.mElements ?? {};
|
|
100
|
+
for (const o of Object.keys(r)) {
|
|
101
|
+
const i = r[o], a = (e = i == null ? void 0 : i.getBindingContext) == null ? void 0 : e.call(i);
|
|
102
102
|
if (a) {
|
|
103
|
-
const
|
|
104
|
-
if (
|
|
105
|
-
return u._sanitize(
|
|
103
|
+
const s = (n = a.getObject) == null ? void 0 : n.call(a);
|
|
104
|
+
if (s && typeof s == "object" && Object.keys(s).length > 0)
|
|
105
|
+
return u._sanitize(s);
|
|
106
106
|
}
|
|
107
107
|
}
|
|
108
108
|
} catch {
|
|
@@ -114,15 +114,15 @@ class u {
|
|
|
114
114
|
try {
|
|
115
115
|
const n = (e = (t = sap == null ? void 0 : sap.ui) == null ? void 0 : t.getCore) == null ? void 0 : e.call(t);
|
|
116
116
|
if (!n) return null;
|
|
117
|
-
const
|
|
118
|
-
for (const
|
|
119
|
-
const
|
|
120
|
-
if (!(
|
|
121
|
-
const a =
|
|
117
|
+
const r = n.mElements ?? {};
|
|
118
|
+
for (const o of Object.keys(r)) {
|
|
119
|
+
const i = r[o];
|
|
120
|
+
if (!(i != null && i.getModel)) continue;
|
|
121
|
+
const a = i.getModel();
|
|
122
122
|
if (!a) continue;
|
|
123
|
-
const
|
|
124
|
-
if (typeof
|
|
125
|
-
return
|
|
123
|
+
const s = a.sServiceUrl ?? a._sServiceUrl;
|
|
124
|
+
if (typeof s == "string" && s.length > 4)
|
|
125
|
+
return s.replace(/\/$/, "");
|
|
126
126
|
}
|
|
127
127
|
} catch {
|
|
128
128
|
}
|
|
@@ -130,8 +130,8 @@ class u {
|
|
|
130
130
|
}
|
|
131
131
|
static _sanitize(t) {
|
|
132
132
|
const e = {};
|
|
133
|
-
for (const [n,
|
|
134
|
-
n.startsWith("__") || (
|
|
133
|
+
for (const [n, r] of Object.entries(t))
|
|
134
|
+
n.startsWith("__") || (r === null || typeof r != "object" ? e[n] = r : r.__deferred || (e[n] = r));
|
|
135
135
|
return e;
|
|
136
136
|
}
|
|
137
137
|
}
|
|
@@ -140,19 +140,19 @@ const c = class c {
|
|
|
140
140
|
const n = `btp-copilot-meta-${t}`;
|
|
141
141
|
if (c._cache.has(n))
|
|
142
142
|
return c._cache.get(n);
|
|
143
|
-
const
|
|
144
|
-
if (
|
|
143
|
+
const r = sessionStorage.getItem(n);
|
|
144
|
+
if (r)
|
|
145
145
|
try {
|
|
146
|
-
const
|
|
147
|
-
return c._cache.set(n,
|
|
146
|
+
const o = JSON.parse(r);
|
|
147
|
+
return c._cache.set(n, o), o;
|
|
148
148
|
} catch {
|
|
149
149
|
}
|
|
150
150
|
try {
|
|
151
|
-
const
|
|
152
|
-
e && (
|
|
153
|
-
const a = await fetch(
|
|
151
|
+
const o = `${t}/$metadata`, i = { Accept: "application/xml" };
|
|
152
|
+
e && (i.Authorization = `Bearer ${e}`);
|
|
153
|
+
const a = await fetch(o, { headers: i });
|
|
154
154
|
if (!a.ok) return [];
|
|
155
|
-
const
|
|
155
|
+
const s = await a.text(), l = c._parseEDMX(s), p = c._schemasToDocuments(l, t);
|
|
156
156
|
return c._cache.set(n, p), sessionStorage.setItem(n, JSON.stringify(p)), p;
|
|
157
157
|
} catch {
|
|
158
158
|
return [];
|
|
@@ -160,26 +160,26 @@ const c = class c {
|
|
|
160
160
|
}
|
|
161
161
|
static _parseEDMX(t) {
|
|
162
162
|
try {
|
|
163
|
-
const
|
|
164
|
-
return Array.from(
|
|
165
|
-
const
|
|
163
|
+
const r = new DOMParser().parseFromString(t, "text/xml").querySelectorAll("EntityType");
|
|
164
|
+
return Array.from(r).map((o) => {
|
|
165
|
+
const i = o.getAttribute("Name") ?? "", a = o.querySelectorAll("Key > PropertyRef"), s = new Set(
|
|
166
166
|
Array.from(a).map((h) => h.getAttribute("Name") ?? "")
|
|
167
167
|
), l = Array.from(
|
|
168
|
-
|
|
168
|
+
o.querySelectorAll("Property")
|
|
169
169
|
).map((h) => ({
|
|
170
170
|
name: h.getAttribute("Name") ?? "",
|
|
171
171
|
type: c._shortType(h.getAttribute("Type") ?? ""),
|
|
172
|
-
isKey:
|
|
172
|
+
isKey: s.has(h.getAttribute("Name") ?? ""),
|
|
173
173
|
nullable: h.getAttribute("Nullable") !== "false"
|
|
174
174
|
})), p = Array.from(
|
|
175
|
-
|
|
175
|
+
o.querySelectorAll("NavigationProperty")
|
|
176
176
|
).map((h) => ({
|
|
177
177
|
name: h.getAttribute("Name") ?? "",
|
|
178
178
|
type: c._shortType(
|
|
179
179
|
h.getAttribute("Type") ?? h.getAttribute("ToRole") ?? ""
|
|
180
180
|
)
|
|
181
181
|
}));
|
|
182
|
-
return { name:
|
|
182
|
+
return { name: i, properties: l, navProperties: p };
|
|
183
183
|
});
|
|
184
184
|
} catch {
|
|
185
185
|
return [];
|
|
@@ -190,24 +190,24 @@ const c = class c {
|
|
|
190
190
|
}
|
|
191
191
|
static _schemasToDocuments(t, e) {
|
|
192
192
|
const n = [];
|
|
193
|
-
for (const
|
|
194
|
-
if (!
|
|
195
|
-
const
|
|
196
|
-
`Entity: ${
|
|
193
|
+
for (const r of t) {
|
|
194
|
+
if (!r.name) continue;
|
|
195
|
+
const o = r.properties.filter((s) => s.isKey), i = r.properties.filter((s) => !s.isKey), a = [
|
|
196
|
+
`Entity: ${r.name}`,
|
|
197
197
|
`OData service: ${e}`,
|
|
198
|
-
`Entity set path: ${e}/${
|
|
199
|
-
`Count path: ${e}/${
|
|
198
|
+
`Entity set path: ${e}/${r.name}`,
|
|
199
|
+
`Count path: ${e}/${r.name}/$count`
|
|
200
200
|
];
|
|
201
|
-
|
|
202
|
-
`Key fields: ${
|
|
203
|
-
),
|
|
204
|
-
`Fields: ${
|
|
205
|
-
(
|
|
201
|
+
o.length && a.push(
|
|
202
|
+
`Key fields: ${o.map((s) => `${s.name} (${s.type})`).join(", ")}`
|
|
203
|
+
), i.length && a.push(
|
|
204
|
+
`Fields: ${i.map(
|
|
205
|
+
(s) => `${s.name} (${s.type}${s.nullable ? "" : ", required"})`
|
|
206
206
|
).join(", ")}`
|
|
207
|
-
),
|
|
208
|
-
`Navigation: ${
|
|
207
|
+
), r.navProperties.length && a.push(
|
|
208
|
+
`Navigation: ${r.navProperties.map((s) => `${s.name} → ${s.type}`).join(", ")}`
|
|
209
209
|
), n.push({
|
|
210
|
-
title: `${
|
|
210
|
+
title: `${r.name} entity schema`,
|
|
211
211
|
content: a.join(`
|
|
212
212
|
`)
|
|
213
213
|
});
|
|
@@ -216,7 +216,7 @@ const c = class c {
|
|
|
216
216
|
title: "Available OData entity sets",
|
|
217
217
|
content: [
|
|
218
218
|
`OData service: ${e}`,
|
|
219
|
-
`Entities: ${t.map((
|
|
219
|
+
`Entities: ${t.map((r) => r.name).join(", ")}`,
|
|
220
220
|
"GET {entity}/$count | ?$filter=field eq 'value' | ?$top=10&$skip=0 | ?$orderby=field desc"
|
|
221
221
|
].join(`
|
|
222
222
|
`)
|
|
@@ -231,15 +231,16 @@ c._cache = /* @__PURE__ */ new Map();
|
|
|
231
231
|
let b = c;
|
|
232
232
|
class g {
|
|
233
233
|
static capture(t) {
|
|
234
|
+
var n, r, o;
|
|
234
235
|
const e = { ...t };
|
|
235
236
|
try {
|
|
236
|
-
const
|
|
237
|
-
|
|
237
|
+
const i = m.getHash();
|
|
238
|
+
i && (e.current_view = i);
|
|
238
239
|
} catch {
|
|
239
240
|
}
|
|
240
241
|
try {
|
|
241
|
-
const
|
|
242
|
-
|
|
242
|
+
const i = u.getCurrentEntity();
|
|
243
|
+
i && Object.keys(i).length > 0 && (e.entity_data = i);
|
|
243
244
|
} catch {
|
|
244
245
|
}
|
|
245
246
|
try {
|
|
@@ -247,8 +248,25 @@ class g {
|
|
|
247
248
|
} catch {
|
|
248
249
|
}
|
|
249
250
|
try {
|
|
250
|
-
const
|
|
251
|
-
|
|
251
|
+
const i = window.location.pathname + window.location.search + window.location.hash;
|
|
252
|
+
(!e.current_view || e.current_view === "") && (e.current_view = i);
|
|
253
|
+
} catch {
|
|
254
|
+
}
|
|
255
|
+
try {
|
|
256
|
+
e.user_locale || (e.user_locale = navigator.language || ((n = navigator.languages) == null ? void 0 : n[0]) || "en");
|
|
257
|
+
} catch {
|
|
258
|
+
}
|
|
259
|
+
try {
|
|
260
|
+
e.extra = {
|
|
261
|
+
...e.extra ?? {},
|
|
262
|
+
page_title: ((r = e.extra) == null ? void 0 : r.page_title) ?? document.title ?? "",
|
|
263
|
+
page_url: ((o = e.extra) == null ? void 0 : o.page_url) ?? window.location.href ?? ""
|
|
264
|
+
};
|
|
265
|
+
} catch {
|
|
266
|
+
}
|
|
267
|
+
try {
|
|
268
|
+
const i = window.__APP_CONTEXT__;
|
|
269
|
+
i && (i.entity_data && (e.entity_data = { ...i.entity_data, ...e.entity_data }), i.current_view && !e.current_view && (e.current_view = i.current_view), i.extra && (e.extra = { ...i.extra, ...e.extra ?? {} }), i.service_url && !e.service_url && (e.service_url = i.service_url));
|
|
252
270
|
} catch {
|
|
253
271
|
}
|
|
254
272
|
return e;
|
|
@@ -258,16 +276,16 @@ class g {
|
|
|
258
276
|
const e = g.capture(t);
|
|
259
277
|
if (e.service_url || (e.service_url = g._discoverServiceUrl() ?? void 0), e.service_url)
|
|
260
278
|
try {
|
|
261
|
-
const
|
|
279
|
+
const r = ((n = e.extra) == null ? void 0 : n.auth_token) ?? null, o = await b.fetchSchemaDocuments(
|
|
262
280
|
e.service_url,
|
|
263
|
-
|
|
281
|
+
r
|
|
264
282
|
);
|
|
265
|
-
if (
|
|
266
|
-
const
|
|
283
|
+
if (o.length > 0) {
|
|
284
|
+
const i = o.map((a) => `## ${a.title}
|
|
267
285
|
${a.content}`).join(`
|
|
268
286
|
|
|
269
287
|
`);
|
|
270
|
-
e.extra = { ...e.extra ?? {}, schema_hint:
|
|
288
|
+
e.extra = { ...e.extra ?? {}, schema_hint: i };
|
|
271
289
|
}
|
|
272
290
|
} catch {
|
|
273
291
|
}
|
|
@@ -303,11 +321,11 @@ ${a.content}`).join(`
|
|
|
303
321
|
try {
|
|
304
322
|
const e = await fetch("/manifest.json");
|
|
305
323
|
if (!e.ok) return null;
|
|
306
|
-
const n = await e.json(),
|
|
307
|
-
for (const
|
|
308
|
-
const
|
|
309
|
-
if ((
|
|
310
|
-
const a =
|
|
324
|
+
const n = await e.json(), r = ((t = n == null ? void 0 : n["sap.app"]) == null ? void 0 : t.dataSources) ?? {};
|
|
325
|
+
for (const o of Object.keys(r)) {
|
|
326
|
+
const i = r[o];
|
|
327
|
+
if ((i == null ? void 0 : i.type) === "ODataAnnotation") continue;
|
|
328
|
+
const a = i == null ? void 0 : i.uri;
|
|
311
329
|
if (typeof a == "string" && a.length > 0)
|
|
312
330
|
return new URL(a, window.location.href).toString().replace(/\/$/, "");
|
|
313
331
|
}
|
|
@@ -315,13 +333,13 @@ ${a.content}`).join(`
|
|
|
315
333
|
}
|
|
316
334
|
return null;
|
|
317
335
|
}
|
|
318
|
-
static listenForUpdates(t, e, n,
|
|
319
|
-
const
|
|
320
|
-
if (!
|
|
321
|
-
const { type: a, payload:
|
|
336
|
+
static listenForUpdates(t, e, n, r) {
|
|
337
|
+
const o = (i) => {
|
|
338
|
+
if (!i.data || typeof i.data != "object") return;
|
|
339
|
+
const { type: a, payload: s, text: l } = i.data;
|
|
322
340
|
switch (a) {
|
|
323
341
|
case "btp-copilot:set-context":
|
|
324
|
-
|
|
342
|
+
s && t(s);
|
|
325
343
|
break;
|
|
326
344
|
case "btp-copilot:send-message":
|
|
327
345
|
l && e(l);
|
|
@@ -330,11 +348,11 @@ ${a.content}`).join(`
|
|
|
330
348
|
n();
|
|
331
349
|
break;
|
|
332
350
|
case "btp-copilot:close":
|
|
333
|
-
|
|
351
|
+
r();
|
|
334
352
|
break;
|
|
335
353
|
}
|
|
336
354
|
};
|
|
337
|
-
return window.addEventListener("message",
|
|
355
|
+
return window.addEventListener("message", o), () => window.removeEventListener("message", o);
|
|
338
356
|
}
|
|
339
357
|
}
|
|
340
358
|
const v = `/* ── Host element ─────────────────────────────────────────────────────────── */
|
|
@@ -474,7 +492,7 @@ const v = `/* ── Host element ───────────────
|
|
|
474
492
|
"theme",
|
|
475
493
|
"token",
|
|
476
494
|
"context-interval"
|
|
477
|
-
],
|
|
495
|
+
], y = class y extends HTMLElement {
|
|
478
496
|
constructor() {
|
|
479
497
|
super(...arguments), this._open = !1, this._isFullscreen = !1, this._iframeEl = null, this._contextTimer = null;
|
|
480
498
|
}
|
|
@@ -499,9 +517,11 @@ const v = `/* ── Host element ───────────────
|
|
|
499
517
|
this._open = !0, this.shadowRoot.querySelector(".panel").classList.remove("closed"), this.shadowRoot.querySelector(".toggle-btn").setAttribute("aria-expanded", "true"), this._clearBadge(), this._pushContextToIframe();
|
|
500
518
|
}
|
|
501
519
|
close() {
|
|
502
|
-
this._open = !1;
|
|
520
|
+
this._open = !1, this._isFullscreen = !1;
|
|
503
521
|
const t = this.shadowRoot.querySelector(".panel");
|
|
504
|
-
t.classList.add("closed"), t.classList.remove("fullscreen")
|
|
522
|
+
t.classList.add("closed"), t.classList.remove("fullscreen");
|
|
523
|
+
const e = this.shadowRoot.querySelector(".toggle-btn");
|
|
524
|
+
e.style.display = "", e.setAttribute("aria-expanded", "false");
|
|
505
525
|
}
|
|
506
526
|
_toggleFullscreen() {
|
|
507
527
|
this._isFullscreen = !this._isFullscreen;
|
|
@@ -519,14 +539,14 @@ const v = `/* ── Host element ───────────────
|
|
|
519
539
|
}
|
|
520
540
|
// ── Shadow DOM ─────────────────────────────────────────────────────────────
|
|
521
541
|
_buildShadow() {
|
|
522
|
-
var
|
|
542
|
+
var r;
|
|
523
543
|
const t = this.attachShadow({ mode: "open" }), e = document.createElement("style");
|
|
524
544
|
e.textContent = v, t.appendChild(e);
|
|
525
545
|
const n = document.createElement("div");
|
|
526
546
|
for (n.innerHTML = this._template(); n.firstChild; ) t.appendChild(n.firstChild);
|
|
527
547
|
t.querySelector(".toggle-btn").addEventListener("click", () => {
|
|
528
548
|
this._open ? this.close() : this.open();
|
|
529
|
-
}), this._iframeEl = t.querySelector(".chat-iframe"), (
|
|
549
|
+
}), this._iframeEl = t.querySelector(".chat-iframe"), (r = this._iframeEl) == null || r.addEventListener("load", () => {
|
|
530
550
|
this._pushAuthToIframe(), this._pushContextToIframe();
|
|
531
551
|
});
|
|
532
552
|
}
|
|
@@ -571,8 +591,8 @@ const v = `/* ── Host element ───────────────
|
|
|
571
591
|
const t = ((e = this._config) == null ? void 0 : e.iframeUrl) ?? "";
|
|
572
592
|
if (!t) return "";
|
|
573
593
|
try {
|
|
574
|
-
const n = new URL(t), { appId:
|
|
575
|
-
|
|
594
|
+
const n = new URL(t), { appId: r, appName: o, serviceUrl: i } = this._config;
|
|
595
|
+
r && n.searchParams.set("appId", r), o && n.searchParams.set("appName", o), i && n.searchParams.set("serviceUrl", i);
|
|
576
596
|
const a = d.resolve(this._config.token);
|
|
577
597
|
return a && n.searchParams.set("token", a), n.toString();
|
|
578
598
|
} catch {
|
|
@@ -593,14 +613,14 @@ const v = `/* ── Host element ───────────────
|
|
|
593
613
|
if (!((e = this._iframeEl) != null && e.contentWindow)) return;
|
|
594
614
|
const t = this._iframeOrigin();
|
|
595
615
|
this._config.autoContext ? g.captureAsync(this._buildBaseContext()).then((n) => {
|
|
596
|
-
var
|
|
597
|
-
(
|
|
616
|
+
var r, o;
|
|
617
|
+
(o = (r = this._iframeEl) == null ? void 0 : r.contentWindow) == null || o.postMessage(
|
|
598
618
|
{ type: "btp-copilot:set-context", payload: n },
|
|
599
619
|
t
|
|
600
620
|
), n.service_url && !this._config.serviceUrl && (this._config = { ...this._config, serviceUrl: n.service_url });
|
|
601
621
|
}).catch(() => {
|
|
602
|
-
var n,
|
|
603
|
-
(
|
|
622
|
+
var n, r;
|
|
623
|
+
(r = (n = this._iframeEl) == null ? void 0 : n.contentWindow) == null || r.postMessage(
|
|
604
624
|
{ type: "btp-copilot:set-context", payload: this._buildBaseContext() },
|
|
605
625
|
t
|
|
606
626
|
);
|
|
@@ -655,11 +675,11 @@ const v = `/* ── Host element ───────────────
|
|
|
655
675
|
return t.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
656
676
|
}
|
|
657
677
|
};
|
|
658
|
-
|
|
659
|
-
let
|
|
660
|
-
customElements.get("btp-copilot") || customElements.define("btp-copilot",
|
|
678
|
+
y.observedAttributes = [...x];
|
|
679
|
+
let _ = y;
|
|
680
|
+
customElements.get("btp-copilot") || customElements.define("btp-copilot", _);
|
|
661
681
|
export {
|
|
662
|
-
|
|
682
|
+
_ as BtpCopilotElement,
|
|
663
683
|
g as ContextBridge
|
|
664
684
|
};
|
|
665
685
|
//# sourceMappingURL=btp-copilot.esm.js.map
|
|
@@ -1 +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, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\");\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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"}
|
|
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 // ── SAP-specific probes (no-ops on non-SAP apps) ──────────────────────────\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 // ── Generic web context (works for any app) ───────────────────────────────\n // current_view: full path + search + hash (more useful than hash alone)\n try {\n const fullPath =\n window.location.pathname +\n window.location.search +\n window.location.hash;\n if (!ctx.current_view || ctx.current_view === \"\") {\n ctx.current_view = fullPath;\n }\n } catch {}\n\n // locale fallback\n try {\n if (!ctx.user_locale) {\n ctx.user_locale =\n navigator.language || (navigator as any).languages?.[0] || \"en\";\n }\n } catch {}\n\n // page_title and page_url give the LLM meaningful screen context\n try {\n ctx.extra = {\n ...(ctx.extra ?? {}),\n page_title:\n (ctx.extra as any)?.page_title ?? document.title ?? \"\",\n page_url:\n (ctx.extra as any)?.page_url ?? window.location.href ?? \"\",\n };\n } catch {}\n\n // ── Host-app injected context (highest priority) ──────────────────────────\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 this._isFullscreen = false;\n const panel = this.shadowRoot!.querySelector(\".panel\")!;\n panel.classList.add(\"closed\");\n panel.classList.remove(\"fullscreen\");\n const fab = this.shadowRoot!.querySelector(\".toggle-btn\") as HTMLElement;\n fab.style.display = \"\"; // always restore FAB — covers minimize-from-fullscreen\n fab.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, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\");\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","fullPath","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/dist/btp-copilot.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
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
|
|
2
|
-
`)})}return t.length>0&&n.push({title:"Available OData entity sets",content:[`OData service: ${e}`,`Entities: ${t.map(
|
|
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
|
|
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 r=localStorage.getItem("access_token");if(r)return r}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,...r]=e.trim().split("=");if(m.XSUAA_COOKIE_NAMES.includes(n.trim()))return decodeURIComponent(r.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,r;try{const o=(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(o){const i=(r=o.hrefForExternal)==null?void 0:r.call(o);if(i)return i}}catch(o){console.log(o)}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,r,o,i;try{return((i=(o=(r=(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:r.call(n))==null?void 0:o.getLanguageTag)==null?void 0:i.call(o))??navigator.language??"en"}catch{return navigator.language??"en"}}}class u{static getCurrentEntity(){var t,e,n,r;try{const o=(e=(t=sap==null?void 0:sap.ui)==null?void 0:t.getCore)==null?void 0:e.call(t);if(!o)return null;let i=document.activeElement;for(;i;){const a=i.getAttribute("id")||i.getAttribute("data-sap-ui");if(a){const s=o.byId(a),l=(n=s==null?void 0:s.getBindingContext)==null?void 0:n.call(s);if(l){const p=(r=l.getObject)==null?void 0:r.call(l);if(p&&typeof p=="object")return u._sanitize(p)}}i=i.parentElement}return u._scanAllControls(o)}catch{return null}}static _scanAllControls(t){var e,n;try{const r=t.mElements??{};for(const o of Object.keys(r)){const i=r[o],a=(e=i==null?void 0:i.getBindingContext)==null?void 0:e.call(i);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 r=n.mElements??{};for(const o of Object.keys(r)){const i=r[o];if(!(i!=null&&i.getModel))continue;const a=i.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,r]of Object.entries(t))n.startsWith("__")||(r===null||typeof r!="object"?e[n]=r:r.__deferred||(e[n]=r));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 r=sessionStorage.getItem(n);if(r)try{const o=JSON.parse(r);return c._cache.set(n,o),o}catch{}try{const o=`${t}/$metadata`,i={Accept:"application/xml"};e&&(i.Authorization=`Bearer ${e}`);const a=await fetch(o,{headers:i});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 r=new DOMParser().parseFromString(t,"text/xml").querySelectorAll("EntityType");return Array.from(r).map(o=>{const i=o.getAttribute("Name")??"",a=o.querySelectorAll("Key > PropertyRef"),s=new Set(Array.from(a).map(h=>h.getAttribute("Name")??"")),l=Array.from(o.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(o.querySelectorAll("NavigationProperty")).map(h=>({name:h.getAttribute("Name")??"",type:c._shortType(h.getAttribute("Type")??h.getAttribute("ToRole")??"")}));return{name:i,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 r of t){if(!r.name)continue;const o=r.properties.filter(s=>s.isKey),i=r.properties.filter(s=>!s.isKey),a=[`Entity: ${r.name}`,`OData service: ${e}`,`Entity set path: ${e}/${r.name}`,`Count path: ${e}/${r.name}/$count`];o.length&&a.push(`Key fields: ${o.map(s=>`${s.name} (${s.type})`).join(", ")}`),i.length&&a.push(`Fields: ${i.map(s=>`${s.name} (${s.type}${s.nullable?"":", required"})`).join(", ")}`),r.navProperties.length&&a.push(`Navigation: ${r.navProperties.map(s=>`${s.name} → ${s.type}`).join(", ")}`),n.push({title:`${r.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(r=>r.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){var n,r,o;const e={...t};try{const i=b.getHash();i&&(e.current_view=i)}catch{}try{const i=u.getCurrentEntity();i&&Object.keys(i).length>0&&(e.entity_data=i)}catch{}try{e.user_locale||(e.user_locale=b.getUserLocale())}catch{}try{const i=window.location.pathname+window.location.search+window.location.hash;(!e.current_view||e.current_view==="")&&(e.current_view=i)}catch{}try{e.user_locale||(e.user_locale=navigator.language||((n=navigator.languages)==null?void 0:n[0])||"en")}catch{}try{e.extra={...e.extra??{},page_title:((r=e.extra)==null?void 0:r.page_title)??document.title??"",page_url:((o=e.extra)==null?void 0:o.page_url)??window.location.href??""}}catch{}try{const i=window.__APP_CONTEXT__;i&&(i.entity_data&&(e.entity_data={...i.entity_data,...e.entity_data}),i.current_view&&!e.current_view&&(e.current_view=i.current_view),i.extra&&(e.extra={...i.extra,...e.extra??{}}),i.service_url&&!e.service_url&&(e.service_url=i.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 r=((n=e.extra)==null?void 0:n.auth_token)??null,o=await _.fetchSchemaDocuments(e.service_url,r);if(o.length>0){const i=o.map(a=>`## ${a.title}
|
|
4
4
|
${a.content}`).join(`
|
|
5
5
|
|
|
6
|
-
`);e.extra={...e.extra??{},schema_hint:
|
|
6
|
+
`);e.extra={...e.extra??{},schema_hint:i}}}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(),r=((t=n==null?void 0:n["sap.app"])==null?void 0:t.dataSources)??{};for(const o of Object.keys(r)){const i=r[o];if((i==null?void 0:i.type)==="ODataAnnotation")continue;const a=i==null?void 0:i.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,r){const o=i=>{if(!i.data||typeof i.data!="object")return;const{type:a,payload:s,text:l}=i.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":r();break}};return window.addEventListener("message",o),()=>window.removeEventListener("message",o)}}const w=`/* ── Host element ─────────────────────────────────────────────────────────── */
|
|
7
7
|
:host {
|
|
8
8
|
position: fixed;
|
|
9
9
|
z-index: 2147483647;
|
|
@@ -130,7 +130,7 @@ ${a.content}`).join(`
|
|
|
130
130
|
}
|
|
131
131
|
.chat-iframe { border-radius: 1rem 1rem 0 0; }
|
|
132
132
|
}
|
|
133
|
-
`,
|
|
133
|
+
`,x=["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,this._isFullscreen=!1;const t=this.shadowRoot.querySelector(".panel");t.classList.add("closed"),t.classList.remove("fullscreen");const e=this.shadowRoot.querySelector(".toggle-btn");e.style.display="",e.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 r;const t=this.attachShadow({mode:"open"}),e=document.createElement("style");e.textContent=w,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"),(r=this._iframeEl)==null||r.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
134
|
<button class="toggle-btn ${t}" aria-label="Open AI assistant" aria-expanded="false" aria-haspopup="dialog">
|
|
135
135
|
<svg class="icon-chat" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
136
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"/>
|
|
@@ -149,5 +149,5 @@ ${a.content}`).join(`
|
|
|
149
149
|
allow="clipboard-read; clipboard-write"
|
|
150
150
|
loading="lazy">
|
|
151
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:
|
|
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:r,appName:o,serviceUrl:i}=this._config;r&&n.searchParams.set("appId",r),o&&n.searchParams.set("appName",o),i&&n.searchParams.set("serviceUrl",i);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 r,o;(o=(r=this._iframeEl)==null?void 0:r.contentWindow)==null||o.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,r;(r=(n=this._iframeEl)==null?void 0:n.contentWindow)==null||r.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=w);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,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}};v.observedAttributes=[...x];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
153
|
//# sourceMappingURL=btp-copilot.js.map
|
package/dist/btp-copilot.js.map
CHANGED
|
@@ -1 +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, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\");\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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"}
|
|
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 // ── SAP-specific probes (no-ops on non-SAP apps) ──────────────────────────\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 // ── Generic web context (works for any app) ───────────────────────────────\n // current_view: full path + search + hash (more useful than hash alone)\n try {\n const fullPath =\n window.location.pathname +\n window.location.search +\n window.location.hash;\n if (!ctx.current_view || ctx.current_view === \"\") {\n ctx.current_view = fullPath;\n }\n } catch {}\n\n // locale fallback\n try {\n if (!ctx.user_locale) {\n ctx.user_locale =\n navigator.language || (navigator as any).languages?.[0] || \"en\";\n }\n } catch {}\n\n // page_title and page_url give the LLM meaningful screen context\n try {\n ctx.extra = {\n ...(ctx.extra ?? {}),\n page_title:\n (ctx.extra as any)?.page_title ?? document.title ?? \"\",\n page_url:\n (ctx.extra as any)?.page_url ?? window.location.href ?? \"\",\n };\n } catch {}\n\n // ── Host-app injected context (highest priority) ──────────────────────────\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 this._isFullscreen = false;\n const panel = this.shadowRoot!.querySelector(\".panel\")!;\n panel.classList.add(\"closed\");\n panel.classList.remove(\"fullscreen\");\n const fab = this.shadowRoot!.querySelector(\".toggle-btn\") as HTMLElement;\n fab.style.display = \"\"; // always restore FAB — covers minimize-from-fullscreen\n fab.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, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\");\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","fullPath","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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"}
|