@tangle-network/ui 11.3.0 → 11.5.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,23 @@
1
1
  # @tangle-network/ui
2
2
 
3
+ ## 11.5.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 8dbe359: Export `RunRowShell` (+ `RunRowStatusDot`, `RunRowStatus`) from the `/run` entry. The shell is the shared run-row grammar beneath `InlineToolItem`/`InlineThinkingItem`; consumers whose row carries behaviors the fixed items don't model (a treated title, a streaming plain-text body) can now compose the grammar directly instead of re-forking it.
8
+
9
+ ## 11.4.0
10
+
11
+ ### Minor Changes
12
+
13
+ - ef1be75: Publish the redaction renderer on its own `./redaction` subpath.
14
+
15
+ `RedactedDocument` is the client half of agent-app's reversible redaction: agent-app builds a document of masked spans and reveals one at a time through `revealSpan`, where authorization and the audit record happen, and this component renders that document and calls back for a reveal. It reached the package only through the root entry, and no consumer imports the bare package — every app takes ui through a subpath — so the component was unreachable in practice.
16
+
17
+ The module gains a header stating what it pairs with, including why its segment type omits the `cipher` that agent-app's carries: the ciphertext stays on the server, so the type a browser holds cannot name it.
18
+
19
+ - b7c12be: `RunRowShell`'s `title` prop widens from `string` to `ReactNode` — purely additive (strings render unchanged). Lets a row carry a treated title (e.g. an active-state shimmer sweep) so consumers composing the canonical run-row grammar don't have to re-fork the shell for it.
20
+
3
21
  ## 11.3.0
4
22
 
5
23
  ### Minor Changes
package/dist/chat.js CHANGED
@@ -5,10 +5,10 @@ import {
5
5
  MessageList,
6
6
  ThinkingIndicator,
7
7
  UserMessage
8
- } from "./chunk-IH2VRPGZ.js";
8
+ } from "./chunk-RKC3GXHE.js";
9
9
  import "./chunk-AZWDI2JG.js";
10
- import "./chunk-SRAKCVPO.js";
11
- import "./chunk-4ORVXSMU.js";
10
+ import "./chunk-R5GVQDL3.js";
11
+ import "./chunk-J2G7KCYH.js";
12
12
  import "./chunk-ULDNFLIM.js";
13
13
  import "./chunk-AAUNOHVL.js";
14
14
  import "./chunk-3M7BPSSW.js";
