@bikdotai/bik-component-library 0.0.862 → 0.0.863-beta.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/cjs/components/bik-copilot/BIKCopilot.js +2 -0
- package/dist/cjs/components/bik-copilot/BIKCopilot.js.map +1 -0
- package/dist/cjs/components/bik-copilot/ControlledCopilot.js +2 -0
- package/dist/cjs/components/bik-copilot/ControlledCopilot.js.map +1 -0
- package/dist/cjs/components/bik-copilot/ControlledCopilot.styled.js +27 -0
- package/dist/cjs/components/bik-copilot/ControlledCopilot.styled.js.map +1 -0
- package/dist/cjs/components/bik-copilot/CopilotBall.js +2 -0
- package/dist/cjs/components/bik-copilot/CopilotBall.js.map +1 -0
- package/dist/cjs/components/bik-copilot/CopilotBall.styled.js +42 -0
- package/dist/cjs/components/bik-copilot/CopilotBall.styled.js.map +1 -0
- package/dist/cjs/components/bik-copilot/CopilotPanel.js +2 -0
- package/dist/cjs/components/bik-copilot/CopilotPanel.js.map +1 -0
- package/dist/cjs/components/bik-copilot/CopilotPanel.styled.js +460 -0
- package/dist/cjs/components/bik-copilot/CopilotPanel.styled.js.map +1 -0
- package/dist/cjs/components/bik-copilot/copilotPlacement.js +2 -0
- package/dist/cjs/components/bik-copilot/copilotPlacement.js.map +1 -0
- package/dist/cjs/components/bik-copilot/services/copilotDb.js +2 -0
- package/dist/cjs/components/bik-copilot/services/copilotDb.js.map +1 -0
- package/dist/cjs/components/bik-copilot/services/copilotIcebreakersClient.js +2 -0
- package/dist/cjs/components/bik-copilot/services/copilotIcebreakersClient.js.map +1 -0
- package/dist/cjs/components/bik-copilot/services/copilotMessagesClient.js +2 -0
- package/dist/cjs/components/bik-copilot/services/copilotMessagesClient.js.map +1 -0
- package/dist/cjs/components/bik-copilot/services/copilotPageSession.js +2 -0
- package/dist/cjs/components/bik-copilot/services/copilotPageSession.js.map +1 -0
- package/dist/cjs/components/bik-copilot/services/copilotSseParser.js +7 -0
- package/dist/cjs/components/bik-copilot/services/copilotSseParser.js.map +1 -0
- package/dist/cjs/components/bik-copilot/services/copilotStreamClient.js +2 -0
- package/dist/cjs/components/bik-copilot/services/copilotStreamClient.js.map +1 -0
- package/dist/cjs/components/bik-copilot/useCopilotIcebreakers.js +2 -0
- package/dist/cjs/components/bik-copilot/useCopilotIcebreakers.js.map +1 -0
- package/dist/cjs/components/bik-copilot/useCopilotStreamChat.js +2 -0
- package/dist/cjs/components/bik-copilot/useCopilotStreamChat.js.map +1 -0
- package/dist/cjs/components/bik-copilot/useDraggableFloater.js +2 -0
- package/dist/cjs/components/bik-copilot/useDraggableFloater.js.map +1 -0
- package/dist/cjs/index.js +1 -1
- package/dist/esm/components/bik-copilot/BIKCopilot.d.ts +32 -0
- package/dist/esm/components/bik-copilot/BIKCopilot.js +114 -0
- package/dist/esm/components/bik-copilot/BIKCopilot.js.map +1 -0
- package/dist/esm/components/bik-copilot/ControlledCopilot.d.ts +14 -0
- package/dist/esm/components/bik-copilot/ControlledCopilot.js +170 -0
- package/dist/esm/components/bik-copilot/ControlledCopilot.js.map +1 -0
- package/dist/esm/components/bik-copilot/ControlledCopilot.styled.d.ts +7 -0
- package/dist/esm/components/bik-copilot/ControlledCopilot.styled.js +31 -0
- package/dist/esm/components/bik-copilot/ControlledCopilot.styled.js.map +1 -0
- package/dist/esm/components/bik-copilot/CopilotBall.d.ts +13 -0
- package/dist/esm/components/bik-copilot/CopilotBall.js +50 -0
- package/dist/esm/components/bik-copilot/CopilotBall.js.map +1 -0
- package/dist/esm/components/bik-copilot/CopilotBall.styled.d.ts +9 -0
- package/dist/esm/components/bik-copilot/CopilotBall.styled.js +46 -0
- package/dist/esm/components/bik-copilot/CopilotBall.styled.js.map +1 -0
- package/dist/esm/components/bik-copilot/CopilotPanel.d.ts +9 -0
- package/dist/esm/components/bik-copilot/CopilotPanel.js +379 -0
- package/dist/esm/components/bik-copilot/CopilotPanel.js.map +1 -0
- package/dist/esm/components/bik-copilot/CopilotPanel.styled.d.ts +64 -0
- package/dist/esm/components/bik-copilot/CopilotPanel.styled.js +496 -0
- package/dist/esm/components/bik-copilot/CopilotPanel.styled.js.map +1 -0
- package/dist/esm/components/bik-copilot/copilotPlacement.d.ts +24 -0
- package/dist/esm/components/bik-copilot/copilotPlacement.js +38 -0
- package/dist/esm/components/bik-copilot/copilotPlacement.js.map +1 -0
- package/dist/esm/components/bik-copilot/index.d.ts +16 -0
- package/dist/esm/components/bik-copilot/model.d.ts +674 -0
- package/dist/esm/components/bik-copilot/services/copilotDb.d.ts +90 -0
- package/dist/esm/components/bik-copilot/services/copilotDb.js +96 -0
- package/dist/esm/components/bik-copilot/services/copilotDb.js.map +1 -0
- package/dist/esm/components/bik-copilot/services/copilotIcebreakersClient.d.ts +11 -0
- package/dist/esm/components/bik-copilot/services/copilotIcebreakersClient.js +54 -0
- package/dist/esm/components/bik-copilot/services/copilotIcebreakersClient.js.map +1 -0
- package/dist/esm/components/bik-copilot/services/copilotMessagesClient.d.ts +23 -0
- package/dist/esm/components/bik-copilot/services/copilotMessagesClient.js +78 -0
- package/dist/esm/components/bik-copilot/services/copilotMessagesClient.js.map +1 -0
- package/dist/esm/components/bik-copilot/services/copilotPageSession.d.ts +37 -0
- package/dist/esm/components/bik-copilot/services/copilotPageSession.js +35 -0
- package/dist/esm/components/bik-copilot/services/copilotPageSession.js.map +1 -0
- package/dist/esm/components/bik-copilot/services/copilotSseParser.d.ts +22 -0
- package/dist/esm/components/bik-copilot/services/copilotSseParser.js +52 -0
- package/dist/esm/components/bik-copilot/services/copilotSseParser.js.map +1 -0
- package/dist/esm/components/bik-copilot/services/copilotStreamClient.d.ts +31 -0
- package/dist/esm/components/bik-copilot/services/copilotStreamClient.js +103 -0
- package/dist/esm/components/bik-copilot/services/copilotStreamClient.js.map +1 -0
- package/dist/esm/components/bik-copilot/useCopilotIcebreakers.d.ts +17 -0
- package/dist/esm/components/bik-copilot/useCopilotIcebreakers.js +60 -0
- package/dist/esm/components/bik-copilot/useCopilotIcebreakers.js.map +1 -0
- package/dist/esm/components/bik-copilot/useCopilotStreamChat.d.ts +20 -0
- package/dist/esm/components/bik-copilot/useCopilotStreamChat.js +333 -0
- package/dist/esm/components/bik-copilot/useCopilotStreamChat.js.map +1 -0
- package/dist/esm/components/bik-copilot/useDraggableFloater.d.ts +9 -0
- package/dist/esm/components/bik-copilot/useDraggableFloater.js +118 -0
- package/dist/esm/components/bik-copilot/useDraggableFloater.js.map +1 -0
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +832 -782
- package/dist/esm/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,460 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("styled-components"),e=require("../../constants/Theme.js"),r=n=>n&&typeof n=="object"&&"default"in n?n:{default:n},t=r(o),a=t.default.div`
|
|
2
|
+
display: flex;
|
|
3
|
+
flex-direction: column;
|
|
4
|
+
min-height: 0;
|
|
5
|
+
overflow: hidden;
|
|
6
|
+
background: ${e.COLORS.surface.standard};
|
|
7
|
+
border: 1px solid ${e.COLORS.stroke.primary};
|
|
8
|
+
border-radius: 16px;
|
|
9
|
+
box-shadow: 0 16px 48px rgba(40, 3, 78, 0.18);
|
|
10
|
+
`,i=t.default.div`
|
|
11
|
+
display: flex;
|
|
12
|
+
align-items: flex-start;
|
|
13
|
+
gap: 10px;
|
|
14
|
+
padding: 12px 12px 12px 16px;
|
|
15
|
+
border-bottom: 1px solid ${e.COLORS.stroke.primary};
|
|
16
|
+
flex-shrink: 0;
|
|
17
|
+
`,d=t.default.div`
|
|
18
|
+
width: 32px;
|
|
19
|
+
height: 32px;
|
|
20
|
+
flex-shrink: 0;
|
|
21
|
+
border-radius: 8px;
|
|
22
|
+
background: ${e.COLORS.background.base};
|
|
23
|
+
display: flex;
|
|
24
|
+
align-items: center;
|
|
25
|
+
justify-content: center;
|
|
26
|
+
color: ${e.COLORS.content.brand};
|
|
27
|
+
overflow: hidden;
|
|
28
|
+
`,s=t.default.div`
|
|
29
|
+
display: flex;
|
|
30
|
+
flex-direction: column;
|
|
31
|
+
gap: 2px;
|
|
32
|
+
min-width: 0;
|
|
33
|
+
flex: 1;
|
|
34
|
+
`,l=t.default.div`
|
|
35
|
+
display: flex;
|
|
36
|
+
align-items: center;
|
|
37
|
+
gap: 6px;
|
|
38
|
+
`,p=t.default.span`
|
|
39
|
+
padding: 1px 6px;
|
|
40
|
+
border-radius: 4px;
|
|
41
|
+
background: ${e.COLORS.background.brandLight};
|
|
42
|
+
color: ${e.COLORS.content.brand};
|
|
43
|
+
font-size: 10px;
|
|
44
|
+
font-weight: 600;
|
|
45
|
+
line-height: 16px;
|
|
46
|
+
white-space: nowrap;
|
|
47
|
+
`,c=t.default.div`
|
|
48
|
+
display: flex;
|
|
49
|
+
align-items: center;
|
|
50
|
+
gap: 2px;
|
|
51
|
+
flex-shrink: 0;
|
|
52
|
+
`,x=t.default.button`
|
|
53
|
+
width: 28px;
|
|
54
|
+
height: 28px;
|
|
55
|
+
display: flex;
|
|
56
|
+
align-items: center;
|
|
57
|
+
justify-content: center;
|
|
58
|
+
padding: 0;
|
|
59
|
+
border: none;
|
|
60
|
+
border-radius: 6px;
|
|
61
|
+
background: transparent;
|
|
62
|
+
color: ${e.COLORS.content.secondary};
|
|
63
|
+
cursor: pointer;
|
|
64
|
+
transition: background 0.15s ease, color 0.15s ease;
|
|
65
|
+
|
|
66
|
+
&:hover {
|
|
67
|
+
background: ${e.COLORS.surface.hovered};
|
|
68
|
+
color: ${e.COLORS.content.primary};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
&:focus-visible {
|
|
72
|
+
outline: 2px solid ${e.COLORS.stroke.brand};
|
|
73
|
+
outline-offset: 1px;
|
|
74
|
+
}
|
|
75
|
+
`,u=t.default.div`
|
|
76
|
+
position: relative;
|
|
77
|
+
flex: 1;
|
|
78
|
+
min-height: 0;
|
|
79
|
+
display: flex;
|
|
80
|
+
flex-direction: column;
|
|
81
|
+
`,f=t.default.div`
|
|
82
|
+
flex: 1;
|
|
83
|
+
min-height: 0;
|
|
84
|
+
overflow-y: auto;
|
|
85
|
+
padding: 16px;
|
|
86
|
+
display: flex;
|
|
87
|
+
flex-direction: column;
|
|
88
|
+
gap: 12px;
|
|
89
|
+
|
|
90
|
+
&::-webkit-scrollbar {
|
|
91
|
+
width: 6px;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
&::-webkit-scrollbar-thumb {
|
|
95
|
+
background: ${e.COLORS.background.inactive};
|
|
96
|
+
border-radius: 3px;
|
|
97
|
+
}
|
|
98
|
+
`,g=t.default.div`
|
|
99
|
+
position: absolute;
|
|
100
|
+
left: 0;
|
|
101
|
+
right: 0;
|
|
102
|
+
bottom: 0;
|
|
103
|
+
height: 72px;
|
|
104
|
+
pointer-events: none;
|
|
105
|
+
opacity: ${n=>n.$visible?1:0};
|
|
106
|
+
transition: opacity 0.2s ease;
|
|
107
|
+
background: linear-gradient(
|
|
108
|
+
to bottom,
|
|
109
|
+
${e.COLORS.surface.standard}00 0%,
|
|
110
|
+
${e.COLORS.surface.standard}B3 55%,
|
|
111
|
+
${e.COLORS.surface.standard} 100%
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
&::after {
|
|
115
|
+
content: '';
|
|
116
|
+
position: absolute;
|
|
117
|
+
inset: 0;
|
|
118
|
+
backdrop-filter: blur(2px);
|
|
119
|
+
-webkit-backdrop-filter: blur(2px);
|
|
120
|
+
mask-image: linear-gradient(to bottom, transparent 0%, #000 60%);
|
|
121
|
+
-webkit-mask-image: linear-gradient(to bottom, transparent 0%, #000 60%);
|
|
122
|
+
}
|
|
123
|
+
`,b=t.default.button`
|
|
124
|
+
position: absolute;
|
|
125
|
+
left: 50%;
|
|
126
|
+
bottom: 12px;
|
|
127
|
+
transform: translateX(-50%)
|
|
128
|
+
translateY(${n=>n.$visible?"0":"6px"});
|
|
129
|
+
width: 28px;
|
|
130
|
+
height: 28px;
|
|
131
|
+
display: flex;
|
|
132
|
+
align-items: center;
|
|
133
|
+
justify-content: center;
|
|
134
|
+
padding: 0;
|
|
135
|
+
border: 1px solid ${e.COLORS.stroke.primary};
|
|
136
|
+
border-radius: 999px;
|
|
137
|
+
background: ${e.COLORS.surface.standard};
|
|
138
|
+
color: ${e.COLORS.content.secondary};
|
|
139
|
+
box-shadow: 0 2px 8px rgba(40, 3, 78, 0.16);
|
|
140
|
+
cursor: pointer;
|
|
141
|
+
opacity: ${n=>n.$visible?1:0};
|
|
142
|
+
/* Hidden to the pointer and to focus order while it is faded out. */
|
|
143
|
+
visibility: ${n=>n.$visible?"visible":"hidden"};
|
|
144
|
+
transition: opacity 0.2s ease, transform 0.2s ease, visibility 0.2s ease,
|
|
145
|
+
background 0.15s ease, color 0.15s ease;
|
|
146
|
+
|
|
147
|
+
&:hover {
|
|
148
|
+
background: ${e.COLORS.surface.hovered};
|
|
149
|
+
color: ${e.COLORS.content.primary};
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
&:focus-visible {
|
|
153
|
+
outline: 2px solid ${e.COLORS.stroke.brand};
|
|
154
|
+
outline-offset: 1px;
|
|
155
|
+
}
|
|
156
|
+
`,O=t.default.div`
|
|
157
|
+
flex: 1;
|
|
158
|
+
display: flex;
|
|
159
|
+
flex-direction: column;
|
|
160
|
+
align-items: center;
|
|
161
|
+
justify-content: center;
|
|
162
|
+
gap: 8px;
|
|
163
|
+
text-align: center;
|
|
164
|
+
padding: 8px 4px;
|
|
165
|
+
`,h=t.default.div`
|
|
166
|
+
color: ${e.COLORS.content.brand};
|
|
167
|
+
display: flex;
|
|
168
|
+
align-items: center;
|
|
169
|
+
justify-content: center;
|
|
170
|
+
margin-bottom: 4px;
|
|
171
|
+
`,m=t.default.div`
|
|
172
|
+
display: flex;
|
|
173
|
+
flex-direction: column;
|
|
174
|
+
align-items: center;
|
|
175
|
+
gap: 8px;
|
|
176
|
+
margin-top: 12px;
|
|
177
|
+
width: 100%;
|
|
178
|
+
`,y=t.default.button`
|
|
179
|
+
display: inline-flex;
|
|
180
|
+
align-items: center;
|
|
181
|
+
gap: 6px;
|
|
182
|
+
max-width: 100%;
|
|
183
|
+
padding: 8px 14px;
|
|
184
|
+
border: 1px solid ${e.COLORS.stroke.primary};
|
|
185
|
+
border-radius: 999px;
|
|
186
|
+
background: ${e.COLORS.surface.standard};
|
|
187
|
+
color: ${e.COLORS.content.primary};
|
|
188
|
+
font-family: Inter;
|
|
189
|
+
font-size: 13px;
|
|
190
|
+
line-height: 18px;
|
|
191
|
+
text-align: left;
|
|
192
|
+
cursor: pointer;
|
|
193
|
+
transition: border-color 0.15s ease, background 0.15s ease;
|
|
194
|
+
|
|
195
|
+
svg {
|
|
196
|
+
flex-shrink: 0;
|
|
197
|
+
color: ${e.COLORS.content.brand};
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
&:hover:not(:disabled) {
|
|
201
|
+
border-color: ${e.COLORS.stroke.brand};
|
|
202
|
+
background: ${e.COLORS.background.brandVeryLight};
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
&:disabled {
|
|
206
|
+
cursor: not-allowed;
|
|
207
|
+
opacity: 0.5;
|
|
208
|
+
}
|
|
209
|
+
`,L=t.default.div`
|
|
210
|
+
font-family: Inter;
|
|
211
|
+
font-size: 13px;
|
|
212
|
+
line-height: 20px;
|
|
213
|
+
word-break: break-word;
|
|
214
|
+
overflow-wrap: break-word;
|
|
215
|
+
|
|
216
|
+
${n=>n.$role==="user"?`
|
|
217
|
+
align-self: flex-end;
|
|
218
|
+
max-width: 85%;
|
|
219
|
+
padding: 10px 14px;
|
|
220
|
+
border-radius: 12px;
|
|
221
|
+
border-bottom-right-radius: 4px;
|
|
222
|
+
background: ${e.COLORS.background.brandLight};
|
|
223
|
+
color: ${e.COLORS.content.primary};
|
|
224
|
+
`:n.$role==="system"?`
|
|
225
|
+
align-self: center;
|
|
226
|
+
max-width: 90%;
|
|
227
|
+
padding: 6px 10px;
|
|
228
|
+
border-radius: 8px;
|
|
229
|
+
background: ${e.COLORS.surface.grey};
|
|
230
|
+
color: ${e.COLORS.content.secondary};
|
|
231
|
+
font-size: 12px;
|
|
232
|
+
text-align: center;
|
|
233
|
+
`:`
|
|
234
|
+
align-self: flex-start;
|
|
235
|
+
max-width: 90%;
|
|
236
|
+
padding: 10px 14px;
|
|
237
|
+
border-radius: 12px;
|
|
238
|
+
border-bottom-left-radius: 4px;
|
|
239
|
+
background: ${e.COLORS.surface.grey};
|
|
240
|
+
color: ${e.COLORS.content.primary};
|
|
241
|
+
border: 1px solid ${e.COLORS.stroke.primary};
|
|
242
|
+
`}
|
|
243
|
+
|
|
244
|
+
/* Markdown emitted by renderMarkdownLite */
|
|
245
|
+
h1,
|
|
246
|
+
h2,
|
|
247
|
+
h3,
|
|
248
|
+
h4 {
|
|
249
|
+
font-size: 14px;
|
|
250
|
+
font-weight: 600;
|
|
251
|
+
margin: 4px 0;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
pre {
|
|
255
|
+
background: ${e.COLORS.background.base};
|
|
256
|
+
border-radius: 6px;
|
|
257
|
+
padding: 8px;
|
|
258
|
+
margin: 6px 0;
|
|
259
|
+
overflow-x: auto;
|
|
260
|
+
font-size: 12px;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
a {
|
|
264
|
+
color: ${e.COLORS.content.brand};
|
|
265
|
+
}
|
|
266
|
+
`,k=t.default.div`
|
|
267
|
+
align-self: flex-start;
|
|
268
|
+
display: inline-flex;
|
|
269
|
+
align-items: center;
|
|
270
|
+
gap: 8px;
|
|
271
|
+
padding: 12px 14px;
|
|
272
|
+
border-radius: 12px;
|
|
273
|
+
border-bottom-left-radius: 4px;
|
|
274
|
+
background: ${e.COLORS.surface.grey};
|
|
275
|
+
border: 1px solid ${e.COLORS.stroke.primary};
|
|
276
|
+
`,S=t.default.div`
|
|
277
|
+
align-self: center;
|
|
278
|
+
display: inline-flex;
|
|
279
|
+
align-items: center;
|
|
280
|
+
gap: 8px;
|
|
281
|
+
padding: 4px 0;
|
|
282
|
+
font-family: Inter;
|
|
283
|
+
font-size: 11px;
|
|
284
|
+
line-height: 16px;
|
|
285
|
+
color: ${e.COLORS.content.placeholder};
|
|
286
|
+
`,$=t.default.div`
|
|
287
|
+
display: flex;
|
|
288
|
+
flex-direction: column;
|
|
289
|
+
align-items: stretch;
|
|
290
|
+
gap: 8px;
|
|
291
|
+
margin-top: 4px;
|
|
292
|
+
`,C=t.default.div`
|
|
293
|
+
font-family: Inter;
|
|
294
|
+
font-size: 11px;
|
|
295
|
+
line-height: 16px;
|
|
296
|
+
color: ${e.COLORS.content.placeholder};
|
|
297
|
+
`,R=t.default.button`
|
|
298
|
+
display: flex;
|
|
299
|
+
align-items: center;
|
|
300
|
+
gap: 8px;
|
|
301
|
+
width: 100%;
|
|
302
|
+
padding: 10px 14px;
|
|
303
|
+
border: 1px solid ${e.COLORS.stroke.primary};
|
|
304
|
+
border-radius: 10px;
|
|
305
|
+
background: ${e.COLORS.surface.standard};
|
|
306
|
+
color: ${e.COLORS.content.primary};
|
|
307
|
+
font-family: Inter;
|
|
308
|
+
font-size: 13px;
|
|
309
|
+
line-height: 18px;
|
|
310
|
+
text-align: left;
|
|
311
|
+
cursor: pointer;
|
|
312
|
+
transition: border-color 0.15s ease, background 0.15s ease;
|
|
313
|
+
|
|
314
|
+
svg {
|
|
315
|
+
flex-shrink: 0;
|
|
316
|
+
color: ${e.COLORS.content.secondary};
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
&:hover:not(:disabled) {
|
|
320
|
+
border-color: ${e.COLORS.stroke.brand};
|
|
321
|
+
background: ${e.COLORS.background.brandVeryLight};
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
&:disabled {
|
|
325
|
+
cursor: not-allowed;
|
|
326
|
+
opacity: 0.5;
|
|
327
|
+
}
|
|
328
|
+
`,v=t.default.div`
|
|
329
|
+
align-self: flex-start;
|
|
330
|
+
display: inline-flex;
|
|
331
|
+
align-items: center;
|
|
332
|
+
gap: 6px;
|
|
333
|
+
font-family: Inter;
|
|
334
|
+
font-size: 12px;
|
|
335
|
+
line-height: 18px;
|
|
336
|
+
color: ${e.COLORS.content.secondary};
|
|
337
|
+
|
|
338
|
+
svg {
|
|
339
|
+
flex-shrink: 0;
|
|
340
|
+
color: ${e.COLORS.content.inactive};
|
|
341
|
+
}
|
|
342
|
+
`,w=t.default.div`
|
|
343
|
+
align-self: flex-start;
|
|
344
|
+
display: flex;
|
|
345
|
+
align-items: center;
|
|
346
|
+
gap: 2px;
|
|
347
|
+
margin-top: -4px;
|
|
348
|
+
`,I=t.default.button`
|
|
349
|
+
display: inline-flex;
|
|
350
|
+
align-items: center;
|
|
351
|
+
gap: 4px;
|
|
352
|
+
height: 24px;
|
|
353
|
+
padding: 0 6px;
|
|
354
|
+
border: none;
|
|
355
|
+
border-radius: 6px;
|
|
356
|
+
background: transparent;
|
|
357
|
+
color: ${e.COLORS.content.placeholder};
|
|
358
|
+
font-family: Inter;
|
|
359
|
+
font-size: 11px;
|
|
360
|
+
line-height: 16px;
|
|
361
|
+
cursor: pointer;
|
|
362
|
+
transition: background 0.15s ease, color 0.15s ease;
|
|
363
|
+
|
|
364
|
+
svg {
|
|
365
|
+
flex-shrink: 0;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
&:hover {
|
|
369
|
+
background: ${e.COLORS.surface.hovered};
|
|
370
|
+
color: ${e.COLORS.content.secondary};
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
&:focus-visible {
|
|
374
|
+
outline: 2px solid ${e.COLORS.stroke.brand};
|
|
375
|
+
outline-offset: 1px;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/* Confirmation reads as success, not as another affordance. */
|
|
379
|
+
&[data-copied='true'],
|
|
380
|
+
&[data-copied='true']:hover {
|
|
381
|
+
color: ${e.COLORS.content.positive};
|
|
382
|
+
}
|
|
383
|
+
`,z=t.default.span`
|
|
384
|
+
font-family: Inter;
|
|
385
|
+
font-size: 13px;
|
|
386
|
+
line-height: 20px;
|
|
387
|
+
color: ${e.COLORS.content.secondary};
|
|
388
|
+
`,H=t.default.div`
|
|
389
|
+
margin: 0 16px;
|
|
390
|
+
padding: 8px 10px;
|
|
391
|
+
border-radius: 8px;
|
|
392
|
+
background: ${e.COLORS.background.negative.light};
|
|
393
|
+
color: ${e.COLORS.content.negative};
|
|
394
|
+
font-family: Inter;
|
|
395
|
+
font-size: 12px;
|
|
396
|
+
line-height: 18px;
|
|
397
|
+
flex-shrink: 0;
|
|
398
|
+
`,M=t.default.div`
|
|
399
|
+
padding: 12px 16px 4px;
|
|
400
|
+
flex-shrink: 0;
|
|
401
|
+
`,A=t.default.div`
|
|
402
|
+
display: flex;
|
|
403
|
+
align-items: flex-end;
|
|
404
|
+
gap: 8px;
|
|
405
|
+
padding: 8px 8px 8px 12px;
|
|
406
|
+
border: 1px solid
|
|
407
|
+
${n=>n.$focused?e.COLORS.stroke.brand:e.COLORS.stroke.primary};
|
|
408
|
+
border-radius: 12px;
|
|
409
|
+
background: ${e.COLORS.surface.standard};
|
|
410
|
+
transition: border-color 0.15s ease;
|
|
411
|
+
`,B=t.default.textarea`
|
|
412
|
+
flex: 1;
|
|
413
|
+
border: none;
|
|
414
|
+
outline: none;
|
|
415
|
+
resize: none;
|
|
416
|
+
background: transparent;
|
|
417
|
+
font-family: Inter;
|
|
418
|
+
font-size: 13px;
|
|
419
|
+
line-height: 20px;
|
|
420
|
+
color: ${e.COLORS.content.primary};
|
|
421
|
+
max-height: 96px;
|
|
422
|
+
min-height: 20px;
|
|
423
|
+
padding: 4px 0;
|
|
424
|
+
|
|
425
|
+
&::placeholder {
|
|
426
|
+
color: ${e.COLORS.content.placeholder};
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
&:disabled {
|
|
430
|
+
cursor: not-allowed;
|
|
431
|
+
}
|
|
432
|
+
`,T=t.default.button`
|
|
433
|
+
width: 28px;
|
|
434
|
+
height: 28px;
|
|
435
|
+
flex-shrink: 0;
|
|
436
|
+
display: flex;
|
|
437
|
+
align-items: center;
|
|
438
|
+
justify-content: center;
|
|
439
|
+
padding: 0;
|
|
440
|
+
border: none;
|
|
441
|
+
border-radius: 8px;
|
|
442
|
+
background: ${n=>n.$active?e.COLORS.background.brand:e.COLORS.background.brandLight};
|
|
443
|
+
color: ${n=>n.$active?e.COLORS.content.primaryInverse:e.COLORS.content.inactive};
|
|
444
|
+
cursor: ${n=>n.$active?"pointer":"not-allowed"};
|
|
445
|
+
transition: background 0.15s ease, color 0.15s ease;
|
|
446
|
+
|
|
447
|
+
&:focus-visible {
|
|
448
|
+
outline: 2px solid ${e.COLORS.stroke.brand};
|
|
449
|
+
outline-offset: 1px;
|
|
450
|
+
}
|
|
451
|
+
`,j=t.default.div`
|
|
452
|
+
padding: 6px 16px 12px;
|
|
453
|
+
text-align: center;
|
|
454
|
+
font-family: Inter;
|
|
455
|
+
font-size: 11px;
|
|
456
|
+
line-height: 16px;
|
|
457
|
+
color: ${e.COLORS.content.placeholder};
|
|
458
|
+
flex-shrink: 0;
|
|
459
|
+
`;exports.Disclaimer=j;exports.EmptyState=O;exports.EmptyStateIcon=h;exports.ErrorBanner=H;exports.FollowUpChip=R;exports.FollowUpList=$;exports.FollowUpsLabel=C;exports.HeaderActions=c;exports.HeaderAvatar=d;exports.HeaderBadge=p;exports.HeaderText=s;exports.HeaderTitleRow=l;exports.HistoryLoader=S;exports.IconAction=x;exports.InputArea=M;exports.InputWrapper=A;exports.InterruptedNote=v;exports.JumpToLatestButton=b;exports.MessageAction=I;exports.MessageActions=w;exports.MessageBubble=L;exports.MessageInput=B;exports.MessagesArea=f;exports.MessagesViewport=u;exports.PanelContainer=a;exports.PanelHeader=i;exports.ScrollFade=g;exports.SendButton=T;exports.SuggestionChip=y;exports.SuggestionList=m;exports.ThinkingBubble=k;exports.ThinkingLabel=z;
|
|
460
|
+
//# sourceMappingURL=CopilotPanel.styled.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CopilotPanel.styled.js","sources":["../../../../src/components/bik-copilot/CopilotPanel.styled.ts"],"sourcesContent":["import styled from 'styled-components';\nimport { COLORS } from '@src/constants/Theme';\n\nexport const PanelContainer = styled.div`\n\tdisplay: flex;\n\tflex-direction: column;\n\tmin-height: 0;\n\toverflow: hidden;\n\tbackground: ${COLORS.surface.standard};\n\tborder: 1px solid ${COLORS.stroke.primary};\n\tborder-radius: 16px;\n\tbox-shadow: 0 16px 48px rgba(40, 3, 78, 0.18);\n`;\n\nexport const PanelHeader = styled.div`\n\tdisplay: flex;\n\talign-items: flex-start;\n\tgap: 10px;\n\tpadding: 12px 12px 12px 16px;\n\tborder-bottom: 1px solid ${COLORS.stroke.primary};\n\tflex-shrink: 0;\n`;\n\nexport const HeaderAvatar = styled.div`\n\twidth: 32px;\n\theight: 32px;\n\tflex-shrink: 0;\n\tborder-radius: 8px;\n\tbackground: ${COLORS.background.base};\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\tcolor: ${COLORS.content.brand};\n\toverflow: hidden;\n`;\n\nexport const HeaderText = styled.div`\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 2px;\n\tmin-width: 0;\n\tflex: 1;\n`;\n\nexport const HeaderTitleRow = styled.div`\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 6px;\n`;\n\nexport const HeaderBadge = styled.span`\n\tpadding: 1px 6px;\n\tborder-radius: 4px;\n\tbackground: ${COLORS.background.brandLight};\n\tcolor: ${COLORS.content.brand};\n\tfont-size: 10px;\n\tfont-weight: 600;\n\tline-height: 16px;\n\twhite-space: nowrap;\n`;\n\nexport const HeaderActions = styled.div`\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 2px;\n\tflex-shrink: 0;\n`;\n\nexport const IconAction = styled.button`\n\twidth: 28px;\n\theight: 28px;\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\tpadding: 0;\n\tborder: none;\n\tborder-radius: 6px;\n\tbackground: transparent;\n\tcolor: ${COLORS.content.secondary};\n\tcursor: pointer;\n\ttransition: background 0.15s ease, color 0.15s ease;\n\n\t&:hover {\n\t\tbackground: ${COLORS.surface.hovered};\n\t\tcolor: ${COLORS.content.primary};\n\t}\n\n\t&:focus-visible {\n\t\toutline: 2px solid ${COLORS.stroke.brand};\n\t\toutline-offset: 1px;\n\t}\n`;\n\n/**\n * Wraps the scroller so the bottom fade and the jump-to-latest button can be\n * absolutely positioned over it.\n */\nexport const MessagesViewport = styled.div`\n\tposition: relative;\n\tflex: 1;\n\tmin-height: 0;\n\tdisplay: flex;\n\tflex-direction: column;\n`;\n\nexport const MessagesArea = styled.div`\n\tflex: 1;\n\tmin-height: 0;\n\toverflow-y: auto;\n\tpadding: 16px;\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 12px;\n\n\t&::-webkit-scrollbar {\n\t\twidth: 6px;\n\t}\n\n\t&::-webkit-scrollbar-thumb {\n\t\tbackground: ${COLORS.background.inactive};\n\t\tborder-radius: 3px;\n\t}\n`;\n\n/**\n * Softens the cut-off edge of a long answer the reader has scrolled up from, so\n * the clipped line reads as continuing rather than as the end of the message.\n *\n * Two layers, because one element cannot ramp a gradient and a blur\n * independently: the element itself whitens the text out, and `::after` lays a\n * masked blur over it that strengthens towards the bottom. Browsers without\n * `backdrop-filter` still get the fade.\n */\nexport const ScrollFade = styled.div<{ $visible: boolean }>`\n\tposition: absolute;\n\tleft: 0;\n\tright: 0;\n\tbottom: 0;\n\theight: 72px;\n\tpointer-events: none;\n\topacity: ${(props) => (props.$visible ? 1 : 0)};\n\ttransition: opacity 0.2s ease;\n\tbackground: linear-gradient(\n\t\tto bottom,\n\t\t${COLORS.surface.standard}00 0%,\n\t\t${COLORS.surface.standard}B3 55%,\n\t\t${COLORS.surface.standard} 100%\n\t);\n\n\t&::after {\n\t\tcontent: '';\n\t\tposition: absolute;\n\t\tinset: 0;\n\t\tbackdrop-filter: blur(2px);\n\t\t-webkit-backdrop-filter: blur(2px);\n\t\tmask-image: linear-gradient(to bottom, transparent 0%, #000 60%);\n\t\t-webkit-mask-image: linear-gradient(to bottom, transparent 0%, #000 60%);\n\t}\n`;\n\nexport const JumpToLatestButton = styled.button<{ $visible: boolean }>`\n\tposition: absolute;\n\tleft: 50%;\n\tbottom: 12px;\n\ttransform: translateX(-50%)\n\t\ttranslateY(${(props) => (props.$visible ? '0' : '6px')});\n\twidth: 28px;\n\theight: 28px;\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\tpadding: 0;\n\tborder: 1px solid ${COLORS.stroke.primary};\n\tborder-radius: 999px;\n\tbackground: ${COLORS.surface.standard};\n\tcolor: ${COLORS.content.secondary};\n\tbox-shadow: 0 2px 8px rgba(40, 3, 78, 0.16);\n\tcursor: pointer;\n\topacity: ${(props) => (props.$visible ? 1 : 0)};\n\t/* Hidden to the pointer and to focus order while it is faded out. */\n\tvisibility: ${(props) => (props.$visible ? 'visible' : 'hidden')};\n\ttransition: opacity 0.2s ease, transform 0.2s ease, visibility 0.2s ease,\n\t\tbackground 0.15s ease, color 0.15s ease;\n\n\t&:hover {\n\t\tbackground: ${COLORS.surface.hovered};\n\t\tcolor: ${COLORS.content.primary};\n\t}\n\n\t&:focus-visible {\n\t\toutline: 2px solid ${COLORS.stroke.brand};\n\t\toutline-offset: 1px;\n\t}\n`;\n\nexport const EmptyState = styled.div`\n\tflex: 1;\n\tdisplay: flex;\n\tflex-direction: column;\n\talign-items: center;\n\tjustify-content: center;\n\tgap: 8px;\n\ttext-align: center;\n\tpadding: 8px 4px;\n`;\n\nexport const EmptyStateIcon = styled.div`\n\tcolor: ${COLORS.content.brand};\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\tmargin-bottom: 4px;\n`;\n\nexport const SuggestionList = styled.div`\n\tdisplay: flex;\n\tflex-direction: column;\n\talign-items: center;\n\tgap: 8px;\n\tmargin-top: 12px;\n\twidth: 100%;\n`;\n\nexport const SuggestionChip = styled.button`\n\tdisplay: inline-flex;\n\talign-items: center;\n\tgap: 6px;\n\tmax-width: 100%;\n\tpadding: 8px 14px;\n\tborder: 1px solid ${COLORS.stroke.primary};\n\tborder-radius: 999px;\n\tbackground: ${COLORS.surface.standard};\n\tcolor: ${COLORS.content.primary};\n\tfont-family: Inter;\n\tfont-size: 13px;\n\tline-height: 18px;\n\ttext-align: left;\n\tcursor: pointer;\n\ttransition: border-color 0.15s ease, background 0.15s ease;\n\n\tsvg {\n\t\tflex-shrink: 0;\n\t\tcolor: ${COLORS.content.brand};\n\t}\n\n\t&:hover:not(:disabled) {\n\t\tborder-color: ${COLORS.stroke.brand};\n\t\tbackground: ${COLORS.background.brandVeryLight};\n\t}\n\n\t&:disabled {\n\t\tcursor: not-allowed;\n\t\topacity: 0.5;\n\t}\n`;\n\nexport const MessageBubble = styled.div<{\n\t$role: 'user' | 'assistant' | 'system';\n}>`\n\tfont-family: Inter;\n\tfont-size: 13px;\n\tline-height: 20px;\n\tword-break: break-word;\n\toverflow-wrap: break-word;\n\n\t${(props) => {\n\t\tif (props.$role === 'user') {\n\t\t\treturn `\n\t\t\t\talign-self: flex-end;\n\t\t\t\tmax-width: 85%;\n\t\t\t\tpadding: 10px 14px;\n\t\t\t\tborder-radius: 12px;\n\t\t\t\tborder-bottom-right-radius: 4px;\n\t\t\t\tbackground: ${COLORS.background.brandLight};\n\t\t\t\tcolor: ${COLORS.content.primary};\n\t\t\t`;\n\t\t}\n\t\tif (props.$role === 'system') {\n\t\t\treturn `\n\t\t\t\talign-self: center;\n\t\t\t\tmax-width: 90%;\n\t\t\t\tpadding: 6px 10px;\n\t\t\t\tborder-radius: 8px;\n\t\t\t\tbackground: ${COLORS.surface.grey};\n\t\t\t\tcolor: ${COLORS.content.secondary};\n\t\t\t\tfont-size: 12px;\n\t\t\t\ttext-align: center;\n\t\t\t`;\n\t\t}\n\t\treturn `\n\t\t\talign-self: flex-start;\n\t\t\tmax-width: 90%;\n\t\t\tpadding: 10px 14px;\n\t\t\tborder-radius: 12px;\n\t\t\tborder-bottom-left-radius: 4px;\n\t\t\tbackground: ${COLORS.surface.grey};\n\t\t\tcolor: ${COLORS.content.primary};\n\t\t\tborder: 1px solid ${COLORS.stroke.primary};\n\t\t`;\n\t}}\n\n\t/* Markdown emitted by renderMarkdownLite */\n\th1,\n\th2,\n\th3,\n\th4 {\n\t\tfont-size: 14px;\n\t\tfont-weight: 600;\n\t\tmargin: 4px 0;\n\t}\n\n\tpre {\n\t\tbackground: ${COLORS.background.base};\n\t\tborder-radius: 6px;\n\t\tpadding: 8px;\n\t\tmargin: 6px 0;\n\t\toverflow-x: auto;\n\t\tfont-size: 12px;\n\t}\n\n\ta {\n\t\tcolor: ${COLORS.content.brand};\n\t}\n`;\n\nexport const ThinkingBubble = styled.div`\n\talign-self: flex-start;\n\tdisplay: inline-flex;\n\talign-items: center;\n\tgap: 8px;\n\tpadding: 12px 14px;\n\tborder-radius: 12px;\n\tborder-bottom-left-radius: 4px;\n\tbackground: ${COLORS.surface.grey};\n\tborder: 1px solid ${COLORS.stroke.primary};\n`;\n\n/** Sits above the oldest message while the page before it is fetched. */\nexport const HistoryLoader = styled.div`\n\talign-self: center;\n\tdisplay: inline-flex;\n\talign-items: center;\n\tgap: 8px;\n\tpadding: 4px 0;\n\tfont-family: Inter;\n\tfont-size: 11px;\n\tline-height: 16px;\n\tcolor: ${COLORS.content.placeholder};\n`;\n\nexport const FollowUpList = styled.div`\n\tdisplay: flex;\n\tflex-direction: column;\n\talign-items: stretch;\n\tgap: 8px;\n\tmargin-top: 4px;\n`;\n\nexport const FollowUpsLabel = styled.div`\n\tfont-family: Inter;\n\tfont-size: 11px;\n\tline-height: 16px;\n\tcolor: ${COLORS.content.placeholder};\n`;\n\nexport const FollowUpChip = styled.button`\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 8px;\n\twidth: 100%;\n\tpadding: 10px 14px;\n\tborder: 1px solid ${COLORS.stroke.primary};\n\tborder-radius: 10px;\n\tbackground: ${COLORS.surface.standard};\n\tcolor: ${COLORS.content.primary};\n\tfont-family: Inter;\n\tfont-size: 13px;\n\tline-height: 18px;\n\ttext-align: left;\n\tcursor: pointer;\n\ttransition: border-color 0.15s ease, background 0.15s ease;\n\n\tsvg {\n\t\tflex-shrink: 0;\n\t\tcolor: ${COLORS.content.secondary};\n\t}\n\n\t&:hover:not(:disabled) {\n\t\tborder-color: ${COLORS.stroke.brand};\n\t\tbackground: ${COLORS.background.brandVeryLight};\n\t}\n\n\t&:disabled {\n\t\tcursor: not-allowed;\n\t\topacity: 0.5;\n\t}\n`;\n\n/**\n * Bubble-less on purpose: a stopped reply is a note about the transcript, not a\n * message in it.\n */\nexport const InterruptedNote = styled.div`\n\talign-self: flex-start;\n\tdisplay: inline-flex;\n\talign-items: center;\n\tgap: 6px;\n\tfont-family: Inter;\n\tfont-size: 12px;\n\tline-height: 18px;\n\tcolor: ${COLORS.content.secondary};\n\n\tsvg {\n\t\tflex-shrink: 0;\n\t\tcolor: ${COLORS.content.inactive};\n\t}\n`;\n\n/**\n * Actions under a finished assistant reply. Kept low-contrast so a row of icons\n * under every message does not compete with the answer itself.\n */\nexport const MessageActions = styled.div`\n\talign-self: flex-start;\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 2px;\n\tmargin-top: -4px;\n`;\n\nexport const MessageAction = styled.button`\n\tdisplay: inline-flex;\n\talign-items: center;\n\tgap: 4px;\n\theight: 24px;\n\tpadding: 0 6px;\n\tborder: none;\n\tborder-radius: 6px;\n\tbackground: transparent;\n\tcolor: ${COLORS.content.placeholder};\n\tfont-family: Inter;\n\tfont-size: 11px;\n\tline-height: 16px;\n\tcursor: pointer;\n\ttransition: background 0.15s ease, color 0.15s ease;\n\n\tsvg {\n\t\tflex-shrink: 0;\n\t}\n\n\t&:hover {\n\t\tbackground: ${COLORS.surface.hovered};\n\t\tcolor: ${COLORS.content.secondary};\n\t}\n\n\t&:focus-visible {\n\t\toutline: 2px solid ${COLORS.stroke.brand};\n\t\toutline-offset: 1px;\n\t}\n\n\t/* Confirmation reads as success, not as another affordance. */\n\t&[data-copied='true'],\n\t&[data-copied='true']:hover {\n\t\tcolor: ${COLORS.content.positive};\n\t}\n`;\n\nexport const ThinkingLabel = styled.span`\n\tfont-family: Inter;\n\tfont-size: 13px;\n\tline-height: 20px;\n\tcolor: ${COLORS.content.secondary};\n`;\n\nexport const ErrorBanner = styled.div`\n\tmargin: 0 16px;\n\tpadding: 8px 10px;\n\tborder-radius: 8px;\n\tbackground: ${COLORS.background.negative.light};\n\tcolor: ${COLORS.content.negative};\n\tfont-family: Inter;\n\tfont-size: 12px;\n\tline-height: 18px;\n\tflex-shrink: 0;\n`;\n\nexport const InputArea = styled.div`\n\tpadding: 12px 16px 4px;\n\tflex-shrink: 0;\n`;\n\nexport const InputWrapper = styled.div<{ $focused: boolean }>`\n\tdisplay: flex;\n\talign-items: flex-end;\n\tgap: 8px;\n\tpadding: 8px 8px 8px 12px;\n\tborder: 1px solid\n\t\t${(props) => (props.$focused ? COLORS.stroke.brand : COLORS.stroke.primary)};\n\tborder-radius: 12px;\n\tbackground: ${COLORS.surface.standard};\n\ttransition: border-color 0.15s ease;\n`;\n\nexport const MessageInput = styled.textarea`\n\tflex: 1;\n\tborder: none;\n\toutline: none;\n\tresize: none;\n\tbackground: transparent;\n\tfont-family: Inter;\n\tfont-size: 13px;\n\tline-height: 20px;\n\tcolor: ${COLORS.content.primary};\n\tmax-height: 96px;\n\tmin-height: 20px;\n\tpadding: 4px 0;\n\n\t&::placeholder {\n\t\tcolor: ${COLORS.content.placeholder};\n\t}\n\n\t&:disabled {\n\t\tcursor: not-allowed;\n\t}\n`;\n\nexport const SendButton = styled.button<{ $active: boolean }>`\n\twidth: 28px;\n\theight: 28px;\n\tflex-shrink: 0;\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\tpadding: 0;\n\tborder: none;\n\tborder-radius: 8px;\n\tbackground: ${(props) =>\n\t\tprops.$active ? COLORS.background.brand : COLORS.background.brandLight};\n\tcolor: ${(props) =>\n\t\tprops.$active ? COLORS.content.primaryInverse : COLORS.content.inactive};\n\tcursor: ${(props) => (props.$active ? 'pointer' : 'not-allowed')};\n\ttransition: background 0.15s ease, color 0.15s ease;\n\n\t&:focus-visible {\n\t\toutline: 2px solid ${COLORS.stroke.brand};\n\t\toutline-offset: 1px;\n\t}\n`;\n\nexport const Disclaimer = styled.div`\n\tpadding: 6px 16px 12px;\n\ttext-align: center;\n\tfont-family: Inter;\n\tfont-size: 11px;\n\tline-height: 16px;\n\tcolor: ${COLORS.content.placeholder};\n\tflex-shrink: 0;\n`;\n"],"names":["PanelContainer","styled","COLORS","PanelHeader","HeaderAvatar","HeaderText","HeaderTitleRow","HeaderBadge","HeaderActions","IconAction","MessagesViewport","MessagesArea","ScrollFade","props","JumpToLatestButton","EmptyState","EmptyStateIcon","SuggestionList","SuggestionChip","MessageBubble","ThinkingBubble","HistoryLoader","FollowUpList","FollowUpsLabel","FollowUpChip","InterruptedNote","MessageActions","MessageAction","ThinkingLabel","ErrorBanner","InputArea","InputWrapper","MessageInput","SendButton","Disclaimer"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const h=8,g=(t,n,c)=>Math.min(Math.max(t,n),Math.max(n,c)),y=({ballPosition:t,ballSize:n,panelWidth:c,panelHeight:r,gap:f,viewport:e})=>{if(!e.width||!e.height)return{left:h,top:h,width:c,height:r};const s=Math.min(c,e.width-h*2),d=Math.min(r,e.height-h*2),m=t.x+n/2,a=t.y+n/2,o=m>e.width/2,M=a>e.height/2,u=o?t.x+n-s:t.x,x=M?t.y-f-d:t.y+n+f;return{left:g(u,h,e.width-s-h),top:g(x,h,e.height-d-h),width:s,height:d}};exports.getCopilotPanelPlacement=y;
|
|
2
|
+
//# sourceMappingURL=copilotPlacement.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copilotPlacement.js","sources":["../../../../src/components/bik-copilot/copilotPlacement.ts"],"sourcesContent":["import { CopilotBallPosition, CopilotViewport } from './model';\n\n/** Smallest gap kept between the panel and the viewport edges. */\nconst VIEWPORT_MARGIN_PX = 8;\n\nexport interface CopilotPanelPlacementOptions {\n\tballPosition: CopilotBallPosition;\n\tballSize: number;\n\tpanelWidth: number;\n\tpanelHeight: number;\n\tgap: number;\n\tviewport: CopilotViewport;\n}\n\nexport interface CopilotPanelPlacement {\n\tleft: number;\n\ttop: number;\n\twidth: number;\n\theight: number;\n}\n\nconst clamp = (value: number, min: number, max: number) =>\n\tMath.min(Math.max(value, min), Math.max(min, max));\n\n/**\n * Places the panel next to the ball, on whichever side has room.\n *\n * The panel opens towards the middle of the screen: a ball parked bottom-right\n * gets a panel above and to its left, a ball parked top-left gets one below and\n * to its right. The result is always clamped inside the viewport, and the panel\n * shrinks on viewports too small to hold it at full size.\n */\nexport const getCopilotPanelPlacement = ({\n\tballPosition,\n\tballSize,\n\tpanelWidth,\n\tpanelHeight,\n\tgap,\n\tviewport,\n}: CopilotPanelPlacementOptions): CopilotPanelPlacement => {\n\tif (!viewport.width || !viewport.height) {\n\t\treturn {\n\t\t\tleft: VIEWPORT_MARGIN_PX,\n\t\t\ttop: VIEWPORT_MARGIN_PX,\n\t\t\twidth: panelWidth,\n\t\t\theight: panelHeight,\n\t\t};\n\t}\n\n\tconst width = Math.min(panelWidth, viewport.width - VIEWPORT_MARGIN_PX * 2);\n\tconst height = Math.min(\n\t\tpanelHeight,\n\t\tviewport.height - VIEWPORT_MARGIN_PX * 2,\n\t);\n\n\tconst ballCenterX = ballPosition.x + ballSize / 2;\n\tconst ballCenterY = ballPosition.y + ballSize / 2;\n\tconst opensLeftwards = ballCenterX > viewport.width / 2;\n\tconst opensUpwards = ballCenterY > viewport.height / 2;\n\n\t// Align the panel's near edge with the ball's, then push it towards the\n\t// screen centre.\n\tconst preferredLeft = opensLeftwards\n\t\t? ballPosition.x + ballSize - width\n\t\t: ballPosition.x;\n\tconst preferredTop = opensUpwards\n\t\t? ballPosition.y - gap - height\n\t\t: ballPosition.y + ballSize + gap;\n\n\treturn {\n\t\tleft: clamp(\n\t\t\tpreferredLeft,\n\t\t\tVIEWPORT_MARGIN_PX,\n\t\t\tviewport.width - width - VIEWPORT_MARGIN_PX,\n\t\t),\n\t\ttop: clamp(\n\t\t\tpreferredTop,\n\t\t\tVIEWPORT_MARGIN_PX,\n\t\t\tviewport.height - height - VIEWPORT_MARGIN_PX,\n\t\t),\n\t\twidth,\n\t\theight,\n\t};\n};\n"],"names":["VIEWPORT_MARGIN_PX","clamp","value","min","max","getCopilotPanelPlacement","ballPosition","ballSize","panelWidth","panelHeight","gap","viewport","width","height","ballCenterX","ballCenterY","opensLeftwards","opensUpwards","preferredLeft","preferredTop"],"mappings":"gFAGA,MAAMA,EAAqB,EAkBrBC,EAAQ,CAACC,EAAeC,EAAaC,IAC1C,KAAK,IAAI,KAAK,IAAIF,EAAOC,CAAG,EAAG,KAAK,IAAIA,EAAKC,CAAG,CAAC,EAUrCC,EAA2B,CAAC,CACxC,aAAAC,EACA,SAAAC,EACA,WAAAC,EACA,YAAAC,EACA,IAAAC,EACA,SAAAC,CACD,IAA2D,CAC1D,GAAI,CAACA,EAAS,OAAS,CAACA,EAAS,OAChC,MAAO,CACN,KAAMX,EACN,IAAKA,EACL,MAAOQ,EACP,OAAQC,CAAA,EAIV,MAAMG,EAAQ,KAAK,IAAIJ,EAAYG,EAAS,MAAQX,EAAqB,CAAC,EACpEa,EAAS,KAAK,IACnBJ,EACAE,EAAS,OAASX,EAAqB,CAAA,EAGlCc,EAAcR,EAAa,EAAIC,EAAW,EAC1CQ,EAAcT,EAAa,EAAIC,EAAW,EAC1CS,EAAiBF,EAAcH,EAAS,MAAQ,EAChDM,EAAeF,EAAcJ,EAAS,OAAS,EAI/CO,EAAgBF,EACnBV,EAAa,EAAIC,EAAWK,EAC5BN,EAAa,EACVa,EAAeF,EAClBX,EAAa,EAAII,EAAMG,EACvBP,EAAa,EAAIC,EAAWG,EAE/B,MAAO,CACN,KAAMT,EACLiB,EACAlB,EACAW,EAAS,MAAQC,EAAQZ,CAAA,EAE1B,IAAKC,EACJkB,EACAnB,EACAW,EAAS,OAASE,EAASb,CAAA,EAE5B,MAAAY,EACA,OAAAC,CAAA,CAEF"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("idb-keyval"),_=require("./copilotMessagesClient.js"),a=i.createStore("bik-copilot","sessions"),p=1440*60*1e3,f=_.COPILOT_HISTORY_PAGE_SIZE,d=(t,e)=>`${e}:${t}`,r=async(t,e)=>{try{return await t()}catch{return e}},m=()=>typeof crypto<"u"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():`copilot-${Date.now()}-${Math.floor(Math.random()*1e6)}`,w=(t,e,n={})=>{const o=Date.now();return{sessionId:e,route:t,createdAt:o,updatedAt:o,expiresAt:o+p,messages:[],...n}},S=(t,e=Date.now())=>(t.expiresAt??t.updatedAt+p)<=e,I=(t,e)=>r(async()=>{const n=d(t,e),o=await i.get(n,a);return o?S(o)?(await i.del(n,a),null):o:null},null),A=t=>r(()=>i.set(d(t.route??"",t.sessionId),t,a),void 0),g=(t,e)=>r(()=>i.del(d(t,e),a),void 0),y=()=>r(async()=>(await i.keys(a)).filter(e=>typeof e=="string"),[]),O=t=>r(async()=>{const e=Date.now(),n=await y();await Promise.all(n.map(async o=>{const l=await i.get(o,a);if(!l)return;(t===void 0?S(l,e):l.updatedAt+t<=e)&&await i.del(o,a)}))},void 0),D=({route:t,storeId:e})=>r(async()=>{const n=`:${t}`,o=await y();return(await Promise.all(o.filter(s=>s.endsWith(n)).map(s=>i.get(s,a)))).filter(s=>!!s).filter(s=>!e||!s.storeId||s.storeId===e).filter(s=>!S(s)).sort((s,c)=>c.updatedAt-s.updatedAt)[0]?.sessionId??null},null),K=async({route:t,sessionId:e,messages:n,previousResponseId:o,storeId:l,agent:u})=>{const s=await I(t,e),c=Date.now(),E={...s??w(t,e),sessionId:e,route:t,updatedAt:c,expiresAt:c+p,messages:n.slice(-f).map(T=>{const C={...T};return delete C.isStreaming,C}),previousResponseId:o,storeId:l,agent:u};await A(E)};exports.COPILOT_SESSION_TTL_MS=p;exports.MAX_PERSISTED_MESSAGES=f;exports.copilotSessionKey=d;exports.createCopilotSession=w;exports.createCopilotSessionId=m;exports.deleteCopilotSession=g;exports.findLatestCopilotSessionId=D;exports.isCopilotSessionExpired=S;exports.listCopilotSessionKeys=y;exports.loadCopilotSession=I;exports.persistCopilotTurn=K;exports.pruneCopilotSessions=O;exports.saveCopilotSession=A;
|
|
2
|
+
//# sourceMappingURL=copilotDb.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copilotDb.js","sources":["../../../../../src/components/bik-copilot/services/copilotDb.ts"],"sourcesContent":["import { createStore, del, get, keys, set } from 'idb-keyval';\nimport { CopilotMessage, CopilotSessionRecord } from '../model';\nimport { COPILOT_HISTORY_PAGE_SIZE } from './copilotMessagesClient';\n\n/**\n * Dedicated IndexedDB store. The chatbot's `db.ts` writes `ai-session:` keys\n * into idb-keyval's default store; the copilot keeps its own database so the two\n * transcripts can never overwrite each other and this schema can evolve freely.\n */\nconst copilotStore = createStore('bik-copilot', 'sessions');\n\n/**\n * How long a conversation outlives its last message.\n *\n * Enforced twice on purpose: `expiresAt` is stamped on every write so a reader\n * can tell a stale record from a live one on its own, and `pruneCopilotSessions`\n * sweeps the expired ones out. Without the stamp, a record would stay readable\n * until a sweep happened to run.\n */\nexport const COPILOT_SESSION_TTL_MS = 24 * 60 * 60 * 1000;\n\n/**\n * Newest messages kept per conversation. Older ones are dropped on write — the\n * backend is the archive, and `/bik-ai/copilot-messages` serves them back a page\n * at a time when the reader scrolls up.\n *\n * Deliberately equal to the endpoint's page size: the cache then holds exactly\n * what page 1 would return, so the first scroll-up asks for page 2 with no gap\n * and no duplicates.\n */\nexport const MAX_PERSISTED_MESSAGES = COPILOT_HISTORY_PAGE_SIZE;\n\n/**\n * Key of one conversation: `{sessionId}:{route}`.\n *\n * Both halves are the identity. The route is in it because a conversation\n * belongs to the page it was started on — coming back to that page continues it,\n * while a different page gets its own. The session id leads because it is what\n * the backend keys `/bik-ai/copilot-messages` by, so a key reads as \"this\n * conversation, on this page\".\n *\n * The separator is `:` rather than `_`, which routes themselves can contain.\n */\nexport const copilotSessionKey = (route: string, sessionId: string): string =>\n\t`${sessionId}:${route}`;\n\n/**\n * Every idb call is wrapped: IndexedDB is unavailable in SSR, in private-mode\n * Safari and when the browser evicts the database. Chat must keep working in\n * memory when persistence fails, so a rejection is swallowed and reported as\n * \"nothing stored\".\n */\nconst safely = async <T>(\n\toperation: () => Promise<T>,\n\tfallback: T,\n): Promise<T> => {\n\ttry {\n\t\treturn await operation();\n\t} catch {\n\t\treturn fallback;\n\t}\n};\n\nexport const createCopilotSessionId = (): string => {\n\tif (\n\t\ttypeof crypto !== 'undefined' &&\n\t\ttypeof crypto.randomUUID === 'function'\n\t) {\n\t\treturn crypto.randomUUID();\n\t}\n\treturn `copilot-${Date.now()}-${Math.floor(Math.random() * 1_000_000)}`;\n};\n\nexport const createCopilotSession = (\n\troute: string,\n\tsessionId: string,\n\tseed: Partial<CopilotSessionRecord> = {},\n): CopilotSessionRecord => {\n\tconst now = Date.now();\n\treturn {\n\t\tsessionId,\n\t\troute,\n\t\tcreatedAt: now,\n\t\tupdatedAt: now,\n\t\texpiresAt: now + COPILOT_SESSION_TTL_MS,\n\t\tmessages: [],\n\t\t...seed,\n\t};\n};\n\n/**\n * Whether a record has outlived its TTL.\n *\n * Records written before `expiresAt` existed fall back to their last write plus\n * the TTL, so an upgrade does not resurrect conversations that should be gone.\n */\nexport const isCopilotSessionExpired = (\n\trecord: CopilotSessionRecord,\n\tnow: number = Date.now(),\n): boolean =>\n\t(record.expiresAt ?? record.updatedAt + COPILOT_SESSION_TTL_MS) <= now;\n\n/**\n * Reads one conversation back, treating an expired record as absent — and\n * deleting it on the way past, so the sweep is not the only thing keeping the\n * store from growing.\n */\nexport const loadCopilotSession = (\n\troute: string,\n\tsessionId: string,\n): Promise<CopilotSessionRecord | null> =>\n\tsafely(async () => {\n\t\tconst key = copilotSessionKey(route, sessionId);\n\t\tconst record = await get<CopilotSessionRecord>(key, copilotStore);\n\t\tif (!record) {\n\t\t\treturn null;\n\t\t}\n\t\tif (isCopilotSessionExpired(record)) {\n\t\t\tawait del(key, copilotStore);\n\t\t\treturn null;\n\t\t}\n\t\treturn record;\n\t}, null);\n\nexport const saveCopilotSession = (\n\trecord: CopilotSessionRecord,\n): Promise<void> =>\n\tsafely(\n\t\t() =>\n\t\t\tset(\n\t\t\t\tcopilotSessionKey(record.route ?? '', record.sessionId),\n\t\t\t\trecord,\n\t\t\t\tcopilotStore,\n\t\t\t),\n\t\tundefined,\n\t);\n\nexport const deleteCopilotSession = (\n\troute: string,\n\tsessionId: string,\n): Promise<void> =>\n\tsafely(\n\t\t() => del(copilotSessionKey(route, sessionId), copilotStore),\n\t\tundefined,\n\t);\n\nexport const listCopilotSessionKeys = (): Promise<string[]> =>\n\tsafely(async () => {\n\t\tconst allKeys = await keys(copilotStore);\n\t\treturn allKeys.filter((key): key is string => typeof key === 'string');\n\t}, []);\n\n/**\n * Drops conversations whose TTL has run out.\n *\n * Without this the store keeps every conversation the merchant ever started, on\n * every route. Expiring by last write rather than by page load keeps a second\n * tab's live conversations intact.\n *\n * `maxAgeMs` overrides the stamped TTL, for callers that want a shorter sweep.\n */\nexport const pruneCopilotSessions = (maxAgeMs?: number): Promise<void> =>\n\tsafely(async () => {\n\t\tconst now = Date.now();\n\t\tconst allKeys = await listCopilotSessionKeys();\n\t\tawait Promise.all(\n\t\t\tallKeys.map(async (key) => {\n\t\t\t\tconst record = await get<CopilotSessionRecord>(key, copilotStore);\n\t\t\t\tif (!record) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst expired =\n\t\t\t\t\tmaxAgeMs === undefined\n\t\t\t\t\t\t? isCopilotSessionExpired(record, now)\n\t\t\t\t\t\t: record.updatedAt + maxAgeMs <= now;\n\t\t\t\tif (expired) {\n\t\t\t\t\tawait del(key, copilotStore);\n\t\t\t\t}\n\t\t\t}),\n\t\t);\n\t}, undefined);\n\n/**\n * The session id of the most recently used conversation on a route, or `null`\n * when that route has none stored.\n *\n * This is what lets a refresh resume rather than start over: the ids themselves\n * only live in memory, so after a reload the stored records are the only place\n * left that knows which conversation the reader was in. Most recent by\n * `updatedAt` wins, which also means a conversation the reader reset — written\n * empty with a fresh stamp — is the one that comes back, not the one they\n * cleared.\n *\n * Scoped by store as well as route: two stores on the same route are two\n * conversations, and resuming the wrong one would show another store's history.\n */\nexport const findLatestCopilotSessionId = ({\n\troute,\n\tstoreId,\n}: {\n\troute: string;\n\tstoreId?: string;\n}): Promise<string | null> =>\n\tsafely(async () => {\n\t\t// The route is the tail of `{sessionId}:{route}`.\n\t\tconst suffix = `:${route}`;\n\t\tconst allKeys = await listCopilotSessionKeys();\n\t\tconst candidates = await Promise.all(\n\t\t\tallKeys\n\t\t\t\t.filter((key) => key.endsWith(suffix))\n\t\t\t\t.map((key) => get<CopilotSessionRecord>(key, copilotStore)),\n\t\t);\n\n\t\tconst newest = candidates\n\t\t\t.filter((record): record is CopilotSessionRecord => Boolean(record))\n\t\t\t// A record written before storeId was tracked has none; only reject on a\n\t\t\t// mismatch, so those stay resumable.\n\t\t\t.filter(\n\t\t\t\t(record) => !storeId || !record.storeId || record.storeId === storeId,\n\t\t\t)\n\t\t\t// An expired conversation must not be resumed, or a reader coming back\n\t\t\t// after a day would land in a session the sweep is about to delete.\n\t\t\t.filter((record) => !isCopilotSessionExpired(record))\n\t\t\t.sort((left, right) => right.updatedAt - left.updatedAt)[0];\n\n\t\treturn newest?.sessionId ?? null;\n\t}, null);\n\n/**\n * Persists one turn's worth of state. Called after every message and after each\n * completed stream, so navigating away mid-conversation loses nothing.\n */\nexport const persistCopilotTurn = async ({\n\troute,\n\tsessionId,\n\tmessages,\n\tpreviousResponseId,\n\tstoreId,\n\tagent,\n}: {\n\troute: string;\n\tsessionId: string;\n\tmessages: CopilotMessage[];\n\tpreviousResponseId?: string;\n\tstoreId?: string;\n\tagent?: string;\n}): Promise<void> => {\n\tconst existing = await loadCopilotSession(route, sessionId);\n\tconst now = Date.now();\n\tconst record: CopilotSessionRecord = {\n\t\t...(existing ?? createCopilotSession(route, sessionId)),\n\t\tsessionId,\n\t\troute,\n\t\tupdatedAt: now,\n\t\t// Restamped every write, so a conversation stays alive as long as it is\n\t\t// being used and starts its 24h only from the last message.\n\t\texpiresAt: now + COPILOT_SESSION_TTL_MS,\n\t\t// Streaming placeholders must not be restored as half-finished bubbles.\n\t\t// Only the newest page survives; anything older is the backend's to serve.\n\t\tmessages: messages.slice(-MAX_PERSISTED_MESSAGES).map((message) => {\n\t\t\tconst stored: CopilotMessage = { ...message };\n\t\t\tdelete stored.isStreaming;\n\t\t\treturn stored;\n\t\t}),\n\t\tpreviousResponseId,\n\t\tstoreId,\n\t\tagent,\n\t};\n\tawait saveCopilotSession(record);\n};\n"],"names":["copilotStore","createStore","COPILOT_SESSION_TTL_MS","MAX_PERSISTED_MESSAGES","COPILOT_HISTORY_PAGE_SIZE","copilotSessionKey","route","sessionId","safely","operation","fallback","createCopilotSessionId","createCopilotSession","seed","now","isCopilotSessionExpired","record","loadCopilotSession","key","get","del","saveCopilotSession","set","deleteCopilotSession","listCopilotSessionKeys","keys","pruneCopilotSessions","maxAgeMs","allKeys","findLatestCopilotSessionId","storeId","suffix","left","right","persistCopilotTurn","messages","previousResponseId","agent","existing","message","stored"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const l="/bik-ai/copilot-icebreakers",w=async({baseUrl:p,endpointPath:d=l,headers:b,authToken:f,getAuthToken:a,fetchImpl:h,agent:s,route:i,storeId:c,signal:u})=>{const k=`${p.replace(/\/$/,"")}${d}`,n=a?await a():f,o=await(h??fetch)(k,{method:"POST",headers:{"Content-Type":"application/json",...n?{authorization:n}:{},...b},body:JSON.stringify({agent:s,route:i,...c?{store_id:c}:{}}),signal:u});if(!o.ok){const t=await o.text().catch(()=>"");throw new Error(`Ice-breaker request failed with ${o.status}${t?`: ${t}`:""}`)}const r=await o.json();if(r.success===!1)throw new Error(r.errors?.[0]?.message||"Could not resolve icebreakers");const e=r.data??{};return{agent:e.agent??s,route:e.route??i,pageName:e.page_name??e.pageName??void 0,icebreakers:(e.icebreakers??[]).filter(t=>typeof t=="string"&&t.trim()!=="")}};exports.COPILOT_ICEBREAKERS_PATH=l;exports.fetchCopilotIcebreakers=w;
|
|
2
|
+
//# sourceMappingURL=copilotIcebreakersClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copilotIcebreakersClient.js","sources":["../../../../../src/components/bik-copilot/services/copilotIcebreakersClient.ts"],"sourcesContent":["import {\n\tCopilotIcebreakersResult,\n\tFetchCopilotIcebreakersOptions,\n} from '../model';\n\n/** Default path of the ice-breaker endpoint. */\nexport const COPILOT_ICEBREAKERS_PATH = '/bik-ai/copilot-icebreakers';\n\n/** The `ApiResponse<T>` envelope every non-streaming BIK AI endpoint returns. */\ninterface ApiEnvelope<T> {\n\tsuccess?: boolean;\n\tdata?: T;\n\terrors?: { code?: string; message?: string }[];\n}\n\ninterface IcebreakersPayload {\n\tagent?: string;\n\troute?: string;\n\tpage_name?: string | null;\n\t/** Tolerated in case the endpoint switches to camelCase serialization. */\n\tpageName?: string | null;\n\ticebreakers?: string[];\n}\n\n/**\n * Fetches the suggested opening prompts for a route.\n *\n * A route with no knowledge file behind it returns an empty list, and the\n * backend is explicit that this is a success rather than a failure — so an empty\n * result must render as \"no chips\", never as an error.\n */\nexport const fetchCopilotIcebreakers = async ({\n\tbaseUrl,\n\tendpointPath = COPILOT_ICEBREAKERS_PATH,\n\theaders,\n\tauthToken,\n\tgetAuthToken,\n\tfetchImpl,\n\tagent,\n\troute,\n\tstoreId,\n\tsignal,\n}: FetchCopilotIcebreakersOptions): Promise<CopilotIcebreakersResult> => {\n\tconst url = `${baseUrl.replace(/\\/$/, '')}${endpointPath}`;\n\tconst token = getAuthToken ? await getAuthToken() : authToken;\n\tconst doFetch = fetchImpl ?? fetch;\n\n\tconst response = await doFetch(url, {\n\t\tmethod: 'POST',\n\t\theaders: {\n\t\t\t'Content-Type': 'application/json',\n\t\t\t...(token ? { authorization: token } : {}),\n\t\t\t...headers,\n\t\t},\n\t\tbody: JSON.stringify({\n\t\t\tagent,\n\t\t\troute,\n\t\t\t...(storeId ? { store_id: storeId } : {}),\n\t\t}),\n\t\tsignal,\n\t});\n\n\tif (!response.ok) {\n\t\tconst detail = await response.text().catch(() => '');\n\t\tthrow new Error(\n\t\t\t`Ice-breaker request failed with ${response.status}${\n\t\t\t\tdetail ? `: ${detail}` : ''\n\t\t\t}`,\n\t\t);\n\t}\n\n\tconst envelope = (await response.json()) as ApiEnvelope<IcebreakersPayload>;\n\tif (envelope.success === false) {\n\t\tthrow new Error(\n\t\t\tenvelope.errors?.[0]?.message || 'Could not resolve icebreakers',\n\t\t);\n\t}\n\n\tconst payload = envelope.data ?? {};\n\treturn {\n\t\tagent: payload.agent ?? agent,\n\t\t// The backend returns the *normalized* route it matched, which can differ\n\t\t// from the one requested.\n\t\troute: payload.route ?? route,\n\t\tpageName: payload.page_name ?? payload.pageName ?? undefined,\n\t\ticebreakers: (payload.icebreakers ?? []).filter(\n\t\t\t(text): text is string => typeof text === 'string' && text.trim() !== '',\n\t\t),\n\t};\n};\n"],"names":["COPILOT_ICEBREAKERS_PATH","fetchCopilotIcebreakers","baseUrl","endpointPath","headers","authToken","getAuthToken","fetchImpl","agent","route","storeId","signal","url","token","response","detail","envelope","payload","text"],"mappings":"gFAMO,MAAMA,EAA2B,8BAyB3BC,EAA0B,MAAO,CAC7C,QAAAC,EACA,aAAAC,EAAeH,EACf,QAAAI,EACA,UAAAC,EACA,aAAAC,EACA,UAAAC,EACA,MAAAC,EACA,MAAAC,EACA,QAAAC,EACA,OAAAC,CACD,IAAyE,CACxE,MAAMC,EAAM,GAAGV,EAAQ,QAAQ,MAAO,EAAE,CAAC,GAAGC,CAAY,GAClDU,EAAQP,EAAe,MAAMA,EAAA,EAAiBD,EAG9CS,EAAW,MAFDP,GAAa,OAEEK,EAAK,CACnC,OAAQ,OACR,QAAS,CACR,eAAgB,mBAChB,GAAIC,EAAQ,CAAE,cAAeA,CAAA,EAAU,CAAA,EACvC,GAAGT,CAAA,EAEJ,KAAM,KAAK,UAAU,CACpB,MAAAI,EACA,MAAAC,EACA,GAAIC,EAAU,CAAE,SAAUA,GAAY,CAAA,CAAC,CACvC,EACD,OAAAC,CAAA,CACA,EAED,GAAI,CAACG,EAAS,GAAI,CACjB,MAAMC,EAAS,MAAMD,EAAS,OAAO,MAAM,IAAM,EAAE,EACnD,MAAM,IAAI,MACT,mCAAmCA,EAAS,MAAM,GACjDC,EAAS,KAAKA,CAAM,GAAK,EAC1B,EAAA,CAEF,CAEA,MAAMC,EAAY,MAAMF,EAAS,KAAA,EACjC,GAAIE,EAAS,UAAY,GACxB,MAAM,IAAI,MACTA,EAAS,SAAS,CAAC,GAAG,SAAW,+BAAA,EAInC,MAAMC,EAAUD,EAAS,MAAQ,CAAA,EACjC,MAAO,CACN,MAAOC,EAAQ,OAAST,EAGxB,MAAOS,EAAQ,OAASR,EACxB,SAAUQ,EAAQ,WAAaA,EAAQ,UAAY,OACnD,aAAcA,EAAQ,aAAe,CAAA,GAAI,OACvCC,GAAyB,OAAOA,GAAS,UAAYA,EAAK,SAAW,EAAA,CACvE,CAEF"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const g="/bik-ai/copilot-messages",h=20,E=e=>e&&/user|merchant|human|staff/i.test(e)?"user":"assistant",T=e=>{if(typeof e=="number")return Number.isFinite(e)?e:0;if(typeof e=="string"&&e.trim().length>0){const s=Number(e);if(Number.isFinite(s))return s;const t=Date.parse(e);if(Number.isFinite(t))return t}return 0},P=(e,s)=>{const t=e.message_id;return{id:t??`copilot-history-${e.created_at??0}-${s}`,role:E(e.owner),content:e.message??"",timestamp:T(e.created_at),...t?{messageId:t}:{}}},b=async({baseUrl:e,endpointPath:s=g,headers:t,authToken:f,getAuthToken:i,fetchImpl:u,storeId:d,sessionId:l,page:c=1,pageSize:m=h,signal:_})=>{const S=new URLSearchParams({store_id:d,session_id:l,page:String(c),page_size:String(m)}),O=`${e.replace(/\/$/,"")}${s}?${S.toString()}`,p=i?await i():f,a=await(u??fetch)(O,{method:"GET",headers:{"Content-Type":"application/json",...p?{authorization:p}:{},...t},signal:_});if(!a.ok){const r=await a.text().catch(()=>"");throw new Error(`Copilot history request failed with ${a.status}${r?`: ${r}`:""}`)}const n=await a.json();if(n.success===!1)throw new Error(n.errors?.[0]?.message||"Could not load the conversation history");const o=n.data??{};return{messages:(o.messages??[]).map(P).filter(r=>r.content.length>0).reverse().sort((r,y)=>r.timestamp-y.timestamp),page:o.page??c,pageSize:o.page_size??o.pageSize??m,hasMore:o.has_more??o.hasMore??!1}};exports.COPILOT_HISTORY_PAGE_SIZE=h;exports.COPILOT_MESSAGES_PATH=g;exports.fetchCopilotMessages=b;
|
|
2
|
+
//# sourceMappingURL=copilotMessagesClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copilotMessagesClient.js","sources":["../../../../../src/components/bik-copilot/services/copilotMessagesClient.ts"],"sourcesContent":["import {\n\tCopilotMessage,\n\tCopilotMessagesPage,\n\tCopilotStoredMessageRow,\n\tFetchCopilotMessagesOptions,\n} from '../model';\n\n/** Default path of the stored-history endpoint. */\nexport const COPILOT_MESSAGES_PATH = '/bik-ai/copilot-messages';\n\n/**\n * How many messages one page holds — and, deliberately, the cap on what\n * IndexedDB keeps.\n *\n * The two are the same number on purpose: the local cache holds exactly what\n * page 1 would return, so the first scroll-up can ask for page 2 without an\n * overlap or a gap. Changing one without the other would tear the transcript.\n */\nexport const COPILOT_HISTORY_PAGE_SIZE = 20;\n\n/** The `ApiResponse<T>` envelope every non-streaming BIK AI endpoint returns. */\ninterface ApiEnvelope<T> {\n\tsuccess?: boolean;\n\tdata?: T;\n\terrors?: { code?: string; message?: string }[];\n}\n\ninterface MessagesPayload {\n\tmessages?: CopilotStoredMessageRow[];\n\tpage?: number;\n\tpage_size?: number;\n\tpageSize?: number;\n\thas_more?: boolean;\n\thasMore?: boolean;\n}\n\n/**\n * Maps the backend's `owner` onto the transcript's `role`.\n *\n * Read as a pattern rather than an exact enum member so a new owner the backend\n * adds lands on a sensible side instead of throwing. Anything that is not\n * recognisably the merchant renders as the assistant, because a mislabelled\n * assistant bubble reads better than a merchant one attributed to the AI.\n */\nconst roleOfOwner = (owner: string | undefined): CopilotMessage['role'] => {\n\tif (owner && /user|merchant|human|staff/i.test(owner)) {\n\t\treturn 'user';\n\t}\n\treturn 'assistant';\n};\n\n/**\n * Coerces a row's `created_at` to epoch millis for ordering.\n *\n * The field is declared as millis, but real responses have arrived as numeric\n * strings and ISO timestamps. Reading all three here keeps the transcript\n * ordered instead of silently falling back to the response order — which is\n * newest-first and would render upside down.\n */\nconst toTimestamp = (value: number | string | undefined): number => {\n\tif (typeof value === 'number') {\n\t\treturn Number.isFinite(value) ? value : 0;\n\t}\n\tif (typeof value === 'string' && value.trim().length > 0) {\n\t\tconst asNumber = Number(value);\n\t\tif (Number.isFinite(asNumber)) {\n\t\t\treturn asNumber;\n\t\t}\n\t\tconst asDate = Date.parse(value);\n\t\tif (Number.isFinite(asDate)) {\n\t\t\treturn asDate;\n\t\t}\n\t}\n\treturn 0;\n};\n\nconst toMessage = (\n\trow: CopilotStoredMessageRow,\n\tindex: number,\n): CopilotMessage => {\n\tconst messageId = row.message_id;\n\treturn {\n\t\t// `message_id` is the server's own id, so a row cannot be prepended twice.\n\t\t// The index fallback only matters for a row that arrives without one.\n\t\tid: messageId ?? `copilot-history-${row.created_at ?? 0}-${index}`,\n\t\trole: roleOfOwner(row.owner),\n\t\tcontent: row.message ?? '',\n\t\ttimestamp: toTimestamp(row.created_at),\n\t\t...(messageId ? { messageId } : {}),\n\t};\n};\n\n/**\n * Reads one page of a conversation's stored history.\n *\n * Page 1 is the newest `pageSize` messages and page 2 the ones before that, so\n * scrolling up walks the pages forward until `hasMore` goes false. Within a page\n * the messages come back oldest-first regardless of the order the backend used,\n * which is the order a transcript is rendered in.\n *\n * Rows with no text are dropped: a blank bubble is worse than a missing one.\n */\nexport const fetchCopilotMessages = async ({\n\tbaseUrl,\n\tendpointPath = COPILOT_MESSAGES_PATH,\n\theaders,\n\tauthToken,\n\tgetAuthToken,\n\tfetchImpl,\n\tstoreId,\n\tsessionId,\n\tpage = 1,\n\tpageSize = COPILOT_HISTORY_PAGE_SIZE,\n\tsignal,\n}: FetchCopilotMessagesOptions): Promise<CopilotMessagesPage> => {\n\tconst query = new URLSearchParams({\n\t\tstore_id: storeId,\n\t\tsession_id: sessionId,\n\t\tpage: String(page),\n\t\tpage_size: String(pageSize),\n\t});\n\tconst url = `${baseUrl.replace(\n\t\t/\\/$/,\n\t\t'',\n\t)}${endpointPath}?${query.toString()}`;\n\tconst token = getAuthToken ? await getAuthToken() : authToken;\n\tconst doFetch = fetchImpl ?? fetch;\n\n\tconst response = await doFetch(url, {\n\t\tmethod: 'GET',\n\t\theaders: {\n\t\t\t'Content-Type': 'application/json',\n\t\t\t...(token ? { authorization: token } : {}),\n\t\t\t...headers,\n\t\t},\n\t\tsignal,\n\t});\n\n\tif (!response.ok) {\n\t\tconst detail = await response.text().catch(() => '');\n\t\tthrow new Error(\n\t\t\t`Copilot history request failed with ${response.status}${\n\t\t\t\tdetail ? `: ${detail}` : ''\n\t\t\t}`,\n\t\t);\n\t}\n\n\tconst envelope = (await response.json()) as ApiEnvelope<MessagesPayload>;\n\tif (envelope.success === false) {\n\t\tthrow new Error(\n\t\t\tenvelope.errors?.[0]?.message ||\n\t\t\t\t'Could not load the conversation history',\n\t\t);\n\t}\n\n\tconst payload = envelope.data ?? {};\n\tconst messages = (payload.messages ?? [])\n\t\t.map(toMessage)\n\t\t.filter((message) => message.content.length > 0)\n\t\t// Render order is oldest-first. The endpoint serves each page newest-first\n\t\t// (page 1 is the newest page), so the base order is reversed first; the\n\t\t// stable sort then corrects any within-page disorder when the rows carry a\n\t\t// usable timestamp, and is a no-op when they do not — leaving the reversed,\n\t\t// oldest-first order intact instead of echoing the newest-first response.\n\t\t.reverse()\n\t\t.sort((left, right) => left.timestamp - right.timestamp);\n\n\treturn {\n\t\tmessages,\n\t\tpage: payload.page ?? page,\n\t\tpageSize: payload.page_size ?? payload.pageSize ?? pageSize,\n\t\thasMore: payload.has_more ?? payload.hasMore ?? false,\n\t};\n};\n"],"names":["COPILOT_MESSAGES_PATH","COPILOT_HISTORY_PAGE_SIZE","roleOfOwner","owner","toTimestamp","value","asNumber","asDate","toMessage","row","index","messageId","fetchCopilotMessages","baseUrl","endpointPath","headers","authToken","getAuthToken","fetchImpl","storeId","sessionId","page","pageSize","signal","query","url","token","response","detail","envelope","payload","message","left","right"],"mappings":"gFAQO,MAAMA,EAAwB,2BAUxBC,EAA4B,GA0BnCC,EAAeC,GAChBA,GAAS,6BAA6B,KAAKA,CAAK,EAC5C,OAED,YAWFC,EAAeC,GAA+C,CACnE,GAAI,OAAOA,GAAU,SACpB,OAAO,OAAO,SAASA,CAAK,EAAIA,EAAQ,EAEzC,GAAI,OAAOA,GAAU,UAAYA,EAAM,KAAA,EAAO,OAAS,EAAG,CACzD,MAAMC,EAAW,OAAOD,CAAK,EAC7B,GAAI,OAAO,SAASC,CAAQ,EAC3B,OAAOA,EAER,MAAMC,EAAS,KAAK,MAAMF,CAAK,EAC/B,GAAI,OAAO,SAASE,CAAM,EACzB,OAAOA,CAET,CACA,MAAO,EACR,EAEMC,EAAY,CACjBC,EACAC,IACoB,CACpB,MAAMC,EAAYF,EAAI,WACtB,MAAO,CAGN,GAAIE,GAAa,mBAAmBF,EAAI,YAAc,CAAC,IAAIC,CAAK,GAChE,KAAMR,EAAYO,EAAI,KAAK,EAC3B,QAASA,EAAI,SAAW,GACxB,UAAWL,EAAYK,EAAI,UAAU,EACrC,GAAIE,EAAY,CAAE,UAAAA,GAAc,CAAA,CAAC,CAEnC,EAYaC,EAAuB,MAAO,CAC1C,QAAAC,EACA,aAAAC,EAAed,EACf,QAAAe,EACA,UAAAC,EACA,aAAAC,EACA,UAAAC,EACA,QAAAC,EACA,UAAAC,EACA,KAAAC,EAAO,EACP,SAAAC,EAAWrB,EACX,OAAAsB,CACD,IAAiE,CAChE,MAAMC,EAAQ,IAAI,gBAAgB,CACjC,SAAUL,EACV,WAAYC,EACZ,KAAM,OAAOC,CAAI,EACjB,UAAW,OAAOC,CAAQ,CAAA,CAC1B,EACKG,EAAM,GAAGZ,EAAQ,QACtB,MACA,EAAA,CACA,GAAGC,CAAY,IAAIU,EAAM,UAAU,GAC9BE,EAAQT,EAAe,MAAMA,EAAA,EAAiBD,EAG9CW,EAAW,MAFDT,GAAa,OAEEO,EAAK,CACnC,OAAQ,MACR,QAAS,CACR,eAAgB,mBAChB,GAAIC,EAAQ,CAAE,cAAeA,CAAA,EAAU,CAAA,EACvC,GAAGX,CAAA,EAEJ,OAAAQ,CAAA,CACA,EAED,GAAI,CAACI,EAAS,GAAI,CACjB,MAAMC,EAAS,MAAMD,EAAS,OAAO,MAAM,IAAM,EAAE,EACnD,MAAM,IAAI,MACT,uCAAuCA,EAAS,MAAM,GACrDC,EAAS,KAAKA,CAAM,GAAK,EAC1B,EAAA,CAEF,CAEA,MAAMC,EAAY,MAAMF,EAAS,KAAA,EACjC,GAAIE,EAAS,UAAY,GACxB,MAAM,IAAI,MACTA,EAAS,SAAS,CAAC,GAAG,SACrB,yCAAA,EAIH,MAAMC,EAAUD,EAAS,MAAQ,CAAA,EAYjC,MAAO,CACN,UAZiBC,EAAQ,UAAY,CAAA,GACpC,IAAItB,CAAS,EACb,OAAQuB,GAAYA,EAAQ,QAAQ,OAAS,CAAC,EAM9C,QAAA,EACA,KAAK,CAACC,EAAMC,IAAUD,EAAK,UAAYC,EAAM,SAAS,EAIvD,KAAMH,EAAQ,MAAQT,EACtB,SAAUS,EAAQ,WAAaA,EAAQ,UAAYR,EACnD,QAASQ,EAAQ,UAAYA,EAAQ,SAAW,EAAA,CAElD"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("./copilotDb.js"),t=new Map,c=(o,e)=>`${o??""}:${e}`,a=({route:o,storeId:e})=>{const s=c(e,o),n=t.get(s);if(n)return n;const r=i.createCopilotSessionId();return t.set(s,r),r},d=async({route:o,storeId:e})=>{const s=c(e,o),n=t.get(s);if(n)return n;const l=await i.findLatestCopilotSessionId({route:o,storeId:e})??i.createCopilotSessionId();return t.set(s,l),l},p=({route:o,storeId:e})=>{const s=i.createCopilotSessionId();return t.set(c(e,o),s),s},u=()=>{t.clear()};exports.clearCopilotPageSessions=u;exports.getCopilotSessionIdForRoute=a;exports.resetCopilotSessionForRoute=p;exports.resolveCopilotSessionIdForRoute=d;
|
|
2
|
+
//# sourceMappingURL=copilotPageSession.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copilotPageSession.js","sources":["../../../../../src/components/bik-copilot/services/copilotPageSession.ts"],"sourcesContent":["import {\n\tcreateCopilotSessionId,\n\tfindLatestCopilotSessionId,\n} from './copilotDb';\n\n/**\n * Registry of the session ids in play for the current page load.\n *\n * Module-level and in-memory, so **navigating away and back to the same route**\n * keeps the id and the copilot picks the conversation up where it was left.\n * Component state could not do this — the copilot unmounts on the way out.\n *\n * A **refresh** empties the registry, so the id has to be recovered from the\n * stored records instead: see `resolveCopilotSessionIdForRoute`, which reads the\n * route's most recent conversation out of IndexedDB before minting a new one.\n * That is what makes history survive a reload, and it is why the id must not be\n * regenerated per page load any more.\n *\n * The transcripts themselves live in IndexedDB under `{sessionId}:{route}`; this\n * registry only decides which of those keys the copilot reads.\n */\nconst routeSessionIds = new Map<string, string>();\n\n/**\n * Registry key.\n *\n * The store is part of it, and each entry gets its own session id rather than a\n * shared per-page one — otherwise two stores on the same route would resolve to\n * the same `{sessionId}:{route}` record and show each other's conversation.\n */\nconst registryKey = (storeId: string | undefined, route: string) =>\n\t`${storeId ?? ''}:${route}`;\n\n/**\n * The session id for a route in this page load, created on first use and stable\n * for the rest of the page load.\n */\nexport const getCopilotSessionIdForRoute = ({\n\troute,\n\tstoreId,\n}: {\n\troute: string;\n\tstoreId?: string;\n}): string => {\n\tconst key = registryKey(storeId, route);\n\tconst existing = routeSessionIds.get(key);\n\tif (existing) {\n\t\treturn existing;\n\t}\n\tconst sessionId = createCopilotSessionId();\n\trouteSessionIds.set(key, sessionId);\n\treturn sessionId;\n};\n\n/**\n * The session id for a route, resuming the stored conversation when this page\n * load has not seen the route yet.\n *\n * Order matters: the in-memory registry first, so a route already in play keeps\n * its id without a database read; then the most recent stored conversation, which\n * is how a refresh resumes; and only then a new id.\n *\n * Prefer this over `getCopilotSessionIdForRoute` anywhere persistence is on — the\n * synchronous version cannot see the stored records, so it always starts fresh.\n */\nexport const resolveCopilotSessionIdForRoute = async ({\n\troute,\n\tstoreId,\n}: {\n\troute: string;\n\tstoreId?: string;\n}): Promise<string> => {\n\tconst key = registryKey(storeId, route);\n\tconst inPlay = routeSessionIds.get(key);\n\tif (inPlay) {\n\t\treturn inPlay;\n\t}\n\n\tconst stored = await findLatestCopilotSessionId({ route, storeId });\n\tconst sessionId = stored ?? createCopilotSessionId();\n\t// Registered either way, so a second mount in this page load skips the read.\n\trouteSessionIds.set(key, sessionId);\n\treturn sessionId;\n};\n\n/**\n * Starts a new conversation for one route, leaving other routes untouched. The\n * new id sticks for the rest of the page load, so navigating away and back does\n * not resurrect the conversation the user just cleared.\n */\nexport const resetCopilotSessionForRoute = ({\n\troute,\n\tstoreId,\n}: {\n\troute: string;\n\tstoreId?: string;\n}): string => {\n\tconst sessionId = createCopilotSessionId();\n\trouteSessionIds.set(registryKey(storeId, route), sessionId);\n\treturn sessionId;\n};\n\n/**\n * Forgets every session id, as a reload would. Call it on logout or when the\n * signed-in user changes; tests use it to simulate a refresh.\n */\nexport const clearCopilotPageSessions = (): void => {\n\trouteSessionIds.clear();\n};\n"],"names":["routeSessionIds","registryKey","storeId","route","getCopilotSessionIdForRoute","key","existing","sessionId","createCopilotSessionId","resolveCopilotSessionIdForRoute","inPlay","findLatestCopilotSessionId","resetCopilotSessionForRoute","clearCopilotPageSessions"],"mappings":"kHAqBMA,MAAsB,IAStBC,EAAc,CAACC,EAA6BC,IACjD,GAAGD,GAAW,EAAE,IAAIC,CAAK,GAMbC,EAA8B,CAAC,CAC3C,MAAAD,EACA,QAAAD,CACD,IAGc,CACb,MAAMG,EAAMJ,EAAYC,EAASC,CAAK,EAChCG,EAAWN,EAAgB,IAAIK,CAAG,EACxC,GAAIC,EACH,OAAOA,EAER,MAAMC,EAAYC,EAAAA,uBAAA,EAClB,OAAAR,EAAgB,IAAIK,EAAKE,CAAS,EAC3BA,CACR,EAaaE,EAAkC,MAAO,CACrD,MAAAN,EACA,QAAAD,CACD,IAGuB,CACtB,MAAMG,EAAMJ,EAAYC,EAASC,CAAK,EAChCO,EAASV,EAAgB,IAAIK,CAAG,EACtC,GAAIK,EACH,OAAOA,EAIR,MAAMH,EADS,MAAMI,EAAAA,2BAA2B,CAAE,MAAAR,EAAO,QAAAD,EAAS,GACtCM,yBAAA,EAE5B,OAAAR,EAAgB,IAAIK,EAAKE,CAAS,EAC3BA,CACR,EAOaK,EAA8B,CAAC,CAC3C,MAAAT,EACA,QAAAD,CACD,IAGc,CACb,MAAMK,EAAYC,EAAAA,uBAAA,EAClB,OAAAR,EAAgB,IAAIC,EAAYC,EAASC,CAAK,EAAGI,CAAS,EACnDA,CACR,EAMaM,EAA2B,IAAY,CACnDb,EAAgB,MAAA,CACjB"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});class a{buffer="";push(n){this.buffer+=n;const t=[];let e=this.findBoundary();for(;e;){const r=this.buffer.slice(0,e.index);this.buffer=this.buffer.slice(e.index+e.length);const i=l(r);i!==null&&t.push(i),e=this.findBoundary()}return t}flush(){const n=this.buffer;this.buffer="";const t=l(n);return t===null?[]:[t]}findBoundary(){const n=this.buffer.indexOf(`
|
|
2
|
+
|
|
3
|
+
`),t=this.buffer.indexOf(`\r
|
|
4
|
+
\r
|
|
5
|
+
`);return t!==-1&&(n===-1||t<n)?{index:t,length:4}:n!==-1?{index:n,length:2}:null}}const l=s=>{const n=s.split(/\r?\n/).filter(e=>e.startsWith("data:")).map(e=>{const r=e.slice(5);return r.startsWith(" ")?r.slice(1):r});if(n.length===0)return null;const t=n.join(`
|
|
6
|
+
`).trim();return t.length===0?null:t};exports.CopilotSseParser=a;
|
|
7
|
+
//# sourceMappingURL=copilotSseParser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copilotSseParser.js","sources":["../../../../../src/components/bik-copilot/services/copilotSseParser.ts"],"sourcesContent":["/**\n * Incremental parser for the SSE frames emitted by `/bik-ai/copilot-chatbot`.\n *\n * The endpoint writes `data: {json}\\n\\n` frames and never sets an `event:` name\n * — the discriminator lives in the JSON payload's `type`. A chunk off the\n * network can split a frame anywhere, so the parser keeps a buffer between\n * calls and only yields frames it has seen terminated.\n */\nexport class CopilotSseParser {\n\tprivate buffer = '';\n\n\t/**\n\t * Feeds one network chunk in and returns every complete `data:` payload it\n\t * completed, as raw strings.\n\t */\n\tpush(chunk: string): string[] {\n\t\tthis.buffer += chunk;\n\t\tconst payloads: string[] = [];\n\n\t\t// Frames are separated by a blank line. \\r\\n\\r\\n is tolerated because\n\t\t// proxies rewrite line endings.\n\t\tlet boundary = this.findBoundary();\n\t\twhile (boundary) {\n\t\t\tconst frame = this.buffer.slice(0, boundary.index);\n\t\t\tthis.buffer = this.buffer.slice(boundary.index + boundary.length);\n\t\t\tconst payload = extractDataPayload(frame);\n\t\t\tif (payload !== null) {\n\t\t\t\tpayloads.push(payload);\n\t\t\t}\n\t\t\tboundary = this.findBoundary();\n\t\t}\n\n\t\treturn payloads;\n\t}\n\n\t/**\n\t * Returns any trailing frame left in the buffer when the stream ends without\n\t * a final blank line, then empties the buffer.\n\t */\n\tflush(): string[] {\n\t\tconst remaining = this.buffer;\n\t\tthis.buffer = '';\n\t\tconst payload = extractDataPayload(remaining);\n\t\treturn payload === null ? [] : [payload];\n\t}\n\n\tprivate findBoundary(): { index: number; length: number } | null {\n\t\tconst lf = this.buffer.indexOf('\\n\\n');\n\t\tconst crlf = this.buffer.indexOf('\\r\\n\\r\\n');\n\t\tif (crlf !== -1 && (lf === -1 || crlf < lf)) {\n\t\t\treturn { index: crlf, length: 4 };\n\t\t}\n\t\tif (lf !== -1) {\n\t\t\treturn { index: lf, length: 2 };\n\t\t}\n\t\treturn null;\n\t}\n}\n\n/**\n * Pulls the payload out of one SSE frame, joining multi-line `data:` fields the\n * way the SSE spec requires. Returns `null` for comment-only or empty frames.\n */\nconst extractDataPayload = (frame: string): string | null => {\n\tconst dataLines = frame\n\t\t.split(/\\r?\\n/)\n\t\t.filter((line) => line.startsWith('data:'))\n\t\t.map((line) => {\n\t\t\tconst value = line.slice('data:'.length);\n\t\t\t// A single leading space after the colon is part of the framing.\n\t\t\treturn value.startsWith(' ') ? value.slice(1) : value;\n\t\t});\n\n\tif (dataLines.length === 0) {\n\t\treturn null;\n\t}\n\tconst payload = dataLines.join('\\n').trim();\n\treturn payload.length === 0 ? null : payload;\n};\n"],"names":["CopilotSseParser","chunk","payloads","boundary","frame","payload","extractDataPayload","remaining","lf","crlf","dataLines","line","value"],"mappings":"gFAQO,MAAMA,CAAiB,CACrB,OAAS,GAMjB,KAAKC,EAAyB,CAC7B,KAAK,QAAUA,EACf,MAAMC,EAAqB,CAAA,EAI3B,IAAIC,EAAW,KAAK,aAAA,EACpB,KAAOA,GAAU,CAChB,MAAMC,EAAQ,KAAK,OAAO,MAAM,EAAGD,EAAS,KAAK,EACjD,KAAK,OAAS,KAAK,OAAO,MAAMA,EAAS,MAAQA,EAAS,MAAM,EAChE,MAAME,EAAUC,EAAmBF,CAAK,EACpCC,IAAY,MACfH,EAAS,KAAKG,CAAO,EAEtBF,EAAW,KAAK,aAAA,CACjB,CAEA,OAAOD,CACR,CAMA,OAAkB,CACjB,MAAMK,EAAY,KAAK,OACvB,KAAK,OAAS,GACd,MAAMF,EAAUC,EAAmBC,CAAS,EAC5C,OAAOF,IAAY,KAAO,CAAA,EAAK,CAACA,CAAO,CACxC,CAEQ,cAAyD,CAChE,MAAMG,EAAK,KAAK,OAAO,QAAQ;AAAA;AAAA,CAAM,EAC/BC,EAAO,KAAK,OAAO,QAAQ;AAAA;AAAA,CAAU,EAC3C,OAAIA,IAAS,KAAOD,IAAO,IAAMC,EAAOD,GAChC,CAAE,MAAOC,EAAM,OAAQ,CAAA,EAE3BD,IAAO,GACH,CAAE,MAAOA,EAAI,OAAQ,CAAA,EAEtB,IACR,CACD,CAMA,MAAMF,EAAsBF,GAAiC,CAC5D,MAAMM,EAAYN,EAChB,MAAM,OAAO,EACb,OAAQO,GAASA,EAAK,WAAW,OAAO,CAAC,EACzC,IAAKA,GAAS,CACd,MAAMC,EAAQD,EAAK,MAAM,CAAc,EAEvC,OAAOC,EAAM,WAAW,GAAG,EAAIA,EAAM,MAAM,CAAC,EAAIA,CACjD,CAAC,EAEF,GAAIF,EAAU,SAAW,EACxB,OAAO,KAER,MAAML,EAAUK,EAAU,KAAK;AAAA,CAAI,EAAE,KAAA,EACrC,OAAOL,EAAQ,SAAW,EAAI,KAAOA,CACtC"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const w=require("./copilotSseParser.js"),h="/bik-ai/copilot-chatbot",v=t=>({store_id:t.storeId,agent:t.agent,route:t.route,user_prompt:t.userPrompt,session_id:t.sessionId,...t.email?.trim()?{email:t.email.trim()}:{},...t.previousResponseId?{previous_response_id:t.previousResponseId}:{},...t.systemPrompt?{system_prompt:t.systemPrompt}:{},...t.model?{model:t.model}:{},...t.maxOutputTokens?{max_output_tokens:t.maxOutputTokens}:{}}),P=t=>{const{content:o}=t;if(typeof o=="string")return{text:o};if(!o||typeof o!="object")return{text:""};const e=Array.isArray(o.followUps)?o.followUps.filter(c=>typeof c=="string"&&c.trim().length>0):void 0;return{text:typeof o.message=="string"?o.message:"",...e&&e.length>0?{followUps:e}:{}}},E=t=>{try{const o=JSON.parse(t);if(typeof o!="object"||o===null)return null;const e=o;return e.type?e:null}catch{return null}},O=({baseUrl:t,endpointPath:o=h,headers:e,authToken:c,getAuthToken:m,fetchImpl:b,...g},l)=>{const p=new AbortController;return(async()=>{const i=`${t.replace(/\/$/,"")}${o}`,u=m?await m():c,a=await(b??fetch)(i,{method:"POST",headers:{"Content-Type":"application/json",Accept:"text/event-stream",...u?{authorization:u}:{},...e},body:JSON.stringify(v(g)),signal:p.signal});if(!a.ok){const n=await a.text().catch(()=>"");throw new Error(`Copilot request failed with ${a.status}${n?`: ${n}`:""}`)}if(!a.body)throw new Error("Copilot response carried no stream body");const C=a.body.getReader(),f=new w.CopilotSseParser;let d;const y=n=>{n.forEach(r=>{const s=E(r);s&&l.onEvent(s)})};for(;;){const{done:n,value:r}=await C.read();if(n)break;if(r===void 0)continue;let s;typeof r=="string"?s=r:(d=d??new TextDecoder,s=d.decode(r,{stream:!0})),y(f.push(s))}y(f.flush())})().then(()=>l.onComplete?.()).catch(i=>{if(p.signal.aborted){l.onAbort?.();return}l.onError?.(i instanceof Error?i:new Error(String(i)))}),()=>p.abort()};exports.COPILOT_ENDPOINT_PATH=h;exports.readCopilotEventContent=P;exports.streamCopilotChat=O;
|
|
2
|
+
//# sourceMappingURL=copilotStreamClient.js.map
|