@kieksme/csp-plugin-chat 0.13.1 → 0.13.3
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/README.md +2 -2
- package/dist/browser.js +201 -149
- package/dist/{chunk-B7EKNOQK.js → chunk-VM2Y3GL7.js} +1 -1
- package/dist/server.js +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ For local provider testing, set `CSP_DEMO=true` and `CSP_CHAT_DEMO=false`: porta
|
|
|
8
8
|
|
|
9
9
|
Langsame lokale Modelle können mit der Runtime-Variable `CSP_CHAT_TIMEOUT_MS` mehr Antwortzeit erhalten (Standard `60000`, Bereich `1000`–`300000` ms).
|
|
10
10
|
|
|
11
|
-
Send a message with Cmd + Enter on macOS, Ctrl + Enter on other systems, or the send button. The hint displays the system-specific shortcut. Plain Enter inserts a line break. A subtle shortcut hint appears
|
|
11
|
+
Send a message with Cmd + Enter on macOS, Ctrl + Enter on other systems, or the send button. The hint displays the system-specific shortcut. Plain Enter inserts a line break. A subtle shortcut hint appears inside the text field at the bottom right; blank messages and shortcuts during an active reply do not send.
|
|
12
12
|
|
|
13
13
|
The input starts with one text row and automatically grows with wrapped text or line breaks. It shrinks when text is removed or sent and adjusts when its width changes.
|
|
14
14
|
|
|
@@ -34,4 +34,4 @@ Long histories follow new messages while the visitor reads at the bottom; scroll
|
|
|
34
34
|
|
|
35
35
|
Both chat modes share a service-chat header and composer. Visitor messages align to the right, assistant and human replies to the left with visible sender labels. Customer theme colours, dark mode and mobile layouts apply throughout. See [chat design](../../docs/chat.md#gestaltung).
|
|
36
36
|
|
|
37
|
-
Dictation uses an icon-only microphone button with the accessible name and tooltip “Nachricht diktieren”.
|
|
37
|
+
Dictation uses an icon-only microphone button with the accessible name and tooltip “Nachricht diktieren”. The microphone sits directly beside Send in the composer toolbar. All composer buttons stay in one row and share a 44 px height. Stop and cancel use accessible icons during recording. The shortcut sits inside the field at the bottom right, with space reserved below editable text. Its privacy notice stays visible underneath.
|
package/dist/browser.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
cspPlugin
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-VM2Y3GL7.js";
|
|
4
4
|
|
|
5
5
|
// src/tools.ts
|
|
6
6
|
import {
|
|
@@ -404,7 +404,8 @@ function VoiceInput({
|
|
|
404
404
|
setValue,
|
|
405
405
|
disabled,
|
|
406
406
|
token,
|
|
407
|
-
onBusy
|
|
407
|
+
onBusy,
|
|
408
|
+
children
|
|
408
409
|
}) {
|
|
409
410
|
const [enabled, setEnabled] = useState2(false), [state, setState] = useState2("idle"), [error, setError] = useState2("");
|
|
410
411
|
const recorder = useRef2(null), stream = useRef2(null), timer = useRef2(null), request = useRef2(null);
|
|
@@ -573,74 +574,101 @@ function VoiceInput({
|
|
|
573
574
|
}
|
|
574
575
|
}
|
|
575
576
|
}
|
|
576
|
-
if (!enabled) return null;
|
|
577
|
-
|
|
577
|
+
if (!enabled) return children(null, null);
|
|
578
|
+
const controls = state === "idle" ? /* @__PURE__ */ jsx2(
|
|
579
|
+
"button",
|
|
580
|
+
{
|
|
581
|
+
type: "button",
|
|
582
|
+
className: "chat-voice-button chat-microphone",
|
|
583
|
+
"aria-label": "Nachricht diktieren",
|
|
584
|
+
title: "Nachricht diktieren",
|
|
585
|
+
disabled,
|
|
586
|
+
onClick: () => void start(),
|
|
587
|
+
children: /* @__PURE__ */ jsxs2(
|
|
588
|
+
"svg",
|
|
589
|
+
{
|
|
590
|
+
"aria-hidden": "true",
|
|
591
|
+
viewBox: "0 0 24 24",
|
|
592
|
+
width: "16",
|
|
593
|
+
height: "16",
|
|
594
|
+
fill: "none",
|
|
595
|
+
stroke: "currentColor",
|
|
596
|
+
strokeWidth: "2",
|
|
597
|
+
children: [
|
|
598
|
+
/* @__PURE__ */ jsx2("rect", { x: "9", y: "2", width: "6", height: "12", rx: "3" }),
|
|
599
|
+
/* @__PURE__ */ jsx2("path", { d: "M5 10v2a7 7 0 0 0 14 0v-2M12 19v3M8 22h8" })
|
|
600
|
+
]
|
|
601
|
+
}
|
|
602
|
+
)
|
|
603
|
+
}
|
|
604
|
+
) : /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
605
|
+
state === "recording" && /* @__PURE__ */ jsx2(
|
|
606
|
+
"button",
|
|
607
|
+
{
|
|
608
|
+
type: "button",
|
|
609
|
+
className: "chat-voice-button",
|
|
610
|
+
"aria-label": "Aufnahme stoppen",
|
|
611
|
+
title: "Aufnahme stoppen",
|
|
612
|
+
onClick: () => recorder.current?.stop(),
|
|
613
|
+
children: /* @__PURE__ */ jsx2(
|
|
614
|
+
"svg",
|
|
615
|
+
{
|
|
616
|
+
"aria-hidden": "true",
|
|
617
|
+
viewBox: "0 0 24 24",
|
|
618
|
+
width: "16",
|
|
619
|
+
height: "16",
|
|
620
|
+
fill: "currentColor",
|
|
621
|
+
children: /* @__PURE__ */ jsx2("rect", { x: "5", y: "5", width: "14", height: "14", rx: "2" })
|
|
622
|
+
}
|
|
623
|
+
)
|
|
624
|
+
}
|
|
625
|
+
),
|
|
626
|
+
/* @__PURE__ */ jsx2(
|
|
627
|
+
"button",
|
|
628
|
+
{
|
|
629
|
+
type: "button",
|
|
630
|
+
className: "chat-voice-cancel",
|
|
631
|
+
"aria-label": "Abbrechen",
|
|
632
|
+
title: "Abbrechen",
|
|
633
|
+
onClick: () => {
|
|
634
|
+
operation.current++;
|
|
635
|
+
cancelled.current = true;
|
|
636
|
+
request.current?.abort();
|
|
637
|
+
if (recorder.current?.state === "recording")
|
|
638
|
+
recorder.current.stop();
|
|
639
|
+
release();
|
|
640
|
+
idle();
|
|
641
|
+
},
|
|
642
|
+
children: /* @__PURE__ */ jsx2(
|
|
643
|
+
"svg",
|
|
644
|
+
{
|
|
645
|
+
"aria-hidden": "true",
|
|
646
|
+
viewBox: "0 0 24 24",
|
|
647
|
+
width: "16",
|
|
648
|
+
height: "16",
|
|
649
|
+
fill: "none",
|
|
650
|
+
stroke: "currentColor",
|
|
651
|
+
strokeWidth: "2",
|
|
652
|
+
children: /* @__PURE__ */ jsx2("path", { d: "m6 6 12 12M18 6 6 18" })
|
|
653
|
+
}
|
|
654
|
+
)
|
|
655
|
+
}
|
|
656
|
+
)
|
|
657
|
+
] });
|
|
658
|
+
const details = /* @__PURE__ */ jsxs2(
|
|
578
659
|
"div",
|
|
579
660
|
{
|
|
580
661
|
className: "chat-voice",
|
|
581
662
|
"data-state": state,
|
|
582
663
|
"data-recording": state === "recording",
|
|
583
664
|
children: [
|
|
584
|
-
state
|
|
585
|
-
"button",
|
|
586
|
-
{
|
|
587
|
-
type: "button",
|
|
588
|
-
className: "chat-voice-button chat-microphone",
|
|
589
|
-
"aria-label": "Nachricht diktieren",
|
|
590
|
-
title: "Nachricht diktieren",
|
|
591
|
-
disabled,
|
|
592
|
-
onClick: () => void start(),
|
|
593
|
-
children: /* @__PURE__ */ jsxs2(
|
|
594
|
-
"svg",
|
|
595
|
-
{
|
|
596
|
-
"aria-hidden": "true",
|
|
597
|
-
viewBox: "0 0 24 24",
|
|
598
|
-
width: "16",
|
|
599
|
-
height: "16",
|
|
600
|
-
fill: "none",
|
|
601
|
-
stroke: "currentColor",
|
|
602
|
-
strokeWidth: "2",
|
|
603
|
-
children: [
|
|
604
|
-
/* @__PURE__ */ jsx2("rect", { x: "9", y: "2", width: "6", height: "12", rx: "3" }),
|
|
605
|
-
/* @__PURE__ */ jsx2("path", { d: "M5 10v2a7 7 0 0 0 14 0v-2M12 19v3M8 22h8" })
|
|
606
|
-
]
|
|
607
|
-
}
|
|
608
|
-
)
|
|
609
|
-
}
|
|
610
|
-
) : /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
611
|
-
/* @__PURE__ */ jsx2("span", { role: "status", className: "chat-voice-status", children: state === "recording" ? "\u25CF Aufnahme l\xE4uft \xB7 maximal 60 Sekunden" : state === "starting" ? "Mikrofon wird gestartet \u2026" : "Sprache wird in Text umgewandelt \u2026" }),
|
|
612
|
-
state === "recording" && /* @__PURE__ */ jsx2(
|
|
613
|
-
"button",
|
|
614
|
-
{
|
|
615
|
-
type: "button",
|
|
616
|
-
className: "chat-voice-button",
|
|
617
|
-
onClick: () => recorder.current?.stop(),
|
|
618
|
-
children: "Aufnahme stoppen"
|
|
619
|
-
}
|
|
620
|
-
),
|
|
621
|
-
/* @__PURE__ */ jsx2(
|
|
622
|
-
"button",
|
|
623
|
-
{
|
|
624
|
-
type: "button",
|
|
625
|
-
className: "chat-voice-cancel",
|
|
626
|
-
onClick: () => {
|
|
627
|
-
operation.current++;
|
|
628
|
-
cancelled.current = true;
|
|
629
|
-
request.current?.abort();
|
|
630
|
-
if (recorder.current?.state === "recording")
|
|
631
|
-
recorder.current.stop();
|
|
632
|
-
release();
|
|
633
|
-
idle();
|
|
634
|
-
},
|
|
635
|
-
children: "Abbrechen"
|
|
636
|
-
}
|
|
637
|
-
)
|
|
638
|
-
] }),
|
|
665
|
+
state !== "idle" && /* @__PURE__ */ jsx2("span", { role: "status", className: "chat-voice-status", children: state === "recording" ? "\u25CF Aufnahme l\xE4uft \xB7 maximal 60 Sekunden" : state === "starting" ? "Mikrofon wird gestartet \u2026" : "Sprache wird in Text umgewandelt \u2026" }),
|
|
639
666
|
/* @__PURE__ */ jsx2("p", { className: "chat-voice-notice", children: "Die Aufnahme wird zur Texterkennung an OpenAI gesendet. Pr\xFCfen Sie den Text vor dem Senden." }),
|
|
640
667
|
error && /* @__PURE__ */ jsx2("p", { role: "alert", className: "text-danger dark:text-warning mt-2", children: error })
|
|
641
668
|
]
|
|
642
669
|
}
|
|
643
670
|
);
|
|
671
|
+
return children(controls, details);
|
|
644
672
|
}
|
|
645
673
|
|
|
646
674
|
// src/support-chat.tsx
|
|
@@ -926,48 +954,61 @@ function SupportChat(ctx) {
|
|
|
926
954
|
children: anonymous ? "Chat neu verbinden" : ctx.config.chatSupport?.auth === "session" ? "Portal-Anmeldung erneuern" : "Mit Microsoft anmelden"
|
|
927
955
|
}
|
|
928
956
|
),
|
|
929
|
-
ready && /* @__PURE__ */
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
957
|
+
ready && /* @__PURE__ */ jsx3("div", { className: "chat-composer", children: /* @__PURE__ */ jsx3(
|
|
958
|
+
VoiceInput,
|
|
959
|
+
{
|
|
960
|
+
ctx,
|
|
961
|
+
value: input,
|
|
962
|
+
setValue: setInput,
|
|
963
|
+
disabled: current?.status === "closed",
|
|
964
|
+
token: auth?.token,
|
|
965
|
+
onBusy: setVoiceBusy,
|
|
966
|
+
children: (controls, details) => /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
967
|
+
/* @__PURE__ */ jsxs3(
|
|
968
|
+
"form",
|
|
969
|
+
{
|
|
970
|
+
onSubmit: submit,
|
|
971
|
+
className: "chat-form flex gap-2.5 items-end",
|
|
972
|
+
children: [
|
|
973
|
+
/* @__PURE__ */ jsx3("label", { htmlFor: "support-chat-input", className: "sr-only", children: "Ihre Nachricht" }),
|
|
974
|
+
/* @__PURE__ */ jsxs3("div", { className: "chat-compose-field", children: [
|
|
975
|
+
/* @__PURE__ */ jsx3(
|
|
976
|
+
"textarea",
|
|
977
|
+
{
|
|
978
|
+
id: "support-chat-input",
|
|
979
|
+
value: input,
|
|
980
|
+
rows: 1,
|
|
981
|
+
maxLength: 4e3,
|
|
982
|
+
disabled: current?.status === "closed",
|
|
983
|
+
className: "flex-1 min-w-0 max-h-[180px] overflow-auto resize-none border border-line rounded-card bg-card p-3",
|
|
984
|
+
onChange: (e) => setInput(e.target.value),
|
|
985
|
+
onKeyDown: (e) => sendShortcut(e, blocked || !input.trim()),
|
|
986
|
+
"aria-keyshortcuts": "Control+Enter Meta+Enter",
|
|
987
|
+
"aria-describedby": "support-chat-shortcut",
|
|
988
|
+
placeholder: "Wie k\xF6nnen wir Ihnen helfen?"
|
|
989
|
+
}
|
|
990
|
+
),
|
|
991
|
+
/* @__PURE__ */ jsx3(Shortcut, { id: "support-chat-shortcut" })
|
|
992
|
+
] }),
|
|
993
|
+
/* @__PURE__ */ jsx3("div", { className: "chat-compose-toolbar", children: /* @__PURE__ */ jsxs3("div", { className: "chat-compose-actions", children: [
|
|
994
|
+
controls,
|
|
995
|
+
/* @__PURE__ */ jsx3(
|
|
996
|
+
"button",
|
|
997
|
+
{
|
|
998
|
+
type: "submit",
|
|
999
|
+
className: "chat-send",
|
|
1000
|
+
disabled: blocked || !input.trim(),
|
|
1001
|
+
children: "Senden"
|
|
1002
|
+
}
|
|
1003
|
+
)
|
|
1004
|
+
] }) })
|
|
1005
|
+
]
|
|
1006
|
+
}
|
|
1007
|
+
),
|
|
1008
|
+
details
|
|
1009
|
+
] })
|
|
1010
|
+
}
|
|
1011
|
+
) }),
|
|
971
1012
|
ready && (!current || current.status === "bot") && /* @__PURE__ */ jsxs3(
|
|
972
1013
|
"button",
|
|
973
1014
|
{
|
|
@@ -1062,7 +1103,7 @@ function SupportChat(ctx) {
|
|
|
1062
1103
|
}
|
|
1063
1104
|
|
|
1064
1105
|
// src/browser.tsx
|
|
1065
|
-
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1106
|
+
import { Fragment as Fragment3, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1066
1107
|
function resizeInput(field) {
|
|
1067
1108
|
if (!field) return;
|
|
1068
1109
|
field.style.height = "auto";
|
|
@@ -1246,56 +1287,67 @@ function LegacyChat(ctx) {
|
|
|
1246
1287
|
}
|
|
1247
1288
|
),
|
|
1248
1289
|
/* @__PURE__ */ jsx4(NewMessages, { visible: scroll.unread, follow: scroll.follow }),
|
|
1249
|
-
/* @__PURE__ */
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1290
|
+
/* @__PURE__ */ jsx4("div", { className: "chat-composer", children: /* @__PURE__ */ jsx4(
|
|
1291
|
+
VoiceInput,
|
|
1292
|
+
{
|
|
1293
|
+
ctx,
|
|
1294
|
+
value: input,
|
|
1295
|
+
setValue: setInput,
|
|
1296
|
+
disabled: resolved,
|
|
1297
|
+
onBusy: setVoiceBusy,
|
|
1298
|
+
children: (controls, details) => /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
1299
|
+
/* @__PURE__ */ jsxs4(
|
|
1300
|
+
"form",
|
|
1255
1301
|
{
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1302
|
+
className: "chat-form flex gap-2.5 items-end",
|
|
1303
|
+
onSubmit: submit,
|
|
1304
|
+
children: [
|
|
1305
|
+
/* @__PURE__ */ jsx4("label", { className: "sr-only", htmlFor: "chat-input", children: "Ihre Frage" }),
|
|
1306
|
+
/* @__PURE__ */ jsxs4("div", { className: "chat-compose-field", children: [
|
|
1307
|
+
/* @__PURE__ */ jsx4(
|
|
1308
|
+
"textarea",
|
|
1309
|
+
{
|
|
1310
|
+
id: "chat-input",
|
|
1311
|
+
ref: inputField,
|
|
1312
|
+
rows: 1,
|
|
1313
|
+
autoFocus: true,
|
|
1314
|
+
className: "search bg-card border border-line rounded-card pt-3.5 pb-7 px-4.5 text-ink w-full block max-h-[180px] overflow-auto",
|
|
1315
|
+
value: input,
|
|
1316
|
+
disabled: resolved,
|
|
1317
|
+
maxLength: 4e3,
|
|
1318
|
+
onChange: (e) => setInput(e.target.value),
|
|
1319
|
+
onKeyDown: (e) => sendShortcut(
|
|
1320
|
+
e,
|
|
1321
|
+
busy || voiceBusy || resolved || !input.trim()
|
|
1322
|
+
),
|
|
1323
|
+
"aria-keyshortcuts": "Control+Enter Meta+Enter",
|
|
1324
|
+
"aria-describedby": "chat-shortcut",
|
|
1325
|
+
placeholder: "Ihre Frage an unser Team \u2026",
|
|
1326
|
+
required: true
|
|
1327
|
+
}
|
|
1328
|
+
),
|
|
1329
|
+
/* @__PURE__ */ jsx4(Shortcut, { id: "chat-shortcut" })
|
|
1330
|
+
] }),
|
|
1331
|
+
/* @__PURE__ */ jsx4("div", { className: "chat-compose-toolbar", children: /* @__PURE__ */ jsxs4("div", { className: "chat-compose-actions", children: [
|
|
1332
|
+
controls,
|
|
1333
|
+
/* @__PURE__ */ jsx4(
|
|
1334
|
+
"button",
|
|
1335
|
+
{
|
|
1336
|
+
type: "submit",
|
|
1337
|
+
disabled: busy || voiceBusy || resolved || !input.trim(),
|
|
1338
|
+
className: "chat-send",
|
|
1339
|
+
"aria-label": "Frage senden",
|
|
1340
|
+
children: "Senden"
|
|
1341
|
+
}
|
|
1342
|
+
)
|
|
1343
|
+
] }) })
|
|
1344
|
+
]
|
|
1273
1345
|
}
|
|
1274
1346
|
),
|
|
1275
|
-
|
|
1276
|
-
] })
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
{
|
|
1280
|
-
type: "submit",
|
|
1281
|
-
disabled: busy || voiceBusy || resolved || !input.trim(),
|
|
1282
|
-
className: "chat-send",
|
|
1283
|
-
"aria-label": "Frage senden",
|
|
1284
|
-
children: "Senden"
|
|
1285
|
-
}
|
|
1286
|
-
)
|
|
1287
|
-
] }),
|
|
1288
|
-
/* @__PURE__ */ jsx4(
|
|
1289
|
-
VoiceInput,
|
|
1290
|
-
{
|
|
1291
|
-
ctx,
|
|
1292
|
-
value: input,
|
|
1293
|
-
setValue: setInput,
|
|
1294
|
-
disabled: resolved,
|
|
1295
|
-
onBusy: setVoiceBusy
|
|
1296
|
-
}
|
|
1297
|
-
)
|
|
1298
|
-
] }),
|
|
1347
|
+
details
|
|
1348
|
+
] })
|
|
1349
|
+
}
|
|
1350
|
+
) }),
|
|
1299
1351
|
messages.length > 0 && !resolved && /* @__PURE__ */ jsx4(
|
|
1300
1352
|
"button",
|
|
1301
1353
|
{
|
package/dist/server.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kieksme/csp-plugin-chat",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"files": [
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"@azure/msal-browser": "^5.25.0",
|
|
26
|
-
"@kieksme/csp-sdk": "^0.13.
|
|
26
|
+
"@kieksme/csp-sdk": "^0.13.3",
|
|
27
27
|
"openai": "^6.3.0",
|
|
28
28
|
"zod": "^3.25.76"
|
|
29
29
|
},
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
},
|
|
36
36
|
"cspPlugin": {
|
|
37
37
|
"id": "chat",
|
|
38
|
-
"sdkVersion": "^0.13.
|
|
38
|
+
"sdkVersion": "^0.13.3",
|
|
39
39
|
"browser": "./browser",
|
|
40
40
|
"server": "./server"
|
|
41
41
|
},
|