@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 +18 -0
- package/dist/chat.js +3 -3
- package/dist/chunk-HGML45QH.js +104 -0
- package/dist/{chunk-4ORVXSMU.js → chunk-J2G7KCYH.js} +13 -14
- package/dist/{chunk-SRAKCVPO.js → chunk-R5GVQDL3.js} +1 -1
- package/dist/{chunk-IH2VRPGZ.js → chunk-RKC3GXHE.js} +2 -2
- package/dist/{chunk-J3YZIQNI.js → chunk-XPYPZMYT.js} +1 -1
- package/dist/{chunk-HW4ROISY.js → chunk-XROQW5J7.js} +1 -1
- package/dist/hooks.js +3 -3
- package/dist/index.d.ts +3 -43
- package/dist/index.js +14 -104
- package/dist/redaction.d.ts +42 -0
- package/dist/redaction.js +7 -0
- package/dist/run.d.ts +48 -1
- package/dist/run.js +9 -5
- package/dist/sdk-hooks.js +3 -3
- package/package.json +7 -2
- package/src/redaction/index.ts +12 -0
- package/src/run/index.ts +6 -0
- package/src/run/run-row-shell.tsx +4 -1
- /package/dist/{chunk-47XH56SV.js → chunk-LQS34IGP.js} +0 -0
- /package/src/primitives/{faint-text.test.tsx → faint-text-tokens.test.tsx} +0 -0
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-
|
|
8
|
+
} from "./chunk-RKC3GXHE.js";
|
|
9
9
|
import "./chunk-AZWDI2JG.js";
|
|
10
|
-
import "./chunk-
|
|
11
|
-
import "./chunk-
|
|
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,
|
|
@@ -6,11 +6,11 @@ import {
|
|
|
6
6
|
import {
|
|
7
7
|
InlineThinkingItem,
|
|
8
8
|
RunGroup
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-R5GVQDL3.js";
|
|
10
10
|
import {
|
|
11
11
|
ToolCallGroup,
|
|
12
12
|
ToolCallStep
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-J2G7KCYH.js";
|
|
14
14
|
import {
|
|
15
15
|
getToolDisplayMetadata
|
|
16
16
|
} from "./chunk-ULDNFLIM.js";
|
package/dist/hooks.js
CHANGED
|
@@ -11,15 +11,15 @@ import {
|
|
|
11
11
|
useSSEStream,
|
|
12
12
|
useSdkSession,
|
|
13
13
|
useToolCallStream
|
|
14
|
-
} from "./chunk-
|
|
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-
|
|
22
|
-
import "./chunk-
|
|
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
|
-
|
|
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-
|
|
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-
|
|
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-
|
|
155
|
+
import "./chunk-LQS34IGP.js";
|
|
153
156
|
import {
|
|
154
157
|
ToolCallFeed,
|
|
155
158
|
parseToolEvent
|
|
156
|
-
} from "./chunk-
|
|
159
|
+
} from "./chunk-XPYPZMYT.js";
|
|
157
160
|
import {
|
|
158
161
|
InlineThinkingItem,
|
|
159
162
|
RunGroup
|
|
160
|
-
} from "./chunk-
|
|
163
|
+
} from "./chunk-R5GVQDL3.js";
|
|
161
164
|
import {
|
|
162
165
|
ExpandedToolDetail,
|
|
163
166
|
InlineToolItem,
|
|
164
|
-
LiveDuration
|
|
165
|
-
|
|
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 };
|
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-
|
|
1
|
+
import "./chunk-LQS34IGP.js";
|
|
2
2
|
import {
|
|
3
3
|
ToolCallFeed,
|
|
4
4
|
parseToolEvent
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-XPYPZMYT.js";
|
|
6
6
|
import {
|
|
7
7
|
InlineThinkingItem,
|
|
8
8
|
RunGroup
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-R5GVQDL3.js";
|
|
10
10
|
import {
|
|
11
11
|
ExpandedToolDetail,
|
|
12
12
|
InlineToolItem,
|
|
13
|
-
LiveDuration
|
|
14
|
-
|
|
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-
|
|
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-
|
|
16
|
-
import "./chunk-
|
|
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
|
+
"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.
|
|
149
|
+
"@tangle-network/brand": "^1.5.0"
|
|
145
150
|
},
|
|
146
151
|
"peerDependenciesMeta": {
|
|
147
152
|
"@nanostores/react": {
|
package/src/redaction/index.ts
CHANGED
|
@@ -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
|
|
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
|
|
File without changes
|