@wallavi/widget 1.13.2 → 1.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/dist/index.d.mts +4 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +72 -11
- package/dist/index.mjs +72 -11
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -358,7 +358,10 @@ interface CommandPanelProps {
|
|
|
358
358
|
ragTopics?: RagTopicInfo[];
|
|
359
359
|
ragDocuments?: RagDocumentInfo[];
|
|
360
360
|
onSend: (text: string) => void;
|
|
361
|
-
onExecuteAction?: (
|
|
361
|
+
onExecuteAction?: (action: {
|
|
362
|
+
name: string;
|
|
363
|
+
steps: any[];
|
|
364
|
+
}) => void;
|
|
362
365
|
accentColor?: string;
|
|
363
366
|
isDark?: boolean;
|
|
364
367
|
watermark?: boolean;
|
package/dist/index.d.ts
CHANGED
|
@@ -358,7 +358,10 @@ interface CommandPanelProps {
|
|
|
358
358
|
ragTopics?: RagTopicInfo[];
|
|
359
359
|
ragDocuments?: RagDocumentInfo[];
|
|
360
360
|
onSend: (text: string) => void;
|
|
361
|
-
onExecuteAction?: (
|
|
361
|
+
onExecuteAction?: (action: {
|
|
362
|
+
name: string;
|
|
363
|
+
steps: any[];
|
|
364
|
+
}) => void;
|
|
362
365
|
accentColor?: string;
|
|
363
366
|
isDark?: boolean;
|
|
364
367
|
watermark?: boolean;
|
package/dist/index.js
CHANGED
|
@@ -351,6 +351,55 @@ function applyUiEventToMessages(prev, proto, msgId) {
|
|
|
351
351
|
return copy;
|
|
352
352
|
}
|
|
353
353
|
|
|
354
|
+
// src/core/quick-action.ts
|
|
355
|
+
var BRACES = /\{\{(?:toolInput\.)?([a-zA-Z0-9_]+)\}\}|\{([a-zA-Z0-9_]+)\}/g;
|
|
356
|
+
var ROUTE = /\{\{(?:toolInput\.)?([a-zA-Z0-9_]+)\}\}|\{([a-zA-Z0-9_]+)\}|\[([a-zA-Z0-9_]+)\]|(?<=^|\/):([a-zA-Z0-9_]+)(?=[/?#]|$)/g;
|
|
357
|
+
function fill(text, pattern, sources, missing) {
|
|
358
|
+
return text.replace(pattern, (match, ...groups) => {
|
|
359
|
+
const key = groups.find((g) => typeof g === "string");
|
|
360
|
+
if (!key) return match;
|
|
361
|
+
for (const source of sources) {
|
|
362
|
+
const value = source?.[key];
|
|
363
|
+
if (typeof value === "string" && value !== "") return value;
|
|
364
|
+
if (typeof value === "number") return String(value);
|
|
365
|
+
}
|
|
366
|
+
missing?.add(key);
|
|
367
|
+
return match;
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
function fillPayload(value, sources) {
|
|
371
|
+
if (typeof value === "string") return fill(value, BRACES, sources);
|
|
372
|
+
if (Array.isArray(value)) return value.map((v) => fillPayload(v, sources));
|
|
373
|
+
if (value && typeof value === "object") {
|
|
374
|
+
return Object.fromEntries(
|
|
375
|
+
Object.entries(value).map(([k, v]) => [k, fillPayload(v, sources)])
|
|
376
|
+
);
|
|
377
|
+
}
|
|
378
|
+
return value;
|
|
379
|
+
}
|
|
380
|
+
function planQuickAction(steps, pageParams, metadata) {
|
|
381
|
+
const sources = [pageParams, metadata];
|
|
382
|
+
const missing = /* @__PURE__ */ new Set();
|
|
383
|
+
const filled = steps.map((original) => {
|
|
384
|
+
const step = original;
|
|
385
|
+
const out = { ...step };
|
|
386
|
+
if (typeof step.value === "string") {
|
|
387
|
+
out.value = step.action === "navigate" ? fill(step.value, ROUTE, sources, missing) : fill(step.value, BRACES, sources);
|
|
388
|
+
}
|
|
389
|
+
if (typeof step.selector === "string") {
|
|
390
|
+
out.selector = fill(step.selector, BRACES, sources);
|
|
391
|
+
}
|
|
392
|
+
if (step.payload !== void 0) {
|
|
393
|
+
out.payload = fillPayload(step.payload, sources);
|
|
394
|
+
}
|
|
395
|
+
return out;
|
|
396
|
+
});
|
|
397
|
+
return missing.size > 0 ? { kind: "ask_agent", missing: [...missing] } : { kind: "run", steps: filled };
|
|
398
|
+
}
|
|
399
|
+
function hasRoutePlaceholder(url) {
|
|
400
|
+
return new RegExp(ROUTE.source).test(url);
|
|
401
|
+
}
|
|
402
|
+
|
|
354
403
|
// src/core/declarative-actions.ts
|
|
355
404
|
function sanitizeSelector(selector) {
|
|
356
405
|
if (!selector || typeof selector !== "string") return null;
|
|
@@ -625,6 +674,12 @@ async function executeDeclarativeSteps(steps, onNavigate, copilotColor) {
|
|
|
625
674
|
}
|
|
626
675
|
case "navigate": {
|
|
627
676
|
const url = sanitizeUrl(step.value);
|
|
677
|
+
if (url && hasRoutePlaceholder(url)) {
|
|
678
|
+
console.warn(
|
|
679
|
+
"[Wallavi Widget] Blocked navigate with unfilled route params"
|
|
680
|
+
);
|
|
681
|
+
break;
|
|
682
|
+
}
|
|
628
683
|
if (url) {
|
|
629
684
|
if (onNavigate) {
|
|
630
685
|
onNavigate(url);
|
|
@@ -3631,7 +3686,7 @@ function CommandPanel({
|
|
|
3631
3686
|
const hasContent = hasActions || hasDocs || hasTopics;
|
|
3632
3687
|
if (!hasContent) return null;
|
|
3633
3688
|
const isSidebar = mode === "sidebar";
|
|
3634
|
-
const handleExecute = (
|
|
3689
|
+
const handleExecute = (action) => onExecuteAction?.(action);
|
|
3635
3690
|
if (isSidebar) {
|
|
3636
3691
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ww-w-[300px] ww-shrink-0 ww-border-l ww-border-border ww-bg-muted/50 ww-flex ww-flex-col ww-h-full ww-overflow-hidden ww-animate-in ww-fade-in ww-slide-in-from-right-2 ww-duration-300", children: [
|
|
3637
3692
|
/* @__PURE__ */ jsxRuntime.jsx(PageBadge, { pageTitle, pageUrl, locale }),
|
|
@@ -3644,7 +3699,7 @@ function CommandPanel({
|
|
|
3644
3699
|
action,
|
|
3645
3700
|
index: i,
|
|
3646
3701
|
accentColor,
|
|
3647
|
-
onExecute: () => handleExecute(action
|
|
3702
|
+
onExecute: () => handleExecute(action)
|
|
3648
3703
|
},
|
|
3649
3704
|
actionKeys[i]
|
|
3650
3705
|
)) })
|
|
@@ -3716,7 +3771,7 @@ function CommandPanel({
|
|
|
3716
3771
|
action,
|
|
3717
3772
|
index: i,
|
|
3718
3773
|
accentColor,
|
|
3719
|
-
onExecute: () => handleExecute(action
|
|
3774
|
+
onExecute: () => handleExecute(action)
|
|
3720
3775
|
},
|
|
3721
3776
|
actionKeys[i]
|
|
3722
3777
|
)) })
|
|
@@ -3936,12 +3991,18 @@ function ChatWidget({
|
|
|
3936
3991
|
const messagesList = isDefaultGreeting ? [getWidgetTranslation("defaultGreeting", locale)] : initialMessages;
|
|
3937
3992
|
const showSidebar = showCommandPanel && widgetLayout === "center" && isDesktop;
|
|
3938
3993
|
const showInlineCommandPanel = showCommandPanel && !showSidebar && chat.messages.length === 0 && (showQuickActions && clientActions.length > 0 || showRagTopics && ragTopics.length > 0 || showRagDocuments && ragDocuments.length > 0);
|
|
3939
|
-
const handleExecuteAction =
|
|
3940
|
-
|
|
3941
|
-
|
|
3942
|
-
|
|
3943
|
-
|
|
3944
|
-
|
|
3994
|
+
const handleExecuteAction = (action) => {
|
|
3995
|
+
const plan = planQuickAction(
|
|
3996
|
+
action.steps,
|
|
3997
|
+
resolvePageContext()?.params,
|
|
3998
|
+
userContext?.metadata
|
|
3999
|
+
);
|
|
4000
|
+
if (plan.kind === "run") {
|
|
4001
|
+
executeDeclarativeSteps(plan.steps, onNavigate, userMessageColor);
|
|
4002
|
+
} else {
|
|
4003
|
+
chat.send(action.name);
|
|
4004
|
+
}
|
|
4005
|
+
};
|
|
3945
4006
|
const [activeActionIndex, setActiveActionIndex] = react.useState(-1);
|
|
3946
4007
|
const query = chat.input.toLowerCase().trim();
|
|
3947
4008
|
const matchingActions = react.useMemo(() => {
|
|
@@ -3987,7 +4048,7 @@ function ChatWidget({
|
|
|
3987
4048
|
e.preventDefault();
|
|
3988
4049
|
const selectedAction = matchingActions[activeActionIndex];
|
|
3989
4050
|
if (selectedAction) {
|
|
3990
|
-
handleExecuteAction(selectedAction
|
|
4051
|
+
handleExecuteAction(selectedAction);
|
|
3991
4052
|
chat.setInput("");
|
|
3992
4053
|
}
|
|
3993
4054
|
} else if (e.key === "Escape") {
|
|
@@ -4222,7 +4283,7 @@ function ChatWidget({
|
|
|
4222
4283
|
"button",
|
|
4223
4284
|
{
|
|
4224
4285
|
onClick: () => {
|
|
4225
|
-
handleExecuteAction(action
|
|
4286
|
+
handleExecuteAction(action);
|
|
4226
4287
|
chat.setInput("");
|
|
4227
4288
|
},
|
|
4228
4289
|
className: cn(
|
package/dist/index.mjs
CHANGED
|
@@ -325,6 +325,55 @@ function applyUiEventToMessages(prev, proto, msgId) {
|
|
|
325
325
|
return copy;
|
|
326
326
|
}
|
|
327
327
|
|
|
328
|
+
// src/core/quick-action.ts
|
|
329
|
+
var BRACES = /\{\{(?:toolInput\.)?([a-zA-Z0-9_]+)\}\}|\{([a-zA-Z0-9_]+)\}/g;
|
|
330
|
+
var ROUTE = /\{\{(?:toolInput\.)?([a-zA-Z0-9_]+)\}\}|\{([a-zA-Z0-9_]+)\}|\[([a-zA-Z0-9_]+)\]|(?<=^|\/):([a-zA-Z0-9_]+)(?=[/?#]|$)/g;
|
|
331
|
+
function fill(text, pattern, sources, missing) {
|
|
332
|
+
return text.replace(pattern, (match, ...groups) => {
|
|
333
|
+
const key = groups.find((g) => typeof g === "string");
|
|
334
|
+
if (!key) return match;
|
|
335
|
+
for (const source of sources) {
|
|
336
|
+
const value = source?.[key];
|
|
337
|
+
if (typeof value === "string" && value !== "") return value;
|
|
338
|
+
if (typeof value === "number") return String(value);
|
|
339
|
+
}
|
|
340
|
+
missing?.add(key);
|
|
341
|
+
return match;
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
function fillPayload(value, sources) {
|
|
345
|
+
if (typeof value === "string") return fill(value, BRACES, sources);
|
|
346
|
+
if (Array.isArray(value)) return value.map((v) => fillPayload(v, sources));
|
|
347
|
+
if (value && typeof value === "object") {
|
|
348
|
+
return Object.fromEntries(
|
|
349
|
+
Object.entries(value).map(([k, v]) => [k, fillPayload(v, sources)])
|
|
350
|
+
);
|
|
351
|
+
}
|
|
352
|
+
return value;
|
|
353
|
+
}
|
|
354
|
+
function planQuickAction(steps, pageParams, metadata) {
|
|
355
|
+
const sources = [pageParams, metadata];
|
|
356
|
+
const missing = /* @__PURE__ */ new Set();
|
|
357
|
+
const filled = steps.map((original) => {
|
|
358
|
+
const step = original;
|
|
359
|
+
const out = { ...step };
|
|
360
|
+
if (typeof step.value === "string") {
|
|
361
|
+
out.value = step.action === "navigate" ? fill(step.value, ROUTE, sources, missing) : fill(step.value, BRACES, sources);
|
|
362
|
+
}
|
|
363
|
+
if (typeof step.selector === "string") {
|
|
364
|
+
out.selector = fill(step.selector, BRACES, sources);
|
|
365
|
+
}
|
|
366
|
+
if (step.payload !== void 0) {
|
|
367
|
+
out.payload = fillPayload(step.payload, sources);
|
|
368
|
+
}
|
|
369
|
+
return out;
|
|
370
|
+
});
|
|
371
|
+
return missing.size > 0 ? { kind: "ask_agent", missing: [...missing] } : { kind: "run", steps: filled };
|
|
372
|
+
}
|
|
373
|
+
function hasRoutePlaceholder(url) {
|
|
374
|
+
return new RegExp(ROUTE.source).test(url);
|
|
375
|
+
}
|
|
376
|
+
|
|
328
377
|
// src/core/declarative-actions.ts
|
|
329
378
|
function sanitizeSelector(selector) {
|
|
330
379
|
if (!selector || typeof selector !== "string") return null;
|
|
@@ -599,6 +648,12 @@ async function executeDeclarativeSteps(steps, onNavigate, copilotColor) {
|
|
|
599
648
|
}
|
|
600
649
|
case "navigate": {
|
|
601
650
|
const url = sanitizeUrl(step.value);
|
|
651
|
+
if (url && hasRoutePlaceholder(url)) {
|
|
652
|
+
console.warn(
|
|
653
|
+
"[Wallavi Widget] Blocked navigate with unfilled route params"
|
|
654
|
+
);
|
|
655
|
+
break;
|
|
656
|
+
}
|
|
602
657
|
if (url) {
|
|
603
658
|
if (onNavigate) {
|
|
604
659
|
onNavigate(url);
|
|
@@ -3605,7 +3660,7 @@ function CommandPanel({
|
|
|
3605
3660
|
const hasContent = hasActions || hasDocs || hasTopics;
|
|
3606
3661
|
if (!hasContent) return null;
|
|
3607
3662
|
const isSidebar = mode === "sidebar";
|
|
3608
|
-
const handleExecute = (
|
|
3663
|
+
const handleExecute = (action) => onExecuteAction?.(action);
|
|
3609
3664
|
if (isSidebar) {
|
|
3610
3665
|
return /* @__PURE__ */ jsxs("div", { className: "ww-w-[300px] ww-shrink-0 ww-border-l ww-border-border ww-bg-muted/50 ww-flex ww-flex-col ww-h-full ww-overflow-hidden ww-animate-in ww-fade-in ww-slide-in-from-right-2 ww-duration-300", children: [
|
|
3611
3666
|
/* @__PURE__ */ jsx(PageBadge, { pageTitle, pageUrl, locale }),
|
|
@@ -3618,7 +3673,7 @@ function CommandPanel({
|
|
|
3618
3673
|
action,
|
|
3619
3674
|
index: i,
|
|
3620
3675
|
accentColor,
|
|
3621
|
-
onExecute: () => handleExecute(action
|
|
3676
|
+
onExecute: () => handleExecute(action)
|
|
3622
3677
|
},
|
|
3623
3678
|
actionKeys[i]
|
|
3624
3679
|
)) })
|
|
@@ -3690,7 +3745,7 @@ function CommandPanel({
|
|
|
3690
3745
|
action,
|
|
3691
3746
|
index: i,
|
|
3692
3747
|
accentColor,
|
|
3693
|
-
onExecute: () => handleExecute(action
|
|
3748
|
+
onExecute: () => handleExecute(action)
|
|
3694
3749
|
},
|
|
3695
3750
|
actionKeys[i]
|
|
3696
3751
|
)) })
|
|
@@ -3910,12 +3965,18 @@ function ChatWidget({
|
|
|
3910
3965
|
const messagesList = isDefaultGreeting ? [getWidgetTranslation("defaultGreeting", locale)] : initialMessages;
|
|
3911
3966
|
const showSidebar = showCommandPanel && widgetLayout === "center" && isDesktop;
|
|
3912
3967
|
const showInlineCommandPanel = showCommandPanel && !showSidebar && chat.messages.length === 0 && (showQuickActions && clientActions.length > 0 || showRagTopics && ragTopics.length > 0 || showRagDocuments && ragDocuments.length > 0);
|
|
3913
|
-
const handleExecuteAction =
|
|
3914
|
-
|
|
3915
|
-
|
|
3916
|
-
|
|
3917
|
-
|
|
3918
|
-
|
|
3968
|
+
const handleExecuteAction = (action) => {
|
|
3969
|
+
const plan = planQuickAction(
|
|
3970
|
+
action.steps,
|
|
3971
|
+
resolvePageContext()?.params,
|
|
3972
|
+
userContext?.metadata
|
|
3973
|
+
);
|
|
3974
|
+
if (plan.kind === "run") {
|
|
3975
|
+
executeDeclarativeSteps(plan.steps, onNavigate, userMessageColor);
|
|
3976
|
+
} else {
|
|
3977
|
+
chat.send(action.name);
|
|
3978
|
+
}
|
|
3979
|
+
};
|
|
3919
3980
|
const [activeActionIndex, setActiveActionIndex] = useState(-1);
|
|
3920
3981
|
const query = chat.input.toLowerCase().trim();
|
|
3921
3982
|
const matchingActions = useMemo(() => {
|
|
@@ -3961,7 +4022,7 @@ function ChatWidget({
|
|
|
3961
4022
|
e.preventDefault();
|
|
3962
4023
|
const selectedAction = matchingActions[activeActionIndex];
|
|
3963
4024
|
if (selectedAction) {
|
|
3964
|
-
handleExecuteAction(selectedAction
|
|
4025
|
+
handleExecuteAction(selectedAction);
|
|
3965
4026
|
chat.setInput("");
|
|
3966
4027
|
}
|
|
3967
4028
|
} else if (e.key === "Escape") {
|
|
@@ -4196,7 +4257,7 @@ function ChatWidget({
|
|
|
4196
4257
|
"button",
|
|
4197
4258
|
{
|
|
4198
4259
|
onClick: () => {
|
|
4199
|
-
handleExecuteAction(action
|
|
4260
|
+
handleExecuteAction(action);
|
|
4200
4261
|
chat.setInput("");
|
|
4201
4262
|
},
|
|
4202
4263
|
className: cn(
|
package/package.json
CHANGED
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
},
|
|
45
45
|
"private": false,
|
|
46
46
|
"types": "./dist/index.d.ts",
|
|
47
|
-
"version": "1.13.
|
|
47
|
+
"version": "1.13.3",
|
|
48
48
|
"scripts": {
|
|
49
49
|
"build": "tsup && pnpm build:css",
|
|
50
50
|
"build:css": "tailwindcss -i ./src/styles.css -o ./dist/styles.css --config tailwind.config.cjs --minify",
|