@candor-ui/react 0.0.0-stage → 1.0.1
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/LICENSE +24 -0
- package/README.md +187 -2
- package/dist/adapters/ag-ui.d.ts +75 -0
- package/dist/adapters/ag-ui.js +441 -0
- package/dist/adapters/ai-sdk.d.ts +22 -0
- package/dist/adapters/ai-sdk.js +129 -0
- package/dist/adapters/claude-agent-sdk.d.ts +80 -0
- package/dist/adapters/claude-agent-sdk.js +265 -0
- package/dist/adapters/claude-agent-server.d.ts +53 -0
- package/dist/adapters/claude-agent-server.js +104 -0
- package/dist/adapters/use-ag-ui.d.ts +55 -0
- package/dist/adapters/use-ag-ui.js +168 -0
- package/dist/adapters/use-candor-chat.d.ts +40 -0
- package/dist/adapters/use-candor-chat.js +56 -0
- package/dist/adapters/use-claude-agent.d.ts +48 -0
- package/dist/adapters/use-claude-agent.js +143 -0
- package/dist/ag-ui.d.ts +2 -0
- package/dist/ag-ui.js +2 -0
- package/dist/ai-sdk.d.ts +2 -0
- package/dist/ai-sdk.js +2 -0
- package/dist/blocks/copy-field.d.ts +13 -0
- package/dist/blocks/copy-field.js +15 -0
- package/dist/blocks/degraded-panel.d.ts +19 -0
- package/dist/blocks/degraded-panel.js +14 -0
- package/dist/blocks/locked.d.ts +26 -0
- package/dist/blocks/locked.js +36 -0
- package/dist/blocks/relative-time.d.ts +13 -0
- package/dist/blocks/relative-time.js +62 -0
- package/dist/blocks/status-dot.d.ts +16 -0
- package/dist/blocks/status-dot.js +25 -0
- package/dist/blocks/step-list.d.ts +23 -0
- package/dist/blocks/step-list.js +37 -0
- package/dist/blocks/streaming-text.d.ts +17 -0
- package/dist/blocks/streaming-text.js +14 -0
- package/dist/blocks/surface.d.ts +9 -0
- package/dist/blocks/surface.js +35 -0
- package/dist/blocks/terms.d.ts +24 -0
- package/dist/blocks/terms.js +17 -0
- package/dist/chat/agent-avatar.d.ts +34 -0
- package/dist/chat/agent-avatar.js +42 -0
- package/dist/chat/card-registry.d.ts +39 -0
- package/dist/chat/card-registry.js +49 -0
- package/dist/chat/citation.d.ts +29 -0
- package/dist/chat/citation.js +44 -0
- package/dist/chat/composer.d.ts +54 -0
- package/dist/chat/composer.js +168 -0
- package/dist/chat/context-meter.d.ts +14 -0
- package/dist/chat/context-meter.js +30 -0
- package/dist/chat/entity-chip.d.ts +37 -0
- package/dist/chat/entity-chip.js +52 -0
- package/dist/chat/message-actions.d.ts +21 -0
- package/dist/chat/message-actions.js +20 -0
- package/dist/chat/message-content.d.ts +25 -0
- package/dist/chat/message-content.js +122 -0
- package/dist/chat/message.d.ts +39 -0
- package/dist/chat/message.js +44 -0
- package/dist/chat/payload.d.ts +16 -0
- package/dist/chat/payload.js +18 -0
- package/dist/chat/prompt-suggestions.d.ts +20 -0
- package/dist/chat/prompt-suggestions.js +18 -0
- package/dist/chat/reasoning.d.ts +18 -0
- package/dist/chat/reasoning.js +31 -0
- package/dist/chat/thread.d.ts +18 -0
- package/dist/chat/thread.js +60 -0
- package/dist/chat/tool-call.d.ts +19 -0
- package/dist/chat/tool-call.js +33 -0
- package/dist/claude-server.d.ts +1 -0
- package/dist/claude-server.js +2 -0
- package/dist/claude.d.ts +2 -0
- package/dist/claude.js +2 -0
- package/dist/index.d.ts +40 -0
- package/dist/index.js +38 -0
- package/dist/lib/chat.d.ts +241 -0
- package/dist/lib/chat.js +1 -0
- package/dist/lib/know.d.ts +123 -0
- package/dist/lib/know.js +1 -0
- package/dist/lib/render-prop.d.ts +16 -0
- package/dist/lib/render-prop.js +7 -0
- package/dist/lib/safe-markdown.d.ts +12 -0
- package/dist/lib/safe-markdown.js +98 -0
- package/dist/lib/status.d.ts +21 -0
- package/dist/lib/status.js +26 -0
- package/dist/lib/use-copy.d.ts +10 -0
- package/dist/lib/use-copy.js +24 -0
- package/dist/lib/use-shortcut.d.ts +15 -0
- package/dist/lib/use-shortcut.js +62 -0
- package/dist/lib/utils.d.ts +2 -0
- package/dist/lib/utils.js +5 -0
- package/dist/styles.css +460 -0
- package/dist/ui/button.d.ts +12 -0
- package/dist/ui/button.js +41 -0
- package/dist/ui/collapsible.d.ts +6 -0
- package/dist/ui/collapsible.js +15 -0
- package/dist/ui/popover.d.ts +11 -0
- package/dist/ui/popover.js +29 -0
- package/dist/ui/skeleton.d.ts +2 -0
- package/dist/ui/skeleton.js +6 -0
- package/dist/ui/tooltip.d.ts +9 -0
- package/dist/ui/tooltip.js +24 -0
- package/package.json +90 -4
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { ChevronRight, Wrench } from "lucide-react";
|
|
5
|
+
import { cn } from "../lib/utils.js";
|
|
6
|
+
import { StepMark } from "../blocks/step-list.js";
|
|
7
|
+
import { ShimmerLabel } from "../blocks/streaming-text.js";
|
|
8
|
+
import { statusLabel } from "../lib/status.js";
|
|
9
|
+
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "../ui/collapsible.js";
|
|
10
|
+
import { Payload } from "./payload.js";
|
|
11
|
+
/**
|
|
12
|
+
* One tool call as a compact row: what it did in plain words, its status, and
|
|
13
|
+
* how long it took. Expands to the input and output. A failed call opens by
|
|
14
|
+
* default and leads with its error.
|
|
15
|
+
*/
|
|
16
|
+
function ToolCall({ call, className, }) {
|
|
17
|
+
const failed = call.status === "failed";
|
|
18
|
+
const [open, setOpen] = React.useState(failed);
|
|
19
|
+
const hasDetail = Boolean(call.input || call.output || call.error);
|
|
20
|
+
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-left outline-none transition-colors duration-150 enabled:hover:bg-accent focus-visible:ring-[3px] focus-visible:ring-ring/40", 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]] })] }), _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: "size-3.5 shrink-0 text-faint-foreground transition-transform duration-200 ease-standard group-data-[state=open]/tool:rotate-90" }))] }), _jsx(CollapsibleContent, { className: "data-[state=open]:animate-in data-[state=open]:fade-in-0", children: _jsxs("div", { className: "mt-1 mb-2 ml-[1.375rem] flex flex-col gap-2 border-l pl-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.input && _jsx(Payload, { language: "json", title: "Input", text: call.input }), call.output && _jsx(Payload, { language: call.outputLanguage ?? "text", title: "Output", text: call.output })] }) })] }));
|
|
21
|
+
}
|
|
22
|
+
/** A run of tool calls, with a count when it's long enough to fold. */
|
|
23
|
+
function ToolCallGroup({ calls, className, }) {
|
|
24
|
+
const done = calls.filter((c) => c.status === "succeeded").length;
|
|
25
|
+
const failed = calls.filter((c) => c.status === "failed").length;
|
|
26
|
+
const running = calls.some((c) => c.status === "running");
|
|
27
|
+
const [open, setOpen] = React.useState(true);
|
|
28
|
+
if (calls.length <= 2) {
|
|
29
|
+
return (_jsx("div", { "data-slot": "tool-call-group", className: cn("flex flex-col", className), children: calls.map((c) => (_jsx(ToolCall, { call: c }, c.id))) }));
|
|
30
|
+
}
|
|
31
|
+
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-left text-xs text-muted-foreground outline-none hover:text-foreground focus-visible:ring-[3px] focus-visible:ring-ring/40 rounded-lg", children: [_jsx(Wrench, { "aria-hidden": true, className: "size-3.5" }), _jsxs("span", { className: "flex-1", children: [calls.length, " tool calls", done > 0 && ` · ${done} done`, failed > 0 && _jsxs("span", { className: "text-destructive-text", children: [" \u00B7 ", failed, " failed"] }), running && " · working"] }), _jsx(ChevronRight, { "aria-hidden": true, className: "size-3.5 transition-transform duration-200 ease-standard group-data-[state=open]/tools:rotate-90" })] }), _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))) }) })] }));
|
|
32
|
+
}
|
|
33
|
+
export { ToolCall, ToolCallGroup };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./adapters/claude-agent-server.js";
|
package/dist/claude.d.ts
ADDED
package/dist/claude.js
ADDED
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export * from "./lib/chat.js";
|
|
2
|
+
export * from "./lib/status.js";
|
|
3
|
+
export * from "./lib/use-copy.js";
|
|
4
|
+
export * from "./lib/use-shortcut.js";
|
|
5
|
+
export * from "./blocks/terms.js";
|
|
6
|
+
export * from "./blocks/locked.js";
|
|
7
|
+
export * from "./blocks/status-dot.js";
|
|
8
|
+
export * from "./blocks/step-list.js";
|
|
9
|
+
export * from "./blocks/streaming-text.js";
|
|
10
|
+
export * from "./blocks/relative-time.js";
|
|
11
|
+
export * from "./blocks/copy-field.js";
|
|
12
|
+
export * from "./blocks/degraded-panel.js";
|
|
13
|
+
export * from "./blocks/surface.js";
|
|
14
|
+
export * from "./chat/agent-avatar.js";
|
|
15
|
+
export * from "./chat/entity-chip.js";
|
|
16
|
+
export * from "./chat/citation.js";
|
|
17
|
+
export * from "./chat/payload.js";
|
|
18
|
+
export * from "./chat/message-content.js";
|
|
19
|
+
export * from "./chat/message.js";
|
|
20
|
+
export * from "./chat/message-actions.js";
|
|
21
|
+
export * from "./chat/reasoning.js";
|
|
22
|
+
export * from "./chat/tool-call.js";
|
|
23
|
+
export * from "./chat/thread.js";
|
|
24
|
+
export * from "./chat/composer.js";
|
|
25
|
+
export * from "./chat/prompt-suggestions.js";
|
|
26
|
+
export * from "./chat/context-meter.js";
|
|
27
|
+
export * from "./chat/card-registry.js";
|
|
28
|
+
export * from "./lib/safe-markdown.js";
|
|
29
|
+
export * from "./ui/button.js";
|
|
30
|
+
export * from "./ui/tooltip.js";
|
|
31
|
+
export * from "./ui/collapsible.js";
|
|
32
|
+
export * from "./ui/popover.js";
|
|
33
|
+
export * from "./ui/skeleton.js";
|
|
34
|
+
export * from "./lib/know.js";
|
|
35
|
+
export * from "./lib/render-prop.js";
|
|
36
|
+
export * from "./lib/utils.js";
|
|
37
|
+
export { ToolCall } from "./chat/tool-call.js";
|
|
38
|
+
export type { ToolCall as ToolCallData } from "./lib/chat.js";
|
|
39
|
+
export { Message } from "./chat/message.js";
|
|
40
|
+
export type { Message as MessageData } from "./lib/chat.js";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export * from "./lib/chat.js";
|
|
2
|
+
export * from "./lib/status.js";
|
|
3
|
+
export * from "./lib/use-copy.js";
|
|
4
|
+
export * from "./lib/use-shortcut.js";
|
|
5
|
+
export * from "./blocks/terms.js";
|
|
6
|
+
export * from "./blocks/locked.js";
|
|
7
|
+
export * from "./blocks/status-dot.js";
|
|
8
|
+
export * from "./blocks/step-list.js";
|
|
9
|
+
export * from "./blocks/streaming-text.js";
|
|
10
|
+
export * from "./blocks/relative-time.js";
|
|
11
|
+
export * from "./blocks/copy-field.js";
|
|
12
|
+
export * from "./blocks/degraded-panel.js";
|
|
13
|
+
export * from "./blocks/surface.js";
|
|
14
|
+
export * from "./chat/agent-avatar.js";
|
|
15
|
+
export * from "./chat/entity-chip.js";
|
|
16
|
+
export * from "./chat/citation.js";
|
|
17
|
+
export * from "./chat/payload.js";
|
|
18
|
+
export * from "./chat/message-content.js";
|
|
19
|
+
export * from "./chat/message.js";
|
|
20
|
+
export * from "./chat/message-actions.js";
|
|
21
|
+
export * from "./chat/reasoning.js";
|
|
22
|
+
export * from "./chat/tool-call.js";
|
|
23
|
+
export * from "./chat/thread.js";
|
|
24
|
+
export * from "./chat/composer.js";
|
|
25
|
+
export * from "./chat/prompt-suggestions.js";
|
|
26
|
+
export * from "./chat/context-meter.js";
|
|
27
|
+
export * from "./chat/card-registry.js";
|
|
28
|
+
export * from "./lib/safe-markdown.js";
|
|
29
|
+
export * from "./ui/button.js";
|
|
30
|
+
export * from "./ui/tooltip.js";
|
|
31
|
+
export * from "./ui/collapsible.js";
|
|
32
|
+
export * from "./ui/popover.js";
|
|
33
|
+
export * from "./ui/skeleton.js";
|
|
34
|
+
export * from "./lib/know.js";
|
|
35
|
+
export * from "./lib/render-prop.js";
|
|
36
|
+
export * from "./lib/utils.js";
|
|
37
|
+
export { ToolCall } from "./chat/tool-call.js";
|
|
38
|
+
export { Message } from "./chat/message.js";
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The data a Candor thread renders. Plain, serialisable shapes: your
|
|
3
|
+
* service produces them from its own model drivers, and an adapter can produce
|
|
4
|
+
* them from any SDK. They follow the Candor design system's ChatMessage contract:
|
|
5
|
+
*
|
|
6
|
+
* - A message is a list of typed blocks, never markdown or HTML. Text from a
|
|
7
|
+
* model or from the user's system is always rendered as text.
|
|
8
|
+
* - An agent message always carries the agent's full identity.
|
|
9
|
+
* - A claim the agent has not verified is marked `provisional`, and reasoning
|
|
10
|
+
* says whether each step is verified, believed or assumed.
|
|
11
|
+
*/
|
|
12
|
+
import type { RunStatus } from "./status.js";
|
|
13
|
+
/** What an agent does: "assistant", "coder", "reviewer"… The app registers each role's glyph and hue (AgentRolesProvider). */
|
|
14
|
+
export type AgentRole = string;
|
|
15
|
+
export type AgentIdentity = {
|
|
16
|
+
id: string;
|
|
17
|
+
/** The displayed name, e.g. "Architect agent". Never derived from model output. */
|
|
18
|
+
name: string;
|
|
19
|
+
role: AgentRole;
|
|
20
|
+
specialty?: string;
|
|
21
|
+
};
|
|
22
|
+
export type MessageAuthor = {
|
|
23
|
+
role: "user";
|
|
24
|
+
name?: string;
|
|
25
|
+
} | {
|
|
26
|
+
role: "agent";
|
|
27
|
+
agent: AgentIdentity;
|
|
28
|
+
}
|
|
29
|
+
/** A person on the app's own team (support staff, a reviewer), not the user: shown by name, with their team. */
|
|
30
|
+
| {
|
|
31
|
+
role: "person";
|
|
32
|
+
name: string;
|
|
33
|
+
team?: string;
|
|
34
|
+
}
|
|
35
|
+
/** System lines are the app's own strings, never model text. */
|
|
36
|
+
| {
|
|
37
|
+
role: "system";
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* What kind of thing an entity is: "record", "table", "workflow"… Any string;
|
|
41
|
+
* the app registers each kind's icon and noun (see EntityKindsProvider), and
|
|
42
|
+
* presets cover common systems (e.g. Salesforce).
|
|
43
|
+
*/
|
|
44
|
+
export type EntityKind = string;
|
|
45
|
+
export type EntityRef = {
|
|
46
|
+
kind: EntityKind;
|
|
47
|
+
/** The identifier, e.g. "Account.Region__c" or "orders.status". */
|
|
48
|
+
name: string;
|
|
49
|
+
/** A friendlier label when there is one, e.g. "Region". */
|
|
50
|
+
label?: string;
|
|
51
|
+
/** Where it lives, when more than one place is in scope, e.g. "Shop staging". */
|
|
52
|
+
location?: string;
|
|
53
|
+
};
|
|
54
|
+
export type InlineNode = {
|
|
55
|
+
kind: "text";
|
|
56
|
+
text: string;
|
|
57
|
+
} | {
|
|
58
|
+
kind: "strong";
|
|
59
|
+
text: string;
|
|
60
|
+
} | {
|
|
61
|
+
kind: "em";
|
|
62
|
+
text: string;
|
|
63
|
+
} | {
|
|
64
|
+
kind: "code";
|
|
65
|
+
text: string;
|
|
66
|
+
}
|
|
67
|
+
/** A value read from the environment (a count, a setting). Shown with its source on hover. */
|
|
68
|
+
| {
|
|
69
|
+
kind: "measured";
|
|
70
|
+
text: string;
|
|
71
|
+
source?: string;
|
|
72
|
+
}
|
|
73
|
+
/** @deprecated Renamed `measured`; still rendered the same way until 2.0. */
|
|
74
|
+
| {
|
|
75
|
+
kind: "orgData";
|
|
76
|
+
text: string;
|
|
77
|
+
source?: string;
|
|
78
|
+
}
|
|
79
|
+
/** The agent asserts this but has not verified it. */
|
|
80
|
+
| {
|
|
81
|
+
kind: "provisional";
|
|
82
|
+
nodes: InlineNode[];
|
|
83
|
+
reason?: string;
|
|
84
|
+
} | {
|
|
85
|
+
kind: "citation";
|
|
86
|
+
sourceId: string;
|
|
87
|
+
} | {
|
|
88
|
+
kind: "entity";
|
|
89
|
+
entity: EntityRef;
|
|
90
|
+
}
|
|
91
|
+
/** An in-app route only; external links are never rendered from model output. */
|
|
92
|
+
| {
|
|
93
|
+
kind: "link";
|
|
94
|
+
text: string;
|
|
95
|
+
to: string;
|
|
96
|
+
};
|
|
97
|
+
/** "document", "web", "query", "code", "data", "workflow", "knowledge", or the app's own; unknown kinds read as "Source". */
|
|
98
|
+
export type SourceKind = string;
|
|
99
|
+
export type MessageSource = {
|
|
100
|
+
id: string;
|
|
101
|
+
/** The [n] shown inline. Assigned by the service, so it is stable across renders. */
|
|
102
|
+
marker: number;
|
|
103
|
+
kind: SourceKind;
|
|
104
|
+
label: string;
|
|
105
|
+
/** An inert excerpt shown in the popover. Text only. */
|
|
106
|
+
snippet?: string;
|
|
107
|
+
/** Where it came from in a human sense: "Docs · Sales process v3", "Query on orders". */
|
|
108
|
+
origin?: string;
|
|
109
|
+
provisional?: boolean;
|
|
110
|
+
};
|
|
111
|
+
type ReasoningBase = {
|
|
112
|
+
id: string;
|
|
113
|
+
title: string;
|
|
114
|
+
body?: string;
|
|
115
|
+
streaming?: boolean;
|
|
116
|
+
};
|
|
117
|
+
export type ReasoningEntry = (ReasoningBase & {
|
|
118
|
+
basis: "verified";
|
|
119
|
+
evidence: string;
|
|
120
|
+
}) | (ReasoningBase & {
|
|
121
|
+
basis: "believed" | "assumed";
|
|
122
|
+
assumption: string;
|
|
123
|
+
});
|
|
124
|
+
export type ToolCall = {
|
|
125
|
+
id: string;
|
|
126
|
+
/** The tool's name, for people who want it: "metadata.describe". */
|
|
127
|
+
tool: string;
|
|
128
|
+
/** What it did, in plain words: "Read Account's fields". */
|
|
129
|
+
title: string;
|
|
130
|
+
status: RunStatus;
|
|
131
|
+
/** Shown when expanded. Text only; long values scroll. */
|
|
132
|
+
input?: string;
|
|
133
|
+
output?: string;
|
|
134
|
+
outputLanguage?: PayloadLanguage;
|
|
135
|
+
/** e.g. "1.2s". Absent while running; never estimated. */
|
|
136
|
+
duration?: string;
|
|
137
|
+
/** Required when status is "failed": what went wrong, in a sentence. */
|
|
138
|
+
error?: string;
|
|
139
|
+
};
|
|
140
|
+
/** The block's language, e.g. "json", "sql", "python", "text". Shown as a label; never executed or highlighted as HTML. */
|
|
141
|
+
export type PayloadLanguage = string;
|
|
142
|
+
export type MessageBlock = {
|
|
143
|
+
kind: "paragraph";
|
|
144
|
+
nodes: InlineNode[];
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Text exactly as someone typed it: line breaks and spacing kept, nothing parsed. For a person's own words, so
|
|
148
|
+
* `*this*` stays `*this*` and a pasted list keeps its lines.
|
|
149
|
+
*/
|
|
150
|
+
| {
|
|
151
|
+
kind: "plain";
|
|
152
|
+
text: string;
|
|
153
|
+
}
|
|
154
|
+
/** A heading inside a reply. Levels are relative to the message, 1 the largest; the page's own headings sit above. */
|
|
155
|
+
| {
|
|
156
|
+
kind: "heading";
|
|
157
|
+
level: 1 | 2 | 3;
|
|
158
|
+
nodes: InlineNode[];
|
|
159
|
+
} | {
|
|
160
|
+
kind: "list";
|
|
161
|
+
ordered?: boolean;
|
|
162
|
+
items: InlineNode[][];
|
|
163
|
+
} | {
|
|
164
|
+
kind: "payload";
|
|
165
|
+
language: PayloadLanguage;
|
|
166
|
+
text: string;
|
|
167
|
+
title?: string;
|
|
168
|
+
} | {
|
|
169
|
+
kind: "tools";
|
|
170
|
+
calls: ToolCall[];
|
|
171
|
+
}
|
|
172
|
+
/** Something the agent could not do, and what is missing because of it. */
|
|
173
|
+
| {
|
|
174
|
+
kind: "degraded";
|
|
175
|
+
reason: string;
|
|
176
|
+
missing?: string;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* A typed card (a result table, a plan, an approval) rendered by the app's
|
|
180
|
+
* card registry. `summary` is the service's plain-text version, used for copy
|
|
181
|
+
* and whenever the card can't be shown.
|
|
182
|
+
*/
|
|
183
|
+
| {
|
|
184
|
+
kind: "card";
|
|
185
|
+
card: string;
|
|
186
|
+
props: unknown;
|
|
187
|
+
summary: string;
|
|
188
|
+
};
|
|
189
|
+
export type MessageStatus = "streaming" | "complete" | "interrupted" | "failed";
|
|
190
|
+
export type Message = {
|
|
191
|
+
id: string;
|
|
192
|
+
author: MessageAuthor;
|
|
193
|
+
/** When it was sent. Absent when the source doesn't say; then no time is shown. */
|
|
194
|
+
createdAt?: string;
|
|
195
|
+
status: MessageStatus;
|
|
196
|
+
blocks: MessageBlock[];
|
|
197
|
+
reasoning?: ReasoningEntry[];
|
|
198
|
+
/** How long the agent spent before answering, e.g. "6s". Only once known. */
|
|
199
|
+
thoughtFor?: string;
|
|
200
|
+
sources?: MessageSource[];
|
|
201
|
+
/** Shown under an agent's reply: model, cost. Only values the service measured. */
|
|
202
|
+
attribution?: {
|
|
203
|
+
model?: string;
|
|
204
|
+
cost?: string;
|
|
205
|
+
};
|
|
206
|
+
};
|
|
207
|
+
/** Where the next message's work lands. */
|
|
208
|
+
export type ComposerScope = {
|
|
209
|
+
account?: string;
|
|
210
|
+
environment: string;
|
|
211
|
+
detail?: string;
|
|
212
|
+
production: boolean;
|
|
213
|
+
};
|
|
214
|
+
export type MentionOption = {
|
|
215
|
+
id: string;
|
|
216
|
+
/** The heading it sits under in the menu, e.g. "Files", "People". Groups appear in the order first used. */
|
|
217
|
+
group: string;
|
|
218
|
+
entity?: EntityRef;
|
|
219
|
+
label: string;
|
|
220
|
+
description?: string;
|
|
221
|
+
};
|
|
222
|
+
export type SlashCommand = {
|
|
223
|
+
id: string;
|
|
224
|
+
name: string;
|
|
225
|
+
description: string;
|
|
226
|
+
/** e.g. "<object>" — shown after the name. */
|
|
227
|
+
args?: string;
|
|
228
|
+
};
|
|
229
|
+
export type Attachment = {
|
|
230
|
+
id: string;
|
|
231
|
+
name: string;
|
|
232
|
+
size?: number;
|
|
233
|
+
/** 0–1 while uploading; absent when done. */
|
|
234
|
+
progress?: number;
|
|
235
|
+
error?: string;
|
|
236
|
+
};
|
|
237
|
+
export type PromptSuggestion = {
|
|
238
|
+
id: string;
|
|
239
|
+
text: string;
|
|
240
|
+
};
|
|
241
|
+
export {};
|
package/dist/lib/chat.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The data behind the agents' knowledge base and agent settings. Its rules: unknown never renders as definitive; no
|
|
3
|
+
* figure without a basis; each source door has its own freshness. The model
|
|
4
|
+
* layer's rule: only zero-data-retention endpoints, and only once an operator
|
|
5
|
+
* has attested the vendor's contract.
|
|
6
|
+
*/
|
|
7
|
+
import type { AgentIdentity } from "./chat.js";
|
|
8
|
+
import type { RunStatus } from "./status.js";
|
|
9
|
+
/** The ways knowledge gets in. */
|
|
10
|
+
/** How knowledge came in: read from the environment's configuration or data, shared as a file or link, answered by a person, or a vendor's release notes. */
|
|
11
|
+
export type KnowDoor = "config" | "data" | "file" | "link" | "answer" | "release-notes";
|
|
12
|
+
export type KnowSource = {
|
|
13
|
+
id: string;
|
|
14
|
+
door: KnowDoor;
|
|
15
|
+
label: string;
|
|
16
|
+
/** Who added it, for files, links and answers. */
|
|
17
|
+
addedBy?: string;
|
|
18
|
+
addedAt?: string;
|
|
19
|
+
/** When it was last read; null if never. */
|
|
20
|
+
readAt: string | null;
|
|
21
|
+
/** How often it should be re-read, in hours, when it has a schedule. */
|
|
22
|
+
everyHours?: number;
|
|
23
|
+
status: RunStatus;
|
|
24
|
+
/** "214 objects", "38 pages" — only when counted. */
|
|
25
|
+
extent?: string;
|
|
26
|
+
/** Required when status is "failed". */
|
|
27
|
+
error?: string;
|
|
28
|
+
};
|
|
29
|
+
export type Confidence = "high" | "medium" | "low" | "unknown";
|
|
30
|
+
export type RaciRole = "R" | "A" | "C" | "I";
|
|
31
|
+
export type RaciAssignment = {
|
|
32
|
+
role: RaciRole;
|
|
33
|
+
who: string;
|
|
34
|
+
};
|
|
35
|
+
export type RetrievedPassage = {
|
|
36
|
+
id: string;
|
|
37
|
+
sourceId: string;
|
|
38
|
+
title: string;
|
|
39
|
+
excerpt: string;
|
|
40
|
+
/** Retrieval score 0–1; null when the retriever didn't score it (e.g. a pinned source). */
|
|
41
|
+
score: number | null;
|
|
42
|
+
/** Whether the answer actually cites it. */
|
|
43
|
+
cited: boolean;
|
|
44
|
+
/** Why it ranked where it did, when the retriever says. */
|
|
45
|
+
why?: string;
|
|
46
|
+
readAt: string | null;
|
|
47
|
+
};
|
|
48
|
+
/** A sentence in an answer and the passages it rests on. */
|
|
49
|
+
export type Claim = {
|
|
50
|
+
id: string;
|
|
51
|
+
text: string;
|
|
52
|
+
evidence: string[];
|
|
53
|
+
};
|
|
54
|
+
export type ModelVendor = "Anthropic" | "Google" | "OpenAI" | "xAI";
|
|
55
|
+
export type ModelOption = {
|
|
56
|
+
id: string;
|
|
57
|
+
vendor: ModelVendor;
|
|
58
|
+
name: string;
|
|
59
|
+
/** One line on what it's good for. */
|
|
60
|
+
note?: string;
|
|
61
|
+
/** Relative cost, 1 (cheapest) to 4. */
|
|
62
|
+
cost: 1 | 2 | 3 | 4;
|
|
63
|
+
/** The vendor's zero-retention contract has been attested by an operator. */
|
|
64
|
+
zdr: "attested" | "not-attested";
|
|
65
|
+
};
|
|
66
|
+
export type ReasoningEffort = "low" | "medium" | "high" | "max";
|
|
67
|
+
export type ModelSettingsValue = {
|
|
68
|
+
model: string;
|
|
69
|
+
reasoning: ReasoningEffort;
|
|
70
|
+
/** Most tool-calling steps per run before it stops and asks. */
|
|
71
|
+
stepLimit: number;
|
|
72
|
+
/** Used when the primary is unavailable; must also be attested. */
|
|
73
|
+
fallback?: string;
|
|
74
|
+
};
|
|
75
|
+
export type ToolPermission = "always" | "ask" | "never";
|
|
76
|
+
export type ToolSetting = {
|
|
77
|
+
id: string;
|
|
78
|
+
name: string;
|
|
79
|
+
description: string;
|
|
80
|
+
/** What the tool can do to the environment. */
|
|
81
|
+
effect: "read" | "write" | "deploy" | "outside";
|
|
82
|
+
permission: ToolPermission;
|
|
83
|
+
/** Permissions this tool can't take, with why. */
|
|
84
|
+
locked?: Partial<Record<ToolPermission, string>>;
|
|
85
|
+
};
|
|
86
|
+
export type AgentConfig = {
|
|
87
|
+
agent: AgentIdentity;
|
|
88
|
+
enabled: boolean;
|
|
89
|
+
status: RunStatus;
|
|
90
|
+
model: string;
|
|
91
|
+
/** Runs per day for the last 14 days, oldest first. */
|
|
92
|
+
runs: {
|
|
93
|
+
ok: number;
|
|
94
|
+
failed: number;
|
|
95
|
+
}[];
|
|
96
|
+
lastFailure?: string;
|
|
97
|
+
};
|
|
98
|
+
export type Memory = {
|
|
99
|
+
id: string;
|
|
100
|
+
text: string;
|
|
101
|
+
/** Who taught it: a person said so, or an agent inferred it. */
|
|
102
|
+
from: {
|
|
103
|
+
person: string;
|
|
104
|
+
} | {
|
|
105
|
+
agent: AgentIdentity;
|
|
106
|
+
};
|
|
107
|
+
createdAt: string;
|
|
108
|
+
scope: "account" | "environment";
|
|
109
|
+
environmentId?: string;
|
|
110
|
+
};
|
|
111
|
+
export type Version = {
|
|
112
|
+
id: string;
|
|
113
|
+
label: string;
|
|
114
|
+
state: "live" | "draft" | "past";
|
|
115
|
+
at: string;
|
|
116
|
+
by: string;
|
|
117
|
+
note?: string;
|
|
118
|
+
};
|
|
119
|
+
export type ContextSegment = {
|
|
120
|
+
label: string;
|
|
121
|
+
tokens: number;
|
|
122
|
+
kind: "system" | "instructions" | "knowledge" | "thread" | "tools" | "files";
|
|
123
|
+
};
|
package/dist/lib/know.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Lets Candor's Radix-based primitives also take Base UI's `render` prop. In projects on a Base UI style
|
|
4
|
+
* (shadcn's `base-*` styles), the shadcn CLI rewrites `<Trigger asChild><button/></Trigger>` into
|
|
5
|
+
* `<Trigger render={<button/>}>`; this turns that back into Radix's asChild, so Candor works in either kind of project.
|
|
6
|
+
*/
|
|
7
|
+
export type RenderProp = {
|
|
8
|
+
/** Base UI's way to render as another element; the same as `asChild` with that element as the child. */
|
|
9
|
+
render?: React.ReactElement;
|
|
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;
|
|
12
|
+
};
|
|
13
|
+
export declare function withRender<P extends {
|
|
14
|
+
asChild?: boolean;
|
|
15
|
+
children?: React.ReactNode;
|
|
16
|
+
}>({ render, nativeButton: _nativeButton, ...props }: P & RenderProp): P;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export function withRender({ render, nativeButton: _nativeButton, ...props }) {
|
|
3
|
+
if (!render)
|
|
4
|
+
return props;
|
|
5
|
+
const children = props.children === undefined ? render : React.cloneElement(render, undefined, props.children);
|
|
6
|
+
return { ...props, asChild: true, children };
|
|
7
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { InlineNode, MessageBlock } from "./chat.js";
|
|
2
|
+
/**
|
|
3
|
+
* Reads model text as safe markdown: paragraphs, lists and fenced code. Never HTML. `#` lines are bold paragraphs
|
|
4
|
+
* unless `headings` is set, when `#`, `##` and `###` (and deeper, as level 3) become heading blocks.
|
|
5
|
+
*/
|
|
6
|
+
export declare function markdownBlocks(text: string, { headings }?: {
|
|
7
|
+
headings?: boolean;
|
|
8
|
+
}): MessageBlock[];
|
|
9
|
+
/** `code`, **strong**, *em* and links (as text). Everything else stays literal. */
|
|
10
|
+
export declare function inline(text: string): InlineNode[];
|
|
11
|
+
/** A person's own words as one block, exactly as typed. Adapters use this for user messages: what someone typed is never read as markdown. */
|
|
12
|
+
export declare function plainBlocks(text: string): MessageBlock[];
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Model text → Candor blocks. Candor never renders model output as HTML or
|
|
3
|
+
* markdown, so text is read as a small, safe subset of markdown (paragraphs,
|
|
4
|
+
* lists, fenced code, `code`, **strong**, *em*) into typed blocks. Links
|
|
5
|
+
* become plain text with the address in brackets: nothing from a model is
|
|
6
|
+
* ever a clickable link. Every adapter uses this.
|
|
7
|
+
*/
|
|
8
|
+
const fenceLanguage = (lang) => (lang === "json" ? "json" : lang === "xml" || lang === "html" ? "xml" : "text");
|
|
9
|
+
/**
|
|
10
|
+
* Reads model text as safe markdown: paragraphs, lists and fenced code. Never HTML. `#` lines are bold paragraphs
|
|
11
|
+
* unless `headings` is set, when `#`, `##` and `###` (and deeper, as level 3) become heading blocks.
|
|
12
|
+
*/
|
|
13
|
+
export function markdownBlocks(text, { headings = false } = {}) {
|
|
14
|
+
const blocks = [];
|
|
15
|
+
const lines = text.replace(/\r\n/g, "\n").split("\n");
|
|
16
|
+
let para = [];
|
|
17
|
+
let list = null;
|
|
18
|
+
const flushPara = () => {
|
|
19
|
+
if (para.length)
|
|
20
|
+
blocks.push({ kind: "paragraph", nodes: inline(para.join(" ")) });
|
|
21
|
+
para = [];
|
|
22
|
+
};
|
|
23
|
+
const flushList = () => {
|
|
24
|
+
if (list)
|
|
25
|
+
blocks.push({ kind: "list", ordered: list.ordered, items: list.items.map(inline) });
|
|
26
|
+
list = null;
|
|
27
|
+
};
|
|
28
|
+
for (let i = 0; i < lines.length; i++) {
|
|
29
|
+
const line = lines[i];
|
|
30
|
+
const fence = /^\s*```(\w*)\s*$/.exec(line);
|
|
31
|
+
if (fence) {
|
|
32
|
+
flushPara();
|
|
33
|
+
flushList();
|
|
34
|
+
const body = [];
|
|
35
|
+
while (++i < lines.length && !/^\s*```\s*$/.test(lines[i]))
|
|
36
|
+
body.push(lines[i]);
|
|
37
|
+
blocks.push({ kind: "payload", language: fenceLanguage(fence[1].toLowerCase()), text: body.join("\n"), title: fence[1] || undefined });
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
const item = /^\s*(?:([-*+])|(\d+)[.)])\s+(.*)$/.exec(line);
|
|
41
|
+
if (item) {
|
|
42
|
+
flushPara();
|
|
43
|
+
const ordered = !!item[2];
|
|
44
|
+
if (!list || list.ordered !== ordered) {
|
|
45
|
+
flushList();
|
|
46
|
+
list = { ordered, items: [] };
|
|
47
|
+
}
|
|
48
|
+
list.items.push(item[3]);
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
if (!line.trim()) {
|
|
52
|
+
flushPara();
|
|
53
|
+
flushList();
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
flushList();
|
|
57
|
+
const heading = /^\s*(#{1,6})\s+(.*)$/.exec(line);
|
|
58
|
+
if (heading) {
|
|
59
|
+
flushPara();
|
|
60
|
+
blocks.push(headings
|
|
61
|
+
? { kind: "heading", level: Math.min(heading[1].length, 3), nodes: inline(heading[2]) }
|
|
62
|
+
: { kind: "paragraph", nodes: [{ kind: "strong", text: heading[2] }] });
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
para.push(line.replace(/^\s*>\s?/, "").trim());
|
|
66
|
+
}
|
|
67
|
+
flushPara();
|
|
68
|
+
flushList();
|
|
69
|
+
return blocks;
|
|
70
|
+
}
|
|
71
|
+
/** `code`, **strong**, *em* and links (as text). Everything else stays literal. */
|
|
72
|
+
export function inline(text) {
|
|
73
|
+
const nodes = [];
|
|
74
|
+
const re = /`([^`]+)`|\*\*([^*]+)\*\*|__([^_]+)__|\*([^*\s][^*]*)\*|_([^_\s][^_]*)_|\[([^\]]+)\]\(([^)\s]+)\)/g;
|
|
75
|
+
let at = 0;
|
|
76
|
+
for (let m = re.exec(text); m; m = re.exec(text)) {
|
|
77
|
+
if (m.index > at)
|
|
78
|
+
nodes.push({ kind: "text", text: text.slice(at, m.index) });
|
|
79
|
+
if (m[1] !== undefined)
|
|
80
|
+
nodes.push({ kind: "code", text: m[1] });
|
|
81
|
+
else if (m[2] !== undefined || m[3] !== undefined)
|
|
82
|
+
nodes.push({ kind: "strong", text: (m[2] ?? m[3]) });
|
|
83
|
+
else if (m[4] !== undefined || m[5] !== undefined)
|
|
84
|
+
nodes.push({ kind: "em", text: (m[4] ?? m[5]) });
|
|
85
|
+
else
|
|
86
|
+
nodes.push({ kind: "text", text: `${m[6]} (${m[7]})` });
|
|
87
|
+
at = m.index + m[0].length;
|
|
88
|
+
}
|
|
89
|
+
if (at < text.length)
|
|
90
|
+
nodes.push({ kind: "text", text: text.slice(at) });
|
|
91
|
+
return nodes;
|
|
92
|
+
}
|
|
93
|
+
/** A person's own words as one block, exactly as typed. Adapters use this for user messages: what someone typed is never read as markdown. */
|
|
94
|
+
export function plainBlocks(text) {
|
|
95
|
+
// Blank lines at the ends would show as empty space in the bubble; inside, they're the person's.
|
|
96
|
+
const t = text.replace(/\r\n/g, "\n").replace(/^\n+|\n+$/g, "");
|
|
97
|
+
return t.trim() ? [{ kind: "plain", text: t }] : [];
|
|
98
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The status vocabulary every Candor agent component shares. Components take
|
|
3
|
+
* plain data in these shapes rather than an SDK's message objects, so they work
|
|
4
|
+
* with your own LLM drivers, the Vercel AI SDK or anything else; adapters
|
|
5
|
+
* map an SDK's parts onto them.
|
|
6
|
+
*/
|
|
7
|
+
export type RunStatus = "idle" | "queued" | "running" | "waiting" | "blocked" | "succeeded" | "failed" | "cancelled" | "skipped";
|
|
8
|
+
export declare const statusLabel: Record<RunStatus, string>;
|
|
9
|
+
/** The Badge variant that carries each status. */
|
|
10
|
+
export declare const statusTone: {
|
|
11
|
+
readonly idle: "outline";
|
|
12
|
+
readonly queued: "secondary";
|
|
13
|
+
readonly running: "running";
|
|
14
|
+
readonly waiting: "warning";
|
|
15
|
+
readonly blocked: "outline";
|
|
16
|
+
readonly succeeded: "success";
|
|
17
|
+
readonly failed: "destructive";
|
|
18
|
+
readonly cancelled: "outline";
|
|
19
|
+
readonly skipped: "outline";
|
|
20
|
+
};
|
|
21
|
+
export declare function isTerminal(status: RunStatus): status is "succeeded" | "failed" | "cancelled" | "skipped";
|