@@ -0,0 +1,104 @@
1
+ import {
2
+ cn
3
+ } from "./chunk-RQHJBTEU.js";
4
+
5
+ // src/redaction/redacted-document.tsx
6
+ import { useCallback, useState } from "react";
7
+ import { Eye, EyeOff, Loader2, ShieldAlert } from "lucide-react";
8
+ import { jsx, jsxs } from "react/jsx-runtime";
9
+ var defaultLabel = (kind) => kind.replace(/[-_]/g, " ").toUpperCase();
10
+ function RedactedChip({
11
+ kind,
12
+ label,
13
+ onReveal
14
+ }) {
15
+ const [state, setState] = useState({ status: "masked" });
16
+ const reveal = useCallback(async () => {
17
+ setState({ status: "loading" });
18
+ try {
19
+ const r = await onReveal();
20
+ setState(
21
+ r.ok && r.value !== void 0 ? { status: "revealed", value: r.value } : { status: "denied", reason: r.reason }
22
+ );
23
+ } catch {
24
+ setState({ status: "denied", reason: "error" });
25
+ }
26
+ }, [onReveal]);
27
+ if (state.status === "revealed") {
28
+ return /* @__PURE__ */ jsxs(
29
+ "button",
30
+ {
31
+ type: "button",
32
+ onClick: () => setState({ status: "masked" }),
33
+ title: "Revealed \u2014 click to hide",
34
+ "aria-label": `${label}: revealed, click to hide`,
35
+ className: cn(
36
+ "inline-flex items-center gap-1 rounded-[var(--radius-sm)] px-1 font-medium",
37
+ "bg-[color-mix(in_oklch,var(--color-warning,orange)_18%,transparent)] text-foreground ring-1 ring-warning/40"
38
+ ),
39
+ children: [
40
+ state.value,
41
+ /* @__PURE__ */ jsx(EyeOff, { className: "size-3 opacity-60" })
42
+ ]
43
+ }
44
+ );
45
+ }
46
+ if (state.status === "denied") {
47
+ return /* @__PURE__ */ jsxs(
48
+ "span",
49
+ {
50
+ title: `Restricted${state.reason ? ` (${state.reason})` : ""}`,
51
+ "aria-label": `${label}: restricted`,
52
+ className: "inline-flex items-center gap-1 rounded-[var(--radius-sm)] bg-muted px-1 text-muted-foreground",
53
+ children: [
54
+ /* @__PURE__ */ jsx(ShieldAlert, { className: "size-3" }),
55
+ " ",
56
+ label
57
+ ]
58
+ }
59
+ );
60
+ }
61
+ return /* @__PURE__ */ jsxs(
62
+ "button",
63
+ {
64
+ type: "button",
65
+ disabled: state.status === "loading",
66
+ onClick: reveal,
67
+ title: `${label} \u2014 click to reveal`,
68
+ "aria-label": `${label} redacted, click to reveal`,
69
+ className: cn(
70
+ "inline-flex items-center gap-1 rounded-[var(--radius-sm)] px-1 font-medium tracking-wide",
71
+ "bg-muted text-muted-foreground hover:bg-muted/80 hover:text-foreground transition-colors",
72
+ "cursor-pointer select-none"
73
+ ),
74
+ children: [
75
+ state.status === "loading" ? /* @__PURE__ */ jsx(Loader2, { className: "size-3 animate-spin" }) : /* @__PURE__ */ jsx(Eye, { className: "size-3 opacity-60" }),
76
+ /* @__PURE__ */ jsx("span", { "aria-hidden": true, children: "\u2588\u2588\u2588" }),
77
+ " ",
78
+ label
79
+ ]
80
+ }
81
+ );
82
+ }
83
+ function RedactedDocument({
84
+ document,
85
+ onReveal,
86
+ labelForKind = defaultLabel,
87
+ className
88
+ }) {
89
+ return /* @__PURE__ */ jsx("div", { className: cn("whitespace-pre-wrap break-words leading-relaxed", className), children: document.segments.map(
90
+ (seg, i) => seg.type === "text" ? /* @__PURE__ */ jsx("span", { children: seg.text }, i) : /* @__PURE__ */ jsx(
91
+ RedactedChip,
92
+ {
93
+ kind: seg.kind,
94
+ label: labelForKind(seg.kind),
95
+ onReveal: () => onReveal(seg.id)
96
+ },
97
+ seg.id
98
+ )
99
+ ) });
100
+ }
101
+
102
+ export {
103
+ RedactedDocument
104
+ };
@@ -216,20 +216,6 @@ function LiveDuration({ startTime }) {
216
216
  return /* @__PURE__ */ jsx3("span", { className: "text-xs font-mono text-neutral-400 dark:text-neutral-500 tabular-nums", children: formatDuration(elapsed) });
217
217
  }
218
218
 
219
- // src/run/inline-tool-item.tsx
220
- import { memo as memo2 } from "react";
221
- import {
222
- Terminal,
223
- FileEdit,
224
- FileSearch,
225
- Search,
226
- PencilLine,
227
- Bot,
228
- Globe,
229
- ClipboardList,
230
- Settings
231
- } from "lucide-react";
232
-
233
219
  // src/run/run-row-shell.tsx
234
220
  import { useState as useState3 } from "react";
235
221
  import * as Collapsible from "@radix-ui/react-collapsible";
@@ -347,6 +333,18 @@ function RunRowShell({
347
333
  }
348
334
 
349
335
  // src/run/inline-tool-item.tsx
336
+ import { memo as memo2 } from "react";
337
+ import {
338
+ Terminal,
339
+ FileEdit,
340
+ FileSearch,
341
+ Search,
342
+ PencilLine,
343
+ Bot,
344
+ Globe,
345
+ ClipboardList,
346
+ Settings
347
+ } from "lucide-react";
350
348
  import { jsx as jsx5 } from "react/jsx-runtime";
351
349
  var TOOL_CATEGORY_ICON_MAP = {
352
350
  command: Terminal,
@@ -500,6 +498,7 @@ export {
500
498
  ExpandableContent,
501
499
  ExpandedToolDetail,
502
500
  LiveDuration,
501
+ RunRowStatusDot,
503
502
  RunRowShell,
504
503
  InlineToolItem,
505
504
  ToolCallStep,
@@ -2,7 +2,7 @@ import {
2
2
  ExpandableContent,
3
3
  InlineToolItem,
4
4
  RunRowShell
5
- } from "./chunk-4ORVXSMU.js";
5
+ } from "./chunk-J2G7KCYH.js";
6
6
  import {
7
7
  formatDuration,
8
8
  truncateText
@@ -6,11 +6,11 @@ import {
6
6
  import {
7
7
  InlineThinkingItem,
8
8
  RunGroup
9
- } from "./chunk-SRAKCVPO.js";
9
+ } from "./chunk-R5GVQDL3.js";
10
10
  import {
11
11
  ToolCallGroup,
12
12
  ToolCallStep
13
- } from "./chunk-4ORVXSMU.js";
13
+ } from "./chunk-J2G7KCYH.js";
14
14
  import {
15
15
  getToolDisplayMetadata
16
16
  } from "./chunk-ULDNFLIM.js";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  ToolCallGroup,
3
3
  ToolCallStep
4
- } from "./chunk-4ORVXSMU.js";
4
+ } from "./chunk-J2G7KCYH.js";
5
5
  import {
6
6
  Markdown
7
7
  } from "./chunk-P5F43A65.js";
