@smarter.sh/ui-chat 0.3.0 → 0.7.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.
Files changed (59) hide show
  1. package/LICENSE +2 -2
  2. package/README.md +235 -173
  3. package/dist/smarter-chat-library.es.js +44331 -12089
  4. package/dist/smarter-chat-library.es.js.map +1 -1
  5. package/dist/smarter-chat-library.umd.js +340 -121
  6. package/dist/smarter-chat-library.umd.js.map +1 -1
  7. package/dist/types/src/components/AppTitle/Component.d.ts +13 -0
  8. package/dist/types/src/components/AppTitle/index.d.ts +2 -0
  9. package/dist/types/src/components/Console/Component.d.ts +17 -0
  10. package/dist/types/src/components/Console/ServerLogs.d.ts +8 -0
  11. package/dist/types/src/components/Console/data.d.ts +7 -0
  12. package/dist/types/src/components/Console/enums.d.ts +9 -0
  13. package/dist/types/src/components/Console/index.d.ts +2 -0
  14. package/dist/types/src/components/ErrorBoundary/Component.d.ts +17 -0
  15. package/dist/types/src/components/ErrorBoundary/index.d.ts +2 -0
  16. package/dist/types/src/components/SmarterChat/Component.d.ts +26 -0
  17. package/dist/types/src/components/SmarterChat/icons.d.ts +17 -0
  18. package/dist/types/src/components/SmarterChat/index.d.ts +2 -0
  19. package/dist/types/src/const.d.ts +5 -0
  20. package/dist/types/src/contract.gen.d.ts +1146 -0
  21. package/dist/types/src/index.d.ts +13 -0
  22. package/dist/types/src/lib/ansi.d.ts +33 -0
  23. package/dist/types/src/lib/api.d.ts +96 -0
  24. package/dist/types/src/lib/code.d.ts +32 -0
  25. package/dist/types/src/lib/cookie.d.ts +17 -0
  26. package/dist/types/src/lib/enums.d.ts +26 -0
  27. package/dist/types/src/lib/layout.d.ts +42 -0
  28. package/dist/types/src/lib/logStream.d.ts +30 -0
  29. package/dist/types/src/lib/math.d.ts +18 -0
  30. package/dist/types/src/lib/mermaid.d.ts +27 -0
  31. package/dist/types/src/lib/messages.d.ts +52 -0
  32. package/dist/types/src/types.d.ts +108 -0
  33. package/dist/ui-chat.css +2 -1
  34. package/package.json +90 -59
  35. package/src/components/Console/Component.css +0 -47
  36. package/src/components/Console/Component.jsx +0 -186
  37. package/src/components/Console/HeadStyles.jsx +0 -20
  38. package/src/components/Console/enums.js +0 -7
  39. package/src/components/Console/index.js +0 -2
  40. package/src/components/ErrorModal/ErrorModal.css +0 -35
  41. package/src/components/ErrorModal/ErrorModal.jsx +0 -56
  42. package/src/components/ErrorModal/index.js +0 -3
  43. package/src/components/SmarterChat/Component.jsx +0 -431
  44. package/src/components/SmarterChat/ErrorBoundary.jsx +0 -32
  45. package/src/components/SmarterChat/Layout.js +0 -47
  46. package/src/components/SmarterChat/api.js +0 -200
  47. package/src/components/SmarterChat/enums.js +0 -17
  48. package/src/components/SmarterChat/index.js +0 -3
  49. package/src/components/SmarterChat/styles.css +0 -152
  50. package/src/components/SmarterChat/utils.jsx +0 -148
  51. package/src/components/enums.js +0 -1
  52. package/src/components/index.js +0 -3
  53. package/src/components/shared/cookie.js +0 -51
  54. package/src/constants.js +0 -2
  55. package/src/index.js +0 -4
  56. package/src/types/index.js +0 -2
  57. package/src/types/propTypes.js +0 -154
  58. package/src/version.js +0 -2
  59. package/types/index.d.ts +0 -17
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @smarter.sh/ui-chat: the public api of the npm package. See vite.config.ts (--mode lib).
3
+ *
4
+ * The Smarter web console builds this package as an app instead. See main.tsx.
5
+ */
6
+ export { default as SmarterChat } from "./components/SmarterChat";
7
+ export { default as Console } from "./components/Console";
8
+ export { MenuItems } from "./components/Console/enums";
9
+ export { MessageDirectionEnum, SenderRoleEnum, ValidMessageRolesEnum } from "./lib/enums";
10
+ export { projectVersion as version } from "./const";
11
+ export { CHAT_CONTRACT_V2_CAPABILITY, normalizeConfig } from "./lib/api";
12
+ export type { PromptProgressEvent } from "./lib/api";
13
+ export type { ApiMessage, ChatConfig, ChatHistory, ChatMessage, ChatMetaData, ChatbotConfig, Contract, LLMClientConfig, SmarterChatProps, } from "./types";
@@ -0,0 +1,33 @@
1
+ /**
2
+ * ANSI escape codes, as the server's log records have them, e.g. "\x1b[1;34m...\x1b[0m".
3
+ *
4
+ * The text of a log record is split into segments, each with the color and the emphasis that its
5
+ * SGR (Select Graphic Rendition) codes give it, so that the Console displays the records as the
6
+ * Smarter web console's log viewer (smarter-terminal-emulator, an xterm.js terminal) does. Other
7
+ * escape sequences, e.g. cursor movements, are removed.
8
+ */
9
+ import type { CSSProperties } from "react";
10
+ /** The xterm.js theme of smarter-terminal-emulator, by ANSI color number: 0-7, then bright 8-15. */
11
+ export declare const ANSI_PALETTE: string[];
12
+ /** The text style that SGR codes set. */
13
+ export interface AnsiStyle {
14
+ color?: string;
15
+ backgroundColor?: string;
16
+ bold?: boolean;
17
+ dim?: boolean;
18
+ italic?: boolean;
19
+ underline?: boolean;
20
+ }
21
+ /** A run of text, with its style. */
22
+ export interface AnsiSegment {
23
+ text: string;
24
+ style: AnsiStyle;
25
+ }
26
+ /** The style after the given SGR codes. An empty list of codes is a reset. */
27
+ export declare function applySgr(style: AnsiStyle, codes: number[]): AnsiStyle;
28
+ /** The text's segments, each with its style, without the escape sequences. */
29
+ export declare function parseAnsi(text: string): AnsiSegment[];
30
+ /** The text without its escape sequences. */
31
+ export declare function stripAnsi(text: string): string;
32
+ /** The css of a style. */
33
+ export declare function ansiCss(style: AnsiStyle): CSSProperties;
@@ -0,0 +1,96 @@
1
+ /**
2
+ * The Smarter api calls of Smarter Chat: the LLMClient's configuration, and its prompts.
3
+ *
4
+ * Both are POSTs, with Django's CSRF token, and with the browser's cookies, so that the Smarter web
5
+ * console's session authenticates them. Each response wraps its payload in "data". See:
6
+ *
7
+ * - smarter.apps.prompt.views.detailviews.prompt_config_view.PromptConfigView: <apiUrl>config/
8
+ * - smarter.apps.llmclient.api.v1.views.base: the LLMClient's prompt api, llmclient.url_llmclient.
9
+ *
10
+ * The contract is versioned (see smarter.apps.prompt.contract). Smarter Chat asks for version 2 with
11
+ * "X-Smarter-Capabilities: chat-contract-v2", and reads version 1 from older platforms, which ignore
12
+ * the header:
13
+ *
14
+ * - version 2: the configuration's LLMClient is "llmclient", and a prompt's response is
15
+ * data: {contract: 2, status, messages, completion}, with "error" beside it if the prompt failed.
16
+ * - version 1: the LLMClient is "chatbot", with "url_chatbot", and a prompt's response is an AWS
17
+ * Lambda style response, whose body is a JSON string of the completion, with Smarter's own messages
18
+ * in body.smarter.messages. A failed prompt's body is {error: {status, message}, response}.
19
+ *
20
+ * Every other error is {error: {errorClass, description, status}}.
21
+ *
22
+ * A prompt can stream its progress, e.g. its tool calls and MCP server requests, as Server-Sent
23
+ * Events: the request accepts text/event-stream, and the response is "progress" events, then a
24
+ * "result" event with the same JSON as a non-streaming response. Servers that don't stream answer
25
+ * with JSON, as before. See smarter.apps.prompt.progress.
26
+ */
27
+ import type { ApiMessage, ChatConfig, ChatCookies, ClientContext, Contract } from "../types";
28
+ /** The capability with which Smarter Chat asks for version 2 of the contract. */
29
+ export declare const CHAT_CONTRACT_V2_CAPABILITY = "chat-contract-v2";
30
+ export declare const CHAT_CONTRACT_V2 = 2;
31
+ export declare class SmarterApiError extends Error {
32
+ status: number;
33
+ constructor(message: string, status: number);
34
+ }
35
+ /** The result of a prompt: the messages to add to the thread, and the error, if it failed. */
36
+ export interface PromptResult {
37
+ messages: ApiMessage[];
38
+ error: string | null;
39
+ }
40
+ /** A step of a prompt that is still running, e.g. a tool call. */
41
+ export interface PromptProgressEvent {
42
+ /** e.g. llm_request, tool_requested, tool_responded, plugin_called, mcp_tool_called */
43
+ type: string;
44
+ /** A short, human-readable description of the step. */
45
+ message: string;
46
+ [key: string]: unknown;
47
+ }
48
+ /** The http status of a response, as errorMessage() reads it. */
49
+ type ResponseStatus = Pick<Response, "status" | "statusText">;
50
+ /** The url of an api endpoint, relative to apiUrl, with the chat session's key. */
51
+ export declare function urlFactory(apiUrl: string, endpoint: string | null, sessionKey: string | null): string;
52
+ /**
53
+ * The request headers. Any custom header must also be in Django's CORS_ALLOW_HEADERS, in
54
+ * smarter.settings.base, for pages on other domains.
55
+ */
56
+ export declare function requestHeadersFactory(cookies: ChatCookies, context: ClientContext): Record<string, string>;
57
+ /** The error message of an api error response, whatever its shape. */
58
+ export declare function errorMessage(json: Record<string, unknown>, response: ResponseStatus): string;
59
+ /**
60
+ * A configuration in version 2 of the contract: as is, or converted from version 1, whose keys are
61
+ * renamed at every depth ("chatbot" for "llmclient", e.g. "url_chatbot" for "url_llmclient"). Null if
62
+ * it has no LLMClient, or no prompt api url.
63
+ */
64
+ export declare function normalizeConfig(data: unknown): ChatConfig | null;
65
+ /**
66
+ * A copy of a version 2 configuration, with the deprecated "chatbot", a read-only alias of its
67
+ * "llmclient", for code written for version 1. The alias is not enumerable, so it is never serialized,
68
+ * e.g. by the Console, which displays the configuration as JSON.
69
+ */
70
+ export declare function withLegacyChatbot(config: Contract.PromptChatApiConfig): ChatConfig;
71
+ /**
72
+ * The LLMClient's configuration. A new chat session's key, and the debug mode, are saved in their
73
+ * cookies, for the next page load.
74
+ */
75
+ export declare function fetchConfig(apiUrl: string, cookies: ChatCookies, context: ClientContext): Promise<ChatConfig>;
76
+ /**
77
+ * Reads a Server-Sent Events stream, and calls onEvent with each event's name and data. Comments
78
+ * (e.g. keepalives) and retry hints are ignored.
79
+ */
80
+ export declare function readEventStream(body: ReadableStream<Uint8Array>, onEvent: (event: string, data: string) => void): Promise<void>;
81
+ /**
82
+ * A "smarter" message that explains a completion that the LLM stopped because it reached the
83
+ * LLMClient's max tokens, i.e. whose finish_reason is "length", or null. A reasoning model can
84
+ * spend all of its tokens reasoning, and then return an empty response, which is otherwise
85
+ * displayed as nothing at all.
86
+ */
87
+ export declare function maxTokensMessage(completion: Record<string, unknown> | null | undefined): ApiMessage | null;
88
+ /**
89
+ * Sends the thread to the LLMClient's prompt api. Resolves to the messages to add to the thread.
90
+ * A failed prompt resolves too, with its error, and with a "smarter_error" message to display.
91
+ *
92
+ * With onProgress, the prompt's progress is requested as Server-Sent Events, and each step is
93
+ * passed to onProgress while the prompt runs.
94
+ */
95
+ export declare function fetchPrompt(config: ChatConfig, messages: ApiMessage[], cookies: ChatCookies, context: ClientContext, onProgress?: (event: PromptProgressEvent) => void): Promise<PromptResult>;
96
+ export {};
@@ -0,0 +1,32 @@
1
+ export declare const CODE_BLOCK_CLASS = "smarter-chat-code";
2
+ export declare const COPY_BUTTON_CLASS = "smarter-chat-code-copy";
3
+ export declare const MERMAID_BLOCK_CLASS = "smarter-chat-mermaid";
4
+ /**
5
+ * The language of a code block, from its fence's info string, e.g. "python" from
6
+ * "```python title=asgi.py", or "" when it has none.
7
+ */
8
+ export declare function codeLanguage(info: string | undefined): string;
9
+ /**
10
+ * A code block's text, without a closing fence that is at the end of its last line rather than on
11
+ * a line of its own, e.g. " )```", which LLMs sometimes write. Markdown does not close the block
12
+ * there, so the block ends with the message, and the fence would otherwise be displayed as code.
13
+ */
14
+ export declare function stripTrailingFence(text: string): string;
15
+ /**
16
+ * Html for a code block's code: highlighted if its language is one that highlight.js knows, by
17
+ * name or alias (e.g. "py", "js", "sh", "yml"), and otherwise escaped, as GitHub does.
18
+ */
19
+ export declare function highlightCode(text: string, language: string): string;
20
+ /**
21
+ * Html for a fenced or indented code block: a header with its language and a copy button, and its
22
+ * highlighted code. A mermaid block is also marked, so that it can be displayed as a diagram. See
23
+ * mermaid.ts.
24
+ */
25
+ export declare function codeBlockHtml(text: string, info?: string): string;
26
+ /**
27
+ * Copies a code block's code to the clipboard when its copy button is clicked, and shows that it
28
+ * did on the button for a moment. Clicks on anything else are ignored.
29
+ *
30
+ * :returns: whether the click was on a copy button.
31
+ */
32
+ export declare function copyCodeBlock(target: EventTarget | null): boolean;
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Cookie management for Smarter Chat: the Django CSRF cookie, which it reads, and the chat
3
+ * session and debug cookies, which it sets for the page's path, so that each LLMClient's
4
+ * workbench has its own chat session.
5
+ */
6
+ import type { CookieMeta } from "../types";
7
+ /**
8
+ * Whether the page's hostname is in a cookie's domain. Django's cookie domain settings may
9
+ * include a port (localhost:9357) or a leading dot (.smarter.sh), and may be empty or "None",
10
+ * which means the page's own domain.
11
+ */
12
+ export declare function inCookieDomain(hostname: string, domain: string | null | undefined): boolean;
13
+ /** The cookie's value: its preset value, else the browser's cookie, else defaultValue. */
14
+ export declare function getCookie(cookie: CookieMeta, defaultValue?: string | null): string | null;
15
+ /** Sets the cookie for the page's path, or deletes it when value is empty. */
16
+ export declare function setCookie(cookie: CookieMeta, value: string | boolean | null | undefined): void;
17
+ export declare function cookieMetaFactory(name: string, expiration: number | null, domain: string | undefined, value?: string | null): CookieMeta;
@@ -0,0 +1,26 @@
1
+ /**
2
+ * The direction and the sender of a chat message.
3
+ *
4
+ * The roles are those of the OpenAI chat completion api, plus Smarter's own: "smarter" messages
5
+ * describe what the Smarter backend did, e.g. which plugins it selected, and "smarter_error"
6
+ * messages describe a failed prompt. See OpenAIMessageKeys in
7
+ * smarter.apps.provider.services.text_completion.const.
8
+ */
9
+ export declare const MessageDirectionEnum: {
10
+ readonly INCOMING: "incoming";
11
+ readonly OUTGOING: "outgoing";
12
+ };
13
+ export type MessageDirection = (typeof MessageDirectionEnum)[keyof typeof MessageDirectionEnum];
14
+ export declare const SenderRoleEnum: {
15
+ readonly SYSTEM: "system";
16
+ readonly ASSISTANT: "assistant";
17
+ readonly USER: "user";
18
+ readonly TOOL: "tool";
19
+ readonly SMARTER: "smarter";
20
+ readonly SMARTER_ERROR: "smarter_error";
21
+ };
22
+ export type SenderRole = (typeof SenderRoleEnum)[keyof typeof SenderRoleEnum];
23
+ /** The roles that the LLM provider accepts. Smarter's own messages are only displayed. */
24
+ export declare const ValidMessageRolesEnum: SenderRole[];
25
+ /** The roles of the backend's messages, which the metadata toggle shows and hides. */
26
+ export declare const MetadataRolesEnum: SenderRole[];
@@ -0,0 +1,42 @@
1
+ /**
2
+ * The layout of the chat and the Console: the width of the chat, which the user changes by dragging
3
+ * the separator between them, whether the Console is visible, and whether its server logs' long
4
+ * lines wrap. They are remembered in the browser's localStorage, which may be unavailable, e.g. in a private window, so they have defaults.
5
+ */
6
+ import { type KeyboardEvent, type PointerEvent, type RefObject, type SetStateAction } from "react";
7
+ /** The chat's width, as a percentage of the component's width. */
8
+ export declare const DEFAULT_CHAT_WIDTH = 33.33;
9
+ export declare const MIN_CHAT_WIDTH = 20;
10
+ export declare const MAX_CHAT_WIDTH = 80;
11
+ /** The change in the chat's width, in percent, for each arrow key press on the separator. */
12
+ export declare const KEYBOARD_STEP = 5;
13
+ export declare const CHAT_WIDTH_STORAGE_KEY = "smarter-chat.chat-width";
14
+ export declare const CONSOLE_VISIBLE_STORAGE_KEY = "smarter-chat.console-visible";
15
+ export declare const LOG_WRAP_STORAGE_KEY = "smarter-chat.log-wrap";
16
+ export declare function clampChatWidth(width: number): number;
17
+ /** Whether the Console is visible. It is, until the user hides it. */
18
+ export declare function useConsoleVisible(): readonly [boolean, (action: SetStateAction<boolean>) => void];
19
+ /** Whether the server logs' long lines wrap. They don't, until the user wraps them: they scroll. */
20
+ export declare function useLogWrap(): readonly [boolean, (action: SetStateAction<boolean>) => void];
21
+ /**
22
+ * The chat's width, and the props of the separator that resizes it. The separator is a focusable
23
+ * "separator", whose value is the chat's width: drag it, or use the arrow, Home and End keys.
24
+ * Double-click it to restore the default width.
25
+ */
26
+ export declare function useChatWidth(containerRef: RefObject<HTMLElement | null>): {
27
+ chatWidth: number;
28
+ separatorProps: {
29
+ role: string;
30
+ tabIndex: number;
31
+ "aria-orientation": "vertical";
32
+ "aria-label": string;
33
+ "aria-valuenow": number;
34
+ "aria-valuemin": number;
35
+ "aria-valuemax": number;
36
+ onPointerDown: (event: PointerEvent<HTMLElement>) => void;
37
+ onPointerMove: (event: PointerEvent<HTMLElement>) => void;
38
+ onPointerUp: (event: PointerEvent<HTMLElement>) => void;
39
+ onDoubleClick: () => void;
40
+ onKeyDown: (event: KeyboardEvent<HTMLElement>) => void;
41
+ };
42
+ };
@@ -0,0 +1,30 @@
1
+ /** A log record. Records that aren't JSON are displayed as their message. */
2
+ export interface LogEvent {
3
+ message: string;
4
+ level?: string;
5
+ levelname?: string;
6
+ timestamp?: number | string;
7
+ logger?: string;
8
+ [key: string]: unknown;
9
+ }
10
+ /** The most records to keep. Older records are dropped. */
11
+ export declare const MAX_LOG_EVENTS = 2000;
12
+ /** The log level of the stream in sandbox mode. Production mode uses the server's log level. */
13
+ export declare const SANDBOX_LOG_LEVEL = "DEBUG";
14
+ /**
15
+ * The log stream's url, for the records at or above the given log level, e.g. "DEBUG". Without a
16
+ * level, the url is unchanged, and the stream sends the records at or above the server's log level.
17
+ */
18
+ export declare function logStreamUrlForLevel(streamUrl: string | null, level?: string | null): string | null;
19
+ /**
20
+ * The log stream's records, and its connection state. Connects only while streamUrl is set.
21
+ *
22
+ * clear() removes the records, e.g. for a new chat session. The records that were logged before
23
+ * then are not displayed again, even when a reconnection replays the history.
24
+ */
25
+ export declare function useLogStream(streamUrl: string | null): {
26
+ logs: LogEvent[];
27
+ connected: boolean;
28
+ error: string | null;
29
+ clear: () => void;
30
+ };
@@ -0,0 +1,18 @@
1
+ import "katex/dist/katex.min.css";
2
+ import type { MarkedExtension } from "marked";
3
+ import "./math.css";
4
+ /**
5
+ * Html for a LaTeX expression, inline or displayed, or for its source if it is not valid LaTeX. A
6
+ * dollar sign, which is not valid in math, e.g. a price in \($1.20\), is a dollar sign.
7
+ */
8
+ export declare function mathHtml(tex: string, displayMode: boolean): string;
9
+ /**
10
+ * The marked extension that tokenizes and renders math. See convertMarkdownToHTML in messages.ts.
11
+ *
12
+ * A display equation that follows a line of text, without a blank line between them, would be read
13
+ * as part of that paragraph, and a line of its own that is "=" or "-", e.g. between the two sides of
14
+ * an equation, would make the paragraph a setext heading, which splits the equation. So a setext
15
+ * heading that contains a display equation is not a heading: the paragraph then ends where the
16
+ * equation begins, and blockMath tokenizes it.
17
+ */
18
+ export declare const mathExtension: MarkedExtension;
@@ -0,0 +1,27 @@
1
+ import "./mermaid.css";
2
+ export declare const DIAGRAM_CLASS = "smarter-chat-mermaid-diagram";
3
+ export declare const TOGGLE_BUTTON_CLASS = "smarter-chat-mermaid-toggle";
4
+ /** A diagram's svg, without anything that could run a script, but with its own styles. */
5
+ export declare function sanitizeSvg(svg: string): string;
6
+ /**
7
+ * A diagram's source, with the ">" of its quoted labels written as mermaid's "#gt;". With svg text
8
+ * labels, mermaid drops ">" from quoted flowchart labels, e.g. "a >= b > 0" is drawn as "a = b 0".
9
+ * Other diagrams display "#gt;" as ">" too.
10
+ */
11
+ export declare function escapeQuotedLabels(source: string): string;
12
+ /** A diagram's sanitized svg, rendered once for each source, or null if it can't be rendered. */
13
+ export declare function diagramSvg(source: string): Promise<string | null>;
14
+ /**
15
+ * Displays the mermaid code blocks within root as their diagrams. Blocks that are already
16
+ * displayed, or are being rendered, are left as they are. A block that leaves the page while its
17
+ * diagram renders, e.g. because its message was displayed again, is skipped: its new block finds
18
+ * the diagram in the cache.
19
+ */
20
+ export declare function renderMermaidDiagrams(root: ParentNode | null | undefined): Promise<void>;
21
+ /**
22
+ * Shows a diagram's code instead of the diagram, or the diagram again, when its button is clicked.
23
+ * Clicks on anything else are ignored.
24
+ *
25
+ * :returns: whether the click was on a diagram's button.
26
+ */
27
+ export declare function toggleMermaidDiagram(target: EventTarget | null): boolean;
@@ -0,0 +1,52 @@
1
+ import type { ApiMessage, ChatMessage } from "../types";
2
+ import { type MessageDirection } from "./enums";
3
+ export declare function escapeHtml(text: string): string;
4
+ /**
5
+ * Html for a message's text: escaped, with markdown images and links as html.
6
+ *
7
+ * - ``![alt](url)`` is an image, which opens at full size in a new tab, unless it's a data url,
8
+ * which browsers don't open.
9
+ * - ``[![alt](url)](href)`` is an image that links to href.
10
+ * - ``[text](href)`` is a link, which opens in a new tab.
11
+ *
12
+ * Urls are http(s) or relative to the page. Images may also be base64 png, jpeg, gif or webp data
13
+ * urls. Anything else, e.g. a javascript: url, stays as text.
14
+ */
15
+ export declare function convertMarkdownLinksToHTML(text: string): string;
16
+ /**
17
+ * Html for a markdown message, e.g. an LLM's response: GitHub flavored markdown, i.e. headings,
18
+ * emphasis, lists, tables, block quotes, code, links and images, and math. Line breaks are kept. Code
19
+ * blocks are syntax highlighted, as GitHub's are. See code.ts. Math, in LaTeX, is typeset by KaTeX.
20
+ * See math.ts.
21
+ *
22
+ * Raw html is displayed as text, and links and images follow the rules of
23
+ * convertMarkdownLinksToHTML. A message that is a single paragraph is not wrapped in one,
24
+ * so that its chat bubble stays as compact as the text.
25
+ */
26
+ export declare function convertMarkdownToHTML(text: string): string;
27
+ /** The direction of a message from the given sender. */
28
+ export declare function directionOf(sender: string): MessageDirection;
29
+ /** Html for a message's text: the user's as they typed it, and the others as markdown. */
30
+ export declare function messageHtml(content: string, sender: string): string;
31
+ /**
32
+ * A new chat message. Messages without text, e.g. an assistant's tool calls, stay in the thread,
33
+ * so that they are sent back to the api, but are not displayed.
34
+ */
35
+ export declare function messageFactory(content: ApiMessage["content"], sender: string, originalMessage?: ApiMessage, direction?: MessageDirection): ChatMessage;
36
+ /** The thread of a chat session, from the messages that the backend saved. */
37
+ export declare function chatRestoreFromBackend(chatHistory: ApiMessage[] | null | undefined): ChatMessage[];
38
+ /** Example prompts, which help the user to get started, as a markdown list. */
39
+ export declare function examplePrompts(prompts: string[] | null | undefined): string;
40
+ /** The thread of a new chat session: the system role, the welcome message, and example prompts. */
41
+ export declare function chatIntro(welcomeMessage: string, systemRole: string, prompts: string[] | null | undefined): ChatMessage[];
42
+ /** The thread of a chat session: its saved history, or the introduction to a new one. */
43
+ export declare function chatInit(welcomeMessage: string, systemRole: string, prompts: string[] | null | undefined, chatHistory: ApiMessage[] | null | undefined): ChatMessage[];
44
+ /**
45
+ * The thread as the api's messages: those the LLM accepts, without Smarter's own. The api's
46
+ * original messages keep their other fields, e.g. an assistant's tool_calls.
47
+ */
48
+ export declare function chatMessages2RequestMessages(messages: ChatMessage[]): ApiMessage[];
49
+ /** Shows or hides the backend's messages (smarter, system and tool), and always shows the rest. */
50
+ export declare function toggleMetadataMessages(messages: ChatMessage[], show: boolean, metadataRoles: string[]): ChatMessage[];
51
+ /** Removes html tags, which pasting text into the message input tends to add. */
52
+ export declare function sanitizeInput(text: string): string;
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Types for Smarter Chat: its props, its messages, and the data that the Smarter api returns.
3
+ *
4
+ * The api's types are generated from the contract's JSON Schema (contract/chat-contract.schema.json,
5
+ * which the Smarter backend generates from smarter.apps.prompt.contract.models) into contract.gen.ts.
6
+ * They describe the fields that Smarter Chat reads. The api returns more, which the Console displays
7
+ * as is.
8
+ */
9
+ import type * as Contract from "./contract.gen";
10
+ import type { MessageDirection, SenderRole } from "./lib/enums";
11
+ export type { Contract };
12
+ /** A message in the format of the OpenAI chat completion api, as the backend stores and returns them. */
13
+ export type ApiMessage = Contract.PromptChatApiMessage;
14
+ /** A message in the chat thread. */
15
+ export interface ChatMessage {
16
+ /** The message's text, as html, for display. */
17
+ message: string;
18
+ /** The message's text, as sent to the api. */
19
+ content: ApiMessage["content"];
20
+ direction: MessageDirection;
21
+ sender: SenderRole | string;
22
+ sentTime: string;
23
+ /** false for messages that are part of the thread, but never displayed, e.g. an assistant's tool calls. */
24
+ display: boolean;
25
+ /** The api's original message, whose other fields (e.g. tool_calls) are sent back to the api. */
26
+ originalMessage?: ApiMessage;
27
+ }
28
+ /** The LLMClient, in the configuration. */
29
+ export type LLMClientConfig = Contract.PromptChatApiLLMClient;
30
+ /** @deprecated Use LLMClientConfig. Version 2 of the contract calls the LLMClient "llmclient", not "chatbot". */
31
+ export type ChatbotConfig = LLMClientConfig;
32
+ /** The chat session's history. Only chat_history is returned to clients that can't read the LLMClient. */
33
+ export type ChatHistory = Contract.PromptChatApiHistory;
34
+ /** The LLMClient's state. */
35
+ export type ChatMetaData = Contract.PromptChatApiMetaData;
36
+ /**
37
+ * The LLMClient's configuration, from its config api, in version 2 of the contract. A version 1
38
+ * configuration, from an older Smarter platform, is converted to it. See lib/api.ts.
39
+ */
40
+ export type ChatConfig = Contract.PromptChatApiConfig & {
41
+ /**
42
+ * @deprecated Use llmclient. Version 2 of the contract calls the LLMClient "llmclient". This is a
43
+ * read-only alias of it, for code written for version 1, which is not enumerable, so it is never
44
+ * serialized or displayed.
45
+ */
46
+ readonly chatbot: LLMClientConfig;
47
+ };
48
+ /** A cookie that Smarter Chat reads, and possibly sets. */
49
+ export interface CookieMeta {
50
+ name: string;
51
+ /** milliseconds, for cookies that Smarter Chat sets. */
52
+ expiration: number | null;
53
+ /** The domain that the page's hostname must be in for the cookie to be read. */
54
+ domain: string;
55
+ /** A value to use instead of the cookie's. */
56
+ value: string | null;
57
+ }
58
+ export interface ChatCookies {
59
+ csrfCookie: CookieMeta;
60
+ sessionCookie: CookieMeta;
61
+ debugCookie: CookieMeta;
62
+ }
63
+ /** Who is calling the api, sent as the X-Smarter-* request headers. */
64
+ export interface ClientContext {
65
+ smarterClient: string;
66
+ smarterClientVersion: string;
67
+ smarterRequestId?: string;
68
+ /** An optional Smarter api key, sent as "Authorization: Token <apiKey>". */
69
+ apiKey?: string | null;
70
+ }
71
+ export interface SmarterChatProps {
72
+ /** The url of the LLMClient's api. example: https://smarter.3141-5926-5359.beta.api.smarter.sh/ */
73
+ apiUrl: string;
74
+ /** An optional Smarter api key, for LLMClients that require authentication. */
75
+ apiKey?: string | null;
76
+ /** Show the button that shows and hides the thread's metadata messages. */
77
+ toggleMetadata?: boolean;
78
+ /** The name of Django's CSRF cookie. */
79
+ csrfCookieName?: string;
80
+ /** Django's CSRF token, when the page cannot read the CSRF cookie. */
81
+ csrftoken?: string | null;
82
+ /** The name of the cookie in which Smarter Chat saves the debug mode. */
83
+ debugCookieName?: string;
84
+ debugCookieExpiration?: number;
85
+ /** Log to the browser console. */
86
+ debugMode?: boolean;
87
+ /** The name of the cookie in which Smarter Chat saves the chat session's key. */
88
+ sessionCookieName?: string;
89
+ sessionCookieExpiration?: number;
90
+ /** @deprecated Not used. Django's session cookie is sent with each request, as is. */
91
+ authSessionCookieName?: string;
92
+ /** Show the Console, which displays the chat's configuration and history. */
93
+ showConsole?: boolean;
94
+ /** The domain whose cookies Smarter Chat reads. example: platform.smarter.sh */
95
+ cookieDomain?: string;
96
+ /** A unique id of the page request, sent as the X-Smarter-RequestId header. */
97
+ smarterRequestId?: string;
98
+ /**
99
+ * The url of the user's server log stream (Server-Sent Events), which the Console displays in
100
+ * its "Server Logs" tab. Without it, the Console has no such tab.
101
+ */
102
+ logStreamUrl?: string | null;
103
+ /**
104
+ * Display the progress of a running prompt, e.g. its tool calls, which the prompt api streams as
105
+ * Server-Sent Events. Servers that don't stream answer as before.
106
+ */
107
+ streamProgress?: boolean;
108
+ }