@frankieai/react 0.2.7 → 0.2.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/frankie.css +1 -1
- package/dist/index.cjs +394 -190
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +63 -9
- package/dist/index.d.ts +63 -9
- package/dist/index.js +377 -175
- package/dist/index.js.map +1 -1
- package/package.json +5 -2
- package/src/components/chat/AgentContext.tsx +2 -1
- package/src/components/chat/ChatPanel.tsx +9 -1
- package/src/components/chat/Choices.tsx +52 -0
- package/src/components/chat/Composer.tsx +12 -2
- package/src/components/chat/FrankieChatPage.tsx +4 -1
- package/src/components/chat/FrankieInline.tsx +7 -2
- package/src/components/chat/FrankieWidget.tsx +11 -2
- package/src/components/chat/Markdown.tsx +15 -8
- package/src/components/chat/MessageBubble.tsx +29 -5
- package/src/hooks/useFrankieChat.ts +65 -3
- package/src/index.ts +3 -0
- package/src/lib/choices.ts +49 -0
- package/src/lib/styles-ready.ts +71 -0
- package/src/styles/frankie.css +106 -3
- package/src/styles-ready.test.tsx +71 -0
- package/src/widget.test.tsx +17 -0
package/dist/index.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
|
-
import { ReactNode, CSSProperties, ButtonHTMLAttributes, HTMLAttributes, TextareaHTMLAttributes } from 'react';
|
|
3
|
-
import { PublicWidgetConfig, CreateSessionResponse, ChatAttachment, FrankieServerEvent, WidgetTheme, LoadedSkill } from '@frankieai/core';
|
|
2
|
+
import { ReactNode, CSSProperties, MutableRefObject, ButtonHTMLAttributes, HTMLAttributes, TextareaHTMLAttributes } from 'react';
|
|
3
|
+
import { PublicWidgetConfig, CreateSessionResponse, ChatAttachment, FrankieServerEvent, WidgetTheme, LoadedSkill, ApiToolInventory } from '@frankieai/core';
|
|
4
4
|
export { FrankieServerEvent, PublicWidgetConfig, WidgetTheme } from '@frankieai/core';
|
|
5
5
|
import * as class_variance_authority_types from 'class-variance-authority/types';
|
|
6
6
|
import { VariantProps } from 'class-variance-authority';
|
|
@@ -148,6 +148,8 @@ interface SendOptions {
|
|
|
148
148
|
}
|
|
149
149
|
interface UseFrankieChatResult {
|
|
150
150
|
loadedSkills: LoadedSkill[] | null;
|
|
151
|
+
/** Which OpenAPI sources are live for this turn, and a content fingerprint of each. */
|
|
152
|
+
activeApis: ApiToolInventory[] | null;
|
|
151
153
|
restoring: boolean;
|
|
152
154
|
messages: ChatMessage[];
|
|
153
155
|
/** True from the moment a message is sent until the turn ends. */
|
|
@@ -263,8 +265,10 @@ interface ComposerProps {
|
|
|
263
265
|
attachments?: ComposerAttachmentsConfig;
|
|
264
266
|
/** Enables a model dropdown when provided with at least one model. */
|
|
265
267
|
modelPicker?: ComposerModelPicker;
|
|
268
|
+
/** Populated with a function that focuses the input, so a "type your own" choice can jump here. */
|
|
269
|
+
focusHandleRef?: MutableRefObject<(() => void) | null>;
|
|
266
270
|
}
|
|
267
|
-
declare function Composer({ onSend, onStop, busy, placeholder, disabled, autoFocus, attachments, modelPicker }: ComposerProps): react.JSX.Element;
|
|
271
|
+
declare function Composer({ onSend, onStop, busy, placeholder, disabled, autoFocus, attachments, modelPicker, focusHandleRef }: ComposerProps): react.JSX.Element;
|
|
268
272
|
|
|
269
273
|
interface MessageBubbleProps {
|
|
270
274
|
message: ChatMessage;
|
|
@@ -272,22 +276,47 @@ interface MessageBubbleProps {
|
|
|
272
276
|
avatarUrl?: string;
|
|
273
277
|
showToolActivity: boolean;
|
|
274
278
|
renderTool?: (tool: ToolActivity) => ReactNode;
|
|
279
|
+
/** Send a picked choice as the next message. Omitted when the host renders its own. */
|
|
280
|
+
onChoose?: (choice: string) => void;
|
|
281
|
+
/** Focus the composer so the user can type their own answer instead of picking. */
|
|
282
|
+
onRequestInput?: () => void;
|
|
283
|
+
/** True only for the newest message, so stale choices from earlier turns aren't clickable. */
|
|
284
|
+
active?: boolean;
|
|
285
|
+
/** A turn is in flight, so choices should be disabled. */
|
|
286
|
+
busy?: boolean;
|
|
275
287
|
}
|
|
276
|
-
declare
|
|
288
|
+
declare const MessageBubble: react.NamedExoticComponent<MessageBubbleProps>;
|
|
277
289
|
declare function TypingDots(): react.JSX.Element;
|
|
278
290
|
|
|
279
291
|
/**
|
|
280
|
-
* A deliberately small Markdown subset — paragraphs, lists, fenced
|
|
281
|
-
* italic, inline code and links.
|
|
292
|
+
* A deliberately small Markdown subset — headings, paragraphs, lists, fenced
|
|
293
|
+
* code, bold, italic, inline code and links.
|
|
282
294
|
*
|
|
283
295
|
* Everything is rendered as React elements; nothing goes through
|
|
284
296
|
* `dangerouslySetInnerHTML`. Model output lands in someone else's production
|
|
285
297
|
* page, so it is never trusted as markup.
|
|
298
|
+
*
|
|
299
|
+
* Memoized on `text`: while a reply streams, the parent re-renders every frame,
|
|
300
|
+
* but the block tree is only recomputed when the text actually grows — the
|
|
301
|
+
* settled messages above never re-parse at all.
|
|
286
302
|
*/
|
|
287
|
-
declare
|
|
303
|
+
declare const Markdown: react.NamedExoticComponent<{
|
|
288
304
|
text: string;
|
|
289
305
|
className?: string;
|
|
290
|
-
}
|
|
306
|
+
}>;
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Clickable answer options the agent offered via a `frankie:choices` block.
|
|
310
|
+
* Picking one sends it as the next message. A trailing "Something else" row
|
|
311
|
+
* doesn't send — it moves the caret to the composer so the user can type their
|
|
312
|
+
* own answer, while the offered options stay put in case they change their mind.
|
|
313
|
+
*/
|
|
314
|
+
declare function Choices({ options, onPick, onSomethingElse, disabled, }: {
|
|
315
|
+
options: string[];
|
|
316
|
+
onPick: (choice: string) => void;
|
|
317
|
+
onSomethingElse?: () => void;
|
|
318
|
+
disabled?: boolean;
|
|
319
|
+
}): react.JSX.Element | null;
|
|
291
320
|
|
|
292
321
|
declare function SuggestedPrompts({ prompts, onPick, disabled, }: {
|
|
293
322
|
prompts: string[];
|
|
@@ -349,6 +378,31 @@ declare function Separator({ className }: {
|
|
|
349
378
|
/** `forwardRef` rather than React 19's ref-as-prop, so React 18 hosts work too. */
|
|
350
379
|
declare const Textarea: react.ForwardRefExoticComponent<TextareaHTMLAttributes<HTMLTextAreaElement> & react.RefAttributes<HTMLTextAreaElement>>;
|
|
351
380
|
|
|
381
|
+
/**
|
|
382
|
+
* Interactive choice blocks.
|
|
383
|
+
*
|
|
384
|
+
* The agent can end a reply with a fenced block to offer the user a small set
|
|
385
|
+
* of discrete answers:
|
|
386
|
+
*
|
|
387
|
+
* ```frankie:choices
|
|
388
|
+
* British
|
|
389
|
+
* Indian
|
|
390
|
+
* Australian
|
|
391
|
+
* ```
|
|
392
|
+
*
|
|
393
|
+
* The SDK lifts that block out of the prose and renders it as clickable options
|
|
394
|
+
* (the composer stays open, so the user can always type their own answer). The
|
|
395
|
+
* block is a plain fenced code block, so a host that doesn't understand it just
|
|
396
|
+
* shows a harmless code listing instead — never broken markup.
|
|
397
|
+
*/
|
|
398
|
+
interface ExtractedChoices {
|
|
399
|
+
/** The reply text with the choices block removed. */
|
|
400
|
+
body: string;
|
|
401
|
+
/** The offered options, or null when there is no complete block. */
|
|
402
|
+
options: string[] | null;
|
|
403
|
+
}
|
|
404
|
+
declare function extractChoices(text: string): ExtractedChoices;
|
|
405
|
+
|
|
352
406
|
/**
|
|
353
407
|
* Map a theme to the CSS custom properties the widget's styles read.
|
|
354
408
|
*
|
|
@@ -363,4 +417,4 @@ declare function resolveMode(mode: WidgetTheme["mode"]): "light" | "dark";
|
|
|
363
417
|
/** shadcn/ui's class helper: conditional classes with Tailwind conflict resolution. */
|
|
364
418
|
declare function cn(...inputs: ClassValue[]): string;
|
|
365
419
|
|
|
366
|
-
export { type AssistantChatMessage, Avatar, Badge, Button, type ButtonProps, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, type ChatMessage, ChatPanel, type ChatPanelProps, Composer, FRANKIE_CLOUD_URL, FrankieApiError, FrankieChatPage, type FrankieChatPageProps, FrankieClient, type FrankieClientOptions, FrankieInline, type FrankieInlineProps, FrankieProvider, type FrankieProviderProps, FrankieWidget, type FrankieWidgetProps, Markdown, type MessageAttachment, MessageBubble, type PageContext, ScrollArea, type SendOptions, Separator, SuggestedPrompts, Textarea, type ToolActivity, ToolActivityList, ToolActivityRow, TypingDots, type UseFrankieChatResult, type UserChatMessage, applyEvent, buttonVariants, cn, newAssistantMessage, newUserMessage, readEventStream, resolveMode, themeToCssVars, useFrankie, useFrankieChat, useFrankieTheme };
|
|
420
|
+
export { type AssistantChatMessage, Avatar, Badge, Button, type ButtonProps, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, type ChatMessage, ChatPanel, type ChatPanelProps, Choices, Composer, type ExtractedChoices, FRANKIE_CLOUD_URL, FrankieApiError, FrankieChatPage, type FrankieChatPageProps, FrankieClient, type FrankieClientOptions, FrankieInline, type FrankieInlineProps, FrankieProvider, type FrankieProviderProps, FrankieWidget, type FrankieWidgetProps, Markdown, type MessageAttachment, MessageBubble, type PageContext, ScrollArea, type SendOptions, Separator, SuggestedPrompts, Textarea, type ToolActivity, ToolActivityList, ToolActivityRow, TypingDots, type UseFrankieChatResult, type UserChatMessage, applyEvent, buttonVariants, cn, extractChoices, newAssistantMessage, newUserMessage, readEventStream, resolveMode, themeToCssVars, useFrankie, useFrankieChat, useFrankieTheme };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
|
-
import { ReactNode, CSSProperties, ButtonHTMLAttributes, HTMLAttributes, TextareaHTMLAttributes } from 'react';
|
|
3
|
-
import { PublicWidgetConfig, CreateSessionResponse, ChatAttachment, FrankieServerEvent, WidgetTheme, LoadedSkill } from '@frankieai/core';
|
|
2
|
+
import { ReactNode, CSSProperties, MutableRefObject, ButtonHTMLAttributes, HTMLAttributes, TextareaHTMLAttributes } from 'react';
|
|
3
|
+
import { PublicWidgetConfig, CreateSessionResponse, ChatAttachment, FrankieServerEvent, WidgetTheme, LoadedSkill, ApiToolInventory } from '@frankieai/core';
|
|
4
4
|
export { FrankieServerEvent, PublicWidgetConfig, WidgetTheme } from '@frankieai/core';
|
|
5
5
|
import * as class_variance_authority_types from 'class-variance-authority/types';
|
|
6
6
|
import { VariantProps } from 'class-variance-authority';
|
|
@@ -148,6 +148,8 @@ interface SendOptions {
|
|
|
148
148
|
}
|
|
149
149
|
interface UseFrankieChatResult {
|
|
150
150
|
loadedSkills: LoadedSkill[] | null;
|
|
151
|
+
/** Which OpenAPI sources are live for this turn, and a content fingerprint of each. */
|
|
152
|
+
activeApis: ApiToolInventory[] | null;
|
|
151
153
|
restoring: boolean;
|
|
152
154
|
messages: ChatMessage[];
|
|
153
155
|
/** True from the moment a message is sent until the turn ends. */
|
|
@@ -263,8 +265,10 @@ interface ComposerProps {
|
|
|
263
265
|
attachments?: ComposerAttachmentsConfig;
|
|
264
266
|
/** Enables a model dropdown when provided with at least one model. */
|
|
265
267
|
modelPicker?: ComposerModelPicker;
|
|
268
|
+
/** Populated with a function that focuses the input, so a "type your own" choice can jump here. */
|
|
269
|
+
focusHandleRef?: MutableRefObject<(() => void) | null>;
|
|
266
270
|
}
|
|
267
|
-
declare function Composer({ onSend, onStop, busy, placeholder, disabled, autoFocus, attachments, modelPicker }: ComposerProps): react.JSX.Element;
|
|
271
|
+
declare function Composer({ onSend, onStop, busy, placeholder, disabled, autoFocus, attachments, modelPicker, focusHandleRef }: ComposerProps): react.JSX.Element;
|
|
268
272
|
|
|
269
273
|
interface MessageBubbleProps {
|
|
270
274
|
message: ChatMessage;
|
|
@@ -272,22 +276,47 @@ interface MessageBubbleProps {
|
|
|
272
276
|
avatarUrl?: string;
|
|
273
277
|
showToolActivity: boolean;
|
|
274
278
|
renderTool?: (tool: ToolActivity) => ReactNode;
|
|
279
|
+
/** Send a picked choice as the next message. Omitted when the host renders its own. */
|
|
280
|
+
onChoose?: (choice: string) => void;
|
|
281
|
+
/** Focus the composer so the user can type their own answer instead of picking. */
|
|
282
|
+
onRequestInput?: () => void;
|
|
283
|
+
/** True only for the newest message, so stale choices from earlier turns aren't clickable. */
|
|
284
|
+
active?: boolean;
|
|
285
|
+
/** A turn is in flight, so choices should be disabled. */
|
|
286
|
+
busy?: boolean;
|
|
275
287
|
}
|
|
276
|
-
declare
|
|
288
|
+
declare const MessageBubble: react.NamedExoticComponent<MessageBubbleProps>;
|
|
277
289
|
declare function TypingDots(): react.JSX.Element;
|
|
278
290
|
|
|
279
291
|
/**
|
|
280
|
-
* A deliberately small Markdown subset — paragraphs, lists, fenced
|
|
281
|
-
* italic, inline code and links.
|
|
292
|
+
* A deliberately small Markdown subset — headings, paragraphs, lists, fenced
|
|
293
|
+
* code, bold, italic, inline code and links.
|
|
282
294
|
*
|
|
283
295
|
* Everything is rendered as React elements; nothing goes through
|
|
284
296
|
* `dangerouslySetInnerHTML`. Model output lands in someone else's production
|
|
285
297
|
* page, so it is never trusted as markup.
|
|
298
|
+
*
|
|
299
|
+
* Memoized on `text`: while a reply streams, the parent re-renders every frame,
|
|
300
|
+
* but the block tree is only recomputed when the text actually grows — the
|
|
301
|
+
* settled messages above never re-parse at all.
|
|
286
302
|
*/
|
|
287
|
-
declare
|
|
303
|
+
declare const Markdown: react.NamedExoticComponent<{
|
|
288
304
|
text: string;
|
|
289
305
|
className?: string;
|
|
290
|
-
}
|
|
306
|
+
}>;
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Clickable answer options the agent offered via a `frankie:choices` block.
|
|
310
|
+
* Picking one sends it as the next message. A trailing "Something else" row
|
|
311
|
+
* doesn't send — it moves the caret to the composer so the user can type their
|
|
312
|
+
* own answer, while the offered options stay put in case they change their mind.
|
|
313
|
+
*/
|
|
314
|
+
declare function Choices({ options, onPick, onSomethingElse, disabled, }: {
|
|
315
|
+
options: string[];
|
|
316
|
+
onPick: (choice: string) => void;
|
|
317
|
+
onSomethingElse?: () => void;
|
|
318
|
+
disabled?: boolean;
|
|
319
|
+
}): react.JSX.Element | null;
|
|
291
320
|
|
|
292
321
|
declare function SuggestedPrompts({ prompts, onPick, disabled, }: {
|
|
293
322
|
prompts: string[];
|
|
@@ -349,6 +378,31 @@ declare function Separator({ className }: {
|
|
|
349
378
|
/** `forwardRef` rather than React 19's ref-as-prop, so React 18 hosts work too. */
|
|
350
379
|
declare const Textarea: react.ForwardRefExoticComponent<TextareaHTMLAttributes<HTMLTextAreaElement> & react.RefAttributes<HTMLTextAreaElement>>;
|
|
351
380
|
|
|
381
|
+
/**
|
|
382
|
+
* Interactive choice blocks.
|
|
383
|
+
*
|
|
384
|
+
* The agent can end a reply with a fenced block to offer the user a small set
|
|
385
|
+
* of discrete answers:
|
|
386
|
+
*
|
|
387
|
+
* ```frankie:choices
|
|
388
|
+
* British
|
|
389
|
+
* Indian
|
|
390
|
+
* Australian
|
|
391
|
+
* ```
|
|
392
|
+
*
|
|
393
|
+
* The SDK lifts that block out of the prose and renders it as clickable options
|
|
394
|
+
* (the composer stays open, so the user can always type their own answer). The
|
|
395
|
+
* block is a plain fenced code block, so a host that doesn't understand it just
|
|
396
|
+
* shows a harmless code listing instead — never broken markup.
|
|
397
|
+
*/
|
|
398
|
+
interface ExtractedChoices {
|
|
399
|
+
/** The reply text with the choices block removed. */
|
|
400
|
+
body: string;
|
|
401
|
+
/** The offered options, or null when there is no complete block. */
|
|
402
|
+
options: string[] | null;
|
|
403
|
+
}
|
|
404
|
+
declare function extractChoices(text: string): ExtractedChoices;
|
|
405
|
+
|
|
352
406
|
/**
|
|
353
407
|
* Map a theme to the CSS custom properties the widget's styles read.
|
|
354
408
|
*
|
|
@@ -363,4 +417,4 @@ declare function resolveMode(mode: WidgetTheme["mode"]): "light" | "dark";
|
|
|
363
417
|
/** shadcn/ui's class helper: conditional classes with Tailwind conflict resolution. */
|
|
364
418
|
declare function cn(...inputs: ClassValue[]): string;
|
|
365
419
|
|
|
366
|
-
export { type AssistantChatMessage, Avatar, Badge, Button, type ButtonProps, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, type ChatMessage, ChatPanel, type ChatPanelProps, Composer, FRANKIE_CLOUD_URL, FrankieApiError, FrankieChatPage, type FrankieChatPageProps, FrankieClient, type FrankieClientOptions, FrankieInline, type FrankieInlineProps, FrankieProvider, type FrankieProviderProps, FrankieWidget, type FrankieWidgetProps, Markdown, type MessageAttachment, MessageBubble, type PageContext, ScrollArea, type SendOptions, Separator, SuggestedPrompts, Textarea, type ToolActivity, ToolActivityList, ToolActivityRow, TypingDots, type UseFrankieChatResult, type UserChatMessage, applyEvent, buttonVariants, cn, newAssistantMessage, newUserMessage, readEventStream, resolveMode, themeToCssVars, useFrankie, useFrankieChat, useFrankieTheme };
|
|
420
|
+
export { type AssistantChatMessage, Avatar, Badge, Button, type ButtonProps, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, type ChatMessage, ChatPanel, type ChatPanelProps, Choices, Composer, type ExtractedChoices, FRANKIE_CLOUD_URL, FrankieApiError, FrankieChatPage, type FrankieChatPageProps, FrankieClient, type FrankieClientOptions, FrankieInline, type FrankieInlineProps, FrankieProvider, type FrankieProviderProps, FrankieWidget, type FrankieWidgetProps, Markdown, type MessageAttachment, MessageBubble, type PageContext, ScrollArea, type SendOptions, Separator, SuggestedPrompts, Textarea, type ToolActivity, ToolActivityList, ToolActivityRow, TypingDots, type UseFrankieChatResult, type UserChatMessage, applyEvent, buttonVariants, cn, extractChoices, newAssistantMessage, newUserMessage, readEventStream, resolveMode, themeToCssVars, useFrankie, useFrankieChat, useFrankieTheme };
|