@kieksme/csp-plugin-chat 0.13.0 → 0.13.2
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 -0
- package/dist/browser.js +180 -148
- package/dist/{chunk-W5TFART7.js → chunk-OGWLCI3O.js} +1 -1
- package/dist/server.js +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -33,3 +33,5 @@ The assistant asks one short clarifying question for vague requests (for example
|
|
|
33
33
|
Long histories follow new messages while the visitor reads at the bottom; scrolling up preserves the reading position and offers **Neue Nachrichten ↓**. Real OpenAI providers expose editable dictation through the server-only transcription API. With a support transport, **Ich möchte mit einer echten Person sprechen** pauses the bot immediately and queues a persistent, directed support request. See [chat behaviour and APIs](../../docs/chat.md) and [runtime options](../../docs/configuration.md#spracheingabe-und-supportanfragen).
|
|
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
|
+
|
|
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. Its privacy notice stays visible underneath, and mobile touch targets remain 44 × 44 px.
|
package/dist/browser.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
cspPlugin
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-OGWLCI3O.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,68 +574,75 @@ function VoiceInput({
|
|
|
573
574
|
}
|
|
574
575
|
}
|
|
575
576
|
}
|
|
576
|
-
if (!enabled) return null;
|
|
577
|
-
|
|
578
|
-
|
|
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(
|
|
579
606
|
"button",
|
|
580
607
|
{
|
|
581
608
|
type: "button",
|
|
582
609
|
className: "chat-voice-button",
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
children: [
|
|
586
|
-
/* @__PURE__ */ jsxs2(
|
|
587
|
-
"svg",
|
|
588
|
-
{
|
|
589
|
-
"aria-hidden": "true",
|
|
590
|
-
viewBox: "0 0 24 24",
|
|
591
|
-
width: "16",
|
|
592
|
-
height: "16",
|
|
593
|
-
className: "inline mr-2",
|
|
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
|
-
"Nachricht diktieren"
|
|
604
|
-
]
|
|
610
|
+
onClick: () => recorder.current?.stop(),
|
|
611
|
+
children: "Aufnahme stoppen"
|
|
605
612
|
}
|
|
606
|
-
)
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
cancelled.current = true;
|
|
625
|
-
request.current?.abort();
|
|
626
|
-
if (recorder.current?.state === "recording")
|
|
627
|
-
recorder.current.stop();
|
|
628
|
-
release();
|
|
629
|
-
idle();
|
|
630
|
-
},
|
|
631
|
-
children: "Abbrechen"
|
|
632
|
-
}
|
|
633
|
-
)
|
|
634
|
-
] }),
|
|
635
|
-
/* @__PURE__ */ jsx2("p", { className: "chat-voice-notice", children: "Die Aufnahme wird zur Texterkennung an OpenAI gesendet. Pr\xFCfen Sie den Text vor dem Senden." }),
|
|
636
|
-
error && /* @__PURE__ */ jsx2("p", { role: "alert", className: "text-danger dark:text-warning mt-2", children: error })
|
|
613
|
+
),
|
|
614
|
+
/* @__PURE__ */ jsx2(
|
|
615
|
+
"button",
|
|
616
|
+
{
|
|
617
|
+
type: "button",
|
|
618
|
+
className: "chat-voice-cancel",
|
|
619
|
+
onClick: () => {
|
|
620
|
+
operation.current++;
|
|
621
|
+
cancelled.current = true;
|
|
622
|
+
request.current?.abort();
|
|
623
|
+
if (recorder.current?.state === "recording")
|
|
624
|
+
recorder.current.stop();
|
|
625
|
+
release();
|
|
626
|
+
idle();
|
|
627
|
+
},
|
|
628
|
+
children: "Abbrechen"
|
|
629
|
+
}
|
|
630
|
+
)
|
|
637
631
|
] });
|
|
632
|
+
const details = /* @__PURE__ */ jsxs2(
|
|
633
|
+
"div",
|
|
634
|
+
{
|
|
635
|
+
className: "chat-voice",
|
|
636
|
+
"data-state": state,
|
|
637
|
+
"data-recording": state === "recording",
|
|
638
|
+
children: [
|
|
639
|
+
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" }),
|
|
640
|
+
/* @__PURE__ */ jsx2("p", { className: "chat-voice-notice", children: "Die Aufnahme wird zur Texterkennung an OpenAI gesendet. Pr\xFCfen Sie den Text vor dem Senden." }),
|
|
641
|
+
error && /* @__PURE__ */ jsx2("p", { role: "alert", className: "text-danger dark:text-warning mt-2", children: error })
|
|
642
|
+
]
|
|
643
|
+
}
|
|
644
|
+
);
|
|
645
|
+
return children(controls, details);
|
|
638
646
|
}
|
|
639
647
|
|
|
640
648
|
// src/support-chat.tsx
|
|
@@ -920,48 +928,61 @@ function SupportChat(ctx) {
|
|
|
920
928
|
children: anonymous ? "Chat neu verbinden" : ctx.config.chatSupport?.auth === "session" ? "Portal-Anmeldung erneuern" : "Mit Microsoft anmelden"
|
|
921
929
|
}
|
|
922
930
|
),
|
|
923
|
-
ready && /* @__PURE__ */
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
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
|
-
|
|
931
|
+
ready && /* @__PURE__ */ jsx3("div", { className: "chat-composer", children: /* @__PURE__ */ jsx3(
|
|
932
|
+
VoiceInput,
|
|
933
|
+
{
|
|
934
|
+
ctx,
|
|
935
|
+
value: input,
|
|
936
|
+
setValue: setInput,
|
|
937
|
+
disabled: current?.status === "closed",
|
|
938
|
+
token: auth?.token,
|
|
939
|
+
onBusy: setVoiceBusy,
|
|
940
|
+
children: (controls, details) => /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
941
|
+
/* @__PURE__ */ jsxs3(
|
|
942
|
+
"form",
|
|
943
|
+
{
|
|
944
|
+
onSubmit: submit,
|
|
945
|
+
className: "chat-form flex gap-2.5 items-end",
|
|
946
|
+
children: [
|
|
947
|
+
/* @__PURE__ */ jsx3("label", { htmlFor: "support-chat-input", className: "sr-only", children: "Ihre Nachricht" }),
|
|
948
|
+
/* @__PURE__ */ jsx3(
|
|
949
|
+
"textarea",
|
|
950
|
+
{
|
|
951
|
+
id: "support-chat-input",
|
|
952
|
+
value: input,
|
|
953
|
+
rows: 2,
|
|
954
|
+
maxLength: 4e3,
|
|
955
|
+
disabled: current?.status === "closed",
|
|
956
|
+
className: "flex-1 min-w-0 max-h-[180px] overflow-auto resize-none border border-line rounded-card bg-card p-3",
|
|
957
|
+
onChange: (e) => setInput(e.target.value),
|
|
958
|
+
onKeyDown: (e) => sendShortcut(e, blocked || !input.trim()),
|
|
959
|
+
"aria-keyshortcuts": "Control+Enter Meta+Enter",
|
|
960
|
+
"aria-describedby": "support-chat-shortcut",
|
|
961
|
+
placeholder: "Wie k\xF6nnen wir Ihnen helfen?"
|
|
962
|
+
}
|
|
963
|
+
),
|
|
964
|
+
/* @__PURE__ */ jsxs3("div", { className: "chat-compose-toolbar", children: [
|
|
965
|
+
/* @__PURE__ */ jsx3(Shortcut, { id: "support-chat-shortcut" }),
|
|
966
|
+
/* @__PURE__ */ jsxs3("div", { className: "chat-compose-actions", children: [
|
|
967
|
+
controls,
|
|
968
|
+
/* @__PURE__ */ jsx3(
|
|
969
|
+
"button",
|
|
970
|
+
{
|
|
971
|
+
type: "submit",
|
|
972
|
+
className: "chat-send",
|
|
973
|
+
disabled: blocked || !input.trim(),
|
|
974
|
+
children: "Senden"
|
|
975
|
+
}
|
|
976
|
+
)
|
|
977
|
+
] })
|
|
978
|
+
] })
|
|
979
|
+
]
|
|
980
|
+
}
|
|
981
|
+
),
|
|
982
|
+
details
|
|
983
|
+
] })
|
|
984
|
+
}
|
|
985
|
+
) }),
|
|
965
986
|
ready && (!current || current.status === "bot") && /* @__PURE__ */ jsxs3(
|
|
966
987
|
"button",
|
|
967
988
|
{
|
|
@@ -1056,7 +1077,7 @@ function SupportChat(ctx) {
|
|
|
1056
1077
|
}
|
|
1057
1078
|
|
|
1058
1079
|
// src/browser.tsx
|
|
1059
|
-
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1080
|
+
import { Fragment as Fragment3, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1060
1081
|
function resizeInput(field) {
|
|
1061
1082
|
if (!field) return;
|
|
1062
1083
|
field.style.height = "auto";
|
|
@@ -1240,56 +1261,67 @@ function LegacyChat(ctx) {
|
|
|
1240
1261
|
}
|
|
1241
1262
|
),
|
|
1242
1263
|
/* @__PURE__ */ jsx4(NewMessages, { visible: scroll.unread, follow: scroll.follow }),
|
|
1243
|
-
/* @__PURE__ */
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1264
|
+
/* @__PURE__ */ jsx4("div", { className: "chat-composer", children: /* @__PURE__ */ jsx4(
|
|
1265
|
+
VoiceInput,
|
|
1266
|
+
{
|
|
1267
|
+
ctx,
|
|
1268
|
+
value: input,
|
|
1269
|
+
setValue: setInput,
|
|
1270
|
+
disabled: resolved,
|
|
1271
|
+
onBusy: setVoiceBusy,
|
|
1272
|
+
children: (controls, details) => /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
1273
|
+
/* @__PURE__ */ jsxs4(
|
|
1274
|
+
"form",
|
|
1249
1275
|
{
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1276
|
+
className: "chat-form flex gap-2.5 items-end",
|
|
1277
|
+
onSubmit: submit,
|
|
1278
|
+
children: [
|
|
1279
|
+
/* @__PURE__ */ jsx4("label", { className: "sr-only", htmlFor: "chat-input", children: "Ihre Frage" }),
|
|
1280
|
+
/* @__PURE__ */ jsx4(
|
|
1281
|
+
"textarea",
|
|
1282
|
+
{
|
|
1283
|
+
id: "chat-input",
|
|
1284
|
+
ref: inputField,
|
|
1285
|
+
rows: 1,
|
|
1286
|
+
autoFocus: true,
|
|
1287
|
+
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",
|
|
1288
|
+
value: input,
|
|
1289
|
+
disabled: resolved,
|
|
1290
|
+
maxLength: 4e3,
|
|
1291
|
+
onChange: (e) => setInput(e.target.value),
|
|
1292
|
+
onKeyDown: (e) => sendShortcut(
|
|
1293
|
+
e,
|
|
1294
|
+
busy || voiceBusy || resolved || !input.trim()
|
|
1295
|
+
),
|
|
1296
|
+
"aria-keyshortcuts": "Control+Enter Meta+Enter",
|
|
1297
|
+
"aria-describedby": "chat-shortcut",
|
|
1298
|
+
placeholder: "Ihre Frage an unser Team \u2026",
|
|
1299
|
+
required: true
|
|
1300
|
+
}
|
|
1301
|
+
),
|
|
1302
|
+
/* @__PURE__ */ jsxs4("div", { className: "chat-compose-toolbar", children: [
|
|
1303
|
+
/* @__PURE__ */ jsx4(Shortcut, { id: "chat-shortcut" }),
|
|
1304
|
+
/* @__PURE__ */ jsxs4("div", { className: "chat-compose-actions", children: [
|
|
1305
|
+
controls,
|
|
1306
|
+
/* @__PURE__ */ jsx4(
|
|
1307
|
+
"button",
|
|
1308
|
+
{
|
|
1309
|
+
type: "submit",
|
|
1310
|
+
disabled: busy || voiceBusy || resolved || !input.trim(),
|
|
1311
|
+
className: "chat-send",
|
|
1312
|
+
"aria-label": "Frage senden",
|
|
1313
|
+
children: "Senden"
|
|
1314
|
+
}
|
|
1315
|
+
)
|
|
1316
|
+
] })
|
|
1317
|
+
] })
|
|
1318
|
+
]
|
|
1267
1319
|
}
|
|
1268
1320
|
),
|
|
1269
|
-
|
|
1270
|
-
] })
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
{
|
|
1274
|
-
type: "submit",
|
|
1275
|
-
disabled: busy || voiceBusy || resolved || !input.trim(),
|
|
1276
|
-
className: "chat-send",
|
|
1277
|
-
"aria-label": "Frage senden",
|
|
1278
|
-
children: "Senden"
|
|
1279
|
-
}
|
|
1280
|
-
)
|
|
1281
|
-
] }),
|
|
1282
|
-
/* @__PURE__ */ jsx4(
|
|
1283
|
-
VoiceInput,
|
|
1284
|
-
{
|
|
1285
|
-
ctx,
|
|
1286
|
-
value: input,
|
|
1287
|
-
setValue: setInput,
|
|
1288
|
-
disabled: resolved,
|
|
1289
|
-
onBusy: setVoiceBusy
|
|
1290
|
-
}
|
|
1291
|
-
)
|
|
1292
|
-
] }),
|
|
1321
|
+
details
|
|
1322
|
+
] })
|
|
1323
|
+
}
|
|
1324
|
+
) }),
|
|
1293
1325
|
messages.length > 0 && !resolved && /* @__PURE__ */ jsx4(
|
|
1294
1326
|
"button",
|
|
1295
1327
|
{
|
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.2",
|
|
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.2",
|
|
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.2",
|
|
39
39
|
"browser": "./browser",
|
|
40
40
|
"server": "./server"
|
|
41
41
|
},
|