@ykurilov/agent-chat-skin-tandem 0.68.0 → 0.69.0

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/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # @ykurilov/agent-chat-skin-tandem
2
2
 
3
+ ## 0.69.0
4
+
5
+ ### Minor Changes
6
+
7
+ - e6c03dc: Значки шагов и заголовки раздумий (106): в простом виде — ряд значков у «Сделано N шагов» и список «значок + фраза» (`StepIcon`, `icon` в `stepPhrases`, `guessStepIcon`); `thoughtTitles` у службы чата — заголовок раздумья от провайдера или пересказ дешёвой моделью в фоне, хранится в части раздумья, в запрос основной модели не идёт, расход `thought_title`; договор скина 28 (`WorkStepsView.live.icon`, `done.items`, `icons`, `moreIcons`, `Reasoning.title`); фраза навыка с именем.
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies [e6c03dc]
12
+ - @ykurilov/agent-chat-react@0.69.0
13
+ - @ykurilov/agent-chat-skills@0.69.0
14
+ - @ykurilov/agent-chat-flows@0.69.0
15
+ - @ykurilov/agent-chat-mcp@0.69.0
16
+ - @ykurilov/agent-chat-messengers@0.69.0
17
+ - @ykurilov/agent-chat-sandbox@0.69.0
18
+
3
19
  ## 0.68.0
4
20
 
5
21
  ### Patch Changes
package/README.md CHANGED
@@ -29,6 +29,10 @@ pnpm add @ykurilov/agent-chat-skin-tandem "@tandem/ui@npm:@ykurilov/tandem-ui@^0
29
29
  (`BranchSwitcher`), правка идёт на месте пузыря (`MessageEditor`). Строка с кнопками занимает прежний промежуток между сообщениями:
30
30
  высота сообщения не меняется. На телефоне кнопки видны без наведения.
31
31
 
32
+ Простой вид работы агента (договор 28): рядом с «Сделано N шагов» — ряд значков шагов lucide (больше 8 — «+N»), в
33
+ раскрытом списке у каждой строки свой значок, в живой строке значок текущего шага заменяет точку. Раздумье с заголовком
34
+ от сервера показывает его вместо «Думал N сек», и в подробном виде тоже.
35
+
32
36
  Свои кнопки приложения под ответом (`messageActions`, договор скина версии 17) стоят в том же ряду, после копирования: с иконкой —
33
37
  кнопка-иконка с подсказкой, как копирование; без иконки — подпись текстом, как «Повторить». Пока обработчик идёт, кнопка неактивна.
34
38
 
package/dist/index.js CHANGED
@@ -1907,10 +1907,10 @@ import { useChatLabels as useChatLabels30 } from "@ykurilov/agent-chat-react";
1907
1907
  import { ChevronDown as ChevronDown3 } from "lucide-react";
1908
1908
  import { useId as useId3 } from "react";
1909
1909
  import { jsx as jsx34, jsxs as jsxs31 } from "react/jsx-runtime";
