@calliopelabs/ui 0.13.0 → 0.16.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/README.md +192 -4
- package/dist/agent/AgentChat.d.ts +63 -0
- package/dist/agent/AgentChat.js +117 -0
- package/dist/agent/AgentLauncher.d.ts +25 -0
- package/dist/agent/AgentLauncher.js +25 -0
- package/dist/agent/AgentProvider.d.ts +82 -0
- package/dist/agent/AgentProvider.js +176 -0
- package/dist/agent/CalliopeAgent.d.ts +43 -0
- package/dist/agent/CalliopeAgent.js +111 -0
- package/dist/agent/WorkflowRenderers.d.ts +61 -0
- package/dist/agent/WorkflowRenderers.js +102 -0
- package/dist/agent/controller.d.ts +167 -0
- package/dist/agent/controller.js +496 -0
- package/dist/agent/copilotkit/CopilotKitAgentProvider.d.ts +41 -0
- package/dist/agent/copilotkit/CopilotKitAgentProvider.js +145 -0
- package/dist/agent/copilotkit/index.d.ts +6 -0
- package/dist/agent/copilotkit/index.js +6 -0
- package/dist/agent/engine.d.ts +41 -0
- package/dist/agent/engine.js +93 -0
- package/dist/agent/index.d.ts +17 -0
- package/dist/agent/index.js +17 -0
- package/dist/agent/mock.d.ts +56 -0
- package/dist/agent/mock.js +143 -0
- package/dist/agent/renderers.d.ts +49 -0
- package/dist/agent/renderers.js +27 -0
- package/dist/agent/surface.d.ts +30 -0
- package/dist/agent/surface.js +90 -0
- package/dist/agent/tool.d.ts +98 -0
- package/dist/agent/tool.js +81 -0
- package/dist/appearance/brands.d.ts +31 -12
- package/dist/appearance/brands.js +32 -51
- package/dist/chat/AgentProgress.d.ts +19 -0
- package/dist/chat/AgentProgress.js +34 -0
- package/dist/chat/Composer.d.ts +31 -0
- package/dist/chat/Composer.js +44 -0
- package/dist/chat/MessageBubble.d.ts +23 -0
- package/dist/chat/MessageBubble.js +26 -0
- package/dist/chat/MessageList.d.ts +43 -0
- package/dist/chat/MessageList.js +71 -0
- package/dist/chat/ModelPicker.d.ts +17 -0
- package/dist/chat/ModelPicker.js +13 -0
- package/dist/chat/ToolCallCard.d.ts +27 -0
- package/dist/chat/ToolCallCard.js +52 -0
- package/dist/chat/model.d.ts +123 -0
- package/dist/chat/model.js +337 -0
- package/dist/chat/patch.d.ts +12 -0
- package/dist/chat/patch.js +149 -0
- package/dist/chat/useAgUiRun.d.ts +52 -0
- package/dist/chat/useAgUiRun.js +137 -0
- package/dist/css/appearance.js +1 -1
- package/dist/css/calliope.css +5 -0
- package/dist/css/tokens.css +5 -0
- package/dist/index.d.ts +15 -1
- package/dist/index.js +16 -1
- package/dist/primitives/Badge.d.ts +14 -0
- package/dist/primitives/Badge.js +25 -0
- package/dist/primitives/Button.d.ts +1 -1
- package/dist/primitives/ContextMenu.d.ts +18 -0
- package/dist/primitives/ContextMenu.js +34 -0
- package/dist/primitives/ScrollArea.d.ts +16 -0
- package/dist/primitives/ScrollArea.js +11 -0
- package/dist/primitives/Toast.d.ts +37 -0
- package/dist/primitives/Toast.js +43 -0
- package/dist/primitives/Tooltip.d.ts +16 -0
- package/dist/primitives/Tooltip.js +26 -0
- package/dist/provider/messages.d.ts +135 -0
- package/dist/provider/messages.js +131 -0
- package/dist/theme/css-layer.js +2 -1
- package/dist/theme/mappings/palette.d.ts +52 -0
- package/dist/theme/mappings/palette.js +208 -0
- package/dist/theme/mappings/render.d.ts +9 -0
- package/dist/theme/mappings/render.js +520 -0
- package/dist/theme/mappings/targets.d.ts +43 -0
- package/dist/theme/mappings/targets.js +222 -0
- package/dist/theme/tokens.d.ts +10 -9
- package/dist/theme/tokens.generated.d.ts +356 -0
- package/dist/theme/tokens.generated.js +360 -0
- package/dist/theme/tokens.js +20 -264
- package/dist/tokens/README.jupyterlab.md +125 -0
- package/dist/tokens/README.md +15 -0
- package/dist/tokens/README.native.md +29 -0
- package/dist/tokens/README.plain.md +84 -0
- package/dist/tokens/README.python.md +33 -0
- package/dist/tokens/README.vscode.md +114 -0
- package/dist/tokens/jupyterlab.css +1710 -0
- package/dist/tokens/plain.css +930 -0
- package/dist/tokens/tokens.native.d.ts +85 -0
- package/dist/tokens/tokens.native.js +773 -0
- package/dist/tokens/tokens.py +1043 -0
- package/dist/tokens/vscode.css +1138 -0
- package/dist/workbench/FileBrowser.d.ts +62 -0
- package/dist/workbench/FileBrowser.js +117 -0
- package/dist/workbench/FileGrid.d.ts +13 -0
- package/dist/workbench/FileGrid.js +114 -0
- package/dist/workbench/FileIcon.d.ts +10 -0
- package/dist/workbench/FileIcon.js +24 -0
- package/dist/workbench/FileList.d.ts +35 -0
- package/dist/workbench/FileList.js +160 -0
- package/dist/workbench/FilePreview.d.ts +66 -0
- package/dist/workbench/FilePreview.js +108 -0
- package/dist/workbench/FileTree.d.ts +37 -0
- package/dist/workbench/FileTree.js +218 -0
- package/dist/workbench/UploadDropzone.d.ts +52 -0
- package/dist/workbench/UploadDropzone.js +115 -0
- package/dist/workbench/dnd.d.ts +17 -0
- package/dist/workbench/dnd.js +77 -0
- package/dist/workbench/index.d.ts +16 -0
- package/dist/workbench/index.js +16 -0
- package/dist/workbench/model.d.ts +72 -0
- package/dist/workbench/model.js +214 -0
- package/dist/workbench/selection.d.ts +16 -0
- package/dist/workbench/selection.js +46 -0
- package/dist/workbench/typeahead.d.ts +15 -0
- package/dist/workbench/typeahead.js +22 -0
- package/package.json +39 -2
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Frontend tools: what the agent may call in the browser, typed once. The
|
|
3
|
+
* parameters are a Standard Schema (zod 3.25+ and 4, valibot, arktype), which
|
|
4
|
+
* types the handler's arguments and validates them, or a plain JSON Schema
|
|
5
|
+
* with the argument type given as a type parameter. Pure: no React, no
|
|
6
|
+
* network, so a Server Component can import a tool's definition.
|
|
7
|
+
*/
|
|
8
|
+
import type * as React from "react";
|
|
9
|
+
import type { ChatToolCall } from "../chat/model.js";
|
|
10
|
+
/** The Standard Schema v1 interface (standardschema.dev), inlined so no schema library is a dependency. */
|
|
11
|
+
export interface StandardSchemaV1<Input = unknown, Output = Input> {
|
|
12
|
+
readonly "~standard": {
|
|
13
|
+
readonly version: 1;
|
|
14
|
+
readonly vendor: string;
|
|
15
|
+
readonly validate: (value: unknown) => StandardResult<Output> | Promise<StandardResult<Output>>;
|
|
16
|
+
readonly types?: {
|
|
17
|
+
readonly input: Input;
|
|
18
|
+
readonly output: Output;
|
|
19
|
+
} | undefined;
|
|
20
|
+
/** Standard JSON Schema v1, when the library implements it. */
|
|
21
|
+
readonly jsonSchema?: {
|
|
22
|
+
readonly input: (options: {
|
|
23
|
+
target: string;
|
|
24
|
+
}) => JsonSchema;
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
type StandardResult<Output> = {
|
|
29
|
+
readonly value: Output;
|
|
30
|
+
readonly issues?: undefined;
|
|
31
|
+
} | {
|
|
32
|
+
readonly issues: readonly {
|
|
33
|
+
readonly message: string;
|
|
34
|
+
}[];
|
|
35
|
+
};
|
|
36
|
+
/** A JSON Schema object, as AG-UI's `Tool.parameters` carries it. */
|
|
37
|
+
export type JsonSchema = Record<string, unknown>;
|
|
38
|
+
/** What a tool's handler is told besides its arguments. */
|
|
39
|
+
export interface AgentToolContext {
|
|
40
|
+
/** Aborts when the person stops the run or the agent unmounts. */
|
|
41
|
+
signal: AbortSignal;
|
|
42
|
+
toolCallId: string;
|
|
43
|
+
}
|
|
44
|
+
/** What a tool's renderer draws from. */
|
|
45
|
+
export interface AgentToolRenderProps<Args = unknown> {
|
|
46
|
+
call: ChatToolCall;
|
|
47
|
+
/** The arguments so far: undefined while they stream and do not parse yet. */
|
|
48
|
+
args: Partial<Args> | undefined;
|
|
49
|
+
/**
|
|
50
|
+
* Set while the call waits on the person (a tool with no handler): answers
|
|
51
|
+
* it, and the answer goes back to the agent as the tool's result.
|
|
52
|
+
*/
|
|
53
|
+
respond?: (result: unknown) => void;
|
|
54
|
+
}
|
|
55
|
+
export interface AgentTool<Args = unknown> {
|
|
56
|
+
/** The name the agent calls it by. */
|
|
57
|
+
name: string;
|
|
58
|
+
/** What it does, for the agent. */
|
|
59
|
+
description?: string;
|
|
60
|
+
parameters?: StandardSchemaV1<unknown, Args> | JsonSchema;
|
|
61
|
+
/**
|
|
62
|
+
* Runs the call and returns its result (sent to the agent as JSON text). A
|
|
63
|
+
* tool with no handler and a `render` is a human-in-the-loop tool: the run
|
|
64
|
+
* waits until the rendered component calls `respond`.
|
|
65
|
+
*/
|
|
66
|
+
handler?: (args: Args, context: AgentToolContext) => unknown;
|
|
67
|
+
/** Draws the call in the conversation instead of the default tool card. */
|
|
68
|
+
render?: (props: AgentToolRenderProps<Args>) => React.ReactNode;
|
|
69
|
+
/** Whether the agent runs again after the result. Defaults to true. */
|
|
70
|
+
followUp?: boolean;
|
|
71
|
+
/** False hides the tool from the agent without unregistering it. */
|
|
72
|
+
available?: boolean;
|
|
73
|
+
}
|
|
74
|
+
/** Types a tool's handler and renderer from its parameters; returns the tool as given. */
|
|
75
|
+
export declare function defineTool<Args = Record<string, unknown>>(tool: AgentTool<Args>): AgentTool<Args>;
|
|
76
|
+
export declare function isStandardSchema(value: unknown): value is StandardSchemaV1;
|
|
77
|
+
/**
|
|
78
|
+
* A tool's parameters as JSON Schema for the agent: Standard JSON Schema when
|
|
79
|
+
* the library implements it, zod 4's `toJSONSchema()`, or the JSON Schema
|
|
80
|
+
* given. Throws for a schema it cannot convert (zod 3 without Standard JSON
|
|
81
|
+
* Schema), naming the tool.
|
|
82
|
+
*/
|
|
83
|
+
export declare function toolJsonSchema(tool: Pick<AgentTool, "name" | "parameters">): JsonSchema;
|
|
84
|
+
/**
|
|
85
|
+
* The arguments as the handler receives them: validated (and transformed)
|
|
86
|
+
* through a Standard Schema, or as parsed for a JSON Schema. Rejects with
|
|
87
|
+
* the schema's issues.
|
|
88
|
+
*/
|
|
89
|
+
export declare function validateToolArgs<Args>(tool: AgentTool<Args>, args: unknown): Promise<Args>;
|
|
90
|
+
/**
|
|
91
|
+
* A tool's parameters as a Standard Schema, for an engine that only takes
|
|
92
|
+
* one (CopilotKit): a JSON Schema becomes a schema that passes values through
|
|
93
|
+
* and reports itself as Standard JSON Schema.
|
|
94
|
+
*/
|
|
95
|
+
export declare function toolStandardSchema(tool: AgentTool): StandardSchemaV1;
|
|
96
|
+
/** A tool result as the text AG-UI's tool message carries. */
|
|
97
|
+
export declare function toolResultText(result: unknown): string;
|
|
98
|
+
export {};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/** Types a tool's handler and renderer from its parameters; returns the tool as given. */
|
|
2
|
+
export function defineTool(tool) {
|
|
3
|
+
return tool;
|
|
4
|
+
}
|
|
5
|
+
export function isStandardSchema(value) {
|
|
6
|
+
return (typeof value === "object" &&
|
|
7
|
+
value !== null &&
|
|
8
|
+
"~standard" in value &&
|
|
9
|
+
typeof value["~standard"]?.validate === "function");
|
|
10
|
+
}
|
|
11
|
+
const EMPTY_OBJECT = { type: "object", properties: {} };
|
|
12
|
+
/**
|
|
13
|
+
* A tool's parameters as JSON Schema for the agent: Standard JSON Schema when
|
|
14
|
+
* the library implements it, zod 4's `toJSONSchema()`, or the JSON Schema
|
|
15
|
+
* given. Throws for a schema it cannot convert (zod 3 without Standard JSON
|
|
16
|
+
* Schema), naming the tool.
|
|
17
|
+
*/
|
|
18
|
+
export function toolJsonSchema(tool) {
|
|
19
|
+
const { parameters } = tool;
|
|
20
|
+
if (parameters === undefined)
|
|
21
|
+
return EMPTY_OBJECT;
|
|
22
|
+
if (!isStandardSchema(parameters))
|
|
23
|
+
return parameters;
|
|
24
|
+
const standard = parameters["~standard"];
|
|
25
|
+
if (typeof standard.jsonSchema?.input === "function") {
|
|
26
|
+
return clean(standard.jsonSchema.input({ target: "draft-07" }));
|
|
27
|
+
}
|
|
28
|
+
const withMethod = parameters;
|
|
29
|
+
if (typeof withMethod.toJSONSchema === "function")
|
|
30
|
+
return clean(withMethod.toJSONSchema());
|
|
31
|
+
throw new Error(`Tool ${tool.name}: its ${standard.vendor} schema has no JSON Schema form. Use a library with Standard JSON Schema (zod 4, valibot 1, arktype 2) or pass a JSON Schema.`);
|
|
32
|
+
}
|
|
33
|
+
function clean(schema) {
|
|
34
|
+
const { $schema: _, ...rest } = schema;
|
|
35
|
+
return rest;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* The arguments as the handler receives them: validated (and transformed)
|
|
39
|
+
* through a Standard Schema, or as parsed for a JSON Schema. Rejects with
|
|
40
|
+
* the schema's issues.
|
|
41
|
+
*/
|
|
42
|
+
export async function validateToolArgs(tool, args) {
|
|
43
|
+
if (!isStandardSchema(tool.parameters))
|
|
44
|
+
return args;
|
|
45
|
+
const result = await tool.parameters["~standard"].validate(args);
|
|
46
|
+
if (result.issues) {
|
|
47
|
+
throw new Error(`Invalid arguments for ${tool.name}: ${result.issues.map((i) => i.message).join("; ")}`);
|
|
48
|
+
}
|
|
49
|
+
return result.value;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* A tool's parameters as a Standard Schema, for an engine that only takes
|
|
53
|
+
* one (CopilotKit): a JSON Schema becomes a schema that passes values through
|
|
54
|
+
* and reports itself as Standard JSON Schema.
|
|
55
|
+
*/
|
|
56
|
+
export function toolStandardSchema(tool) {
|
|
57
|
+
if (isStandardSchema(tool.parameters))
|
|
58
|
+
return tool.parameters;
|
|
59
|
+
const schema = toolJsonSchema(tool);
|
|
60
|
+
return {
|
|
61
|
+
"~standard": {
|
|
62
|
+
version: 1,
|
|
63
|
+
vendor: "calliope-json-schema",
|
|
64
|
+
validate: (value) => ({ value }),
|
|
65
|
+
jsonSchema: { input: () => schema },
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
/** A tool result as the text AG-UI's tool message carries. */
|
|
70
|
+
export function toolResultText(result) {
|
|
71
|
+
if (result === undefined)
|
|
72
|
+
return "";
|
|
73
|
+
if (typeof result === "string")
|
|
74
|
+
return result;
|
|
75
|
+
try {
|
|
76
|
+
return JSON.stringify(result);
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
return String(result);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The
|
|
3
|
-
*
|
|
2
|
+
* The family's brands, kept here so every app and the catalog read the same
|
|
3
|
+
* values. Their colours (sidebar and the product's own accent) live in
|
|
4
|
+
* `tokens/brand/*.json`; this file adds names, grounds, defaults and themes.
|
|
5
|
+
* An app adds its navigation:
|
|
4
6
|
*
|
|
5
7
|
* export const astrolift = defineProduct({ ...astroliftBrand, nav: NAV });
|
|
6
8
|
*/
|
|
@@ -78,12 +80,12 @@ export declare const zentinelleBrand: {
|
|
|
78
80
|
readonly id: "zentinelle";
|
|
79
81
|
readonly name: "Zentinelle AI";
|
|
80
82
|
readonly accent: {
|
|
81
|
-
readonly key: "teal";
|
|
82
|
-
readonly label: "Teal";
|
|
83
83
|
readonly dark: "#37efed";
|
|
84
84
|
readonly onDark: "#0b0b19";
|
|
85
85
|
readonly light: "#0d7470";
|
|
86
86
|
readonly onLight: "#f3fbf7";
|
|
87
|
+
readonly key: "teal";
|
|
88
|
+
readonly label: "Teal";
|
|
87
89
|
};
|
|
88
90
|
readonly sidebar: "#0b0b19";
|
|
89
91
|
readonly grounds: readonly ["black", "charcoal", "graphite", "paper", "mist"];
|
|
@@ -102,12 +104,12 @@ export declare const workbenchBrand: {
|
|
|
102
104
|
readonly id: "workbench";
|
|
103
105
|
readonly name: "Calliope AI Workbench";
|
|
104
106
|
readonly accent: {
|
|
105
|
-
readonly key: "workbench-blue";
|
|
106
|
-
readonly label: "Workbench blue";
|
|
107
107
|
readonly dark: "#8fb8e8";
|
|
108
108
|
readonly onDark: "#0b1120";
|
|
109
109
|
readonly light: "#2f5d94";
|
|
110
110
|
readonly onLight: "#f3fbf7";
|
|
111
|
+
readonly key: "workbench-blue";
|
|
112
|
+
readonly label: "Workbench blue";
|
|
111
113
|
};
|
|
112
114
|
readonly sidebar: "#0e1730";
|
|
113
115
|
readonly grounds: readonly ["navy", "black", "charcoal", "graphite", "paper", "mist"];
|
|
@@ -124,12 +126,12 @@ export declare const chatStudioBrand: {
|
|
|
124
126
|
readonly id: "chat-studio";
|
|
125
127
|
readonly name: "Calliope AI Chat Studio";
|
|
126
128
|
readonly accent: {
|
|
127
|
-
readonly key: "studio-blue";
|
|
128
|
-
readonly label: "Studio blue";
|
|
129
129
|
readonly dark: "#8ab4f8";
|
|
130
130
|
readonly onDark: "#0c0c0c";
|
|
131
131
|
readonly light: "#1d4ed8";
|
|
132
132
|
readonly onLight: "#ffffff";
|
|
133
|
+
readonly key: "studio-blue";
|
|
134
|
+
readonly label: "Studio blue";
|
|
133
135
|
};
|
|
134
136
|
readonly sidebar: "#080808";
|
|
135
137
|
readonly grounds: readonly ["black", "charcoal", "graphite", "paper", "mist"];
|
|
@@ -147,12 +149,12 @@ export declare const loadrBrand: {
|
|
|
147
149
|
readonly id: "loadr";
|
|
148
150
|
readonly name: "Calliope AI Loadr";
|
|
149
151
|
readonly accent: {
|
|
150
|
-
readonly key: "loadr-blue";
|
|
151
|
-
readonly label: "Loadr blue";
|
|
152
152
|
readonly dark: "#89b4fa";
|
|
153
153
|
readonly onDark: "#11111b";
|
|
154
154
|
readonly light: "#1e66f5";
|
|
155
155
|
readonly onLight: "#ffffff";
|
|
156
|
+
readonly key: "loadr-blue";
|
|
157
|
+
readonly label: "Loadr blue";
|
|
156
158
|
};
|
|
157
159
|
readonly sidebar: "#181825";
|
|
158
160
|
readonly grounds: readonly ["black", "charcoal", "graphite", "paper", "mist"];
|
|
@@ -161,6 +163,23 @@ export declare const loadrBrand: {
|
|
|
161
163
|
readonly light: "paper";
|
|
162
164
|
};
|
|
163
165
|
};
|
|
166
|
+
/**
|
|
167
|
+
* Calliope AI Deep Data Agent: the family amber on a warm umber sidebar, with
|
|
168
|
+
* charcoal and mist as its defaults. A separate product from Chat Studio, and
|
|
169
|
+
* kept visibly apart from it (Studio blue on black and paper), from Astrolift
|
|
170
|
+
* (green), Zentinelle (teal) and Loadr (blue).
|
|
171
|
+
*/
|
|
172
|
+
export declare const deepDataAgentBrand: {
|
|
173
|
+
readonly id: "deep-data-agent";
|
|
174
|
+
readonly name: "Deep Data Agent";
|
|
175
|
+
readonly accent: "amber";
|
|
176
|
+
readonly sidebar: "#1a150c";
|
|
177
|
+
readonly grounds: readonly ["charcoal", "black", "graphite", "paper", "mist"];
|
|
178
|
+
readonly defaultGround: {
|
|
179
|
+
readonly dark: "charcoal";
|
|
180
|
+
readonly light: "mist";
|
|
181
|
+
};
|
|
182
|
+
};
|
|
164
183
|
/**
|
|
165
184
|
* Cykick: cyan on near-black with square corners, from
|
|
166
185
|
* `ui/theme/native-themes.json` (primary, background, radius 0). Cykick's
|
|
@@ -171,12 +190,12 @@ export declare const cykickBrand: {
|
|
|
171
190
|
readonly id: "cykick";
|
|
172
191
|
readonly name: "Cykick";
|
|
173
192
|
readonly accent: {
|
|
174
|
-
readonly key: "cykick-cyan";
|
|
175
|
-
readonly label: "Cykick cyan";
|
|
176
193
|
readonly dark: "#22d3ee";
|
|
177
194
|
readonly onDark: "#07090e";
|
|
178
195
|
readonly light: "#0e7490";
|
|
179
196
|
readonly onLight: "#ffffff";
|
|
197
|
+
readonly key: "cykick-cyan";
|
|
198
|
+
readonly label: "Cykick cyan";
|
|
180
199
|
};
|
|
181
200
|
readonly sidebar: "#07090e";
|
|
182
201
|
readonly grounds: readonly ["black", "charcoal", "graphite", "paper", "mist"];
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
import { TOKENS } from "../theme/tokens.generated.js";
|
|
1
2
|
/**
|
|
2
|
-
* The
|
|
3
|
-
*
|
|
3
|
+
* The family's brands, kept here so every app and the catalog read the same
|
|
4
|
+
* values. Their colours (sidebar and the product's own accent) live in
|
|
5
|
+
* `tokens/brand/*.json`; this file adds names, grounds, defaults and themes.
|
|
6
|
+
* An app adds its navigation:
|
|
4
7
|
*
|
|
5
8
|
* export const astrolift = defineProduct({ ...astroliftBrand, nav: NAV });
|
|
6
9
|
*/
|
|
@@ -13,7 +16,7 @@ export const astroliftBrand = {
|
|
|
13
16
|
id: "astrolift",
|
|
14
17
|
name: "Astrolift AI",
|
|
15
18
|
accent: "green",
|
|
16
|
-
sidebar:
|
|
19
|
+
sidebar: TOKENS.brand.astrolift.sidebar,
|
|
17
20
|
grounds: ["black", "charcoal", "graphite", "emerald", "paper", "mist"],
|
|
18
21
|
defaultGround: { dark: "graphite", light: "mist" },
|
|
19
22
|
themes: [
|
|
@@ -47,15 +50,8 @@ export const astroliftBrand = {
|
|
|
47
50
|
export const zentinelleBrand = {
|
|
48
51
|
id: "zentinelle",
|
|
49
52
|
name: "Zentinelle AI",
|
|
50
|
-
accent: {
|
|
51
|
-
|
|
52
|
-
label: "Teal",
|
|
53
|
-
dark: "#37efed",
|
|
54
|
-
onDark: "#0b0b19",
|
|
55
|
-
light: "#0d7470",
|
|
56
|
-
onLight: "#f3fbf7",
|
|
57
|
-
},
|
|
58
|
-
sidebar: "#0b0b19",
|
|
53
|
+
accent: { key: "teal", label: "Teal", ...TOKENS.brand.zentinelle.accent },
|
|
54
|
+
sidebar: TOKENS.brand.zentinelle.sidebar,
|
|
59
55
|
grounds: ["black", "charcoal", "graphite", "paper", "mist"],
|
|
60
56
|
defaultGround: { dark: "black", light: "mist" },
|
|
61
57
|
};
|
|
@@ -63,7 +59,8 @@ export const zentinelleBrand = {
|
|
|
63
59
|
* The brands below are copied from what each product ships today, so nothing
|
|
64
60
|
* changes when an app moves onto the library. Where a product has no value
|
|
65
61
|
* the model needs (usually a light-ground accent), the nearest one that
|
|
66
|
-
* passes the contrast tests is used and
|
|
62
|
+
* passes the contrast tests is used and its token's description says
|
|
63
|
+
* "Derived" for the designer.
|
|
67
64
|
*/
|
|
68
65
|
/**
|
|
69
66
|
* Calliope AI Workbench (JunoHub, the installer's default theme, the desktop
|
|
@@ -74,16 +71,8 @@ export const zentinelleBrand = {
|
|
|
74
71
|
export const workbenchBrand = {
|
|
75
72
|
id: "workbench",
|
|
76
73
|
name: "Calliope AI Workbench",
|
|
77
|
-
accent: {
|
|
78
|
-
|
|
79
|
-
label: "Workbench blue",
|
|
80
|
-
dark: "#8fb8e8",
|
|
81
|
-
onDark: "#0b1120",
|
|
82
|
-
// derived: the hub has no light ground
|
|
83
|
-
light: "#2f5d94",
|
|
84
|
-
onLight: "#f3fbf7",
|
|
85
|
-
},
|
|
86
|
-
sidebar: "#0e1730",
|
|
74
|
+
accent: { key: "workbench-blue", label: "Workbench blue", ...TOKENS.brand.workbench.accent },
|
|
75
|
+
sidebar: TOKENS.brand.workbench.sidebar,
|
|
87
76
|
grounds: ["navy", "black", "charcoal", "graphite", "paper", "mist"],
|
|
88
77
|
defaultGround: { dark: "navy", light: "mist" },
|
|
89
78
|
};
|
|
@@ -94,15 +83,8 @@ export const workbenchBrand = {
|
|
|
94
83
|
export const chatStudioBrand = {
|
|
95
84
|
id: "chat-studio",
|
|
96
85
|
name: "Calliope AI Chat Studio",
|
|
97
|
-
accent: {
|
|
98
|
-
|
|
99
|
-
label: "Studio blue",
|
|
100
|
-
dark: "#8ab4f8",
|
|
101
|
-
onDark: "#0c0c0c",
|
|
102
|
-
light: "#1d4ed8",
|
|
103
|
-
onLight: "#ffffff",
|
|
104
|
-
},
|
|
105
|
-
sidebar: "#080808",
|
|
86
|
+
accent: { key: "studio-blue", label: "Studio blue", ...TOKENS.brand["chat-studio"].accent },
|
|
87
|
+
sidebar: TOKENS.brand["chat-studio"].sidebar,
|
|
106
88
|
grounds: ["black", "charcoal", "graphite", "paper", "mist"],
|
|
107
89
|
defaultGround: { dark: "black", light: "paper" },
|
|
108
90
|
};
|
|
@@ -114,18 +96,25 @@ export const chatStudioBrand = {
|
|
|
114
96
|
export const loadrBrand = {
|
|
115
97
|
id: "loadr",
|
|
116
98
|
name: "Calliope AI Loadr",
|
|
117
|
-
accent: {
|
|
118
|
-
|
|
119
|
-
label: "Loadr blue",
|
|
120
|
-
dark: "#89b4fa",
|
|
121
|
-
onDark: "#11111b",
|
|
122
|
-
light: "#1e66f5",
|
|
123
|
-
onLight: "#ffffff",
|
|
124
|
-
},
|
|
125
|
-
sidebar: "#181825",
|
|
99
|
+
accent: { key: "loadr-blue", label: "Loadr blue", ...TOKENS.brand.loadr.accent },
|
|
100
|
+
sidebar: TOKENS.brand.loadr.sidebar,
|
|
126
101
|
grounds: ["black", "charcoal", "graphite", "paper", "mist"],
|
|
127
102
|
defaultGround: { dark: "charcoal", light: "paper" },
|
|
128
103
|
};
|
|
104
|
+
/**
|
|
105
|
+
* Calliope AI Deep Data Agent: the family amber on a warm umber sidebar, with
|
|
106
|
+
* charcoal and mist as its defaults. A separate product from Chat Studio, and
|
|
107
|
+
* kept visibly apart from it (Studio blue on black and paper), from Astrolift
|
|
108
|
+
* (green), Zentinelle (teal) and Loadr (blue).
|
|
109
|
+
*/
|
|
110
|
+
export const deepDataAgentBrand = {
|
|
111
|
+
id: "deep-data-agent",
|
|
112
|
+
name: "Deep Data Agent",
|
|
113
|
+
accent: "amber",
|
|
114
|
+
sidebar: TOKENS.brand["deep-data-agent"].sidebar,
|
|
115
|
+
grounds: ["charcoal", "black", "graphite", "paper", "mist"],
|
|
116
|
+
defaultGround: { dark: "charcoal", light: "mist" },
|
|
117
|
+
};
|
|
129
118
|
/**
|
|
130
119
|
* Cykick: cyan on near-black with square corners, from
|
|
131
120
|
* `ui/theme/native-themes.json` (primary, background, radius 0). Cykick's
|
|
@@ -135,16 +124,8 @@ export const loadrBrand = {
|
|
|
135
124
|
export const cykickBrand = {
|
|
136
125
|
id: "cykick",
|
|
137
126
|
name: "Cykick",
|
|
138
|
-
accent: {
|
|
139
|
-
|
|
140
|
-
label: "Cykick cyan",
|
|
141
|
-
dark: "#22d3ee",
|
|
142
|
-
onDark: "#07090e",
|
|
143
|
-
// derived: no light accent in native-themes.json
|
|
144
|
-
light: "#0e7490",
|
|
145
|
-
onLight: "#ffffff",
|
|
146
|
-
},
|
|
147
|
-
sidebar: "#07090e",
|
|
127
|
+
accent: { key: "cykick-cyan", label: "Cykick cyan", ...TOKENS.brand.cykick.accent },
|
|
128
|
+
sidebar: TOKENS.brand.cykick.sidebar,
|
|
148
129
|
grounds: ["black", "charcoal", "graphite", "paper", "mist"],
|
|
149
130
|
defaultGround: { dark: "black", light: "mist" },
|
|
150
131
|
defaultCorners: 0,
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { StatusTone } from "../status/tones.js";
|
|
2
|
+
import type { RunStage } from "../workflow/run.js";
|
|
3
|
+
import type { ChatRunStatus, ChatStep, ChatView } from "./model.js";
|
|
4
|
+
export interface AgentProgressProps {
|
|
5
|
+
/** The run: a `ChatView`, or the part of one this reads. */
|
|
6
|
+
view: Pick<ChatView, "status" | "steps" | "error">;
|
|
7
|
+
/** Names the section. Defaults to "Agent progress". */
|
|
8
|
+
label?: string;
|
|
9
|
+
className?: string;
|
|
10
|
+
}
|
|
11
|
+
export declare const CHAT_RUN_TONE: Record<ChatRunStatus, StatusTone>;
|
|
12
|
+
/** A run's steps as the run timeline's stages. */
|
|
13
|
+
export declare function chatStepStages(steps: readonly ChatStep[]): RunStage[];
|
|
14
|
+
/**
|
|
15
|
+
* Where the agent's run stands: its status, and its steps on the library's
|
|
16
|
+
* RunTimeline, so a chat run reads like any other run. The error, when the
|
|
17
|
+
* run failed, sits beside the status.
|
|
18
|
+
*/
|
|
19
|
+
export declare function AgentProgress({ view, label, className }: AgentProgressProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { cn } from "../lib/cn.js";
|
|
4
|
+
import { useUI } from "../provider/UIProvider.js";
|
|
5
|
+
import { StatusBadge } from "../status/StatusBadge.js";
|
|
6
|
+
import { RunTimeline } from "../workflow/RunTimeline.js";
|
|
7
|
+
export const CHAT_RUN_TONE = {
|
|
8
|
+
idle: "muted",
|
|
9
|
+
running: "info",
|
|
10
|
+
finished: "ok",
|
|
11
|
+
interrupted: "warn",
|
|
12
|
+
cancelled: "muted",
|
|
13
|
+
error: "error",
|
|
14
|
+
};
|
|
15
|
+
const STAGE = {
|
|
16
|
+
running: "running",
|
|
17
|
+
finished: "passed",
|
|
18
|
+
failed: "failed",
|
|
19
|
+
cancelled: "cancelled",
|
|
20
|
+
};
|
|
21
|
+
/** A run's steps as the run timeline's stages. */
|
|
22
|
+
export function chatStepStages(steps) {
|
|
23
|
+
return steps.map((step, i) => ({ id: String(i), label: step.name, status: STAGE[step.status] }));
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Where the agent's run stands: its status, and its steps on the library's
|
|
27
|
+
* RunTimeline, so a chat run reads like any other run. The error, when the
|
|
28
|
+
* run failed, sits beside the status.
|
|
29
|
+
*/
|
|
30
|
+
export function AgentProgress({ view, label, className }) {
|
|
31
|
+
const { messages } = useUI();
|
|
32
|
+
const t = messages.chat;
|
|
33
|
+
return (_jsxs("section", { "aria-label": label ?? t.progress, "data-slot": "agent-progress", className: cn("flex min-w-0 flex-col gap-3", className), children: [_jsxs("div", { className: "flex min-w-0 flex-wrap items-center gap-2", children: [_jsx(StatusBadge, { tone: CHAT_RUN_TONE[view.status], pulse: view.status === "running", children: t.runStatus(view.status) }), view.status === "error" && view.error && (_jsx("p", { className: "min-w-0 text-sm [overflow-wrap:anywhere] text-danger-fg", children: view.error.message }))] }), view.steps.length > 0 && _jsx(RunTimeline, { stages: chatStepStages(view.steps), label: t.steps })] }));
|
|
34
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export interface ComposerProps {
|
|
3
|
+
/** The draft, when the host holds it. Leave it out and the composer keeps its own. */
|
|
4
|
+
value?: string;
|
|
5
|
+
onValueChange?: (value: string) => void;
|
|
6
|
+
/**
|
|
7
|
+
* Sends the trimmed draft. A composer that keeps its own draft clears it;
|
|
8
|
+
* a host that holds it clears it when it wants to.
|
|
9
|
+
*/
|
|
10
|
+
onSubmit: (text: string) => void;
|
|
11
|
+
/** A run is in flight: send is held, and stop shows when `onStop` is given. */
|
|
12
|
+
running?: boolean;
|
|
13
|
+
onStop?: () => void;
|
|
14
|
+
disabled?: boolean;
|
|
15
|
+
placeholder?: string;
|
|
16
|
+
/** Names the field. Defaults to "Message". */
|
|
17
|
+
label?: string;
|
|
18
|
+
/** Above the field: the files the host has attached, as chips. */
|
|
19
|
+
attachments?: React.ReactNode;
|
|
20
|
+
/** Beside send: an attach button, a ModelPicker. */
|
|
21
|
+
actions?: React.ReactNode;
|
|
22
|
+
autoFocus?: boolean;
|
|
23
|
+
className?: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Where the person writes. Multi-line, growing with the text; Enter sends,
|
|
27
|
+
* Shift+Enter breaks the line, and nothing sends while an input method is
|
|
28
|
+
* composing. While a run is in flight, send is held and stop is offered.
|
|
29
|
+
* Attachments and actions are slots: the host owns files and models.
|
|
30
|
+
*/
|
|
31
|
+
export declare function Composer({ value, onValueChange, onSubmit, running, onStop, disabled, placeholder, label, attachments, actions, autoFocus, className, }: ComposerProps): React.JSX.Element;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { ArrowUpIcon, SquareIcon } from "lucide-react";
|
|
4
|
+
import * as React from "react";
|
|
5
|
+
import { cn } from "../lib/cn.js";
|
|
6
|
+
import { Button } from "../primitives/Button.js";
|
|
7
|
+
import { useUI } from "../provider/UIProvider.js";
|
|
8
|
+
/**
|
|
9
|
+
* Where the person writes. Multi-line, growing with the text; Enter sends,
|
|
10
|
+
* Shift+Enter breaks the line, and nothing sends while an input method is
|
|
11
|
+
* composing. While a run is in flight, send is held and stop is offered.
|
|
12
|
+
* Attachments and actions are slots: the host owns files and models.
|
|
13
|
+
*/
|
|
14
|
+
export function Composer({ value, onValueChange, onSubmit, running = false, onStop, disabled = false, placeholder, label, attachments, actions, autoFocus, className, }) {
|
|
15
|
+
const { messages } = useUI();
|
|
16
|
+
const t = messages.chat;
|
|
17
|
+
const hintId = React.useId();
|
|
18
|
+
const [own, setOwn] = React.useState("");
|
|
19
|
+
const draft = value ?? own;
|
|
20
|
+
const canSend = !disabled && !running && draft.trim() !== "";
|
|
21
|
+
const change = (next) => {
|
|
22
|
+
if (value === undefined)
|
|
23
|
+
setOwn(next);
|
|
24
|
+
onValueChange?.(next);
|
|
25
|
+
};
|
|
26
|
+
const submit = () => {
|
|
27
|
+
if (!canSend)
|
|
28
|
+
return;
|
|
29
|
+
onSubmit(draft.trim());
|
|
30
|
+
if (value === undefined)
|
|
31
|
+
setOwn("");
|
|
32
|
+
};
|
|
33
|
+
return (_jsxs("form", { "data-slot": "composer", onSubmit: (event) => {
|
|
34
|
+
event.preventDefault();
|
|
35
|
+
submit();
|
|
36
|
+
}, className: cn("flex min-w-0 flex-col rounded-lg border border-input bg-background focus-within:border-ring focus-within:ring-3 focus-within:ring-ring/50 dark:bg-input/30", disabled && "opacity-50", className), children: [attachments && (_jsx("div", { role: "group", "aria-label": t.attachments, className: "flex min-w-0 flex-wrap gap-2 px-3 pt-2", children: attachments })), _jsx("textarea", { "aria-label": label ?? t.composer, "aria-describedby": hintId, value: draft, disabled: disabled, placeholder: placeholder ?? t.placeholder, rows: 1,
|
|
37
|
+
// eslint-disable-next-line jsx-a11y/no-autofocus -- the host asks for it, on a chat screen
|
|
38
|
+
autoFocus: autoFocus, onChange: (event) => change(event.target.value), onKeyDown: (event) => {
|
|
39
|
+
if (event.key !== "Enter" || event.shiftKey || event.nativeEvent.isComposing)
|
|
40
|
+
return;
|
|
41
|
+
event.preventDefault();
|
|
42
|
+
submit();
|
|
43
|
+
}, className: "field-sizing-content max-h-48 min-h-10 w-full min-w-0 resize-none bg-transparent px-3 py-2 text-base outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed md:text-sm" }), _jsx("p", { id: hintId, className: "sr-only", children: t.composerHint }), _jsxs("div", { className: "flex min-w-0 items-center gap-2 px-2 pb-2", children: [_jsx("div", { className: "flex min-w-0 flex-1 flex-wrap items-center gap-2", children: actions }), running && onStop ? (_jsxs(Button, { type: "button", variant: "outline", size: "sm", onClick: onStop, children: [_jsx(SquareIcon, { "aria-hidden": true }), t.stop] })) : (_jsxs(Button, { type: "submit", size: "sm", disabled: !canSend, children: [_jsx(ArrowUpIcon, { "aria-hidden": true }), t.send] }))] })] }));
|
|
44
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type * as React from "react";
|
|
2
|
+
import type { ChatMessage } from "./model.js";
|
|
3
|
+
/**
|
|
4
|
+
* Renders a message's text: the host's markdown renderer, say. It receives
|
|
5
|
+
* the text so far (it grows while the message streams) and must treat it as
|
|
6
|
+
* untrusted. Without one, the text shows as plain text.
|
|
7
|
+
*/
|
|
8
|
+
export type ChatContentRenderer = (content: string, message: ChatMessage) => React.ReactNode;
|
|
9
|
+
export interface MessageBubbleProps {
|
|
10
|
+
message: ChatMessage;
|
|
11
|
+
renderContent?: ChatContentRenderer;
|
|
12
|
+
/** Beside the speaker: a time, a copy button. */
|
|
13
|
+
meta?: React.ReactNode;
|
|
14
|
+
className?: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* One message, by role: the person's on the right in a muted bubble, the
|
|
18
|
+
* assistant's full width, system and developer notes dashed and quiet, a tool
|
|
19
|
+
* message in mono. While it streams, an empty one says it is thinking and a
|
|
20
|
+
* growing one shows a caret. Text is plain unless the host passes
|
|
21
|
+
* `renderContent`; plain text is never parsed as HTML.
|
|
22
|
+
*/
|
|
23
|
+
export declare function MessageBubble({ message, renderContent, meta, className }: MessageBubbleProps): React.JSX.Element;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import { cn } from "../lib/cn.js";
|
|
4
|
+
import { useUI } from "../provider/UIProvider.js";
|
|
5
|
+
import { StatusDot } from "../status/StatusDot.js";
|
|
6
|
+
const ROLE_CLASS = {
|
|
7
|
+
user: "ml-auto max-w-[85%] rounded-lg bg-muted px-3 py-2",
|
|
8
|
+
assistant: "",
|
|
9
|
+
system: "rounded-lg border border-dashed px-3 py-2 text-xs text-muted-foreground",
|
|
10
|
+
developer: "rounded-lg border border-dashed px-3 py-2 text-xs text-muted-foreground",
|
|
11
|
+
tool: "rounded-lg border bg-card px-3 py-2 font-mono text-xs",
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* One message, by role: the person's on the right in a muted bubble, the
|
|
15
|
+
* assistant's full width, system and developer notes dashed and quiet, a tool
|
|
16
|
+
* message in mono. While it streams, an empty one says it is thinking and a
|
|
17
|
+
* growing one shows a caret. Text is plain unless the host passes
|
|
18
|
+
* `renderContent`; plain text is never parsed as HTML.
|
|
19
|
+
*/
|
|
20
|
+
export function MessageBubble({ message, renderContent, meta, className }) {
|
|
21
|
+
const { messages } = useUI();
|
|
22
|
+
const t = messages.chat;
|
|
23
|
+
const speaker = message.name ?? t.role(message.role);
|
|
24
|
+
const empty = message.content === "";
|
|
25
|
+
return (_jsxs("article", { "aria-label": t.messageFrom(speaker), "aria-busy": message.streaming || undefined, "data-slot": "message-bubble", "data-role": message.role, className: cn("flex min-w-0 flex-col gap-1", ROLE_CLASS[message.role], className), children: [(message.role !== "user" || meta) && (_jsxs("header", { className: "flex min-w-0 items-center gap-2 text-xs text-muted-foreground", children: [message.role !== "user" && _jsx("span", { className: "font-medium", children: speaker }), meta && _jsx("span", { className: "ml-auto flex items-center gap-2", children: meta })] })), message.streaming && empty ? (_jsxs("p", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [_jsx(StatusDot, { tone: "info", pulse: true }), t.thinking] })) : (_jsxs("div", { className: "min-w-0 text-sm [overflow-wrap:break-word]", children: [renderContent ? (renderContent(message.content, message)) : (_jsx("p", { className: "whitespace-pre-wrap", children: message.content })), message.streaming && (_jsxs(_Fragment, { children: [_jsx("span", { "aria-hidden": true, className: "ml-0.5 inline-block h-4 w-1.5 translate-y-0.5 bg-foreground/60 motion-safe:animate-pulse" }), _jsx("span", { className: "sr-only", children: t.writing })] }))] }))] }));
|
|
26
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { type ChatContentRenderer } from "./MessageBubble.js";
|
|
3
|
+
import type { ChatTimelineItem, ChatToolCall, ChatView } from "./model.js";
|
|
4
|
+
import { type ToolCallCardProps } from "./ToolCallCard.js";
|
|
5
|
+
export interface MessageListProps {
|
|
6
|
+
/** The conversation: a `ChatView`, or the part of one the list reads. */
|
|
7
|
+
view: Pick<ChatView, "messages" | "toolCalls" | "timeline" | "status" | "error">;
|
|
8
|
+
renderContent?: ChatContentRenderer;
|
|
9
|
+
/**
|
|
10
|
+
* Draws a tool call the host has its own component for; return undefined
|
|
11
|
+
* for the default `ToolCallCard`.
|
|
12
|
+
*/
|
|
13
|
+
renderToolCall?: (call: ChatToolCall) => React.ReactNode;
|
|
14
|
+
/** The tool's name for people, per call. */
|
|
15
|
+
toolTitle?: (call: ChatToolCall) => string | undefined;
|
|
16
|
+
onApprove?: ToolCallCardProps["onApprove"];
|
|
17
|
+
onDeny?: ToolCallCardProps["onDeny"];
|
|
18
|
+
/**
|
|
19
|
+
* Draws something after a timeline item: generative UI an agent sent
|
|
20
|
+
* between messages (a progress card, an artifact). Called for each item.
|
|
21
|
+
*/
|
|
22
|
+
renderAfter?: (item: ChatTimelineItem) => React.ReactNode;
|
|
23
|
+
/** Drawn after the whole conversation, before a failed run's error: what the run waits on. */
|
|
24
|
+
footer?: React.ReactNode;
|
|
25
|
+
/** Offered beside a failed run's error. */
|
|
26
|
+
onRetry?: () => void;
|
|
27
|
+
/** The first page of history is loading. */
|
|
28
|
+
loading?: boolean;
|
|
29
|
+
/** Replaces the default empty state. */
|
|
30
|
+
empty?: React.ReactNode;
|
|
31
|
+
/** Names the list. Defaults to "Conversation". */
|
|
32
|
+
label?: string;
|
|
33
|
+
className?: string;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* The conversation in arrival order: message bubbles with tool call cards
|
|
37
|
+
* between them, a failed run's error at the end. It follows the stream while
|
|
38
|
+
* the person is at the bottom and stops following when they scroll up, with
|
|
39
|
+
* a button back to the latest. Each bubble re-renders only when its message
|
|
40
|
+
* changes, so a long conversation streams without virtualization; a host
|
|
41
|
+
* with thousands of turns pages its history.
|
|
42
|
+
*/
|
|
43
|
+
export declare function MessageList({ view, renderContent, renderToolCall, renderAfter, footer, toolTitle, onApprove, onDeny, onRetry, loading, empty, label, className, }: MessageListProps): React.JSX.Element;
|