@candor-ui/react 1.3.0 → 1.7.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/dist/adapters/ag-ui.d.ts +81 -16
- package/dist/adapters/ag-ui.js +308 -1
- package/dist/adapters/ai-sdk.d.ts +11 -6
- package/dist/adapters/ai-sdk.js +18 -1
- package/dist/adapters/claude-agent-sdk.d.ts +123 -14
- package/dist/adapters/claude-agent-sdk.js +163 -5
- package/dist/adapters/claude-agent-server.d.ts +199 -14
- package/dist/adapters/claude-agent-server.js +448 -49
- package/dist/adapters/use-ag-ui.d.ts +12 -6
- package/dist/adapters/use-ag-ui.js +23 -5
- package/dist/adapters/use-candor-chat.d.ts +1 -1
- package/dist/adapters/use-candor-chat.js +3 -3
- package/dist/adapters/use-claude-agent.d.ts +38 -9
- package/dist/adapters/use-claude-agent.js +96 -20
- package/dist/blocks/copy-field.d.ts +1 -1
- package/dist/blocks/copy-field.js +1 -1
- package/dist/blocks/degraded-panel.d.ts +5 -5
- package/dist/blocks/locale.d.ts +6 -6
- package/dist/blocks/locked.d.ts +8 -8
- package/dist/blocks/relative-time.d.ts +6 -6
- package/dist/blocks/status-dot.d.ts +3 -3
- package/dist/blocks/step-list.d.ts +3 -3
- package/dist/blocks/streaming-text.d.ts +3 -3
- package/dist/chat/agent-avatar.d.ts +4 -4
- package/dist/chat/ai-disclosure.d.ts +37 -0
- package/dist/chat/ai-disclosure.js +48 -0
- package/dist/chat/attachment-preview.d.ts +6 -6
- package/dist/chat/attachment-preview.js +2 -2
- package/dist/chat/card-registry.js +1 -1
- package/dist/chat/citation.d.ts +3 -3
- package/dist/chat/citation.js +6 -4
- package/dist/chat/composer.d.ts +31 -20
- package/dist/chat/composer.js +10 -6
- package/dist/chat/context-meter.d.ts +1 -1
- package/dist/chat/context-meter.js +1 -1
- package/dist/chat/entity-chip.d.ts +3 -3
- package/dist/chat/entity-chip.js +1 -1
- package/dist/chat/folded-turns.d.ts +11 -6
- package/dist/chat/folded-turns.js +2 -2
- package/dist/chat/message-actions.d.ts +6 -6
- package/dist/chat/message-actions.js +1 -1
- package/dist/chat/message-content.d.ts +13 -7
- package/dist/chat/message-content.js +10 -5
- package/dist/chat/message.d.ts +64 -37
- package/dist/chat/message.js +17 -11
- package/dist/chat/payload.d.ts +4 -4
- package/dist/chat/payload.js +5 -2
- package/dist/chat/permission-prompt.d.ts +129 -0
- package/dist/chat/permission-prompt.js +144 -0
- package/dist/chat/prompt-suggestions.d.ts +4 -4
- package/dist/chat/prompt-suggestions.js +1 -1
- package/dist/chat/reasoning.d.ts +3 -3
- package/dist/chat/reasoning.js +1 -1
- package/dist/chat/thread-divider.d.ts +3 -3
- package/dist/chat/thread-event.d.ts +10 -5
- package/dist/chat/thread-event.js +3 -2
- package/dist/chat/thread.d.ts +23 -7
- package/dist/chat/thread.js +29 -6
- package/dist/chat/tool-call.d.ts +7 -2
- package/dist/chat/tool-call.js +8 -3
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/lib/chat.d.ts +53 -38
- package/dist/lib/know.d.ts +14 -12
- package/dist/lib/render-prop.d.ts +4 -4
- package/dist/lib/safe-markdown.d.ts +1 -1
- package/dist/lib/status.d.ts +21 -0
- package/dist/lib/status.js +17 -0
- package/dist/lib/use-shortcut.d.ts +1 -1
- package/dist/lib/use-virtual-list.d.ts +6 -6
- package/dist/styles.css +4 -1
- package/dist/ui/button.d.ts +1 -1
- package/dist/ui/button.js +1 -1
- package/package.json +1 -1
package/dist/chat/thread.js
CHANGED
|
@@ -19,18 +19,41 @@ export const threadStrings = {
|
|
|
19
19
|
* For long histories, `virtualize` renders only the messages in or near view
|
|
20
20
|
* (each child is one item, keyed by its `key`). The column stays a `log`, the
|
|
21
21
|
* message holding focus stays rendered, and Jump to latest works the same.
|
|
22
|
+
*
|
|
23
|
+
* It opens at the bottom, or at `anchor` (the `id` of something in it, such as
|
|
24
|
+
* a chapter divider or the card that needs the reader), and then waits for the
|
|
25
|
+
* reader instead of following.
|
|
22
26
|
*/
|
|
23
|
-
function Thread({ children, empty, footer, className, contentClassName, virtualize = false, }) {
|
|
27
|
+
function Thread({ children, empty, footer, className, contentClassName, virtualize = false, anchor, scrollerRef, onDrop, fade = true, }) {
|
|
24
28
|
const t = useStrings("thread", threadStrings);
|
|
25
29
|
const scroller = React.useRef(null);
|
|
26
30
|
const content = React.useRef(null);
|
|
27
|
-
|
|
28
|
-
const
|
|
31
|
+
// Opening at an anchor means not following the bottom until the reader gets there.
|
|
32
|
+
const anchoring = Boolean(anchor) && !virtualize;
|
|
33
|
+
const pinnedRef = React.useRef(!anchoring);
|
|
34
|
+
const [pinned, setPinned] = React.useState(!anchoring);
|
|
35
|
+
React.useImperativeHandle(scrollerRef, () => scroller.current, []);
|
|
29
36
|
const toBottom = React.useCallback((behavior = "auto") => {
|
|
30
37
|
const el = scroller.current;
|
|
31
38
|
if (el)
|
|
32
39
|
el.scrollTo({ top: el.scrollHeight, behavior });
|
|
33
40
|
}, []);
|
|
41
|
+
// Open at the anchor once, when it first appears.
|
|
42
|
+
const anchored = React.useRef(false);
|
|
43
|
+
React.useLayoutEffect(() => {
|
|
44
|
+
if (!anchoring || anchored.current || !content.current?.childElementCount)
|
|
45
|
+
return;
|
|
46
|
+
anchored.current = true;
|
|
47
|
+
const target = content.current.querySelector(`#${CSS.escape(anchor)}`);
|
|
48
|
+
if (target) {
|
|
49
|
+
target.scrollIntoView?.({ block: "start" });
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
// The anchor isn't in the thread: open at the bottom and follow, as without one.
|
|
53
|
+
pinnedRef.current = true;
|
|
54
|
+
setPinned(true);
|
|
55
|
+
toBottom();
|
|
56
|
+
});
|
|
34
57
|
React.useEffect(() => {
|
|
35
58
|
const el = content.current;
|
|
36
59
|
if (!el)
|
|
@@ -75,14 +98,14 @@ function Thread({ children, empty, footer, className, contentClassName, virtuali
|
|
|
75
98
|
pin: focused,
|
|
76
99
|
gap: () => (content.current ? Number.parseFloat(getComputedStyle(content.current).rowGap) || 0 : 0),
|
|
77
100
|
});
|
|
78
|
-
return (_jsxs("div", { "data-slot": "thread", className: cn("flex min-h-0 flex-col", className), children: [_jsxs("div", { className: "relative min-h-0 flex-1", children: [_jsx("div", { ref: scroller, onScroll: onScroll, onFocus: virtualize
|
|
101
|
+
return (_jsxs("div", { "data-slot": "thread", className: cn("flex min-h-0 flex-col", className), children: [_jsxs("div", { className: "relative min-h-0 flex-1", children: [_jsx("div", { ref: scroller, onScroll: onScroll, onDragOver: onDrop ? (e) => e.preventDefault() : undefined, onDrop: onDrop, onFocus: virtualize
|
|
79
102
|
? (e) => {
|
|
80
103
|
setFocused(e.target.closest("[data-virtual-key]")?.getAttribute("data-virtual-key") ?? null);
|
|
81
104
|
}
|
|
82
|
-
: undefined, onBlur: virtualize ? (e) => !e.currentTarget.contains(e.relatedTarget) && setFocused(null) : undefined, className: "h-full overflow-y-auto overscroll-contain", children: _jsx("div", { ref: content, role: "log", "aria-label": t("messages"), className: cn("mx-auto flex w-full max-w-(--cd-thread-width) flex-col gap-7 px-4 py-6", contentClassName), children: !hasMessages ? (empty) : virtualize ? (_jsx(_Fragment, { children: list.rows.map((row) => "spacer" in row ? (_jsx("div", { "aria-hidden": true, style: { height: row.spacer } }, row.key)) : (_jsx("div", { ref: list.measure, "data-virtual-key": String(keyOf(row.index)), className: "flex flex-col", children: items[row.index] }, keyOf(row.index)))) })) : (children) }) }), !pinned && hasMessages && (_jsxs("button", { type: "button", onClick: () => {
|
|
105
|
+
: undefined, onBlur: virtualize ? (e) => !e.currentTarget.contains(e.relatedTarget) && setFocused(null) : undefined, className: "h-full scroll-pb-14 overflow-y-auto overscroll-contain", children: _jsx("div", { ref: content, role: "log", "aria-label": t("messages"), className: cn("mx-auto flex w-full max-w-(--cd-thread-width) flex-col gap-7 px-4 py-6", contentClassName), children: !hasMessages ? (empty) : virtualize ? (_jsx(_Fragment, { children: list.rows.map((row) => "spacer" in row ? (_jsx("div", { "aria-hidden": true, style: { height: row.spacer } }, row.key)) : (_jsx("div", { ref: list.measure, "data-virtual-key": String(keyOf(row.index)), className: "flex flex-col", children: items[row.index] }, keyOf(row.index)))) })) : (children) }) }), !pinned && hasMessages && (_jsxs("button", { type: "button", onClick: () => {
|
|
83
106
|
pinnedRef.current = true;
|
|
84
107
|
setPinned(true);
|
|
85
108
|
toBottom("smooth");
|
|
86
|
-
}, className: "absolute bottom-3 left-1/2 z-10 inline-flex -translate-x-1/2 items-center gap-1.5 rounded-full border bg-popover px-3 py-1.5 text-xs font-medium shadow-float animate-in fade-in-0 slide-in-from-bottom-1", children: [_jsx(ArrowDown, { "aria-hidden": true, className: "size-3" }), " ", t("jumpToLatest")] })), _jsx("div", { "aria-hidden": true, className: "pointer-events-none absolute inset-x-0 bottom-0 h-6 bg-gradient-to-t from-background to-transparent" })] }), footer && _jsx("div", { className: "mx-auto w-full max-w-(--cd-thread-width) px-4 pb-4", children: footer })] }));
|
|
109
|
+
}, className: "absolute bottom-3 left-1/2 z-10 inline-flex -translate-x-1/2 items-center gap-1.5 rounded-full border bg-popover px-3 py-1.5 text-xs font-medium shadow-float animate-in fade-in-0 slide-in-from-bottom-1", children: [_jsx(ArrowDown, { "aria-hidden": true, className: "size-3" }), " ", t("jumpToLatest")] })), fade && _jsx("div", { "aria-hidden": true, "data-slot": "thread-fade", className: "pointer-events-none absolute inset-x-0 bottom-0 h-6 bg-gradient-to-t from-background to-transparent" })] }), footer && _jsx("div", { className: "mx-auto w-full max-w-(--cd-thread-width) px-4 pb-4", children: footer })] }));
|
|
87
110
|
}
|
|
88
111
|
export { Thread };
|
package/dist/chat/tool-call.d.ts
CHANGED
|
@@ -11,6 +11,11 @@ export declare const toolCallStrings: {
|
|
|
11
11
|
done: string;
|
|
12
12
|
failed: string;
|
|
13
13
|
working: string;
|
|
14
|
+
approvedAutomatically: string;
|
|
15
|
+
approvedByPerson: string;
|
|
16
|
+
editedBeforeRun: string;
|
|
17
|
+
editedNote: string;
|
|
18
|
+
proposed: string;
|
|
14
19
|
};
|
|
15
20
|
/**
|
|
16
21
|
* One tool call as a compact row: what it did in plain words, its status, and
|
|
@@ -20,12 +25,12 @@ export declare const toolCallStrings: {
|
|
|
20
25
|
declare function ToolCall({ call, className, }: {
|
|
21
26
|
/** The call: tool name, plain-words title, status, input, output, duration or error. */
|
|
22
27
|
call: ToolCallData;
|
|
23
|
-
className?: string;
|
|
28
|
+
className?: string | undefined;
|
|
24
29
|
}): React.JSX.Element;
|
|
25
30
|
/** A run of tool calls, with a count when it's long enough to fold. */
|
|
26
31
|
declare function ToolCallGroup({ calls, className, }: {
|
|
27
32
|
/** Several calls, summarised as a group. */
|
|
28
33
|
calls: ToolCallData[];
|
|
29
|
-
className?: string;
|
|
34
|
+
className?: string | undefined;
|
|
30
35
|
}): React.JSX.Element;
|
|
31
36
|
export { ToolCall, ToolCallGroup };
|
package/dist/chat/tool-call.js
CHANGED
|
@@ -17,6 +17,11 @@ export const toolCallStrings = {
|
|
|
17
17
|
done: "{count} done",
|
|
18
18
|
failed: "{count} failed",
|
|
19
19
|
working: "working",
|
|
20
|
+
approvedAutomatically: "Approved automatically",
|
|
21
|
+
approvedByPerson: "Approved by a person",
|
|
22
|
+
editedBeforeRun: "Edited before it ran",
|
|
23
|
+
editedNote: "A person changed the input before allowing it. Input is what ran.",
|
|
24
|
+
proposed: "As the agent proposed it",
|
|
20
25
|
};
|
|
21
26
|
/**
|
|
22
27
|
* One tool call as a compact row: what it did in plain words, its status, and
|
|
@@ -28,8 +33,8 @@ function ToolCall({ call, className, }) {
|
|
|
28
33
|
const statusLabel = useStatusLabel();
|
|
29
34
|
const failed = call.status === "failed";
|
|
30
35
|
const [open, setOpen] = React.useState(failed);
|
|
31
|
-
const hasDetail = Boolean(call.input || call.output || call.error);
|
|
32
|
-
return (_jsxs(Collapsible, { open: open, onOpenChange: setOpen, "data-slot": "tool-call", "data-status": call.status, className: cn("group/tool", className), children: [_jsxs(CollapsibleTrigger, { disabled: !hasDetail, className: "flex w-full items-center gap-2.5 rounded-md px-1.5 py-1 text-start outline-none transition-colors duration-150 enabled:hover:bg-accent focus-visible:ring-[3px] focus-visible:ring-ring/
|
|
36
|
+
const hasDetail = Boolean(call.input || call.output || call.error || call.approval?.note || call.approval?.originalInput);
|
|
37
|
+
return (_jsxs(Collapsible, { open: open, onOpenChange: setOpen, "data-slot": "tool-call", "data-status": call.status, className: cn("group/tool", className), children: [_jsxs(CollapsibleTrigger, { disabled: !hasDetail, className: "flex w-full items-center gap-2.5 rounded-md px-1.5 py-1 text-start outline-none transition-colors duration-150 enabled:hover:bg-accent focus-visible:ring-[3px] focus-visible:ring-ring/80", children: [_jsx(StepMark, { status: call.status }), _jsxs("span", { className: "min-w-0 flex-1 truncate text-sm", children: [call.status === "running" ? _jsx(ShimmerLabel, { className: "font-normal", children: call.title }) : call.title, _jsxs("span", { className: "sr-only", children: [" \u2014 ", statusLabel(call.status)] })] }), call.approval?.originalInput !== undefined && (_jsx("span", { "data-slot": "tool-call-edited", className: "shrink-0 rounded-xs bg-warning-weak px-1 text-2xs text-warning-text", children: t("editedBeforeRun") })), call.approval?.by === "automatic" && (_jsx("span", { "data-slot": "tool-call-approval", className: "shrink-0 rounded-xs bg-muted px-1 text-2xs text-muted-foreground", children: t("approvedAutomatically") })), _jsx("code", { className: "hidden shrink-0 font-mono text-2xs text-faint-foreground sm:inline", children: call.tool }), call.duration && _jsx("span", { className: "shrink-0 text-xs tabular-nums text-faint-foreground", children: call.duration }), hasDetail && (_jsx(ChevronRight, { "aria-hidden": true, className: "rtl:-scale-x-100 size-3.5 shrink-0 text-faint-foreground transition-transform duration-200 ease-standard group-data-[state=open]/tool:[transform:rotate(90deg)]" }))] }), _jsx(CollapsibleContent, { className: "data-[state=open]:animate-in data-[state=open]:fade-in-0", children: _jsxs("div", { className: "mt-1 mb-2 ms-[1.375rem] flex flex-col gap-2 border-s ps-3.5", children: [call.error && (_jsx("p", { className: "rounded-md bg-destructive-weak px-2.5 py-1.5 text-xs text-destructive-text", children: call.error })), call.approval?.note && (_jsxs("p", { className: "text-xs text-muted-foreground", children: [call.approval.by === "automatic" ? t("approvedAutomatically") : t("approvedByPerson"), ": ", call.approval.note] })), call.approval?.originalInput !== undefined && _jsx("p", { className: "text-xs text-muted-foreground", children: t("editedNote") }), call.input && _jsx(Payload, { language: "json", title: t("input"), text: call.input }), call.approval?.originalInput !== undefined && _jsx(Payload, { language: "json", title: t("proposed"), text: call.approval.originalInput }), call.output && _jsx(Payload, { language: call.outputLanguage ?? "text", title: t("output"), text: call.output })] }) })] }));
|
|
33
38
|
}
|
|
34
39
|
/** A run of tool calls, with a count when it's long enough to fold. */
|
|
35
40
|
function ToolCallGroup({ calls, className, }) {
|
|
@@ -41,6 +46,6 @@ function ToolCallGroup({ calls, className, }) {
|
|
|
41
46
|
if (calls.length <= 2) {
|
|
42
47
|
return (_jsx("div", { "data-slot": "tool-call-group", className: cn("flex flex-col", className), children: calls.map((c) => (_jsx(ToolCall, { call: c }, c.id))) }));
|
|
43
48
|
}
|
|
44
|
-
return (_jsxs(Collapsible, { open: open, onOpenChange: setOpen, "data-slot": "tool-call-group", className: cn("group/tools rounded-lg border bg-card", className), children: [_jsxs(CollapsibleTrigger, { className: "flex w-full items-center gap-2 px-3 py-2 text-start text-xs text-muted-foreground outline-none hover:text-foreground focus-visible:ring-[3px] focus-visible:ring-ring/
|
|
49
|
+
return (_jsxs(Collapsible, { open: open, onOpenChange: setOpen, "data-slot": "tool-call-group", className: cn("group/tools rounded-lg border bg-card", className), children: [_jsxs(CollapsibleTrigger, { className: "flex w-full items-center gap-2 px-3 py-2 text-start text-xs text-muted-foreground outline-none hover:text-foreground focus-visible:ring-[3px] focus-visible:ring-ring/80 rounded-lg", children: [_jsx(Wrench, { "aria-hidden": true, className: "size-3.5" }), _jsxs("span", { className: "flex-1", children: [t("calls", { count: calls.length }), done > 0 && ` · ${t("done", { count: done })}`, failed > 0 && _jsxs("span", { className: "text-destructive-text", children: [" \u00B7 ", t("failed", { count: failed })] }), running && ` · ${t("working")}`] }), _jsx(ChevronRight, { "aria-hidden": true, className: "rtl:-scale-x-100 size-3.5 transition-transform duration-200 ease-standard group-data-[state=open]/tools:[transform:rotate(90deg)]" })] }), _jsx(CollapsibleContent, { children: _jsx("div", { className: "flex flex-col border-t px-1.5 py-1.5", children: calls.map((c) => (_jsx(ToolCall, { call: c }, c.id))) }) })] }));
|
|
45
50
|
}
|
|
46
51
|
export { ToolCall, ToolCallGroup };
|
package/dist/index.d.ts
CHANGED
|
@@ -40,6 +40,8 @@ export * from "./ui/popover.js";
|
|
|
40
40
|
export * from "./ui/skeleton.js";
|
|
41
41
|
export * from "./lib/know.js";
|
|
42
42
|
export * from "./lib/render-prop.js";
|
|
43
|
+
export * from "./chat/ai-disclosure.js";
|
|
44
|
+
export * from "./chat/permission-prompt.js";
|
|
43
45
|
export * from "./lib/utils.js";
|
|
44
46
|
export { ToolCall } from "./chat/tool-call.js";
|
|
45
47
|
export type { ToolCall as ToolCallData } from "./lib/chat.js";
|
package/dist/index.js
CHANGED
|
@@ -40,6 +40,8 @@ export * from "./ui/popover.js";
|
|
|
40
40
|
export * from "./ui/skeleton.js";
|
|
41
41
|
export * from "./lib/know.js";
|
|
42
42
|
export * from "./lib/render-prop.js";
|
|
43
|
+
export * from "./chat/ai-disclosure.js";
|
|
44
|
+
export * from "./chat/permission-prompt.js";
|
|
43
45
|
export * from "./lib/utils.js";
|
|
44
46
|
export { ToolCall } from "./chat/tool-call.js";
|
|
45
47
|
export { Message } from "./chat/message.js";
|
package/dist/lib/chat.d.ts
CHANGED
|
@@ -17,11 +17,11 @@ export type AgentIdentity = {
|
|
|
17
17
|
/** The displayed name, e.g. "Architect agent". Never derived from model output. */
|
|
18
18
|
name: string;
|
|
19
19
|
role: AgentRole;
|
|
20
|
-
specialty?: string;
|
|
20
|
+
specialty?: string | undefined;
|
|
21
21
|
};
|
|
22
22
|
export type MessageAuthor = {
|
|
23
23
|
role: "user";
|
|
24
|
-
name?: string;
|
|
24
|
+
name?: string | undefined;
|
|
25
25
|
} | {
|
|
26
26
|
role: "agent";
|
|
27
27
|
agent: AgentIdentity;
|
|
@@ -30,7 +30,7 @@ export type MessageAuthor = {
|
|
|
30
30
|
| {
|
|
31
31
|
role: "person";
|
|
32
32
|
name: string;
|
|
33
|
-
team?: string;
|
|
33
|
+
team?: string | undefined;
|
|
34
34
|
}
|
|
35
35
|
/** System lines are the app's own strings, never model text. */
|
|
36
36
|
| {
|
|
@@ -47,9 +47,9 @@ export type EntityRef = {
|
|
|
47
47
|
/** The identifier, e.g. "orders.status" or "billing.invoice.due_date". */
|
|
48
48
|
name: string;
|
|
49
49
|
/** A friendlier label when there is one, e.g. "Region". */
|
|
50
|
-
label?: string;
|
|
50
|
+
label?: string | undefined;
|
|
51
51
|
/** Where it lives, when more than one place is in scope, e.g. "Shop staging". */
|
|
52
|
-
location?: string;
|
|
52
|
+
location?: string | undefined;
|
|
53
53
|
};
|
|
54
54
|
export type InlineNode = {
|
|
55
55
|
kind: "text";
|
|
@@ -68,19 +68,19 @@ export type InlineNode = {
|
|
|
68
68
|
| {
|
|
69
69
|
kind: "measured";
|
|
70
70
|
text: string;
|
|
71
|
-
source?: string;
|
|
71
|
+
source?: string | undefined;
|
|
72
72
|
}
|
|
73
73
|
/** @deprecated Renamed `measured`; still rendered the same way until 2.0. */
|
|
74
74
|
| {
|
|
75
75
|
kind: "orgData";
|
|
76
76
|
text: string;
|
|
77
|
-
source?: string;
|
|
77
|
+
source?: string | undefined;
|
|
78
78
|
}
|
|
79
79
|
/** The agent asserts this but has not verified it. */
|
|
80
80
|
| {
|
|
81
81
|
kind: "provisional";
|
|
82
82
|
nodes: InlineNode[];
|
|
83
|
-
reason?: string;
|
|
83
|
+
reason?: string | undefined;
|
|
84
84
|
} | {
|
|
85
85
|
kind: "citation";
|
|
86
86
|
sourceId: string;
|
|
@@ -103,16 +103,21 @@ export type MessageSource = {
|
|
|
103
103
|
kind: SourceKind;
|
|
104
104
|
label: string;
|
|
105
105
|
/** An inert excerpt shown in the popover. Text only. */
|
|
106
|
-
snippet?: string;
|
|
106
|
+
snippet?: string | undefined;
|
|
107
107
|
/** Where it came from in a human sense: "Docs · Sales process v3", "Query on orders". */
|
|
108
|
-
origin?: string;
|
|
109
|
-
provisional?: boolean;
|
|
108
|
+
origin?: string | undefined;
|
|
109
|
+
provisional?: boolean | undefined;
|
|
110
|
+
};
|
|
111
|
+
/** A source a tool's result supports, without the id and [n] an adapter assigns. */
|
|
112
|
+
export type ToolSource = Omit<MessageSource, "id" | "marker"> & {
|
|
113
|
+
/** Makes two results naming the same thing one source; defaults to `kind` and `label`. */
|
|
114
|
+
key?: string | undefined;
|
|
110
115
|
};
|
|
111
116
|
type ReasoningBase = {
|
|
112
117
|
id: string;
|
|
113
118
|
title: string;
|
|
114
|
-
body?: string;
|
|
115
|
-
streaming?: boolean;
|
|
119
|
+
body?: string | undefined;
|
|
120
|
+
streaming?: boolean | undefined;
|
|
116
121
|
};
|
|
117
122
|
export type ReasoningEntry = (ReasoningBase & {
|
|
118
123
|
basis: "verified";
|
|
@@ -129,13 +134,23 @@ export type ToolCall = {
|
|
|
129
134
|
title: string;
|
|
130
135
|
status: RunStatus;
|
|
131
136
|
/** Shown when expanded. Text only; long values scroll. */
|
|
132
|
-
input?: string;
|
|
133
|
-
output?: string;
|
|
134
|
-
outputLanguage?: PayloadLanguage;
|
|
137
|
+
input?: string | undefined;
|
|
138
|
+
output?: string | undefined;
|
|
139
|
+
outputLanguage?: PayloadLanguage | undefined;
|
|
135
140
|
/** e.g. "1.2s". Absent while running; never estimated. */
|
|
136
|
-
duration?: string;
|
|
141
|
+
duration?: string | undefined;
|
|
137
142
|
/** Required when status is "failed": what went wrong, in a sentence. */
|
|
138
|
-
error?: string;
|
|
143
|
+
error?: string | undefined;
|
|
144
|
+
/**
|
|
145
|
+
* Who let it run, when it needed a go-ahead: a person, or something automatic (a policy, a classifier, a rule).
|
|
146
|
+
* `note` is why, in the source's words. Left out when it needed none or the source doesn't say.
|
|
147
|
+
*/
|
|
148
|
+
approval?: {
|
|
149
|
+
by: "person" | "automatic";
|
|
150
|
+
note?: string | undefined;
|
|
151
|
+
/** The input as the agent proposed it, when a person edited it before it ran; `input` is then what ran. */
|
|
152
|
+
originalInput?: string | undefined;
|
|
153
|
+
} | undefined;
|
|
139
154
|
};
|
|
140
155
|
/** The block's language, e.g. "json", "sql", "python", "text". Shown as a label; never executed or highlighted as HTML. */
|
|
141
156
|
export type PayloadLanguage = string;
|
|
@@ -158,13 +173,13 @@ export type MessageBlock = {
|
|
|
158
173
|
nodes: InlineNode[];
|
|
159
174
|
} | {
|
|
160
175
|
kind: "list";
|
|
161
|
-
ordered?: boolean;
|
|
176
|
+
ordered?: boolean | undefined;
|
|
162
177
|
items: InlineNode[][];
|
|
163
178
|
} | {
|
|
164
179
|
kind: "payload";
|
|
165
180
|
language: PayloadLanguage;
|
|
166
181
|
text: string;
|
|
167
|
-
title?: string;
|
|
182
|
+
title?: string | undefined;
|
|
168
183
|
} | {
|
|
169
184
|
kind: "tools";
|
|
170
185
|
calls: ToolCall[];
|
|
@@ -173,7 +188,7 @@ export type MessageBlock = {
|
|
|
173
188
|
| {
|
|
174
189
|
kind: "degraded";
|
|
175
190
|
reason: string;
|
|
176
|
-
missing?: string;
|
|
191
|
+
missing?: string | undefined;
|
|
177
192
|
}
|
|
178
193
|
/**
|
|
179
194
|
* A typed card (a result table, a plan, an approval) rendered by the app's
|
|
@@ -196,53 +211,53 @@ export type Message = {
|
|
|
196
211
|
id: string;
|
|
197
212
|
author: MessageAuthor;
|
|
198
213
|
/** When it was sent. Absent when the source doesn't say; then no time is shown. */
|
|
199
|
-
createdAt?: string;
|
|
214
|
+
createdAt?: string | undefined;
|
|
200
215
|
status: MessageStatus;
|
|
201
216
|
blocks: MessageBlock[];
|
|
202
|
-
reasoning?: ReasoningEntry[];
|
|
217
|
+
reasoning?: ReasoningEntry[] | undefined;
|
|
203
218
|
/** How long the agent spent before answering, e.g. "6s". Only once known. */
|
|
204
|
-
thoughtFor?: string;
|
|
205
|
-
sources?: MessageSource[];
|
|
219
|
+
thoughtFor?: string | undefined;
|
|
220
|
+
sources?: MessageSource[] | undefined;
|
|
206
221
|
/** Shown under an agent's reply: model, cost. Only values the service measured. */
|
|
207
222
|
attribution?: {
|
|
208
|
-
model?: string;
|
|
209
|
-
cost?: string;
|
|
210
|
-
};
|
|
223
|
+
model?: string | undefined;
|
|
224
|
+
cost?: string | undefined;
|
|
225
|
+
} | undefined;
|
|
211
226
|
};
|
|
212
227
|
/** Where the next message's work lands. */
|
|
213
228
|
export type ComposerScope = {
|
|
214
|
-
account?: string;
|
|
229
|
+
account?: string | undefined;
|
|
215
230
|
environment: string;
|
|
216
|
-
detail?: string;
|
|
231
|
+
detail?: string | undefined;
|
|
217
232
|
production: boolean;
|
|
218
233
|
};
|
|
219
234
|
export type MentionOption = {
|
|
220
235
|
id: string;
|
|
221
236
|
/** The heading it sits under in the menu, e.g. "Files", "People". Groups appear in the order first used. */
|
|
222
237
|
group: string;
|
|
223
|
-
entity?: EntityRef;
|
|
238
|
+
entity?: EntityRef | undefined;
|
|
224
239
|
label: string;
|
|
225
|
-
description?: string;
|
|
240
|
+
description?: string | undefined;
|
|
226
241
|
};
|
|
227
242
|
export type SlashCommand = {
|
|
228
243
|
id: string;
|
|
229
244
|
name: string;
|
|
230
245
|
description: string;
|
|
231
246
|
/** e.g. "<object>" — shown after the name. */
|
|
232
|
-
args?: string;
|
|
247
|
+
args?: string | undefined;
|
|
233
248
|
};
|
|
234
249
|
export type Attachment = {
|
|
235
250
|
id: string;
|
|
236
251
|
name: string;
|
|
237
252
|
/** In bytes. */
|
|
238
|
-
size?: number;
|
|
253
|
+
size?: number | undefined;
|
|
239
254
|
/** e.g. "image/png", "application/pdf": picks the icon, and allows an image preview. */
|
|
240
|
-
mediaType?: string;
|
|
255
|
+
mediaType?: string | undefined;
|
|
241
256
|
/** A thumbnail your app serves (or a blob: URL), shown for images. Never a URL from model output. */
|
|
242
|
-
previewUrl?: string;
|
|
257
|
+
previewUrl?: string | undefined;
|
|
243
258
|
/** 0–1 while uploading; absent when done. */
|
|
244
|
-
progress?: number;
|
|
245
|
-
error?: string;
|
|
259
|
+
progress?: number | undefined;
|
|
260
|
+
error?: string | undefined;
|
|
246
261
|
};
|
|
247
262
|
export type PromptSuggestion = {
|
|
248
263
|
id: string;
|
package/dist/lib/know.d.ts
CHANGED
|
@@ -14,17 +14,17 @@ export type KnowSource = {
|
|
|
14
14
|
door: KnowDoor;
|
|
15
15
|
label: string;
|
|
16
16
|
/** Who added it, for files, links and answers. */
|
|
17
|
-
addedBy?: string;
|
|
18
|
-
addedAt?: string;
|
|
17
|
+
addedBy?: string | undefined;
|
|
18
|
+
addedAt?: string | undefined;
|
|
19
19
|
/** When it was last read; null if never. */
|
|
20
20
|
readAt: string | null;
|
|
21
21
|
/** How often it should be re-read, in hours, when it has a schedule. */
|
|
22
|
-
everyHours?: number;
|
|
22
|
+
everyHours?: number | undefined;
|
|
23
23
|
status: RunStatus;
|
|
24
24
|
/** "214 objects", "38 pages" — only when counted. */
|
|
25
|
-
extent?: string;
|
|
25
|
+
extent?: string | undefined;
|
|
26
26
|
/** Required when status is "failed". */
|
|
27
|
-
error?: string;
|
|
27
|
+
error?: string | undefined;
|
|
28
28
|
};
|
|
29
29
|
export type Confidence = "high" | "medium" | "low" | "unknown";
|
|
30
30
|
export type RaciRole = "R" | "A" | "C" | "I";
|
|
@@ -42,7 +42,7 @@ export type RetrievedPassage = {
|
|
|
42
42
|
/** Whether the answer actually cites it. */
|
|
43
43
|
cited: boolean;
|
|
44
44
|
/** Why it ranked where it did, when the retriever says. */
|
|
45
|
-
why?: string;
|
|
45
|
+
why?: string | undefined;
|
|
46
46
|
readAt: string | null;
|
|
47
47
|
};
|
|
48
48
|
/** A sentence in an answer and the passages it rests on. */
|
|
@@ -57,7 +57,7 @@ export type ModelOption = {
|
|
|
57
57
|
vendor: ModelVendor;
|
|
58
58
|
name: string;
|
|
59
59
|
/** One line on what it's good for. */
|
|
60
|
-
note?: string;
|
|
60
|
+
note?: string | undefined;
|
|
61
61
|
/** Relative cost, 1 (cheapest) to 4. */
|
|
62
62
|
cost: 1 | 2 | 3 | 4;
|
|
63
63
|
/** The vendor's zero-retention contract has been attested by an operator. */
|
|
@@ -70,7 +70,7 @@ export type ModelSettingsValue = {
|
|
|
70
70
|
/** Most tool-calling steps per run before it stops and asks. */
|
|
71
71
|
stepLimit: number;
|
|
72
72
|
/** Used when the primary is unavailable; must also be attested. */
|
|
73
|
-
fallback?: string;
|
|
73
|
+
fallback?: string | undefined;
|
|
74
74
|
};
|
|
75
75
|
export type ToolPermission = "always" | "ask" | "never";
|
|
76
76
|
export type ToolSetting = {
|
|
@@ -81,7 +81,7 @@ export type ToolSetting = {
|
|
|
81
81
|
effect: "read" | "write" | "deploy" | "outside";
|
|
82
82
|
permission: ToolPermission;
|
|
83
83
|
/** Permissions this tool can't take, with why. */
|
|
84
|
-
locked?: Partial<Record<ToolPermission, string
|
|
84
|
+
locked?: Partial<Record<ToolPermission, string | undefined>> | undefined;
|
|
85
85
|
};
|
|
86
86
|
export type AgentConfig = {
|
|
87
87
|
agent: AgentIdentity;
|
|
@@ -93,7 +93,7 @@ export type AgentConfig = {
|
|
|
93
93
|
ok: number;
|
|
94
94
|
failed: number;
|
|
95
95
|
}[];
|
|
96
|
-
lastFailure?: string;
|
|
96
|
+
lastFailure?: string | undefined;
|
|
97
97
|
};
|
|
98
98
|
export type Memory = {
|
|
99
99
|
id: string;
|
|
@@ -106,15 +106,17 @@ export type Memory = {
|
|
|
106
106
|
};
|
|
107
107
|
createdAt: string;
|
|
108
108
|
scope: "account" | "environment";
|
|
109
|
-
environmentId?: string;
|
|
109
|
+
environmentId?: string | undefined;
|
|
110
110
|
};
|
|
111
|
+
/** Whether agents use memory: on, paused (kept and not used for now), or off. */
|
|
112
|
+
export type MemoryModeValue = "on" | "paused" | "off";
|
|
111
113
|
export type Version = {
|
|
112
114
|
id: string;
|
|
113
115
|
label: string;
|
|
114
116
|
state: "live" | "draft" | "past";
|
|
115
117
|
at: string;
|
|
116
118
|
by: string;
|
|
117
|
-
note?: string;
|
|
119
|
+
note?: string | undefined;
|
|
118
120
|
};
|
|
119
121
|
export type ContextSegment = {
|
|
120
122
|
label: string;
|
|
@@ -6,11 +6,11 @@ import * as React from "react";
|
|
|
6
6
|
*/
|
|
7
7
|
export type RenderProp = {
|
|
8
8
|
/** Base UI's way to render as another element; the same as `asChild` with that element as the child. */
|
|
9
|
-
render?: React.ReactElement;
|
|
9
|
+
render?: React.ReactElement | undefined;
|
|
10
10
|
/** Base UI's flag for a button rendered as another element; shadcn adds it with `render`. Radix doesn't need it. */
|
|
11
|
-
nativeButton?: boolean;
|
|
11
|
+
nativeButton?: boolean | undefined;
|
|
12
12
|
};
|
|
13
13
|
export declare function withRender<P extends {
|
|
14
|
-
asChild?: boolean;
|
|
15
|
-
children?: React.ReactNode;
|
|
14
|
+
asChild?: boolean | undefined;
|
|
15
|
+
children?: React.ReactNode | undefined;
|
|
16
16
|
}>({ render, nativeButton: _nativeButton, ...props }: P & RenderProp): P;
|
|
@@ -4,7 +4,7 @@ import type { InlineNode, MessageBlock } from "./chat.js";
|
|
|
4
4
|
* unless `headings` is set, when `#`, `##` and `###` (and deeper, as level 3) become heading blocks.
|
|
5
5
|
*/
|
|
6
6
|
export declare function markdownBlocks(text: string, { headings }?: {
|
|
7
|
-
headings?: boolean;
|
|
7
|
+
headings?: boolean | undefined;
|
|
8
8
|
}): MessageBlock[];
|
|
9
9
|
/** `code`, **strong**, *em* and links (as text). Everything else stays literal. */
|
|
10
10
|
export declare function inline(text: string): InlineNode[];
|
package/dist/lib/status.d.ts
CHANGED
|
@@ -34,3 +34,24 @@ export declare const statusTone: {
|
|
|
34
34
|
readonly skipped: "outline";
|
|
35
35
|
};
|
|
36
36
|
export declare function isTerminal(status: RunStatus): status is "succeeded" | "failed" | "cancelled" | "skipped";
|
|
37
|
+
/** The machine or worker a run is on, when the app can't reach it. */
|
|
38
|
+
export type HostOffline = {
|
|
39
|
+
/** The host's name as the app knows it: "Build runner 3", "Priya’s laptop". Left out, it's "The host". */
|
|
40
|
+
host?: string | undefined;
|
|
41
|
+
/** When the app lost contact. */
|
|
42
|
+
since?: string | undefined;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Whether a run can be called alive. "live": heard from recently, or the app doesn't track it. "stale": running, but
|
|
46
|
+
* nothing heard for longer than `staleAfter`, so it may have stopped. "offline": its host can't be reached.
|
|
47
|
+
* "unchecked": there's no clock yet (rendering on the server), so freshness isn't claimed either way. "settled": it
|
|
48
|
+
* has finished, so silence is expected. Only a running run goes stale: a queued or waiting one is quiet by design.
|
|
49
|
+
*/
|
|
50
|
+
export type RunLiveness = "live" | "stale" | "offline" | "unchecked" | "settled";
|
|
51
|
+
/** Two minutes: the default silence after which a running run is no longer called running. */
|
|
52
|
+
export declare const STALE_AFTER = 120000;
|
|
53
|
+
export declare function runLiveness(run: {
|
|
54
|
+
status: RunStatus;
|
|
55
|
+
lastHeardAt?: Date | string | undefined;
|
|
56
|
+
hostOffline?: HostOffline | undefined;
|
|
57
|
+
}, now: number | null, staleAfter?: number): RunLiveness;
|
package/dist/lib/status.js
CHANGED
|
@@ -33,3 +33,20 @@ export const statusTone = {
|
|
|
33
33
|
export function isTerminal(status) {
|
|
34
34
|
return status === "succeeded" || status === "failed" || status === "cancelled" || status === "skipped";
|
|
35
35
|
}
|
|
36
|
+
/** Two minutes: the default silence after which a running run is no longer called running. */
|
|
37
|
+
export const STALE_AFTER = 120_000;
|
|
38
|
+
export function runLiveness(run, now, staleAfter = STALE_AFTER) {
|
|
39
|
+
if (isTerminal(run.status))
|
|
40
|
+
return "settled";
|
|
41
|
+
if (run.hostOffline)
|
|
42
|
+
return "offline";
|
|
43
|
+
if (run.status !== "running" || run.lastHeardAt === undefined)
|
|
44
|
+
return "live";
|
|
45
|
+
const heard = new Date(run.lastHeardAt).getTime();
|
|
46
|
+
// An unreadable time ("", "10:42") is no evidence the run is alive.
|
|
47
|
+
if (Number.isNaN(heard))
|
|
48
|
+
return "stale";
|
|
49
|
+
if (now === null)
|
|
50
|
+
return "unchecked";
|
|
51
|
+
return now - heard > staleAfter ? "stale" : "live";
|
|
52
|
+
}
|
|
@@ -11,5 +11,5 @@ export declare function comboKeys(combo: string): string[];
|
|
|
11
11
|
* the person is typing in a field, so "?" still types a question mark.
|
|
12
12
|
*/
|
|
13
13
|
export declare function useShortcut(combo: string, handler: (e: KeyboardEvent) => void, { enabled }?: {
|
|
14
|
-
enabled?: boolean;
|
|
14
|
+
enabled?: boolean | undefined;
|
|
15
15
|
}): void;
|
|
@@ -27,13 +27,13 @@ export declare function useVirtualList({ enabled, count, keyOf, scroller, estima
|
|
|
27
27
|
count: number;
|
|
28
28
|
keyOf: (index: number) => React.Key;
|
|
29
29
|
scroller: React.RefObject<HTMLElement | null>;
|
|
30
|
-
estimate?: number;
|
|
31
|
-
overscan?: number;
|
|
32
|
-
initial?: number;
|
|
30
|
+
estimate?: number | undefined;
|
|
31
|
+
overscan?: number | undefined;
|
|
32
|
+
initial?: number | undefined;
|
|
33
33
|
/** Which end to show before the scroller is measured: "end" for a thread (newest last), "start" for a list. Defaults to "end". */
|
|
34
|
-
anchor?: "start" | "end";
|
|
34
|
+
anchor?: "start" | "end" | undefined;
|
|
35
35
|
/** The gap between items, in pixels, read once the scroller is measured (e.g. from the list's computed `row-gap`). */
|
|
36
|
-
gap?: () => number;
|
|
36
|
+
gap?: (() => number) | undefined;
|
|
37
37
|
/** The key of an item to keep rendered, such as the one holding focus. */
|
|
38
|
-
pin?: string | null;
|
|
38
|
+
pin?: string | null | undefined;
|
|
39
39
|
}): VirtualList;
|
package/dist/styles.css
CHANGED
|
@@ -238,6 +238,9 @@
|
|
|
238
238
|
* (--primary, --background…), everything else by its --cd-* name. A brand theme
|
|
239
239
|
* is just such a file.
|
|
240
240
|
*
|
|
241
|
+
* Font: Inter when the font-inter item is installed (styles/candor-font-inter.css),
|
|
242
|
+
* else the system's sans-serif. Point --cd-font at your own font to use it instead.
|
|
243
|
+
*
|
|
241
244
|
* Density: data-density="compact" on <html> (or any container) tightens type for
|
|
242
245
|
* dense apps: 14px conversation text and 13px body and label text, with a narrower
|
|
243
246
|
* thread and sidebar.
|
|
@@ -476,7 +479,7 @@
|
|
|
476
479
|
|
|
477
480
|
@layer base {
|
|
478
481
|
* {
|
|
479
|
-
@apply border-border outline-ring/
|
|
482
|
+
@apply border-border outline-ring/80;
|
|
480
483
|
}
|
|
481
484
|
body {
|
|
482
485
|
@apply bg-background text-foreground font-sans text-sm;
|
package/dist/ui/button.d.ts
CHANGED
|
@@ -7,6 +7,6 @@ declare const buttonVariants: (props?: ({
|
|
|
7
7
|
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
8
8
|
declare function Button(allProps: React.ComponentProps<"button"> & VariantProps<typeof buttonVariants> & {
|
|
9
9
|
/** Render the child element (a link, say) with the button's styles instead of a <button>. */
|
|
10
|
-
asChild?: boolean;
|
|
10
|
+
asChild?: boolean | undefined;
|
|
11
11
|
} & RenderProp): React.JSX.Element;
|
|
12
12
|
export { Button, buttonVariants };
|
package/dist/ui/button.js
CHANGED
|
@@ -7,7 +7,7 @@ import { withRender } from "../lib/render-prop.js";
|
|
|
7
7
|
import { cn } from "../lib/utils.js";
|
|
8
8
|
// The accent fills the one primary act, the radius is the theme's
|
|
9
9
|
// --cd-radius-button, and buttons press down slightly on :active.
|
|
10
|
-
const buttonVariants = cva("inline-flex shrink-0 items-center justify-center gap-2 rounded-button text-sm font-medium whitespace-nowrap outline-none select-none transition-[background-color,color,border-color,box-shadow,transform,opacity] duration-150 ease-standard active:scale-[0.98] focus-visible:ring-[3px] focus-visible:ring-ring/
|
|
10
|
+
const buttonVariants = cva("inline-flex shrink-0 items-center justify-center gap-2 rounded-button text-sm font-medium whitespace-nowrap outline-none select-none transition-[background-color,color,border-color,box-shadow,transform,opacity] duration-150 ease-standard active:scale-[0.98] focus-visible:ring-[3px] focus-visible:ring-ring/80 disabled:pointer-events-none disabled:opacity-45 data-[locked]:cursor-not-allowed data-[locked]:opacity-45 data-[locked]:active:scale-100 aria-invalid:ring-destructive/25 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", {
|
|
11
11
|
variants: {
|
|
12
12
|
variant: {
|
|
13
13
|
default: "bg-primary text-primary-foreground hover:bg-primary-hover",
|
package/package.json
CHANGED