@wallavi/widget 1.6.1 → 1.6.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/dist/index.d.mts CHANGED
@@ -21,13 +21,25 @@ type PickerPart = {
21
21
  }>;
22
22
  selectedValue?: string;
23
23
  };
24
+ type PlanStepState = {
25
+ index: number;
26
+ description: string;
27
+ status: "pending" | "executing" | "success" | "failed";
28
+ error?: string;
29
+ };
30
+ type PlanPart = {
31
+ type: "plan";
32
+ planId: string;
33
+ goal: string;
34
+ steps: PlanStepState[];
35
+ };
24
36
  type MessagePart = {
25
37
  type: "text";
26
38
  text: string;
27
39
  } | {
28
40
  type: "reasoning";
29
41
  text: string;
30
- } | ToolPart | PickerPart;
42
+ } | ToolPart | PickerPart | PlanPart;
31
43
  type Message = {
32
44
  id: string;
33
45
  role: "user" | "assistant";
package/dist/index.d.ts CHANGED
@@ -21,13 +21,25 @@ type PickerPart = {
21
21
  }>;
22
22
  selectedValue?: string;
23
23
  };
24
+ type PlanStepState = {
25
+ index: number;
26
+ description: string;
27
+ status: "pending" | "executing" | "success" | "failed";
28
+ error?: string;
29
+ };
30
+ type PlanPart = {
31
+ type: "plan";
32
+ planId: string;
33
+ goal: string;
34
+ steps: PlanStepState[];
35
+ };
24
36
  type MessagePart = {
25
37
  type: "text";
26
38
  text: string;
27
39
  } | {
28
40
  type: "reasoning";
29
41
  text: string;
30
- } | ToolPart | PickerPart;
42
+ } | ToolPart | PickerPart | PlanPart;
31
43
  type Message = {
32
44
  id: string;
33
45
  role: "user" | "assistant";
package/dist/index.js CHANGED
@@ -205,6 +205,30 @@ function useChat({
205
205
  });
206
206
  break;
207
207
  }
208
+ case "plan-created": {
209
+ msg.parts.push({
210
+ type: "plan",
211
+ planId: proto.planId,
212
+ goal: proto.goal,
213
+ steps: proto.steps.map((s) => ({ ...s, status: "pending" }))
214
+ });
215
+ break;
216
+ }
217
+ case "plan-step-update": {
218
+ const pIdx = msg.parts.findIndex(
219
+ (p) => p.type === "plan" && p.planId === proto.planId
220
+ );
221
+ if (pIdx !== -1) {
222
+ const prev2 = msg.parts[pIdx];
223
+ msg.parts[pIdx] = {
224
+ ...prev2,
225
+ steps: prev2.steps.map(
226
+ (s) => s.index === proto.stepIndex ? { ...s, status: proto.status, ...proto.error ? { error: proto.error } : {} } : s
227
+ )
228
+ };
229
+ }
230
+ break;
231
+ }
208
232
  }
209
233
  const copy = [...prev];
210
234
  copy[idx] = msg;
@@ -717,6 +741,60 @@ function SentAttachments({ attachments, contrastColor }) {
717
741
  )) })
718
742
  ] });
719
743
  }