@@ -11,7 +11,7 @@ import {
11
11
  } from "./chunk-OEX7NZE3.js";
12
12
  import {
13
13
  parseToolEvent
14
- } from "./chunk-J3YZIQNI.js";
14
+ } from "./chunk-XPYPZMYT.js";
15
15
 
16
16
  // src/hooks/use-dropdown-menu.ts
17
17
  import { useEffect, useRef, useState } from "react";
package/dist/hooks.js CHANGED
@@ -11,15 +11,15 @@ import {
11
11
  useSSEStream,
12
12
  useSdkSession,
13
13
  useToolCallStream
14
- } from "./chunk-HW4ROISY.js";
14
+ } from "./chunk-XROQW5J7.js";
15
15
  import "./chunk-OEX7NZE3.js";
16
16
  import {
17
17
  useAutoScroll,
18
18
  useRunCollapseState,
19
19
  useRunGroups
20
20
  } from "./chunk-AZWDI2JG.js";
21
- import "./chunk-J3YZIQNI.js";
22
- import "./chunk-4ORVXSMU.js";
21
+ import "./chunk-XPYPZMYT.js";
22
+ import "./chunk-J2G7KCYH.js";
23
23
  import "./chunk-ULDNFLIM.js";
24
24
  import "./chunk-AAUNOHVL.js";
25
25
  import "./chunk-ZRVH3WCA.js";
