@actioneer/ads 0.5.2 → 0.5.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.
@@ -14,12 +14,17 @@ import { ToolState } from './tool';
14
14
  * What it renders, always:
15
15
  * 1. Phases — steps grouped by `group`, each a `Task` disclosure; finished
16
16
  * phases fold away while another is active.
17
- * 2. Steps — a `ChainOfThought connector="tree"` per phase; settled steps
17
+ * 2. Steps — a tree-connected `ChainOfThought` per phase; settled steps
18
18
  * hang off the phase on a measured tree connector.
19
19
  * 3. Tools — each call is a `Tool` card hung off its step as a branch.
20
20
  * Plus the reason-first live line (the `active` step is narrated by
21
21
  * `ResearchActivity` and joins the tree only once it settles) and, when an
22
22
  * active step outruns `slowSeconds`, the handoff `Alert`.
23
+ *
24
+ * A FULLY SETTLED trace rests as ONE summary line ("Completed N research
25
+ * steps · time") and expands on click to reveal the phases — the same
26
+ * single-line contract the Chain of Thought family keeps. The phase rows
27
+ * never stack above the answer once the run is over.
23
28
  */
24
29
  /** A single tool call within a step. */
25
30
  export interface AgentTraceCall {
@@ -1,51 +1,51 @@
1
1
  "use client";
2
- import { jsxs as a, jsx as t, Fragment as j } from "react/jsx-runtime";
3
- import { memo as b, useState as D, useRef as _, useEffect as z } from "react";
4
- import { cn as L } from "../../lib/cn.js";
5
- import { Clock as F } from "../../lib/icons.js";
6
- import { Alert as G, AlertTitle as H, AlertDescription as U } from "../alert.js";
7
- import { Button as B } from "../button.js";
8
- import { Text as K } from "../typography.js";
9
- import { ChainOfThoughtStep as P, ChainOfThoughtTrigger as W, ChainOfThoughtContent as q, ChainOfThoughtItem as J, ChainOfThoughtSearchResults as Q, ChainOfThoughtSearchResult as V, ChainOfThought as X } from "./chain-of-thought.js";
10
- import { ResearchActivity as Y } from "./research-activity.js";
11
- import { Task as Z, TaskTrigger as ee, TaskContent as te } from "./task.js";
12
- import { Tool as ne, ToolHeader as re, ToolContent as oe, ToolInput as se, ToolOutput as ie } from "./tool.js";
13
- const ae = "Main Agent", le = 60;
14
- function x(e) {
2
+ import { jsxs as a, jsx as t, Fragment as U } from "react/jsx-runtime";
3
+ import { memo as I, useState as B, useRef as k, useEffect as M } from "react";
4
+ import { cn as K } from "../../lib/cn.js";
5
+ import { Clock as W } from "../../lib/icons.js";
6
+ import { Alert as q, AlertTitle as J, AlertDescription as P } from "../alert.js";
7
+ import { Button as Q } from "../button.js";
8
+ import { Text as V } from "../typography.js";
9
+ import { ChainOfThoughtStep as X, ChainOfThoughtTrigger as Y, ChainOfThoughtContent as Z, ChainOfThoughtItem as ee, ChainOfThoughtSearchResults as te, ChainOfThoughtSearchResult as ne, ChainOfThought as re } from "./chain-of-thought.js";
10
+ import { ResearchActivity as E } from "./research-activity.js";
11
+ import { Task as oe, TaskTrigger as se, TaskContent as le } from "./task.js";
12
+ import { Tool as ae, ToolHeader as ie, ToolContent as ce, ToolInput as de, ToolOutput as ue } from "./tool.js";
13
+ const he = "Main Agent", me = 60;
14
+ function S(e) {
15
15
  const o = Math.floor(e);
16
16
  return `${Math.floor(o / 60)}:${String(o % 60).padStart(2, "0")}`;
17
17
  }
18
- function v(e) {
18
+ function A(e) {
19
19
  if (e.elapsed != null) return e.elapsed;
20
- if (e.seconds != null) return x(e.seconds);
20
+ if (e.seconds != null) return S(e.seconds);
21
21
  }
22
- function y(e) {
22
+ function T(e) {
23
23
  const o = [];
24
24
  for (const s of e) o.includes(s.group) || o.push(s.group);
25
25
  return o;
26
26
  }
27
- function ce(e) {
28
- const o = new Set(e.flatMap((i) => i.sources ?? [])).size, s = e.reduce((i, c) => i + (c.seconds ?? 0), 0), l = [];
29
- return o && l.push(`${o} ${o === 1 ? "source" : "sources"}`), s && e.length > 1 && l.push(x(s)), l.join(" · ") || void 0;
27
+ function fe(e) {
28
+ const o = new Set(e.flatMap((l) => l.sources ?? [])).size, s = e.reduce((l, c) => l + (c.seconds ?? 0), 0), i = [];
29
+ return o && i.push(`${o} ${o === 1 ? "source" : "sources"}`), s && e.length > 1 && i.push(S(s)), i.join(" · ") || void 0;
30
30
  }
31
- function de(e) {
32
- var i, c, h;
33
- const o = (c = (i = e.calls) == null ? void 0 : i[0]) == null ? void 0 : c.name, s = (((h = e.calls) == null ? void 0 : h.length) ?? 0) - 1, l = s > 0 ? ` ${s} other call${s === 1 ? "" : "s"} in this step ${s === 1 ? "is" : "are"} waiting behind it.` : "";
31
+ function pe(e) {
32
+ var l, c, p;
33
+ const o = (c = (l = e.calls) == null ? void 0 : l[0]) == null ? void 0 : c.name, s = (((p = e.calls) == null ? void 0 : p.length) ?? 0) - 1, i = s > 0 ? ` ${s} other call${s === 1 ? "" : "s"} in this step ${s === 1 ? "is" : "are"} waiting behind it.` : "";
34
34
  return {
35
35
  title: o ? `The ${o} call has not returned` : "This step has not finished",
36
- detail: /* @__PURE__ */ a(j, { children: [
36
+ detail: /* @__PURE__ */ a(U, { children: [
37
37
  e.detail,
38
- l,
38
+ i,
39
39
  " Send for review to the Actioneer team to help with future runs."
40
40
  ] })
41
41
  };
42
42
  }
43
- const A = b(({ call: e }) => /* @__PURE__ */ a(ne, { children: [
44
- /* @__PURE__ */ t(re, { title: e.name, type: `tool-${e.name}`, state: e.state }),
45
- /* @__PURE__ */ a(oe, { children: [
46
- e.input !== void 0 && /* @__PURE__ */ t(se, { input: e.input }),
43
+ const R = I(({ call: e }) => /* @__PURE__ */ a(ae, { children: [
44
+ /* @__PURE__ */ t(ie, { title: e.name, type: `tool-${e.name}`, state: e.state }),
45
+ /* @__PURE__ */ a(ce, { children: [
46
+ e.input !== void 0 && /* @__PURE__ */ t(de, { input: e.input }),
47
47
  /* @__PURE__ */ t(
48
- ie,
48
+ ue,
49
49
  {
50
50
  output: e.state === "output-available" ? e.output : void 0,
51
51
  errorText: e.state === "output-error" ? e.error : void 0
@@ -53,28 +53,28 @@ const A = b(({ call: e }) => /* @__PURE__ */ a(ne, { children: [
53
53
  )
54
54
  ] })
55
55
  ] }));
56
- A.displayName = "AgentTrace.ToolCard";
57
- const O = b(
56
+ R.displayName = "AgentTrace.ToolCard";
57
+ const j = I(
58
58
  ({
59
59
  step: e,
60
60
  mainAgent: o,
61
61
  renderCall: s
62
62
  }) => {
63
- const l = v(e);
64
- return /* @__PURE__ */ a(P, { status: e.status === "error" ? "error" : "complete", children: [
65
- /* @__PURE__ */ a(W, { leftIcon: e.icon, endContent: l, children: [
63
+ const i = A(e);
64
+ return /* @__PURE__ */ a(X, { status: e.status === "error" ? "error" : "complete", children: [
65
+ /* @__PURE__ */ a(Y, { leftIcon: e.icon, endContent: i, children: [
66
66
  /* @__PURE__ */ t("span", { children: e.label }),
67
67
  e.agent && e.agent !== o && /* @__PURE__ */ t("span", { className: "ml-2 text-xs font-normal text-tertiary", children: e.agent })
68
68
  ] }),
69
- /* @__PURE__ */ t(q, { children: /* @__PURE__ */ a("div", { className: "-ml-5", style: { "--tree-rail-lead": "18px" }, children: [
70
- e.detail != null && /* @__PURE__ */ t("div", { className: "ads-tree-rail pb-3", children: /* @__PURE__ */ t(J, { children: e.detail }) }),
71
- e.sources && e.sources.length > 0 && /* @__PURE__ */ t("div", { className: "ads-tree-rail pb-3", children: /* @__PURE__ */ t(Q, { children: e.sources.map((i) => /* @__PURE__ */ t(V, { children: i }, i)) }) }),
72
- (e.calls ?? []).map((i, c) => /* @__PURE__ */ t(
69
+ /* @__PURE__ */ t(Z, { rail: !1, children: /* @__PURE__ */ a("div", { className: "-ml-5", style: { "--tree-rail-lead": "18px" }, children: [
70
+ e.detail != null && /* @__PURE__ */ t("div", { className: "ads-tree-rail pb-3", children: /* @__PURE__ */ t(ee, { children: e.detail }) }),
71
+ e.sources && e.sources.length > 0 && /* @__PURE__ */ t("div", { className: "ads-tree-rail pb-3", children: /* @__PURE__ */ t(te, { children: e.sources.map((l) => /* @__PURE__ */ t(ne, { children: l }, l)) }) }),
72
+ (e.calls ?? []).map((l, c) => /* @__PURE__ */ t(
73
73
  "div",
74
74
  {
75
75
  className: "ads-tree-branch pb-2 last:pb-0",
76
76
  style: { "--tree-elbow": "23px" },
77
- children: s ? s(i) : /* @__PURE__ */ t(A, { call: i })
77
+ children: s ? s(l) : /* @__PURE__ */ t(R, { call: l })
78
78
  },
79
79
  c
80
80
  ))
@@ -82,99 +82,129 @@ const O = b(
82
82
  ] });
83
83
  }
84
84
  );
85
- O.displayName = "AgentTrace.StepRow";
86
- const ue = ({
85
+ j.displayName = "AgentTrace.StepRow";
86
+ const ge = ({
87
87
  steps: e,
88
- mainAgent: o = ae,
89
- slowSeconds: s = le,
90
- reviewedStepIds: l,
91
- onSendForReview: i,
92
- slowMessage: c = de,
93
- renderCall: h,
94
- className: $,
95
- ...k
88
+ mainAgent: o = he,
89
+ slowSeconds: s = me,
90
+ reviewedStepIds: i,
91
+ onSendForReview: l,
92
+ slowMessage: c = pe,
93
+ renderCall: p,
94
+ className: z,
95
+ ...D
96
96
  }) => {
97
- var S;
98
- const n = e.find((r) => r.status === "active") ?? null, f = e.filter((r) => r.status === "complete" || r.status === "error"), p = new Set(l ?? []), [E, C] = D(/* @__PURE__ */ new Set()), w = _(null);
99
- z(() => {
100
- const r = (n == null ? void 0 : n.group) ?? null;
101
- r == null || r === w.current || (w.current = r, C(new Set(y(e).filter((d) => d !== r))));
102
- }, [n == null ? void 0 : n.group, e]);
103
- const N = y(f).map((r) => {
104
- var d;
97
+ const r = e.find((n) => n.status === "active") ?? null, d = e.filter((n) => n.status === "complete" || n.status === "error"), w = new Set(i ?? []), m = e.length > 0 && e.every((n) => n.status === "complete" || n.status === "error"), [L, C] = B(() => new Set(T(e))), v = k(null);
98
+ M(() => {
99
+ const n = (r == null ? void 0 : r.group) ?? null;
100
+ n == null || n === v.current || (v.current = n, C(new Set(T(e).filter((u) => u !== n))));
101
+ }, [r == null ? void 0 : r.group, e]);
102
+ const $ = k(m);
103
+ M(() => {
104
+ m && !$.current && (C(new Set(T(e))), v.current = null), $.current = m;
105
+ }, [m, e]);
106
+ const f = T(d).map((n) => {
107
+ var u;
105
108
  return {
106
- group: r,
107
- icon: (d = f.find((u) => u.group === r)) == null ? void 0 : d.groupIcon,
108
- steps: f.filter((u) => u.group === r)
109
+ group: n,
110
+ icon: (u = d.find((h) => h.group === n)) == null ? void 0 : u.groupIcon,
111
+ steps: d.filter((h) => h.group === n)
109
112
  };
110
- }), M = (n == null ? void 0 : n.seconds) ?? 0, I = n != null && M >= s, g = n ? c(n) : null;
111
- return /* @__PURE__ */ a("div", { "data-slot": "agent-trace", className: L("w-full", $), ...k, children: [
112
- /* @__PURE__ */ t("div", { className: "flex flex-col gap-3", children: N.map(({ group: r, icon: d, steps: u }) => /* @__PURE__ */ a(
113
- Z,
113
+ }), _ = (r == null ? void 0 : r.seconds) ?? 0, F = r != null && _ >= s, N = r ? c(r) : null, b = d.reduce((n, u) => n + (u.seconds ?? 0), 0), O = new Set(d.flatMap((n) => n.sources ?? [])).size, G = `Completed ${d.length} research ${d.length === 1 ? "step" : "steps"}${b ? ` · ${S(b)}` : ""}`, y = (
114
+ /* Each PHASE is a branch row hanging off the summary/live line — the same
115
+ tree language the steps use one level down. The wrapper (not the
116
+ container) carries the rail + elbow per principle 14; inter-phase
117
+ spacing is padding INSIDE the wrapper so the rail spans it unbroken.
118
+ --tree-elbow lands on the TaskTrigger icon's centre (measured). */
119
+ /* @__PURE__ */ t("div", { className: "flex flex-col", children: f.map(({ group: n, icon: u, steps: h }) => /* @__PURE__ */ t(
120
+ "div",
114
121
  {
115
- open: !E.has(r),
116
- onOpenChange: (m) => C((R) => {
117
- const T = new Set(R);
118
- return m ? T.delete(r) : T.add(r), T;
119
- }),
120
- children: [
121
- /* @__PURE__ */ t(ee, { title: r, icon: d, endContent: ce(u) }),
122
- /* @__PURE__ */ t(te, { children: /* @__PURE__ */ t(X, { connector: "tree", children: u.map((m) => /* @__PURE__ */ t(
123
- O,
124
- {
125
- step: m,
126
- mainAgent: o,
127
- renderCall: h
128
- },
129
- m.id
130
- )) }) })
131
- ]
122
+ className: "ads-tree-branch pb-3 last:pb-0 [--tree-elbow:11px]",
123
+ children: /* @__PURE__ */ a(
124
+ oe,
125
+ {
126
+ open: !L.has(n),
127
+ onOpenChange: (g) => C((H) => {
128
+ const x = new Set(H);
129
+ return g ? x.delete(n) : x.add(n), x;
130
+ }),
131
+ children: [
132
+ /* @__PURE__ */ t(se, { title: n, icon: u, endContent: fe(h) }),
133
+ /* @__PURE__ */ t(le, { children: /* @__PURE__ */ t(re, { children: h.map((g) => /* @__PURE__ */ t(
134
+ j,
135
+ {
136
+ step: g,
137
+ mainAgent: o,
138
+ renderCall: p
139
+ },
140
+ g.id
141
+ )) }) })
142
+ ]
143
+ }
144
+ )
132
145
  },
133
- r
134
- )) }),
135
- n && /* @__PURE__ */ a("div", { className: "mt-3", children: [
146
+ n
147
+ )) })
148
+ );
149
+ return /* @__PURE__ */ a("div", { "data-slot": "agent-trace", className: K("w-full", z), ...D, children: [
150
+ m && f.length > 0 ? (
151
+ /* Settled trace = one summary line; the phase tree waits one click
152
+ away instead of stacking above the answer. */
136
153
  /* @__PURE__ */ t(
137
- Y,
154
+ E,
155
+ {
156
+ status: "complete",
157
+ elapsed: S(b),
158
+ sourceCount: O,
159
+ summary: G,
160
+ children: y
161
+ }
162
+ )
163
+ ) : r ? (
164
+ /* Running trace = the live line IS the one summary line (reason
165
+ first: the in-flight step is narrated here, not placed in the
166
+ tree). The settled phases rest behind it, hidden until the reader
167
+ expands — never stacked open above the answer while work runs. */
168
+ /* @__PURE__ */ t(
169
+ E,
138
170
  {
139
171
  status: "active",
140
- open: !0,
141
- onOpenChange: () => {
142
- },
143
- elapsed: v(n) ?? "0:00",
144
- sourceCount: ((S = n.sources) == null ? void 0 : S.length) ?? 0,
145
- activity: n.label,
146
- activityKey: n.id,
147
- activityPlacement: "bottom",
148
- collapsible: !1,
149
- children: /* @__PURE__ */ t("span", {})
172
+ elapsed: A(r) ?? "0:00",
173
+ sourceCount: O,
174
+ activity: r.label,
175
+ activityKey: r.id,
176
+ stepIndex: d.length + 1,
177
+ stepCount: e.length,
178
+ collapsible: f.length > 0,
179
+ children: f.length > 0 ? y : /* @__PURE__ */ t("span", {})
150
180
  }
151
- ),
152
- I && g && /* @__PURE__ */ t(G, { variant: "warning", icon: /* @__PURE__ */ t(F, {}), className: "mt-3", children: /* @__PURE__ */ a("div", { className: "flex flex-wrap items-center justify-between gap-3", children: [
153
- /* @__PURE__ */ a("div", { className: "min-w-0", children: [
154
- /* @__PURE__ */ a(H, { children: [
155
- g.title,
156
- " —",
157
- " ",
158
- /* @__PURE__ */ t("span", { className: "tabular-nums text-tertiary", children: v(n) })
159
- ] }),
160
- /* @__PURE__ */ t(U, { children: g.detail })
181
+ )
182
+ ) : y,
183
+ r && F && N && /* @__PURE__ */ t(q, { variant: "warning", icon: /* @__PURE__ */ t(W, {}), className: "mt-3", children: /* @__PURE__ */ a("div", { className: "flex flex-wrap items-center justify-between gap-3", children: [
184
+ /* @__PURE__ */ a("div", { className: "min-w-0", children: [
185
+ /* @__PURE__ */ a(J, { children: [
186
+ N.title,
187
+ " —",
188
+ " ",
189
+ /* @__PURE__ */ t("span", { className: "tabular-nums text-tertiary", children: A(r) })
161
190
  ] }),
162
- i && /* @__PURE__ */ t(
163
- B,
164
- {
165
- size: "sm",
166
- variant: p.has(n.id) ? "ghost" : "secondary",
167
- disabled: p.has(n.id),
168
- onClick: () => i(n),
169
- children: p.has(n.id) ? "Sent" : "Skip and send"
170
- }
171
- )
172
- ] }) })
173
- ] }),
174
- N.length === 0 && !n && /* @__PURE__ */ t(K, { size: "sm", className: "text-tertiary", children: "No steps yet." })
191
+ /* @__PURE__ */ t(P, { children: N.detail })
192
+ ] }),
193
+ l && /* @__PURE__ */ t(
194
+ Q,
195
+ {
196
+ size: "sm",
197
+ variant: w.has(r.id) ? "ghost" : "solid",
198
+ disabled: w.has(r.id),
199
+ onClick: () => l(r),
200
+ children: w.has(r.id) ? "Sent" : "Skip and send"
201
+ }
202
+ )
203
+ ] }) }),
204
+ f.length === 0 && !r && /* @__PURE__ */ t(V, { size: "sm", className: "text-tertiary", children: "No steps yet." })
175
205
  ] });
176
206
  };
177
- ue.displayName = "AgentTrace";
207
+ ge.displayName = "AgentTrace";
178
208
  export {
179
- ue as AgentTrace
209
+ ge as AgentTrace
180
210
  };
@@ -3,9 +3,11 @@ import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '../collapsi
3
3
  import { ComponentProps, ReactNode } from 'react';
4
4
  /**
5
5
  * How steps connect to one another.
6
- * - `rail` — a short vertical segment between icons (the default).
7
6
  * - `tree` — the Tree connector: a continuous rail with an elbow reaching
8
- * EVERY step, so a nested trace reads as branches of its parent.
7
+ * EVERY step, so a trace reads as branches of its parent (the
8
+ * default — every trace carries the branch language).
9
+ * - `rail` — a short vertical segment between icons; opt-in for flat lists
10
+ * where the branch metaphor doesn't apply.
9
11
  * - `none` — no connector; an outer structure carries the hierarchy.
10
12
  */
11
13
  export type ChainOfThoughtConnector = "rail" | "tree" | "none";
@@ -48,8 +50,17 @@ export type ChainOfThoughtTriggerProps = Omit<ComponentProps<typeof CollapsibleT
48
50
  swapIconOnHover?: boolean;
49
51
  };
50
52
  export declare const ChainOfThoughtTrigger: import('react').MemoExoticComponent<({ className, children, leftIcon, endContent, caret, swapIconOnHover, ...props }: ChainOfThoughtTriggerProps) => import("react").JSX.Element>;
51
- export type ChainOfThoughtContentProps = ComponentProps<typeof CollapsibleContent>;
52
- export declare const ChainOfThoughtContent: import('react').MemoExoticComponent<({ className, children, ...props }: ChainOfThoughtContentProps) => import("react").JSX.Element>;
53
+ export type ChainOfThoughtContentProps = ComponentProps<typeof CollapsibleContent> & {
54
+ /**
55
+ * Draw the pass-through rail descending from the step icon alongside the
56
+ * open content (default). Turn OFF when the content draws its own
57
+ * `.ads-tree-rail`/`.ads-tree-branch` structure at the same x — AgentTrace's
58
+ * step body does — so the branch termination stays with the last elbow
59
+ * instead of running past it.
60
+ */
61
+ rail?: boolean;
62
+ };
63
+ export declare const ChainOfThoughtContent: import('react').MemoExoticComponent<({ className, children, rail, ...props }: ChainOfThoughtContentProps) => import("react").JSX.Element>;
53
64
  export type ChainOfThoughtItemProps = ComponentProps<"div">;
54
65
  export declare const ChainOfThoughtItem: import('react').MemoExoticComponent<({ className, ...props }: ChainOfThoughtItemProps) => import("react").JSX.Element>;
55
66
  export type ChainOfThoughtSearchResultsProps = ComponentProps<"div">;
@@ -103,7 +114,12 @@ export type ChainOfThoughtEvidenceTableProps = Omit<ComponentProps<"div">, "chil
103
114
  */
104
115
  export declare const ChainOfThoughtEvidenceTable: import('react').MemoExoticComponent<({ className, columns, rows, totalRows, flag, ...props }: ChainOfThoughtEvidenceTableProps) => import("react").JSX.Element>;
105
116
  export type ChainOfThoughtMetricsProps = ComponentProps<"div">;
106
- /** A quiet inline stat row — no fills, separated by spacing alone. */
117
+ /** The stat readout on one recessed fill — the warm greige muted surface
118
+ * groups the metrics into a single contained block (principle 1: delineate
119
+ * with fill, never a stroke; a sage-50 tint was tried and reverted — the
120
+ * neutral fill keeps the semantic value colors as the only color). One
121
+ * metric per ROW, receipt-style: label leading, value trailing, so the
122
+ * figures align on the right edge and scan vertically. */
107
123
  export declare const ChainOfThoughtMetrics: import('react').MemoExoticComponent<({ className, role, ...props }: ChainOfThoughtMetricsProps) => import("react").JSX.Element>;
108
124
  export type ChainOfThoughtMetricProps = Omit<ComponentProps<"div">, "children" | "color"> & {
109
125
  label: ReactNode;