lemma-sdk 0.2.10 → 0.2.12
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 +88 -0
- package/dist/react/components/AssistantChrome.d.ts +77 -0
- package/dist/react/components/AssistantChrome.js +54 -0
- package/dist/react/components/AssistantEmbedded.d.ts +8 -0
- package/dist/react/components/AssistantEmbedded.js +13 -0
- package/dist/react/components/AssistantExperience.d.ts +79 -0
- package/dist/react/components/AssistantExperience.js +1021 -0
- package/dist/react/components/assistant-types.d.ts +72 -0
- package/dist/react/components/assistant-types.js +1 -0
- package/dist/react/index.d.ts +10 -0
- package/dist/react/index.js +5 -0
- package/dist/react/useAssistantController.d.ts +83 -0
- package/dist/react/useAssistantController.js +1091 -0
- package/dist/react/useAssistantRuntime.d.ts +3 -1
- package/dist/react/useAssistantRuntime.js +27 -14
- package/dist/react/useAssistantSession.js +26 -8
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -169,6 +169,94 @@ Notes:
|
|
|
169
169
|
|
|
170
170
|
## Assistants + Agent Runs
|
|
171
171
|
|
|
172
|
+
### React assistant controller + primitives
|
|
173
|
+
|
|
174
|
+
`lemma-sdk/react` now exposes the assistant controller plus the reusable UI primitives used by the app shell. A simple integration looks like this:
|
|
175
|
+
|
|
176
|
+
```tsx
|
|
177
|
+
import {
|
|
178
|
+
MessageGroup,
|
|
179
|
+
PlanSummaryStrip,
|
|
180
|
+
ThinkingIndicator,
|
|
181
|
+
buildDisplayMessageRows,
|
|
182
|
+
getActiveToolBanner,
|
|
183
|
+
latestPlanSummary,
|
|
184
|
+
useAssistantController,
|
|
185
|
+
} from "lemma-sdk/react";
|
|
186
|
+
|
|
187
|
+
function AssistantSurface() {
|
|
188
|
+
const assistant = useAssistantController({
|
|
189
|
+
client,
|
|
190
|
+
assistantId: "support_assistant",
|
|
191
|
+
podId: "pod_123",
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
const rows = buildDisplayMessageRows(assistant.messages);
|
|
195
|
+
const plan = latestPlanSummary(assistant.messages);
|
|
196
|
+
const activeToolBanner = getActiveToolBanner(assistant.messages);
|
|
197
|
+
|
|
198
|
+
return (
|
|
199
|
+
<div>
|
|
200
|
+
{plan ? <PlanSummaryStrip plan={plan} onHide={() => {}} /> : null}
|
|
201
|
+
{activeToolBanner ? <div>{activeToolBanner.summary}</div> : null}
|
|
202
|
+
|
|
203
|
+
{rows.map((row, index) => (
|
|
204
|
+
<MessageGroup
|
|
205
|
+
key={row.id}
|
|
206
|
+
message={row.message}
|
|
207
|
+
conversationId={assistant.activeConversationId}
|
|
208
|
+
onWidgetSendPrompt={(text) => assistant.sendMessage(text)}
|
|
209
|
+
isStreaming={assistant.isActiveConversationRunning && row.sourceIndexes.includes(assistant.messages.length - 1)}
|
|
210
|
+
showAssistantHeader={index === 0 || rows[index - 1]?.message.role !== "assistant"}
|
|
211
|
+
renderMessageContent={({ message }) => <div>{message.content}</div>}
|
|
212
|
+
/>
|
|
213
|
+
))}
|
|
214
|
+
|
|
215
|
+
{assistant.isActiveConversationRunning ? <ThinkingIndicator /> : null}
|
|
216
|
+
</div>
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
The intended split is:
|
|
222
|
+
|
|
223
|
+
- SDK: `useAssistantController`, message/tool normalization, plan parsing, tool rollups, and assistant UI primitives.
|
|
224
|
+
- App: modal shell, fullscreen behavior, route navigation, workspace/file viewers, and product-specific renderers.
|
|
225
|
+
|
|
226
|
+
Useful UI primitives exported from `lemma-sdk/react`:
|
|
227
|
+
|
|
228
|
+
- `AssistantHeader`
|
|
229
|
+
- `AssistantConversationList`
|
|
230
|
+
- `AssistantModelPicker`
|
|
231
|
+
- `AssistantShellLayout`
|
|
232
|
+
- `AssistantComposer`
|
|
233
|
+
- `AssistantMessageViewport`
|
|
234
|
+
- `AssistantAskOverlay`
|
|
235
|
+
- `AssistantPendingFileChip`
|
|
236
|
+
- `AssistantStatusPill`
|
|
237
|
+
- `MessageGroup`
|
|
238
|
+
- `PlanSummaryStrip`
|
|
239
|
+
|
|
240
|
+
For a direct plug-and-play component, `AssistantEmbedded` wires `useAssistantController` into the default assistant experience:
|
|
241
|
+
|
|
242
|
+
```tsx
|
|
243
|
+
import { AssistantEmbedded } from "lemma-sdk/react";
|
|
244
|
+
|
|
245
|
+
function SupportAssistant() {
|
|
246
|
+
return (
|
|
247
|
+
<AssistantEmbedded
|
|
248
|
+
client={client}
|
|
249
|
+
assistantId="support_assistant"
|
|
250
|
+
podId="pod_123"
|
|
251
|
+
title="Support Assistant"
|
|
252
|
+
subtitle="Ask questions about this pod."
|
|
253
|
+
placeholder="Message Support Assistant"
|
|
254
|
+
showConversationList
|
|
255
|
+
/>
|
|
256
|
+
);
|
|
257
|
+
}
|
|
258
|
+
```
|
|
259
|
+
|
|
172
260
|
### Assistant names (resource key)
|
|
173
261
|
|
|
174
262
|
Assistant CRUD is name-based:
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { type ComponentPropsWithoutRef, type ReactNode } from "react";
|
|
2
|
+
import type { AssistantConversationListItem, AssistantConversationRenderArgs } from "./assistant-types.js";
|
|
3
|
+
export interface AssistantHeaderProps {
|
|
4
|
+
title: ReactNode;
|
|
5
|
+
subtitle?: ReactNode;
|
|
6
|
+
badge?: ReactNode;
|
|
7
|
+
controls?: ReactNode;
|
|
8
|
+
className?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface AssistantMessageViewportProps extends ComponentPropsWithoutRef<"div"> {
|
|
11
|
+
innerClassName?: string;
|
|
12
|
+
children: ReactNode;
|
|
13
|
+
}
|
|
14
|
+
export declare const AssistantMessageViewport: import("react").ForwardRefExoticComponent<AssistantMessageViewportProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
15
|
+
export interface AssistantShellLayoutProps {
|
|
16
|
+
sidebar?: ReactNode;
|
|
17
|
+
sidebarVisible?: boolean;
|
|
18
|
+
main: ReactNode;
|
|
19
|
+
className?: string;
|
|
20
|
+
}
|
|
21
|
+
export declare function AssistantShellLayout({ sidebar, sidebarVisible, main, className, }: AssistantShellLayoutProps): import("react/jsx-runtime").JSX.Element;
|
|
22
|
+
export declare function AssistantHeader({ title, subtitle, badge, controls, className, }: AssistantHeaderProps): import("react/jsx-runtime").JSX.Element;
|
|
23
|
+
export interface AssistantConversationListProps {
|
|
24
|
+
conversations: AssistantConversationListItem[];
|
|
25
|
+
activeConversationId: string | null;
|
|
26
|
+
onSelectConversation: (conversationId: string) => void;
|
|
27
|
+
onNewConversation?: () => void;
|
|
28
|
+
renderConversationLabel?: (args: AssistantConversationRenderArgs) => ReactNode;
|
|
29
|
+
title?: ReactNode;
|
|
30
|
+
newLabel?: ReactNode;
|
|
31
|
+
className?: string;
|
|
32
|
+
}
|
|
33
|
+
export declare function AssistantConversationList({ conversations, activeConversationId, onSelectConversation, onNewConversation, renderConversationLabel, title, newLabel, className, }: AssistantConversationListProps): import("react/jsx-runtime").JSX.Element;
|
|
34
|
+
export interface AssistantModelPickerProps<TValue extends string = string> {
|
|
35
|
+
value: TValue | null;
|
|
36
|
+
options: TValue[];
|
|
37
|
+
disabled?: boolean;
|
|
38
|
+
autoLabel?: ReactNode;
|
|
39
|
+
getOptionLabel?: (value: TValue) => ReactNode;
|
|
40
|
+
onChange: (value: TValue | null) => void;
|
|
41
|
+
className?: string;
|
|
42
|
+
}
|
|
43
|
+
export declare function AssistantModelPicker<TValue extends string = string>({ value, options, disabled, autoLabel, getOptionLabel, onChange, className, }: AssistantModelPickerProps<TValue>): import("react/jsx-runtime").JSX.Element;
|
|
44
|
+
export interface AssistantAskOverlayProps {
|
|
45
|
+
questionNumber: number;
|
|
46
|
+
totalQuestions: number;
|
|
47
|
+
question: ReactNode;
|
|
48
|
+
options: string[];
|
|
49
|
+
selectedOptions: string[];
|
|
50
|
+
canContinue: boolean;
|
|
51
|
+
continueLabel: ReactNode;
|
|
52
|
+
onSelectOption: (option: string) => void;
|
|
53
|
+
onContinue?: () => void;
|
|
54
|
+
onSkip?: () => void;
|
|
55
|
+
mode?: "single_select" | "multi_select" | "rank_priorities";
|
|
56
|
+
}
|
|
57
|
+
export declare function AssistantAskOverlay({ questionNumber, totalQuestions, question, options, selectedOptions, canContinue, continueLabel, onSelectOption, onContinue, onSkip, mode, }: AssistantAskOverlayProps): import("react/jsx-runtime").JSX.Element;
|
|
58
|
+
export interface AssistantPendingFileChipProps {
|
|
59
|
+
label: ReactNode;
|
|
60
|
+
onRemove?: () => void;
|
|
61
|
+
className?: string;
|
|
62
|
+
}
|
|
63
|
+
export interface AssistantComposerProps {
|
|
64
|
+
floating?: ReactNode;
|
|
65
|
+
status?: ReactNode;
|
|
66
|
+
pendingFiles?: ReactNode;
|
|
67
|
+
children: ReactNode;
|
|
68
|
+
className?: string;
|
|
69
|
+
}
|
|
70
|
+
export declare function AssistantComposer({ floating, status, pendingFiles, children, className, }: AssistantComposerProps): import("react/jsx-runtime").JSX.Element;
|
|
71
|
+
export declare function AssistantPendingFileChip({ label, onRemove, className, }: AssistantPendingFileChipProps): import("react/jsx-runtime").JSX.Element;
|
|
72
|
+
export interface AssistantStatusPillProps {
|
|
73
|
+
label: ReactNode;
|
|
74
|
+
subtle?: boolean;
|
|
75
|
+
className?: string;
|
|
76
|
+
}
|
|
77
|
+
export declare function AssistantStatusPill({ label, subtle, className, }: AssistantStatusPillProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef } from "react";
|
|
3
|
+
function cx(...values) {
|
|
4
|
+
return values.filter(Boolean).join(" ");
|
|
5
|
+
}
|
|
6
|
+
export const AssistantMessageViewport = forwardRef(function AssistantMessageViewport({ className, innerClassName, children, ...props }, ref) {
|
|
7
|
+
return (_jsx("div", { ref: ref, className: cx("min-h-0 flex-1 overflow-y-auto bg-[var(--bg-surface)] px-4 py-4", className), ...props, children: _jsx("div", { className: cx("mx-auto flex w-full max-w-5xl flex-col gap-3", innerClassName), children: children }) }));
|
|
8
|
+
});
|
|
9
|
+
export function AssistantShellLayout({ sidebar, sidebarVisible = false, main, className, }) {
|
|
10
|
+
return (_jsxs("div", { className: cx("mx-auto flex h-full w-full min-h-0 flex-col gap-3 font-sans antialiased", !!sidebar && sidebarVisible && "lg:grid lg:grid-cols-[280px_minmax(0,1fr)] lg:gap-3", className), children: [sidebar && sidebarVisible ? (_jsx("div", { className: "hidden h-full min-h-0 lg:block", children: sidebar })) : null, main] }));
|
|
11
|
+
}
|
|
12
|
+
export function AssistantHeader({ title, subtitle, badge, controls, className, }) {
|
|
13
|
+
return (_jsxs("div", { className: cx("flex items-center justify-between border-b border-[color:color-mix(in_srgb,_var(--border-default)_80%,_transparent)] px-4 py-3", className), children: [_jsxs("div", { className: "flex items-center gap-2.5", children: [badge ? (_jsx("div", { className: "flex h-7 w-7 items-center justify-center rounded-full bg-[linear-gradient(135deg,var(--brand-primary),var(--brand-secondary))] shadow-[var(--shadow-xs)]", children: badge })) : null, _jsxs("div", { children: [_jsx("h3", { className: "text-[13px] font-semibold leading-tight text-[var(--text-primary)]", children: title }), subtitle ? (_jsx("p", { className: "text-[11px] text-[var(--text-tertiary)]", children: subtitle })) : null] })] }), controls ? (_jsx("div", { className: "flex items-center gap-1", children: controls })) : null] }));
|
|
14
|
+
}
|
|
15
|
+
export function AssistantConversationList({ conversations, activeConversationId, onSelectConversation, onNewConversation, renderConversationLabel, title = "Conversations", newLabel = "New", className, }) {
|
|
16
|
+
return (_jsxs("aside", { className: cx("flex h-full min-h-0 flex-col overflow-hidden rounded-2xl border border-[color:color-mix(in_srgb,_var(--border-default)_80%,_transparent)] bg-[var(--bg-surface)] shadow-[var(--shadow-lg)]", className), children: [_jsx("div", { className: "border-b border-[color:color-mix(in_srgb,_var(--border-default)_80%,_transparent)] px-4 py-3", children: _jsxs("div", { className: "flex items-center justify-between gap-3", children: [_jsxs("div", { children: [_jsx("div", { className: "text-[13px] font-semibold text-[var(--text-primary)]", children: title }), _jsxs("div", { className: "mt-1 text-[11px] text-[var(--text-tertiary)]", children: [conversations.length, " total"] })] }), onNewConversation ? (_jsx("button", { type: "button", onClick: onNewConversation, className: "rounded-full border border-[var(--border-default)] bg-[var(--bg-surface)] px-3 py-1.5 text-[11px] font-medium text-[var(--text-secondary)] hover:text-[var(--text-primary)]", children: newLabel })) : null] }) }), _jsx("div", { className: "min-h-0 flex-1 overflow-y-auto p-3 space-y-2", children: conversations.map((conversation) => {
|
|
17
|
+
const isActive = conversation.id === activeConversationId;
|
|
18
|
+
return (_jsxs("button", { type: "button", onClick: () => onSelectConversation(conversation.id), className: cx("w-full rounded-xl border px-3 py-2.5 text-left transition-colors", isActive
|
|
19
|
+
? "border-[color:color-mix(in_srgb,_var(--brand-primary)_44%,_var(--border-default))] bg-[color:color-mix(in_srgb,_var(--brand-glow)_42%,_var(--bg-surface))]"
|
|
20
|
+
: "border-[var(--border-default)] bg-[var(--bg-surface)] hover:bg-[var(--bg-subtle)]"), children: [_jsx("div", { className: "truncate text-[12px] font-medium text-[var(--text-primary)]", children: renderConversationLabel
|
|
21
|
+
? renderConversationLabel({ conversation, isActive })
|
|
22
|
+
: (conversation.title || "Untitled conversation") }), _jsx("div", { className: "mt-1 text-[10px] uppercase tracking-[0.08em] text-[var(--text-tertiary)]", children: (conversation.status || "waiting").toLowerCase() })] }, conversation.id));
|
|
23
|
+
}) })] }));
|
|
24
|
+
}
|
|
25
|
+
export function AssistantModelPicker({ value, options, disabled, autoLabel = "Auto", getOptionLabel, onChange, className, }) {
|
|
26
|
+
const autoValue = "__AUTO__";
|
|
27
|
+
return (_jsxs("select", { value: value ?? autoValue, onChange: (event) => onChange(event.target.value === autoValue ? null : event.target.value), disabled: disabled, className: cx("h-8 rounded-full border border-[color:color-mix(in_srgb,_var(--border-default)_80%,_transparent)] bg-[var(--bg-surface)] px-3 text-[11px] text-[var(--text-secondary)]", className), "aria-label": "Conversation model", title: "Conversation model", children: [_jsx("option", { value: autoValue, children: autoLabel }), options.map((option) => (_jsx("option", { value: option, children: getOptionLabel ? getOptionLabel(option) : option }, option)))] }));
|
|
28
|
+
}
|
|
29
|
+
export function AssistantAskOverlay({ questionNumber, totalQuestions, question, options, selectedOptions, canContinue, continueLabel, onSelectOption, onContinue, onSkip, mode = "single_select", }) {
|
|
30
|
+
return (_jsxs("div", { className: "space-y-2", children: [_jsxs("div", { className: "flex items-start justify-between gap-3", children: [_jsxs("div", { children: [_jsxs("div", { className: "text-[11px] uppercase tracking-[0.12em] text-[var(--text-tertiary)]", children: ["Question ", questionNumber, " of ", totalQuestions] }), _jsx("p", { className: "mt-1 text-[14px] font-medium leading-6 text-[var(--text-primary)]", children: question })] }), onSkip ? (_jsx("button", { type: "button", onClick: onSkip, className: "rounded-md px-2 py-1 text-[12px] text-[var(--text-tertiary)] transition-colors hover:bg-[var(--bg-subtle)] hover:text-[var(--text-primary)]", children: "Skip" })) : null] }), _jsx("div", { className: "max-h-[260px] space-y-1.5 overflow-y-auto pr-1", children: options.map((option, optionIndex) => {
|
|
31
|
+
const isSelected = selectedOptions.includes(option);
|
|
32
|
+
const rankLabel = mode === "rank_priorities" && isSelected
|
|
33
|
+
? selectedOptions.indexOf(option) + 1
|
|
34
|
+
: null;
|
|
35
|
+
return (_jsx("button", { type: "button", onClick: () => onSelectOption(option), className: cx("w-full rounded-lg border px-2.5 py-2 text-left text-[13px] transition-colors", isSelected
|
|
36
|
+
? "border-[color:color-mix(in_srgb,_var(--brand-primary)_64%,_var(--border-subtle))] bg-[color:color-mix(in_srgb,_var(--brand-primary)_14%,_transparent)] text-[var(--text-primary)]"
|
|
37
|
+
: "border-[var(--border-default)] bg-[var(--bg-canvas)] text-[var(--text-secondary)] hover:bg-[var(--bg-subtle)] hover:text-[var(--text-primary)]"), children: _jsxs("span", { className: "inline-flex items-center gap-2", children: [rankLabel ? (_jsx("span", { className: "inline-flex h-4 min-w-4 items-center justify-center rounded-full bg-[var(--brand-primary)] px-1 text-[10px] font-semibold text-[var(--text-on-brand)]", children: rankLabel })) : (_jsx("span", { className: cx("inline-block h-2.5 w-2.5 rounded-full border", isSelected
|
|
38
|
+
? "border-[var(--brand-primary)] bg-[var(--brand-primary)]"
|
|
39
|
+
: "border-[var(--border-default)] bg-transparent") })), option] }) }, `${option}-${optionIndex}`));
|
|
40
|
+
}) }), onContinue ? (_jsx("div", { className: "flex justify-end", children: _jsx("button", { type: "button", onClick: onContinue, disabled: !canContinue, className: cx("rounded-md px-2.5 py-1.5 text-[12px] font-medium transition-colors", canContinue
|
|
41
|
+
? "bg-[var(--brand-primary)] text-[var(--text-on-brand)] hover:bg-[color:color-mix(in_srgb,_var(--brand-primary)_88%,_var(--text-primary))]"
|
|
42
|
+
: "bg-[var(--bg-subtle)] text-[var(--text-tertiary)]"), children: continueLabel }) })) : null] }));
|
|
43
|
+
}
|
|
44
|
+
export function AssistantComposer({ floating, status, pendingFiles, children, className, }) {
|
|
45
|
+
return (_jsxs("div", { className: cx("relative rounded-2xl border border-[color:color-mix(in_srgb,_var(--border-default)_80%,_transparent)] bg-[var(--bg-surface)] p-2 shadow-[var(--shadow-md)]", className), children: [floating ? (_jsx("div", { className: "absolute bottom-[calc(100%+8px)] left-0 right-0 z-20", children: floating })) : null, _jsx("div", { className: "min-h-[34px] px-2 pb-1", children: _jsx("div", { className: "flex min-h-[26px] items-center transition-opacity duration-200", children: status || _jsx("span", { "aria-hidden": "true", className: "inline-block h-[30px]" }) }) }), pendingFiles ? (_jsx("div", { className: "flex flex-wrap items-center gap-1.5 px-1 pb-1.5", children: pendingFiles })) : null, children] }));
|
|
46
|
+
}
|
|
47
|
+
export function AssistantPendingFileChip({ label, onRemove, className, }) {
|
|
48
|
+
return (_jsxs("span", { className: cx("inline-flex max-w-full items-center gap-1.5 rounded-full bg-[var(--bg-subtle)] px-2 py-1 text-[11px] text-[var(--text-secondary)]", className), children: [_jsx("span", { className: "truncate max-w-[180px]", children: label }), onRemove ? (_jsx("button", { type: "button", onClick: onRemove, className: "inline-flex h-4 w-4 items-center justify-center rounded-full hover:bg-[var(--bg-canvas)]", title: "Remove file", children: "\u00D7" })) : null] }));
|
|
49
|
+
}
|
|
50
|
+
export function AssistantStatusPill({ label, subtle = false, className, }) {
|
|
51
|
+
return (_jsxs("div", { className: cx("inline-flex min-h-[30px] max-w-full items-center gap-2 rounded-full px-3 py-1.5 text-[12px] transition-all duration-200", subtle
|
|
52
|
+
? "border border-[color:color-mix(in_srgb,_var(--border-default)_72%,_transparent)] bg-[color:color-mix(in_srgb,_var(--bg-surface)_90%,_transparent)] text-[var(--text-tertiary)]"
|
|
53
|
+
: "border border-[color:color-mix(in_srgb,_var(--brand-primary)_24%,_var(--border-default))] bg-[color:color-mix(in_srgb,_var(--brand-glow)_28%,_var(--bg-surface))] text-[var(--text-secondary)]", className), children: [_jsxs("span", { className: "relative inline-flex h-2.5 w-2.5 shrink-0", children: [_jsx("span", { className: "absolute inline-flex h-full w-full animate-ping rounded-full bg-[var(--brand-primary)]/45" }), _jsx("span", { className: "relative inline-flex h-2.5 w-2.5 rounded-full bg-[var(--brand-primary)]" })] }), _jsx("span", { className: "truncate", children: label })] }));
|
|
54
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { LemmaClient } from "../../client.js";
|
|
2
|
+
import { type AssistantConversationScope } from "../useAssistantController.js";
|
|
3
|
+
import { type AssistantExperienceViewProps } from "./AssistantExperience.js";
|
|
4
|
+
export interface AssistantEmbeddedProps extends Omit<AssistantExperienceViewProps, "controller">, AssistantConversationScope {
|
|
5
|
+
client: LemmaClient;
|
|
6
|
+
enabled?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export declare function AssistantEmbedded({ client, podId, assistantId, organizationId, enabled, ...props }: AssistantEmbeddedProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useAssistantController } from "../useAssistantController.js";
|
|
3
|
+
import { AssistantExperienceView } from "./AssistantExperience.js";
|
|
4
|
+
export function AssistantEmbedded({ client, podId, assistantId, organizationId, enabled = true, ...props }) {
|
|
5
|
+
const controller = useAssistantController({
|
|
6
|
+
client,
|
|
7
|
+
podId: podId ?? undefined,
|
|
8
|
+
assistantId: assistantId ?? undefined,
|
|
9
|
+
organizationId: organizationId ?? undefined,
|
|
10
|
+
enabled,
|
|
11
|
+
});
|
|
12
|
+
return _jsx(AssistantExperienceView, { controller: controller, ...props });
|
|
13
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import type { AssistantRenderableMessage, AssistantToolInvocation } from "../useAssistantController.js";
|
|
3
|
+
import type { AssistantControllerView, AssistantConversationRenderArgs, AssistantMessageRenderArgs, AssistantPendingFileRenderArgs, AssistantPresentedFileRenderArgs, AssistantToolRenderArgs } from "./assistant-types.js";
|
|
4
|
+
type PlanStatus = "pending" | "in_progress" | "completed";
|
|
5
|
+
export interface PlanStepState {
|
|
6
|
+
step: string;
|
|
7
|
+
status: PlanStatus;
|
|
8
|
+
}
|
|
9
|
+
export interface PlanSummaryState {
|
|
10
|
+
steps: PlanStepState[];
|
|
11
|
+
completedCount: number;
|
|
12
|
+
inProgressCount: number;
|
|
13
|
+
running: boolean;
|
|
14
|
+
activeStep?: string;
|
|
15
|
+
}
|
|
16
|
+
type AskQuestionType = "single_select" | "multi_select" | "rank_priorities";
|
|
17
|
+
export interface AskUserInputQuestion {
|
|
18
|
+
question: string;
|
|
19
|
+
options: string[];
|
|
20
|
+
type: AskQuestionType;
|
|
21
|
+
}
|
|
22
|
+
export interface PendingAskUserInput {
|
|
23
|
+
toolCallId: string;
|
|
24
|
+
messageIndex: number;
|
|
25
|
+
questions: AskUserInputQuestion[];
|
|
26
|
+
}
|
|
27
|
+
export interface DisplayMessageRow {
|
|
28
|
+
id: string;
|
|
29
|
+
message: AssistantRenderableMessage;
|
|
30
|
+
sourceIndexes: number[];
|
|
31
|
+
}
|
|
32
|
+
export interface ActiveToolBanner {
|
|
33
|
+
summary: string;
|
|
34
|
+
activeCount: number;
|
|
35
|
+
}
|
|
36
|
+
export interface AssistantExperienceViewProps {
|
|
37
|
+
controller: AssistantControllerView;
|
|
38
|
+
title?: ReactNode;
|
|
39
|
+
subtitle?: ReactNode;
|
|
40
|
+
placeholder?: string;
|
|
41
|
+
emptyState?: ReactNode;
|
|
42
|
+
draft?: string;
|
|
43
|
+
onDraftChange?: (value: string) => void;
|
|
44
|
+
showConversationList?: boolean;
|
|
45
|
+
onNavigateResource?: (resourceType: string, resourceId: string, meta?: Record<string, unknown>) => void;
|
|
46
|
+
renderConversationLabel?: (args: AssistantConversationRenderArgs) => ReactNode;
|
|
47
|
+
renderMessageContent?: (args: AssistantMessageRenderArgs) => ReactNode;
|
|
48
|
+
renderPresentedFile?: (args: AssistantPresentedFileRenderArgs) => ReactNode;
|
|
49
|
+
renderPendingFile?: (args: AssistantPendingFileRenderArgs) => ReactNode;
|
|
50
|
+
renderToolInvocation?: (args: AssistantToolRenderArgs) => ReactNode;
|
|
51
|
+
}
|
|
52
|
+
export declare function dedupToolInvocations(message: AssistantRenderableMessage): AssistantToolInvocation[];
|
|
53
|
+
export declare function latestPlanSummary(messages: AssistantRenderableMessage[]): PlanSummaryState | null;
|
|
54
|
+
export declare function findPendingAskUserInput(messages: AssistantRenderableMessage[]): PendingAskUserInput | null;
|
|
55
|
+
export declare function formatAskUserInputAnswers(questions: AskUserInputQuestion[], answers: string[][]): string;
|
|
56
|
+
export declare function extractPresentFilePathsFromInvocation(invocation: AssistantToolInvocation): string[];
|
|
57
|
+
export declare function buildDisplayMessageRows(messages: AssistantRenderableMessage[]): DisplayMessageRow[];
|
|
58
|
+
export declare function getActiveToolBanner(messages: AssistantRenderableMessage[]): ActiveToolBanner | null;
|
|
59
|
+
export declare function PlanSummaryStrip({ plan, onHide }: {
|
|
60
|
+
plan: PlanSummaryState;
|
|
61
|
+
onHide: () => void;
|
|
62
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
63
|
+
export declare function ThinkingIndicator(): import("react/jsx-runtime").JSX.Element | null;
|
|
64
|
+
export declare function EmptyState({ onSendMessage }: {
|
|
65
|
+
onSendMessage: (msg: string) => void;
|
|
66
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
67
|
+
export declare function MessageGroup({ message, conversationId, onNavigateResource, onWidgetSendPrompt, isStreaming, showAssistantHeader, renderMessageContent, renderPresentedFile, renderToolInvocation, }: {
|
|
68
|
+
message: AssistantRenderableMessage;
|
|
69
|
+
conversationId?: string | null;
|
|
70
|
+
onNavigateResource?: (resourceType: string, resourceId: string, meta?: Record<string, unknown>) => void;
|
|
71
|
+
onWidgetSendPrompt: (text: string) => void | Promise<void>;
|
|
72
|
+
isStreaming: boolean;
|
|
73
|
+
showAssistantHeader: boolean;
|
|
74
|
+
renderMessageContent: (args: AssistantMessageRenderArgs) => ReactNode;
|
|
75
|
+
renderPresentedFile?: (args: AssistantPresentedFileRenderArgs) => ReactNode;
|
|
76
|
+
renderToolInvocation?: (args: AssistantToolRenderArgs) => ReactNode;
|
|
77
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
78
|
+
export declare function AssistantExperienceView({ controller, title, subtitle, placeholder, emptyState, draft: controlledDraft, onDraftChange, showConversationList, onNavigateResource, renderConversationLabel, renderMessageContent, renderPresentedFile, renderPendingFile, renderToolInvocation, }: AssistantExperienceViewProps): import("react/jsx-runtime").JSX.Element;
|
|
79
|
+
export {};
|