package/dist/index.d.ts CHANGED
@@ -3,7 +3,7 @@ export { Avatar, AvatarFallback, AvatarImage, Badge, BadgeProps, Card, CardConte
3
3
  export { Logo, LogoProps, TangleKnot } from '@tangle-network/brand';
4
4
  export { A as ArtifactPane, a as ArtifactPaneProps } from './artifact-pane-DpuWcAiF.js';
5
5
  export { AgentTimeline, AgentTimelineArtifactItem, AgentTimelineCustomItem, AgentTimelineItem, AgentTimelineMessageItem, AgentTimelineProps, AgentTimelineStatusItem, AgentTimelineTone, AgentTimelineToolGroupItem, AgentTimelineToolItem, ChatContainer, ChatContainerProps, ChatMessage, ChatMessageProps, MessageList, MessageListProps, MessageRole, ThinkingIndicator, ThinkingIndicatorProps, UserMessage, UserMessageProps } from './chat.js';
6
- export { ExpandedToolDetail, ExpandedToolDetailProps, InlineThinkingItem, InlineThinkingItemProps, InlineToolItem, InlineToolItemProps, LiveDuration, RunGroup, RunGroupProps } from './run.js';
6
+ export { ExpandedToolDetail, ExpandedToolDetailProps, InlineThinkingItem, InlineThinkingItemProps, InlineToolItem, InlineToolItemProps, LiveDuration, RunGroup, RunGroupProps, RunRowShell, RunRowShellProps, RunRowStatus, RunRowStatusDot } from './run.js';
7
7
  export { F as FeedSegment, T as ToolCallData, a as ToolCallFeed, b as ToolCallFeedProps, c as ToolCallStatus, d as ToolCallType, p as parseToolEvent } from './tool-call-feed-D9iofJgW.js';
8
8
  export { OpenUIAction, OpenUIActionsNode, OpenUIArtifactRenderer, OpenUIArtifactRendererProps, OpenUIBadgeNode, OpenUICardNode, OpenUICodeNode, OpenUIComponentNode, OpenUIGridNode, OpenUIHeadingNode, OpenUIKeyValueNode, OpenUIMarkdownNode, OpenUIPrimitive, OpenUISeparatorNode, OpenUIStackNode, OpenUIStatNode, OpenUITableNode, OpenUITextNode } from './openui.js';
9
9
  export { FileArtifactPane, FileArtifactPaneProps, FileFormat, FileNode, FilePreview, FilePreviewProps, FileTabData, FileTabs, FileTabsProps, FileTree, FileTreeProps, FileTreeVisibilityOptions, RichFileTree, RichFileTreeGitEntry, RichFileTreeGitStatus, RichFileTreeProps, RichFileTreeThemeVars, detectFileFormat, fileExtension, filterFileTree, getCodeLanguage, getFormatLabel, getSyntaxLanguage } from './files.js';
@@ -21,8 +21,9 @@ export { F as FinalTextPart, G as GroupedMessage, M as MessageRun, a as MessageU
21
21
  export { C as CustomToolRenderer, D as DisplayVariant, T as ToolDisplayMetadata } from './tool-display-z4JcDmMQ.js';
22
22
  export { TOOL_CATEGORY_ICONS, cn, copyText, formatBytes, formatDuration, formatUptime, getToolCategory, getToolDisplayMetadata, getToolErrorText, timeAgo, truncateText } from './utils.js';
23
23
  export { CommandPreview, CommandPreviewProps, DiffPreview, DiffPreviewProps, GlobResultsPreview, GlobResultsPreviewProps, GrepResultsPreview, GrepResultsPreviewProps, QuestionPreview, QuestionPreviewProps, WebSearchPreview, WebSearchPreviewProps, WriteFilePreview, WriteFilePreviewProps } from './tool-previews.js';
24
- import { ReactNode } from 'react';
24
+ export { RedactedDocSegment, RedactedDocument, RedactedDocumentData, RedactedDocumentProps, RevealResult } from './redaction.js';
25
25
  import 'class-variance-authority/types';
26
+ import 'react';
26
27
  import 'react/jsx-runtime';
27
28
  import '@radix-ui/react-dialog';
28
29
  import 'class-variance-authority';
@@ -39,44 +40,3 @@ import '@hocuspocus/provider';
39
40
  import 'yjs';
40
41
  import 'nanostores';
41
42
  import 'clsx';
42
-
43
- /**
44
- * Viewer for a server-produced redacted document. Renders text inline and each
45
- * redacted span as a masked chip; clicking a chip asks the server to reveal that
46
- * one span. The original plaintext is NEVER in the document the client holds —
47
- * the chip carries only an id + kind; `onReveal` round-trips to the server, where
48
- * `@tangle-network/agent-app/redact`'s `revealSpan` runs the authorization check
49
- * and writes the audit trail. So authz + audit are server-truth; this is display.
50
- *
51
- * Structural types (no `@tangle-network/agent-app` dependency) — the viewer needs
52
- * only `{ id, kind }` per span; the cipher stays server-side.
53
- */
54
- type RedactedDocSegment = {
55
- type: "text";
56
- text: string;
57
- } | {
58
- type: "redacted";
59
- id: string;
60
- kind: string;
61
- };
62
- interface RedactedDocumentData {
63
- segments: RedactedDocSegment[];
64
- }
65
- interface RevealResult {
66
- ok: boolean;
67
- value?: string;
68
- /** e.g. `forbidden` | `not_found` when `ok` is false. */
69
- reason?: string;
70
- }
71
- interface RedactedDocumentProps {
72
- document: RedactedDocumentData;
73
- /** Reveal one span by id. Wire to a server route that calls agent-app's
74
- * `revealSpan` (authz + audit happen there). Resolves with the original. */
75
- onReveal: (spanId: string) => Promise<RevealResult>;
76
- /** Display label for a redaction kind (default: the kind, upper-cased). */
77
- labelForKind?: (kind: string) => string;
78
- className?: string;
79
- }
80
- declare function RedactedDocument({ document, onReveal, labelForKind, className, }: RedactedDocumentProps): ReactNode;
81
-
82
- export { type RedactedDocSegment, RedactedDocument, type RedactedDocumentData, type RedactedDocumentProps, type RevealResult };
package/dist/index.js CHANGED
@@ -1,3 +1,6 @@
1
+ import {
2
+ RedactedDocument
3
+ } from "./chunk-HGML45QH.js";
1
4
  import {
2
5
  AuthHeader,
3
6
  GitHubLoginButton,
@@ -17,7 +20,7 @@ import {
17
20
  useSSEStream,
18
21
  useSdkSession,
19
22
  useToolCallStream
20
- } from "./chunk-HW4ROISY.js";
23
+ } from "./chunk-XROQW5J7.js";
21
24
  import {
22
25
  addMessage,
23
26
  addParts,
@@ -143,26 +146,28 @@ import {
143
146
  MessageList,
144
147
  ThinkingIndicator,
145
148
  UserMessage
146
- } from "./chunk-IH2VRPGZ.js";
149
+ } from "./chunk-RKC3GXHE.js";
147
150
  import {
148
151
  useAutoScroll,
149
152
  useRunCollapseState,
150
153
  useRunGroups
151
154
  } from "./chunk-AZWDI2JG.js";
152
- import "./chunk-47XH56SV.js";
155
+ import "./chunk-LQS34IGP.js";
153
156
  import {
154
157
  ToolCallFeed,
155
158
  parseToolEvent
156
- } from "./chunk-J3YZIQNI.js";
159
+ } from "./chunk-XPYPZMYT.js";
157
160
  import {
158
161
  InlineThinkingItem,
159
162
  RunGroup
160
- } from "./chunk-SRAKCVPO.js";
163
+ } from "./chunk-R5GVQDL3.js";
161
164
  import {
162
165
  ExpandedToolDetail,
163
166
  InlineToolItem,
164
- LiveDuration
165
- } from "./chunk-4ORVXSMU.js";
167
+ LiveDuration,
168
+ RunRowShell,
169
+ RunRowStatusDot
170
+ } from "./chunk-J2G7KCYH.js";
166
171
  import {
167
172
  TOOL_CATEGORY_ICONS,
168
173
  formatBytes,
@@ -244,103 +249,6 @@ import {
244
249
  import {
245
250
  cn
246
251
  } from "./chunk-RQHJBTEU.js";
247
-
248
- // src/redaction/redacted-document.tsx
249
- import { useCallback, useState } from "react";
250
- import { Eye, EyeOff, Loader2, ShieldAlert } from "lucide-react";
251
- import { jsx, jsxs } from "react/jsx-runtime";
252
- var defaultLabel = (kind) => kind.replace(/[-_]/g, " ").toUpperCase();
253
- function RedactedChip({
254
- kind,
255
- label,
256
- onReveal
257
- }) {
258
- const [state, setState] = useState({ status: "masked" });
259
- const reveal = useCallback(async () => {
260
- setState({ status: "loading" });
261
- try {
262
- const r = await onReveal();
263
- setState(
264
- r.ok && r.value !== void 0 ? { status: "revealed", value: r.value } : { status: "denied", reason: r.reason }
265
- );
266
- } catch {
267
- setState({ status: "denied", reason: "error" });
268
- }
269
- }, [onReveal]);
270
- if (state.status === "revealed") {
271
- return /* @__PURE__ */ jsxs(
272
- "button",
273
- {
274
- type: "button",
275
- onClick: () => setState({ status: "masked" }),
276
- title: "Revealed \u2014 click to hide",
277
- "aria-label": `${label}: revealed, click to hide`,
278
- className: cn(
279
- "inline-flex items-center gap-1 rounded-[var(--radius-sm)] px-1 font-medium",
280
- "bg-[color-mix(in_oklch,var(--color-warning,orange)_18%,transparent)] text-foreground ring-1 ring-warning/40"
281
- ),
282
- children: [
283
- state.value,
284
- /* @__PURE__ */ jsx(EyeOff, { className: "size-3 opacity-60" })
285
- ]
286
- }
287
- );
288
- }
289
- if (state.status === "denied") {
290
- return /* @__PURE__ */ jsxs(
291
- "span",
292
- {
293
- title: `Restricted${state.reason ? ` (${state.reason})` : ""}`,
294
- "aria-label": `${label}: restricted`,
295
- className: "inline-flex items-center gap-1 rounded-[var(--radius-sm)] bg-muted px-1 text-muted-foreground",
296
- children: [
297
- /* @__PURE__ */ jsx(ShieldAlert, { className: "size-3" }),
298
- " ",
299
- label
300
- ]
301
- }
302
- );
303
- }
304
- return /* @__PURE__ */ jsxs(
305
- "button",
306
- {
307
- type: "button",
308
- disabled: state.status === "loading",
309
- onClick: reveal,
310
- title: `${label} \u2014 click to reveal`,
311
- "aria-label": `${label} redacted, click to reveal`,
312
- className: cn(
313
- "inline-flex items-center gap-1 rounded-[var(--radius-sm)] px-1 font-medium tracking-wide",
314
- "bg-muted text-muted-foreground hover:bg-muted/80 hover:text-foreground transition-colors",
315
- "cursor-pointer select-none"
316
- ),
317
- children: [
318
- state.status === "loading" ? /* @__PURE__ */ jsx(Loader2, { className: "size-3 animate-spin" }) : /* @__PURE__ */ jsx(Eye, { className: "size-3 opacity-60" }),
319
- /* @__PURE__ */ jsx("span", { "aria-hidden": true, children: "\u2588\u2588\u2588" }),
320
- " ",
321
- label
322
- ]
323
- }
324
- );
325
- }
326
- function RedactedDocument({
327
- document,
328
- onReveal,
329
- labelForKind = defaultLabel,
330
- className
331
- }) {
332
- return /* @__PURE__ */ jsx("div", { className: cn("whitespace-pre-wrap break-words leading-relaxed", className), children: document.segments.map(
333
- (seg, i) => seg.type === "text" ? /* @__PURE__ */ jsx("span", { children: seg.text }, i) : /* @__PURE__ */ jsx(
334
- RedactedChip,
335
- {
336
- kind: seg.kind,
337
- label: labelForKind(seg.kind),
338
- onReveal: () => onReveal(seg.id)
339
- },
340
- seg.id
341
- )
342
- ) });
343
- }
344
252
  export {
345
253
  AgentTimeline,
346
254
  ArtifactPane,
@@ -418,6 +326,8 @@ export {
418
326
  RedactedDocument,
419
327
  RichFileTree,
420
328
  RunGroup,
329
+ RunRowShell,
330
+ RunRowStatusDot,
421
331
  SegmentedControl,
422
332
  Select,
423
333
  SelectContent,
@@ -0,0 +1,42 @@
1
+ import { ReactNode } from 'react';
2
+
3
+ /**
4
+ * Viewer for a server-produced redacted document. Renders text inline and each
5
+ * redacted span as a masked chip; clicking a chip asks the server to reveal that
6
+ * one span. The original plaintext is NEVER in the document the client holds —
7
+ * the chip carries only an id + kind; `onReveal` round-trips to the server, where
8
+ * `@tangle-network/agent-app/redact`'s `revealSpan` runs the authorization check
9
+ * and writes the audit trail. So authz + audit are server-truth; this is display.
10
+ *
11
+ * Structural types (no `@tangle-network/agent-app` dependency) — the viewer needs
12
+ * only `{ id, kind }` per span; the cipher stays server-side.
13
+ */
14
+ type RedactedDocSegment = {
15
+ type: "text";
16
+ text: string;
17
+ } | {
18
+ type: "redacted";
19
+ id: string;
20
+ kind: string;
21
+ };
22
+ interface RedactedDocumentData {
23
+ segments: RedactedDocSegment[];
24
+ }
25
+ interface RevealResult {
26
+ ok: boolean;
27
+ value?: string;
28
+ /** e.g. `forbidden` | `not_found` when `ok` is false. */
29
+ reason?: string;
30
+ }
31
+ interface RedactedDocumentProps {
32
+ document: RedactedDocumentData;
33
+ /** Reveal one span by id. Wire to a server route that calls agent-app's
34
+ * `revealSpan` (authz + audit happen there). Resolves with the original. */
35
+ onReveal: (spanId: string) => Promise<RevealResult>;
36
+ /** Display label for a redaction kind (default: the kind, upper-cased). */
37
+ labelForKind?: (kind: string) => string;
38
+ className?: string;
39
+ }
40
+ declare function RedactedDocument({ document, onReveal, labelForKind, className, }: RedactedDocumentProps): ReactNode;
41
+
42
+ export { type RedactedDocSegment, RedactedDocument, type RedactedDocumentData, type RedactedDocumentProps, type RevealResult };
@@ -0,0 +1,7 @@
1
+ import {
2
+ RedactedDocument
3
+ } from "./chunk-HGML45QH.js";
4
+ import "./chunk-RQHJBTEU.js";
5
+ export {
6
+ RedactedDocument
7
+ };
package/dist/run.d.ts CHANGED
@@ -28,6 +28,53 @@ interface RunGroupProps {
28
28
  */
29
29
  declare const RunGroup: React.MemoExoticComponent<({ run, partMap, collapsed, onToggle, branding, renderToolDetail, headerActions, renderToolActions, }: RunGroupProps) => react_jsx_runtime.JSX.Element | null>;
30
30
 
31
+ type RunRowStatus = "running" | "success" | "error" | "idle";
32
+ /**
33
+ * Trailing status indicator shared by every run row: a spinner while running,
34
+ * a green/red dot on terminal states, nothing when idle. Status is shown here
35
+ * — it never replaces the row's semantic lead icon.
36
+ */
37
+ declare function RunRowStatusDot({ status }: {
38
+ status: RunRowStatus;
39
+ }): react_jsx_runtime.JSX.Element | null;
40
+ interface RunRowShellProps {
41
+ /** Semantic lead glyph — always visible; never replaced by status. */
42
+ icon: ReactNode;
43
+ /** Row title. A string in the common case; a node when the title carries its
44
+ * own treatment (e.g. an active-state shimmer sweep) — it renders inline in
45
+ * the shell's title slot either way. */
46
+ title: ReactNode;
47
+ /** Secondary inline text (tool path/command, or a reasoning preview). */
48
+ description?: string;
49
+ /** Render the description in mono (tools) vs prose (reasoning). */
50
+ descriptionMono?: boolean;
51
+ status?: RunRowStatus;
52
+ /** Live-ticks a duration while running. */
53
+ startTime?: number;
54
+ /** Static duration shown once the row is no longer running. */
55
+ durationMs?: number;
56
+ /** Radius shaping when rows are stacked into a group. */
57
+ groupPosition?: "single" | "first" | "middle" | "last";
58
+ /** Message shown below the header while collapsed (tool errors). */
59
+ collapsedError?: string;
60
+ actions?: ReactNode;
61
+ /** Controlled open state. Omit for internal (uncontrolled) state. */
62
+ open?: boolean;
63
+ onOpenChange?: (open: boolean) => void;
64
+ defaultOpen?: boolean;
65
+ className?: string;
66
+ contentClassName?: string;
67
+ /** Expanded body. When absent the row is not expandable. */
68
+ children?: ReactNode;
69
+ }
70
+ /**
71
+ * Shared shell for the agent activity rows (reasoning + tool). Owns the
72
+ * bordered container, the lead icon badge, title/description, the trailing
73
+ * meta cluster (duration + status + chevron) and the collapsible body, so
74
+ * both row kinds read as one family instead of two bespoke layouts.
75
+ */
76
+ declare function RunRowShell({ icon, title, description, descriptionMono, status, startTime, durationMs, groupPosition, collapsedError, actions, open: openProp, onOpenChange, defaultOpen, className, contentClassName, children, }: RunRowShellProps): react_jsx_runtime.JSX.Element;
77
+
31
78
  interface InlineToolItemProps {
32
79
  part: ToolPart;
33
80
  renderToolDetail?: CustomToolRenderer;
@@ -71,4 +118,4 @@ declare function LiveDuration({ startTime }: {
71
118
  startTime: number;
72
119
  }): react_jsx_runtime.JSX.Element;
73
120
 
74
- export { ExpandedToolDetail, type ExpandedToolDetailProps, InlineThinkingItem, type InlineThinkingItemProps, InlineToolItem, type InlineToolItemProps, LiveDuration, RunGroup, type RunGroupProps };
121
+ export { ExpandedToolDetail, type ExpandedToolDetailProps, InlineThinkingItem, type InlineThinkingItemProps, InlineToolItem, type InlineToolItemProps, LiveDuration, RunGroup, type RunGroupProps, RunRowShell, type RunRowShellProps, type RunRowStatus, RunRowStatusDot };
package/dist/run.js CHANGED
@@ -1,17 +1,19 @@
1
- import "./chunk-47XH56SV.js";
1
+ import "./chunk-LQS34IGP.js";
2
2
  import {
3
3
  ToolCallFeed,
4
4
  parseToolEvent
5
- } from "./chunk-J3YZIQNI.js";
5
+ } from "./chunk-XPYPZMYT.js";
6
6
  import {
7
7
  InlineThinkingItem,
8
8
  RunGroup
9
- } from "./chunk-SRAKCVPO.js";
9
+ } from "./chunk-R5GVQDL3.js";
10
10
  import {
11
11
  ExpandedToolDetail,
12
12
  InlineToolItem,
13
- LiveDuration
14
- } from "./chunk-4ORVXSMU.js";
13
+ LiveDuration,
14
+ RunRowShell,
15
+ RunRowStatusDot
16
+ } from "./chunk-J2G7KCYH.js";
15
17
  import "./chunk-ULDNFLIM.js";
16
18
  import "./chunk-AAUNOHVL.js";
17
19
  import "./chunk-3M7BPSSW.js";
@@ -27,6 +29,8 @@ export {
27
29
  InlineToolItem,
28
30
  LiveDuration,
29
31
  RunGroup,
32
+ RunRowShell,
33
+ RunRowStatusDot,
30
34
  ToolCallFeed,
31
35
  parseToolEvent
32
36
  };
package/dist/sdk-hooks.js CHANGED
@@ -5,15 +5,15 @@ import {
5
5
  useSSEStream,
6
6
  useSdkSession,
7
7
  useToolCallStream
8
- } from "./chunk-HW4ROISY.js";
8
+ } from "./chunk-XROQW5J7.js";
9
9
  import "./chunk-OEX7NZE3.js";
10
10
  import {
11
11
  useAutoScroll,
12
12
  useRunCollapseState,
13
13
  useRunGroups
14
14
  } from "./chunk-AZWDI2JG.js";
15
- import "./chunk-J3YZIQNI.js";
16
- import "./chunk-4ORVXSMU.js";
15
+ import "./chunk-XPYPZMYT.js";
16
+ import "./chunk-J2G7KCYH.js";
17
17
  import "./chunk-ULDNFLIM.js";
18
18
  import "./chunk-AAUNOHVL.js";
19
19
  import "./chunk-ZRVH3WCA.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangle-network/ui",
3
- "version": "11.3.0",
3
+ "version": "11.5.0",
4
4
  "description": "Generic React UI components for Tangle products — primitives, chat, run, files, editor, markdown.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -101,6 +101,11 @@
101
101
  "types": "./dist/nav.d.ts",
102
102
  "import": "./dist/nav.js",
103
103
  "default": "./dist/nav.js"
104
+ },
105
+ "./redaction": {
106
+ "types": "./dist/redaction.d.ts",
107
+ "import": "./dist/redaction.js",
108
+ "default": "./dist/redaction.js"
104
109
  }
105
110
  },