744
+ function PlanStepIcon({ status }) {
745
+ if (status === "executing") return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "h-3 w-3 animate-spin text-primary" });
746
+ if (status === "success") return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckCircle2, { className: "h-3 w-3 text-emerald-500" });
747
+ if (status === "failed") return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircle, { className: "h-3 w-3 text-destructive" });
748
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-3 w-3 rounded-full border-2 border-muted-foreground/30" });
749
+ }
750
+ function PlanCard({ part }) {
751
+ const successCount = part.steps.filter((s) => s.status === "success").length;
752
+ const hasExecuting = part.steps.some((s) => s.status === "executing");
753
+ const allDone = successCount === part.steps.length && part.steps.length > 0;
754
+ const anyFailed = part.steps.some((s) => s.status === "failed");
755
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border bg-background overflow-hidden text-xs w-full shadow-sm", children: [
756
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 px-3 py-2 bg-muted/50 border-b", children: [
757
+ hasExecuting ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "h-3.5 w-3.5 shrink-0 animate-spin text-primary/80" }) : allDone ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckCircle2, { className: "h-3.5 w-3.5 shrink-0 text-emerald-500" }) : anyFailed ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircle, { className: "h-3.5 w-3.5 shrink-0 text-destructive" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Zap, { className: "h-3.5 w-3.5 shrink-0 text-primary/70" }),
758
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-foreground/80 truncate flex-1 leading-snug", children: part.goal }),
759
+ part.steps.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "shrink-0 tabular-nums text-muted-foreground", children: [
760
+ successCount,
761
+ "/",
762
+ part.steps.length
763
+ ] })
764
+ ] }),
765
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "divide-y divide-border/40", children: part.steps.map((step) => /* @__PURE__ */ jsxRuntime.jsxs(
766
+ "div",
767
+ {
768
+ className: cn(
769
+ "flex items-start gap-2.5 px-3 py-2 transition-colors duration-200",
770
+ step.status === "executing" && "bg-primary/5"
771
+ ),
772
+ children: [
773
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-0.5 shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(PlanStepIcon, { status: step.status }) }),
774
+ /* @__PURE__ */ jsxRuntime.jsxs(
775
+ "span",
776
+ {
777
+ className: cn(
778
+ "leading-relaxed",
779
+ step.status === "pending" && "text-muted-foreground",
780
+ step.status === "executing" && "text-foreground font-medium",
781
+ step.status === "success" && "text-foreground/60 line-through decoration-foreground/20",
782
+ step.status === "failed" && "text-destructive"
783
+ ),
784
+ children: [
785
+ step.index + 1,
786
+ ". ",
787
+ step.description,
788
+ step.error && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "block text-destructive/70 text-[10px] mt-0.5 no-underline", children: step.error })
789
+ ]
790
+ }
791
+ )
792
+ ]
793
+ },
794
+ step.index
795
+ )) })
796
+ ] });
797
+ }
720
798
  function ThinkingDots() {
721
799
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
722
800
  /* @__PURE__ */ jsxRuntime.jsx("style", { children: `
@@ -905,6 +983,7 @@ function MessageBubble({
905
983
  const reasoningPart = message.parts.find((p) => p.type === "reasoning");
906
984
  const toolParts = message.parts.filter((p) => p.type === "tool");
907
985
  const pickerParts = message.parts.filter((p) => p.type === "picker");
986
+ const planParts = message.parts.filter((p) => p.type === "plan");
908
987
  const contrastColor = getContrastColor(userColor);
909
988
  if (isUser) {
910
989
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-end", children: /* @__PURE__ */ jsxRuntime.jsxs(
@@ -925,6 +1004,7 @@ function MessageBubble({
925
1004
  /* @__PURE__ */ jsxRuntime.jsx(Avatar2, { style: { width: 28, height: 28, marginTop: 2, border: "1px solid rgba(0,0,0,0.08)" }, children: profilePicture ? /* @__PURE__ */ jsxRuntime.jsx(AvatarImage2, { src: profilePicture, alt: agentName }) : /* @__PURE__ */ jsxRuntime.jsx(AvatarFallback2, { style: { fontSize: 10, fontWeight: 600, backgroundColor: "var(--primary, #19191c)", color: "var(--primary-foreground, #fff)" }, children: agentName.slice(0, 2).toUpperCase() }) }),
926
1005
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1.5 min-w-0 max-w-[82%]", children: [
927
1006
  showThinking && reasoningPart && /* @__PURE__ */ jsxRuntime.jsx(ReasoningBlock, { text: reasoningPart.text }),
1007
+ planParts.map((p) => /* @__PURE__ */ jsxRuntime.jsx(PlanCard, { part: p }, p.planId)),
928
1008
  visibleToolParts.map((t) => /* @__PURE__ */ jsxRuntime.jsx(ToolCallBadge, { part: t }, t.toolCallId)),
929
1009
  pickerParts.map((p) => /* @__PURE__ */ jsxRuntime.jsx(
930
1010
  PickerSelector,
package/dist/index.mjs CHANGED
@@ -179,6 +179,30 @@ function useChat({
179
179
  });
180
180
  break;
181
181
  }
182
+ case "plan-created": {
183
+ msg.parts.push({
184
+ type: "plan",
185
+ planId: proto.planId,
186
+ goal: proto.goal,
187
+ steps: proto.steps.map((s) => ({ ...s, status: "pending" }))
188
+ });
189
+ break;
190
+ }
191
+ case "plan-step-update": {
192
+ const pIdx = msg.parts.findIndex(
193
+ (p) => p.type === "plan" && p.planId === proto.planId
194
+ );
195
+ if (pIdx !== -1) {
196
+ const prev2 = msg.parts[pIdx];
197
+ msg.parts[pIdx] = {
198
+ ...prev2,
199
+ steps: prev2.steps.map(
200
+ (s) => s.index === proto.stepIndex ? { ...s, status: proto.status, ...proto.error ? { error: proto.error } : {} } : s
201
+ )
202
+ };
203
+ }
204
+ break;
205
+ }
182
206
  }
183
207
  const copy = [...prev];
184
208
  copy[idx] = msg;
@@ -691,6 +715,60 @@ function SentAttachments({ attachments, contrastColor }) {
691
715
  )) })
692
716
  ] });
693
717
  }
718
+ function PlanStepIcon({ status }) {
719
+ if (status === "executing") return /* @__PURE__ */ jsx(Loader2, { className: "h-3 w-3 animate-spin text-primary" });
720
+ if (status === "success") return /* @__PURE__ */ jsx(CheckCircle2, { className: "h-3 w-3 text-emerald-500" });
721
+ if (status === "failed") return /* @__PURE__ */ jsx(AlertCircle, { className: "h-3 w-3 text-destructive" });
722
+ return /* @__PURE__ */ jsx("div", { className: "h-3 w-3 rounded-full border-2 border-muted-foreground/30" });
723
+ }
724
+ function PlanCard({ part }) {
725
+ const successCount = part.steps.filter((s) => s.status === "success").length;
726
+ const hasExecuting = part.steps.some((s) => s.status === "executing");
727
+ const allDone = successCount === part.steps.length && part.steps.length > 0;
728
+ const anyFailed = part.steps.some((s) => s.status === "failed");
729
+ return /* @__PURE__ */ jsxs("div", { className: "rounded-xl border bg-background overflow-hidden text-xs w-full shadow-sm", children: [
730
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 px-3 py-2 bg-muted/50 border-b", children: [
731
+ hasExecuting ? /* @__PURE__ */ jsx(Loader2, { className: "h-3.5 w-3.5 shrink-0 animate-spin text-primary/80" }) : allDone ? /* @__PURE__ */ jsx(CheckCircle2, { className: "h-3.5 w-3.5 shrink-0 text-emerald-500" }) : anyFailed ? /* @__PURE__ */ jsx(AlertCircle, { className: "h-3.5 w-3.5 shrink-0 text-destructive" }) : /* @__PURE__ */ jsx(Zap, { className: "h-3.5 w-3.5 shrink-0 text-primary/70" }),
732
+ /* @__PURE__ */ jsx("span", { className: "font-medium text-foreground/80 truncate flex-1 leading-snug", children: part.goal }),
733
+ part.steps.length > 0 && /* @__PURE__ */ jsxs("span", { className: "shrink-0 tabular-nums text-muted-foreground", children: [
734
+ successCount,
735
+ "/",
736
+ part.steps.length
737
+ ] })
738
+ ] }),
739
+ /* @__PURE__ */ jsx("div", { className: "divide-y divide-border/40", children: part.steps.map((step) => /* @__PURE__ */ jsxs(
740
+ "div",
741
+ {
742
+ className: cn(
743
+ "flex items-start gap-2.5 px-3 py-2 transition-colors duration-200",
744
+ step.status === "executing" && "bg-primary/5"
745
+ ),
746
+ children: [
747
+ /* @__PURE__ */ jsx("div", { className: "mt-0.5 shrink-0", children: /* @__PURE__ */ jsx(PlanStepIcon, { status: step.status }) }),
748
+ /* @__PURE__ */ jsxs(
749
+ "span",
750
+ {
751
+ className: cn(
752
+ "leading-relaxed",
753
+ step.status === "pending" && "text-muted-foreground",
754
+ step.status === "executing" && "text-foreground font-medium",
755
+ step.status === "success" && "text-foreground/60 line-through decoration-foreground/20",
756
+ step.status === "failed" && "text-destructive"
757
+ ),
758
+ children: [
759
+ step.index + 1,
760
+ ". ",
761
+ step.description,
762
+ step.error && /* @__PURE__ */ jsx("span", { className: "block text-destructive/70 text-[10px] mt-0.5 no-underline", children: step.error })
763
+ ]
764
+ }
765
+ )
766
+ ]
767
+ },
768
+ step.index
769
+ )) })
770
+ ] });
771
+ }
694
772
  function ThinkingDots() {
695
773
  return /* @__PURE__ */ jsxs(Fragment, { children: [
696
774
  /* @__PURE__ */ jsx("style", { children: `
@@ -879,6 +957,7 @@ function MessageBubble({
879
957
  const reasoningPart = message.parts.find((p) => p.type === "reasoning");
880
958
  const toolParts = message.parts.filter((p) => p.type === "tool");
881
959
  const pickerParts = message.parts.filter((p) => p.type === "picker");
960
+ const planParts = message.parts.filter((p) => p.type === "plan");
882
961
  const contrastColor = getContrastColor(userColor);
883
962
  if (isUser) {
884
963
  return /* @__PURE__ */ jsx("div", { className: "flex justify-end", children: /* @__PURE__ */ jsxs(
@@ -899,6 +978,7 @@ function MessageBubble({
899
978
  /* @__PURE__ */ jsx(Avatar2, { style: { width: 28, height: 28, marginTop: 2, border: "1px solid rgba(0,0,0,0.08)" }, children: profilePicture ? /* @__PURE__ */ jsx(AvatarImage2, { src: profilePicture, alt: agentName }) : /* @__PURE__ */ jsx(AvatarFallback2, { style: { fontSize: 10, fontWeight: 600, backgroundColor: "var(--primary, #19191c)", color: "var(--primary-foreground, #fff)" }, children: agentName.slice(0, 2).toUpperCase() }) }),
900
979
  /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5 min-w-0 max-w-[82%]", children: [
901
980
  showThinking && reasoningPart && /* @__PURE__ */ jsx(ReasoningBlock, { text: reasoningPart.text }),
981
+ planParts.map((p) => /* @__PURE__ */ jsx(PlanCard, { part: p }, p.planId)),
902
982
  visibleToolParts.map((t) => /* @__PURE__ */ jsx(ToolCallBadge, { part: t }, t.toolCallId)),
903
983
  pickerParts.map((p) => /* @__PURE__ */ jsx(
904
984
  PickerSelector,
package/package.json CHANGED
@@ -33,7 +33,7 @@
33
33
  },
34
34
  "private": false,
35
35
  "types": "./dist/index.d.ts",
36
- "version": "1.6.1",
36
+ "version": "1.6.2",
37
37
  "scripts": {
38
38
  "build": "tsup",
39
39
  "typecheck": "tsc --noEmit"