@smarter.sh/ui-chat 0.7.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.
@@ -8,5 +8,6 @@ export { default as Console } from "./components/Console";
8
8
  export { MenuItems } from "./components/Console/enums";
9
9
  export { MessageDirectionEnum, SenderRoleEnum, ValidMessageRolesEnum } from "./lib/enums";
10
10
  export { projectVersion as version } from "./const";
11
+ export { CHAT_CONTRACT_V2_CAPABILITY, normalizeConfig } from "./lib/api";
11
12
  export type { PromptProgressEvent } from "./lib/api";
12
- export type { ApiMessage, ChatConfig, ChatHistory, ChatMessage, ChatMetaData, ChatbotConfig, SmarterChatProps, } from "./types";
13
+ export type { ApiMessage, ChatConfig, ChatHistory, ChatMessage, ChatMetaData, ChatbotConfig, Contract, LLMClientConfig, SmarterChatProps, } from "./types";
@@ -5,18 +5,29 @@
5
5
  * console's session authenticates them. Each response wraps its payload in "data". See:
6
6
  *
7
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, chatbot.url_chatbot. Its
9
- * payload is an AWS Lambda style response, whose body is a JSON string of the completion, with
10
- * Smarter's own messages in body.smarter.messages. A failed prompt has the LLM provider's status,
11
- * and its body is {error: {status, message}, response: <the completion>}, whose messages include a
12
- * "smarter_error" message.
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}}.
13
21
  *
14
22
  * A prompt can stream its progress, e.g. its tool calls and MCP server requests, as Server-Sent
15
23
  * Events: the request accepts text/event-stream, and the response is "progress" events, then a
16
24
  * "result" event with the same JSON as a non-streaming response. Servers that don't stream answer
17
25
  * with JSON, as before. See smarter.apps.prompt.progress.
18
26
  */