106
111
  "dependencies": {
@@ -141,7 +146,7 @@
141
146
  "react-dom": "^18 || ^19",
142
147
  "react-router": "^7 || ^8",
143
148
  "yjs": "^13.6.0",
144
- "@tangle-network/brand": "^1.4.0"
149
+ "@tangle-network/brand": "^1.5.0"
145
150
  },
146
151
  "peerDependenciesMeta": {
147
152
  "@nanostores/react": {
@@ -1,3 +1,15 @@
1
+ /**
2
+ * The client half of agent-app's reversible redaction.
3
+ *
4
+ * `agent-app/redact` builds a document of masked spans with each original kept
5
+ * encrypted, and reveals one span at a time through `revealSpan`, where the
6
+ * authorization and the audit record happen. This module renders that document
7
+ * and calls back for a reveal.
8
+ *
9
+ * The two segment types are deliberately not identical: agent-app's carries the
10
+ * `cipher` for a masked span, and this one does not. The ciphertext stays on the
11
+ * server, so the type a browser holds cannot name it.
12
+ */
1
13
  export {
2
14
  RedactedDocument,
3
15
  type RedactedDocumentProps,
package/src/run/index.ts CHANGED
@@ -1,4 +1,10 @@
1
1
  export { RunGroup, type RunGroupProps } from "./run-group";
2
+ export {
3
+ RunRowShell,
4
+ RunRowStatusDot,
5
+ type RunRowShellProps,
6
+ type RunRowStatus,
7
+ } from "./run-row-shell";
2
8
  export { InlineToolItem, type InlineToolItemProps } from "./inline-tool-item";
3
9
  export {
4
10
  InlineThinkingItem,
@@ -32,7 +32,10 @@ export function RunRowStatusDot({ status }: { status: RunRowStatus }) {
32
32
  export interface RunRowShellProps {
33
33
  /** Semantic lead glyph — always visible; never replaced by status. */
34
34
  icon: ReactNode;
35
- title: string;
35
+ /** Row title. A string in the common case; a node when the title carries its
36
+ * own treatment (e.g. an active-state shimmer sweep) — it renders inline in
37
+ * the shell's title slot either way. */
38
+ title: ReactNode;
36
39
  /** Secondary inline text (tool path/command, or a reasoning preview). */
37
40
  description?: string;
38
41
  /** Render the description in mono (tools) vs prose (reasoning). */
File without changes