1910
- function TandemReasoning({ text, streaming, durationMs, open, onOpenChange }) {
1910
+ function TandemReasoning({ text, streaming, durationMs, title: thoughtTitle, open, onOpenChange }) {
1911
1911
  const labels = useChatLabels30();
1912
1912
  const contentId = useId3();
1913
- const title = streaming ? /* @__PURE__ */ jsx34(TandemThinkingLabel, {}) : durationMs === null ? labels.reasoningRunning : labels.reasoningDone(Math.max(1, Math.round(durationMs / 1e3)));
1913
+ const title = streaming ? /* @__PURE__ */ jsx34(TandemThinkingLabel, {}) : thoughtTitle ? thoughtTitle : durationMs === null ? labels.reasoningRunning : labels.reasoningDone(Math.max(1, Math.round(durationMs / 1e3)));
1914
1914
  return /* @__PURE__ */ jsxs31("div", { className: "mb-2 not-first:mt-3", children: [
1915
1915
  /* @__PURE__ */ jsxs31(
1916
1916
  Button20,
@@ -2775,22 +2775,53 @@ function StatusMark2({ status }) {
2775
2775
  }
2776
2776
 
2777
2777
  // src/work-steps.tsx
2778
- import { Button as Button29, cn as cn12 } from "@tandem/ui";
2778
+ import { Button as Button29, cn as cn13 } from "@tandem/ui";
2779
2779
  import { useChatLabels as useChatLabels43 } from "@ykurilov/agent-chat-react";
2780
2780
  import { ChevronDown as ChevronDown6 } from "lucide-react";
2781
2781
  import { useId as useId13 } from "react";
2782
- import { jsx as jsx51, jsxs as jsxs42 } from "react/jsx-runtime";
2782
+
2783
+ // src/step-icon.tsx
2784
+ import { cn as cn12 } from "@tandem/ui";
2785
+ import { BookOpen, Bookmark, Bot, Brain as Brain2, Camera, CircleCheck, Clock as Clock2, Eye, Film as Film2, Globe, Image, Pencil as Pencil4, Plug, Search, SquareTerminal, Wrench } from "lucide-react";
2786
+ import { jsx as jsx51 } from "react/jsx-runtime";
2787
+ var ICONS = {
2788
+ thinking: Brain2,
2789
+ read: Eye,
2790
+ edit: Pencil4,
2791
+ search: Search,
2792
+ web: Globe,
2793
+ skill: BookOpen,
2794
+ mcp: Plug,
2795
+ image: Image,
2796
+ video: Film2,
2797
+ check: CircleCheck,
2798
+ snapshot: Camera,
2799
+ run: SquareTerminal,
2800
+ memory: Bookmark,
2801
+ helper: Bot,
2802
+ task: Clock2,
2803
+ tool: Wrench
2804
+ };
2805
+ function TandemStepIcon({ icon, className }) {
2806
+ const known = Object.hasOwn(ICONS, icon) ? icon : "tool";
2807
+ const Icon = ICONS[known];
2808
+ return /* @__PURE__ */ jsx51(Icon, { "aria-hidden": "true", "data-step-icon": known, className: cn12("size-3.5 shrink-0", className), strokeWidth: 1.75 });
2809
+ }
2810
+
2811
+ // src/work-steps.tsx
2812
+ import { jsx as jsx52, jsxs as jsxs42 } from "react/jsx-runtime";
2783
2813
  function TandemWorkSteps(view) {
2784
2814
  const labels = useChatLabels43();
2785
2815
  const listId = useId13();
2786
2816
  if (view.state === "live") {
2787
2817
  return /* @__PURE__ */ jsxs42("div", { "data-work-live": true, className: "mb-2 flex h-7 min-w-0 items-center gap-2 last:mb-0 text-xs font-medium text-[var(--foreground-muted)] not-first:mt-3", children: [
2788
- /* @__PURE__ */ jsx51("span", { "aria-hidden": "true", className: "size-1.5 shrink-0 rounded-full bg-[var(--action)] motion-safe:animate-pulse" }),
2789
- /* @__PURE__ */ jsx51("span", { "aria-hidden": "true", "data-work-phrase": true, className: "min-w-0 truncate motion-safe:animate-[tandem-fade-in_var(--motion-fast)_ease-out]", children: view.phrase }, view.phrase),
2790
- /* @__PURE__ */ jsx51("span", { role: "status", className: "sr-only", children: labels.workView.live(labels.workView.stepRunning) })
2818
+ view.icon ? /* @__PURE__ */ jsx52(TandemStepIcon, { icon: view.icon, className: "text-[var(--action)] motion-safe:animate-pulse" }) : /* @__PURE__ */ jsx52("span", { "aria-hidden": "true", className: "size-1.5 shrink-0 rounded-full bg-[var(--action)] motion-safe:animate-pulse" }),
2819
+ /* @__PURE__ */ jsx52("span", { "aria-hidden": "true", "data-work-phrase": true, className: "min-w-0 truncate motion-safe:animate-[tandem-fade-in_var(--motion-fast)_ease-out]", children: view.phrase }, view.phrase),
2820
+ /* @__PURE__ */ jsx52("span", { role: "status", className: "sr-only", children: labels.workView.live(labels.workView.stepRunning) })
2791
2821
  ] });
2792
2822
  }
2793
- const { steps, count, open, onOpenChange } = view;
2823
+ const { steps, count, open, onOpenChange, items, icons = [], moreIcons = 0 } = view;
2824
+ const list = items ?? steps.map((step) => ({ ...step, icon: void 0 }));
2794
2825
  return /* @__PURE__ */ jsxs42("div", { className: "mb-2 not-first:mt-3", children: [
2795
2826
  /* @__PURE__ */ jsxs42(
2796
2827
  Button29,
@@ -2800,14 +2831,30 @@ function TandemWorkSteps(view) {
2800
2831
  "aria-expanded": open,
2801
2832
  "aria-controls": listId,
2802
2833
  onClick: () => onOpenChange(!open),
2803
- className: "-ml-2 h-7 gap-1 px-2 text-xs font-medium text-[var(--foreground-muted)]",
2834
+ className: "-ml-2 h-7 max-w-full min-w-0 gap-1 px-2 text-xs font-medium text-[var(--foreground-muted)]",
2804
2835
  children: [
2805
- labels.workView.stepsDone(count),
2806
- /* @__PURE__ */ jsx51(ChevronDown6, { "aria-hidden": "true", className: cn12("size-3.5 transition-transform duration-[var(--motion-fast)]", open && "rotate-180") })
2836
+ /* @__PURE__ */ jsx52("span", { className: "shrink-0", children: labels.workView.stepsDone(count) }),
2837
+ icons.length > 0 && /* @__PURE__ */ jsxs42("span", { "data-step-icons": true, "aria-hidden": "true", className: "ml-1 flex min-w-0 items-center gap-1 overflow-hidden text-[var(--foreground-subtle)]", children: [
2838
+ icons.map((icon, index) => /* @__PURE__ */ jsx52(TandemStepIcon, { icon }, index)),
2839
+ moreIcons > 0 && /* @__PURE__ */ jsx52("span", { className: "shrink-0 tabular-nums", children: labels.workView.moreSteps(moreIcons) })
2840
+ ] }),
2841
+ /* @__PURE__ */ jsx52(ChevronDown6, { "aria-hidden": "true", className: cn13("size-3.5 shrink-0 transition-transform duration-[var(--motion-fast)]", open && "rotate-180") })
2807
2842
  ]
2808
2843
  }
2809
2844
  ),
2810
- /* @__PURE__ */ jsx51("ol", { id: listId, hidden: !open, className: "mt-1 space-y-1 border-l-2 border-[var(--border)] pl-3 text-xs leading-5 text-[var(--foreground-muted)]", children: open && steps.map((step, index) => /* @__PURE__ */ jsx51("li", { "data-work-step": true, "data-failed": String(step.failed), className: cn12("min-w-0 break-words [overflow-wrap:anywhere]", step.failed && "text-[var(--foreground-subtle)] line-through decoration-[var(--border)]"), children: step.phrase }, index)) })
2845
+ /* @__PURE__ */ jsx52("ol", { id: listId, hidden: !open, className: "mt-1 space-y-1 border-l-2 border-[var(--border)] pl-3 text-xs leading-5 text-[var(--foreground-muted)]", children: open && list.map((step, index) => /* @__PURE__ */ jsxs42(
2846
+ "li",
2847
+ {
2848
+ "data-work-step": true,
2849
+ "data-failed": String(step.failed),
2850
+ className: cn13("flex min-w-0 items-start gap-1.5 break-words [overflow-wrap:anywhere]", step.failed && "text-[var(--foreground-subtle)] line-through decoration-[var(--border)]"),
2851
+ children: [
2852
+ step.icon && /* @__PURE__ */ jsx52(TandemStepIcon, { icon: step.icon, className: "mt-[3px] text-[var(--foreground-subtle)]" }),
2853
+ /* @__PURE__ */ jsx52("span", { className: "min-w-0", children: step.phrase })
2854
+ ]
2855
+ },
2856
+ index
2857
+ )) })
2811
2858
  ] });
2812
2859
  }
2813
2860