19
- import type { ApiMessage, ChatConfig, ChatCookies, ClientContext } from "../types";
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;
20
31
  export declare class SmarterApiError extends Error {
21
32
  status: number;
22
33
  constructor(message: string, status: number);
@@ -45,6 +56,18 @@ export declare function urlFactory(apiUrl: string, endpoint: string | null, sess
45
56
  export declare function requestHeadersFactory(cookies: ChatCookies, context: ClientContext): Record<string, string>;
46
57
  /** The error message of an api error response, whatever its shape. */
47
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;
48
71
  /**
49
72
  * The LLMClient's configuration. A new chat session's key, and the debug mode, are saved in their
50
73
  * cookies, for the next page load.
@@ -32,7 +32,7 @@ export declare function messageHtml(content: string, sender: string): string;
32
32
  * A new chat message. Messages without text, e.g. an assistant's tool calls, stay in the thread,
33
33
  * so that they are sent back to the api, but are not displayed.
34
34
  */
35
- export declare function messageFactory(content: string | null | undefined, sender: string, originalMessage?: ApiMessage, direction?: MessageDirection): ChatMessage;
35
+ export declare function messageFactory(content: ApiMessage["content"], sender: string, originalMessage?: ApiMessage, direction?: MessageDirection): ChatMessage;
36
36
  /** The thread of a chat session, from the messages that the backend saved. */
37
37
  export declare function chatRestoreFromBackend(chatHistory: ApiMessage[] | null | undefined): ChatMessage[];
38
38
  /** Example prompts, which help the user to get started, as a markdown list. */
@@ -1,23 +1,22 @@
1
1
  /**
2
2
  * Types for Smarter Chat: its props, its messages, and the data that the Smarter api returns.
3
3
  *
4
- * The api's types describe the fields that Smarter Chat reads. The api returns more, which the
5
- * Console displays as is. See smarter.apps.prompt.views.detailviews.prompt_config_view.PromptConfigView,
6
- * which returns the configuration with its legacy keys ("chatbot" for "llmclient").
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.
7
8
  */
9
+ import type * as Contract from "./contract.gen";
8
10
  import type { MessageDirection, SenderRole } from "./lib/enums";
11
+ export type { Contract };
9
12
  /** A message in the format of the OpenAI chat completion api, as the backend stores and returns them. */
10
- export interface ApiMessage {
11
- role: string;
12
- content: string | null;
13
- [key: string]: unknown;
14
- }
13
+ export type ApiMessage = Contract.PromptChatApiMessage;
15
14
  /** A message in the chat thread. */
16
15
  export interface ChatMessage {
17
16
  /** The message's text, as html, for display. */
18
17
  message: string;
19
18
  /** The message's text, as sent to the api. */
20
- content: string | null;
19
+ content: ApiMessage["content"];
21
20
  direction: MessageDirection;
22
21
  sender: SenderRole | string;
23
22
  sentTime: string;
@@ -26,60 +25,26 @@ export interface ChatMessage {
26
25
  /** The api's original message, whose other fields (e.g. tool_calls) are sent back to the api. */
27
26
  originalMessage?: ApiMessage;
28
27
  }
29
- /** The LLMClient, which the config api calls "chatbot". */
30
- export interface ChatbotConfig {
31
- id: number;
32
- name: string;
33
- version?: string;
34
- provider: string;
35
- default_model: string;
36
- default_system_role: string;
37
- app_name: string;
38
- app_assistant: string;
39
- app_welcome_message: string;
40
- app_example_prompts: string[];
41
- app_placeholder: string;
42
- app_info_url?: string | null;
43
- app_file_attachment: boolean;
44
- /** The url of the LLMClient's prompt api. */
45
- url_chatbot: string;
46
- [key: string]: unknown;
47
- }
48
- export interface ChatHistory {
49
- chat_history?: ApiMessage[];
50
- prompt_tool_call_history?: unknown[];
51
- prompt_plugin_usage_history?: unknown[];
52
- llmclient_request_history?: unknown[];
53
- plugin_selector_history?: unknown[];
54
- /** Legacy names of prompt_tool_call_history, prompt_plugin_usage_history and llmclient_request_history. */
55
- chat_tool_call_history?: unknown[];
56
- chat_plugin_usage_history?: unknown[];
57
- chatbot_request_history?: unknown[];
58
- [key: string]: unknown;
59
- }
60
- export interface ChatMetaData {
61
- is_valid?: boolean;
62
- ready?: boolean;
63
- is_deployed?: boolean;
64
- [key: string]: unknown;
65
- }
66
- /** The LLMClient's configuration, from its config api. */
67
- export interface ChatConfig {
68
- session_key: string;
69
- sandbox_mode: boolean;
70
- debug_mode: boolean;
71
- chatbot: ChatbotConfig;
72
- history: ChatHistory;
73
- meta_data: ChatMetaData;
74
- plugins: {
75
- meta_data: {
76
- total_plugins: number;
77
- plugins_returned: number;
78
- };
79
- plugins: unknown[];
80
- };
81
- [key: string]: unknown;
82
- }
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
+ };
83
48
  /** A cookie that Smarter Chat reads, and possibly sets. */
84
49
  export interface CookieMeta {
85
50
  name: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smarter.sh/ui-chat",
3
- "version": "0.7.0",
3
+ "version": "0.7.1",
4
4
  "description": "chatbot React.js component for the https://smarter.sh declarative, plugin-based AI resource management platform.",
5
5
  "homepage": "https://smarter.sh",
6
6
  "type": "module",
@@ -53,6 +53,7 @@
53
53
  "dev": "NODE_ENV=dev && vite",
54
54
  "build": "tsc -b && vite build",
55
55
  "build:lib": "vite build --mode lib && tsc -p tsconfig.lib.json",
56
+ "contract:types": "node scripts/contract-types.mjs",
56
57
  "lint": "eslint --max-warnings=0 .",
57
58
  "preview": "vite preview",
58
59
  "storybook": "storybook dev -p 6006",
@@ -94,6 +95,7 @@
94
95
  "@vitejs/plugin-react": "^6.1.1",
95
96
  "@vitest/coverage-v8": "^5.0.3",
96
97
  "@vitest/eslint-plugin": "^1.6.27",
98
+ "ajv": "^8.20.0",
97
99
  "bootstrap": "^5.3.8",
98
100
  "bootstrap-icons": "^1.13.1",
99
101
  "eslint": "^10.11.0",
@@ -106,6 +108,7 @@
106
108
  "eslint-plugin-testing-library": "^7.16.2",
107
109
  "globals": "^17.13.0",
108
110
  "jsdom": "^30.1.2",
111
+ "json-schema-to-typescript": "^15.0.4",
109
112
  "msw": "^2.15.0",
110
113
  "prettier": "^3.9.9",
111
114
  "react": "^19.3.0",