@4djs/assistant 0.0.1 → 0.1.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.
- package/README.md +151 -68
- package/dist/core/chat-activity.d.ts +2 -1
- package/dist/core/chat-activity.d.ts.map +1 -1
- package/dist/core/chat-commands.d.ts +6 -4
- package/dist/core/chat-commands.d.ts.map +1 -1
- package/dist/core/chat-history.d.ts.map +1 -1
- package/dist/core/chat-reply-suggestions-parse.d.ts.map +1 -1
- package/dist/core/create-assistant-store.d.ts.map +1 -1
- package/dist/core/fetch-suggested-prompts.d.ts.map +1 -1
- package/dist/core/index.d.ts +2 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +175 -26
- package/dist/core/interactive-tools/choices.d.ts.map +1 -1
- package/dist/core/interactive-tools/confirmation.d.ts.map +1 -1
- package/dist/core/interactive-tools/execute.d.ts.map +1 -1
- package/dist/core/interactive-tools/index.d.ts.map +1 -1
- package/dist/core/interactive-tools/suggestions.d.ts.map +1 -1
- package/dist/core/interactive-tools/waiters.d.ts.map +1 -1
- package/dist/core/llm-chat.d.ts.map +1 -1
- package/dist/core/llm-config.d.ts.map +1 -1
- package/dist/core/llm-models.d.ts.map +1 -1
- package/dist/core/llm-provider.d.ts.map +1 -1
- package/dist/core/llm-settings-storage.d.ts.map +1 -1
- package/dist/core/llm-sse.d.ts.map +1 -1
- package/dist/core/llm-types.d.ts.map +1 -1
- package/dist/core/types.d.ts.map +1 -1
- package/dist/index.js +387 -187
- package/dist/labels.d.ts +136 -0
- package/dist/labels.d.ts.map +1 -0
- package/dist/react/Assistant.d.ts.map +1 -1
- package/dist/react/components/HighlightedJsonCode.d.ts.map +1 -1
- package/dist/react/components/MarkdownContent.d.ts.map +1 -1
- package/dist/react/components/MarkdownEditor.d.ts.map +1 -1
- package/dist/react/components/MermaidDiagram.d.ts.map +1 -1
- package/dist/react/components/ModelSelector.d.ts.map +1 -1
- package/dist/react/components/chat/AssistantErrorCallout.d.ts +3 -1
- package/dist/react/components/chat/AssistantErrorCallout.d.ts.map +1 -1
- package/dist/react/components/chat/ChatActivity.d.ts.map +1 -1
- package/dist/react/components/chat/ChatComposer.d.ts +3 -1
- package/dist/react/components/chat/ChatComposer.d.ts.map +1 -1
- package/dist/react/components/chat/ChatEmptyState.d.ts.map +1 -1
- package/dist/react/components/chat/ChatInteractivePrompt/choices-prompt.d.ts.map +1 -1
- package/dist/react/components/chat/ChatInteractivePrompt/confirmation-prompt.d.ts.map +1 -1
- package/dist/react/components/chat/ChatInteractivePrompt/index.d.ts.map +1 -1
- package/dist/react/components/chat/ChatInteractivePrompt/shell.d.ts.map +1 -1
- package/dist/react/components/chat/ChatMessage.d.ts.map +1 -1
- package/dist/react/components/chat/ChatMessageScroll.d.ts.map +1 -1
- package/dist/react/components/chat/ChatReplySuggestions.d.ts.map +1 -1
- package/dist/react/components/chat/ComposerCommandMenu.d.ts.map +1 -1
- package/dist/react/components/chat/LlmSettingsStrip.d.ts.map +1 -1
- package/dist/react/components/chat/LlmSetupPrompt.d.ts.map +1 -1
- package/dist/react/components/chat/LlmUnavailableBanner.d.ts.map +1 -1
- package/dist/react/components/chat/SuggestedPromptsList.d.ts.map +1 -1
- package/dist/react/components/chat/SuggestedPromptsStrip.d.ts.map +1 -1
- package/dist/react/components/chat/SystemPromptField.d.ts.map +1 -1
- package/dist/react/components/highlighted-code.d.ts.map +1 -1
- package/dist/react/context.d.ts +2 -0
- package/dist/react/context.d.ts.map +1 -1
- package/dist/react/hooks/use-composer-commands.d.ts +3 -1
- package/dist/react/hooks/use-composer-commands.d.ts.map +1 -1
- package/dist/react/hooks/use-suggested-prompts.d.ts +1 -0
- package/dist/react/hooks/use-suggested-prompts.d.ts.map +1 -1
- package/dist/react/index.d.ts +3 -1
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/lib/parse-assistant-error.d.ts +2 -1
- package/dist/react/lib/parse-assistant-error.d.ts.map +1 -1
- package/dist/react/lib/prompt-icons.d.ts.map +1 -1
- package/dist/react/types.d.ts +4 -0
- package/dist/react/types.d.ts.map +1 -1
- package/dist/react/utils/cn.d.ts.map +1 -1
- package/dist/styles.css +1806 -1806
- package/package.json +50 -50
package/README.md
CHANGED
|
@@ -1,17 +1,13 @@
|
|
|
1
|
-
# @
|
|
1
|
+
# @4djs/assistant
|
|
2
2
|
|
|
3
|
-
Embeddable React chat assistant with LLM tool-calling, streaming, markdown rendering, and
|
|
3
|
+
Embeddable React chat assistant with LLM tool-calling, streaming, markdown rendering, and an in-app LLM settings panel. Connect any OpenAI-compatible provider — cloud APIs or a local server such as Ollama or LM Studio.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
"dependencies": {
|
|
12
|
-
"@4d/assistant": "workspace:*"
|
|
13
|
-
}
|
|
14
|
-
}
|
|
7
|
+
```bash
|
|
8
|
+
npm install @4djs/assistant
|
|
9
|
+
# or
|
|
10
|
+
bun add @4djs/assistant
|
|
15
11
|
```
|
|
16
12
|
|
|
17
13
|
Peer dependencies: `react` and `react-dom` (^19).
|
|
@@ -19,7 +15,7 @@ Peer dependencies: `react` and `react-dom` (^19).
|
|
|
19
15
|
Import styles once in your app entry (required for the UI):
|
|
20
16
|
|
|
21
17
|
```ts
|
|
22
|
-
import "@
|
|
18
|
+
import "@4djs/assistant/styles.css";
|
|
23
19
|
```
|
|
24
20
|
|
|
25
21
|
The stylesheet uses CSS variables from your host app (`--brand`, `--surface-panel`, `--text-heading`, etc.). Define those tokens in your global CSS so the assistant matches your design system.
|
|
@@ -29,15 +25,15 @@ The stylesheet uses CSS variables from your host app (`--brand`, `--surface-pane
|
|
|
29
25
|
The simplest integration is `AssistantRoot`, which wires the provider, store bootstrap, and default panel UI:
|
|
30
26
|
|
|
31
27
|
```tsx
|
|
32
|
-
import { AssistantRoot, type AssistantConfig } from "@
|
|
28
|
+
import { AssistantRoot, type AssistantConfig } from "@4djs/assistant";
|
|
33
29
|
|
|
34
30
|
const config: AssistantConfig = {
|
|
35
31
|
llm: {
|
|
36
|
-
enabled:
|
|
37
|
-
baseUrl: import.meta.env.
|
|
38
|
-
apiKey: import.meta.env.
|
|
39
|
-
model: import.meta.env.
|
|
40
|
-
systemPrompt: "You are a helpful assistant
|
|
32
|
+
enabled: true,
|
|
33
|
+
baseUrl: import.meta.env.VITE_LLM_BASE_URL ?? "https://api.openai.com/v1",
|
|
34
|
+
apiKey: import.meta.env.VITE_LLM_KEY ?? null,
|
|
35
|
+
model: import.meta.env.VITE_LLM_MODEL ?? "gpt-4o-mini",
|
|
36
|
+
systemPrompt: "You are a helpful assistant with access to tools.",
|
|
41
37
|
},
|
|
42
38
|
storageKeys: {
|
|
43
39
|
history: "my-app-chat-history",
|
|
@@ -47,8 +43,8 @@ const config: AssistantConfig = {
|
|
|
47
43
|
id: "welcome",
|
|
48
44
|
role: "assistant",
|
|
49
45
|
content: llmEnabled
|
|
50
|
-
? `Hello! Using **${model ?? "LLM"}
|
|
51
|
-
: "Hello!
|
|
46
|
+
? `Hello! Using **${model ?? "LLM"}**. Ask me anything.`
|
|
47
|
+
: "Hello! Connect an LLM in **LLM settings** to start chatting.",
|
|
52
48
|
timestamp: Date.now(),
|
|
53
49
|
}),
|
|
54
50
|
listTools: async () => myTools,
|
|
@@ -60,7 +56,7 @@ export function MyAssistant() {
|
|
|
60
56
|
}
|
|
61
57
|
```
|
|
62
58
|
|
|
63
|
-
|
|
59
|
+
When no LLM is configured, chat input is disabled and the UI prompts users to open **LLM settings**. Settings and clear-chat remain available without a provider.
|
|
64
60
|
|
|
65
61
|
## Configuration
|
|
66
62
|
|
|
@@ -80,10 +76,10 @@ See [`apps/web/src/assistant/config.ts`](../../apps/web/src/assistant/config.ts)
|
|
|
80
76
|
| --- | --- |
|
|
81
77
|
| `llm` | OpenAI-compatible provider settings (see below). |
|
|
82
78
|
| `storageKeys` | `localStorage` keys for chat history and LLM settings (including selected model). |
|
|
83
|
-
| `fallbackHandler` | Called when LLM is disabled. Return an `AssistantMessage` or `null`. |
|
|
84
79
|
| `onToolInvoked` | Side-effect hook after each tool completes (e.g. refresh app state). |
|
|
85
80
|
| `fetchSuggestedPrompts` | Async hook to generate contextual starter prompts via LLM. |
|
|
86
81
|
| `autoLoadLlmStatus` | Fetch LLM config on mount (default: `true`). |
|
|
82
|
+
| `labels` | Partial UI copy overrides for translation or branding (see below). |
|
|
87
83
|
|
|
88
84
|
### UI options
|
|
89
85
|
|
|
@@ -91,9 +87,9 @@ See [`apps/web/src/assistant/config.ts`](../../apps/web/src/assistant/config.ts)
|
|
|
91
87
|
{
|
|
92
88
|
header: {
|
|
93
89
|
title: "Assistant",
|
|
94
|
-
subtitle: "Query and explore your
|
|
95
|
-
icon: Sparkles,
|
|
96
|
-
showClearButton: true,
|
|
90
|
+
subtitle: "Query and explore your data",
|
|
91
|
+
icon: Sparkles, // lucide-react icon
|
|
92
|
+
showClearButton: true, // footer toolbar (default: true)
|
|
97
93
|
showSuggestionsButton: true, // footer toolbar when fetchSuggestedPrompts is set
|
|
98
94
|
},
|
|
99
95
|
emptyState: {
|
|
@@ -108,13 +104,113 @@ See [`apps/web/src/assistant/config.ts`](../../apps/web/src/assistant/config.ts)
|
|
|
108
104
|
composerPlaceholder: "Ask the assistant…",
|
|
109
105
|
showModelSelector: true,
|
|
110
106
|
maxWidth: "56rem",
|
|
111
|
-
className: "panel",
|
|
107
|
+
className: "panel", // extra class on the root panel
|
|
112
108
|
},
|
|
113
109
|
}
|
|
114
110
|
```
|
|
115
111
|
|
|
116
112
|
Per-instance overrides are supported via `Assistant` / `AssistantRoot` props: `header`, `emptyState`, `ui`.
|
|
117
113
|
|
|
114
|
+
### Labels and i18n
|
|
115
|
+
|
|
116
|
+
All built-in UI strings (buttons, placeholders, error titles, trace labels, aria text, etc.) live in a flat dictionary keyed by dot notation, e.g. `composer.placeholder`, `commands.clear.description`, `errors.network.title`.
|
|
117
|
+
|
|
118
|
+
Pass partial overrides on `AssistantConfig.labels`. Only the keys you set are replaced; everything else keeps the English default:
|
|
119
|
+
|
|
120
|
+
```ts
|
|
121
|
+
import {
|
|
122
|
+
AssistantRoot,
|
|
123
|
+
DEFAULT_ASSISTANT_LABELS,
|
|
124
|
+
type AssistantConfig,
|
|
125
|
+
} from "@4djs/assistant";
|
|
126
|
+
|
|
127
|
+
const config: AssistantConfig = {
|
|
128
|
+
// …store hooks
|
|
129
|
+
labels: {
|
|
130
|
+
"header.title": "Assistant",
|
|
131
|
+
"composer.placeholder": "Posez une question…",
|
|
132
|
+
"composer.placeholderDisabled":
|
|
133
|
+
"LLM non configuré — le chat est désactivé",
|
|
134
|
+
"common.save": "Enregistrer",
|
|
135
|
+
"common.cancel": "Annuler",
|
|
136
|
+
"llmSettings.title": "Paramètres LLM",
|
|
137
|
+
"errors.network.title": "Connexion perdue",
|
|
138
|
+
"commands.clear.description": "Effacer la conversation",
|
|
139
|
+
},
|
|
140
|
+
};
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
For a full locale file, spread it in:
|
|
144
|
+
|
|
145
|
+
```ts
|
|
146
|
+
import { frLabels } from "./locales/fr";
|
|
147
|
+
|
|
148
|
+
labels: { ...frLabels, "header.title": "Mon assistant" },
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Some keys support placeholders — use `{name}` or `{model}` in the string; the package substitutes them at runtime:
|
|
152
|
+
|
|
153
|
+
```ts
|
|
154
|
+
labels: {
|
|
155
|
+
"activity.steps.running": "Exécution de {name}…",
|
|
156
|
+
"llmSettings.connected": "Connecté · {model}",
|
|
157
|
+
"commands.unknown": "Commande inconnue : /{name}",
|
|
158
|
+
},
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Use `formatLabel` from `@4djs/assistant` (or `@4djs/assistant/core`) if you need the same substitution in host code.
|
|
162
|
+
|
|
163
|
+
#### Key groups
|
|
164
|
+
|
|
165
|
+
| Prefix | Examples |
|
|
166
|
+
| --- | --- |
|
|
167
|
+
| `common.*` | `save`, `cancel`, `loading`, `tryAgain` |
|
|
168
|
+
| `composer.*` | `placeholder`, `send`, `stop`, `hint` |
|
|
169
|
+
| `llmSettings.*` | Form labels, placeholders, `connected` |
|
|
170
|
+
| `llmSetup.*` | “Connect an LLM” banner copy |
|
|
171
|
+
| `suggestions.*` / `emptyState.*` | Prompt strips and welcome CTA |
|
|
172
|
+
| `activity.*` | Trace panel and tool step labels |
|
|
173
|
+
| `interactive.*` | Confirmation / choice prompts |
|
|
174
|
+
| `errors.*` | Parsed error titles and hints |
|
|
175
|
+
| `commands.*` | `/clear` description and errors |
|
|
176
|
+
|
|
177
|
+
The full list of keys is `ASSISTANT_LABEL_KEYS`, or inspect `DEFAULT_ASSISTANT_LABELS`.
|
|
178
|
+
|
|
179
|
+
#### Legacy shortcuts
|
|
180
|
+
|
|
181
|
+
These older options still work and are merged into labels automatically:
|
|
182
|
+
|
|
183
|
+
- `header.title` → `labels["header.title"]`
|
|
184
|
+
- `ui.composerPlaceholder` → `labels["composer.placeholder"]`
|
|
185
|
+
|
|
186
|
+
Prefer `labels` for new work so all copy stays in one place.
|
|
187
|
+
|
|
188
|
+
#### Custom components
|
|
189
|
+
|
|
190
|
+
Inside `AssistantProvider`, read the resolved dictionary with `useAssistantLabels()`:
|
|
191
|
+
|
|
192
|
+
```tsx
|
|
193
|
+
import { useAssistantLabels } from "@4djs/assistant";
|
|
194
|
+
|
|
195
|
+
function MyPanel() {
|
|
196
|
+
const labels = useAssistantLabels();
|
|
197
|
+
return <p>{labels["common.loading"]}</p>;
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Outside the provider, components fall back to `DEFAULT_ASSISTANT_LABELS`.
|
|
202
|
+
|
|
203
|
+
Headless helpers (also exported from `@4djs/assistant/core`):
|
|
204
|
+
|
|
205
|
+
| Export | Use |
|
|
206
|
+
| --- | --- |
|
|
207
|
+
| `DEFAULT_ASSISTANT_LABELS` | English defaults |
|
|
208
|
+
| `ASSISTANT_LABEL_KEYS` | All valid keys |
|
|
209
|
+
| `resolveAssistantLabels(overrides?)` | Merge overrides onto defaults |
|
|
210
|
+
| `formatLabel(template, values)` | Replace `{placeholders}` |
|
|
211
|
+
|
|
212
|
+
**Not covered by `labels`:** `welcomeMessage` content, `emptyState.title` / `description`, and static or dynamic `suggestedPrompts` (`label`, `hint`, `prompt`) — those remain app-defined on `AssistantConfig`.
|
|
213
|
+
|
|
118
214
|
## LLM provider
|
|
119
215
|
|
|
120
216
|
The assistant calls an **OpenAI-compatible** chat completions API directly from the browser (or your host runtime). No proxy `/api/chat` routes are required.
|
|
@@ -122,12 +218,12 @@ The assistant calls an **OpenAI-compatible** chat completions API directly from
|
|
|
122
218
|
Pass `llm` on `AssistantConfig`:
|
|
123
219
|
|
|
124
220
|
```ts
|
|
125
|
-
import type { AssistantLlmSettings } from "@
|
|
221
|
+
import type { AssistantLlmSettings } from "@4djs/assistant/core";
|
|
126
222
|
|
|
127
223
|
const llm: AssistantLlmSettings = {
|
|
128
224
|
enabled: true,
|
|
129
225
|
baseUrl: "https://api.openai.com/v1",
|
|
130
|
-
apiKey:
|
|
226
|
+
apiKey: process.env.LLM_KEY ?? null,
|
|
131
227
|
model: "gpt-4o-mini",
|
|
132
228
|
systemPrompt: "You are a helpful assistant with access to tools.",
|
|
133
229
|
models: ["gpt-4o-mini", "gpt-4o"], // optional static list
|
|
@@ -136,9 +232,9 @@ const llm: AssistantLlmSettings = {
|
|
|
136
232
|
|
|
137
233
|
| Field | Description |
|
|
138
234
|
| --- | --- |
|
|
139
|
-
| `enabled` | When `false`,
|
|
140
|
-
| `baseUrl` | Provider base URL (e.g. `https://api.openai.com/v1`). |
|
|
141
|
-
| `apiKey` | Bearer token for
|
|
235
|
+
| `enabled` | When `false`, chat is disabled until the user configures a provider. |
|
|
236
|
+
| `baseUrl` | Provider base URL (e.g. `https://api.openai.com/v1` or `http://127.0.0.1:11434/v1`). |
|
|
237
|
+
| `apiKey` | Bearer token for remote providers. Optional for local servers on `localhost`, `127.0.0.1`, or `*.local`. |
|
|
142
238
|
| `model` | Default model when the user has not picked one. |
|
|
143
239
|
| `models` | Optional static model list. When omitted, models are fetched from `{baseUrl}/models`. |
|
|
144
240
|
| `systemPrompt` | Prepended system message for each completion. |
|
|
@@ -157,30 +253,32 @@ llm: async () => ({
|
|
|
157
253
|
Configure globally outside React:
|
|
158
254
|
|
|
159
255
|
```ts
|
|
160
|
-
import { configureAssistantLlm } from "@
|
|
256
|
+
import { configureAssistantLlm } from "@4djs/assistant/core";
|
|
161
257
|
|
|
162
258
|
configureAssistantLlm({ enabled: true, baseUrl: "…", apiKey: "…", model: "…" });
|
|
163
259
|
```
|
|
164
260
|
|
|
165
|
-
|
|
261
|
+
Users can override provider settings in the built-in **LLM settings** panel. Values are persisted under `storageKeys.llmSettings` (default: `assistant-llm-settings`).
|
|
166
262
|
|
|
167
|
-
|
|
263
|
+
### Environment variables
|
|
264
|
+
|
|
265
|
+
A typical Vite or Next.js app might expose provider defaults like this:
|
|
168
266
|
|
|
169
267
|
| Variable | Description |
|
|
170
268
|
| --- | --- |
|
|
171
|
-
| `LLM_KEY` | API key
|
|
172
|
-
| `LLM_BASE_URL` | Provider URL (default: OpenAI) |
|
|
173
|
-
| `LLM_MODEL` | Default model |
|
|
174
|
-
| `LLM_MODELS` | Comma-separated extra models for the selector |
|
|
269
|
+
| `VITE_LLM_KEY` / `LLM_KEY` | API key for remote providers |
|
|
270
|
+
| `VITE_LLM_BASE_URL` / `LLM_BASE_URL` | Provider URL (default: OpenAI) |
|
|
271
|
+
| `VITE_LLM_MODEL` / `LLM_MODEL` | Default model |
|
|
272
|
+
| `VITE_LLM_MODELS` / `LLM_MODELS` | Comma-separated extra models for the selector |
|
|
175
273
|
|
|
176
|
-
**
|
|
274
|
+
**Security:** Calls are made directly to the provider from the client. Any API key in your bundle is visible to users. Use scoped keys for public apps, or proxy requests through your backend for production.
|
|
177
275
|
|
|
178
276
|
## Wiring tools
|
|
179
277
|
|
|
180
278
|
Tools must match the shape expected by the LLM agent:
|
|
181
279
|
|
|
182
280
|
```ts
|
|
183
|
-
import type { AssistantToolDefinition, AssistantToolResult } from "@
|
|
281
|
+
import type { AssistantToolDefinition, AssistantToolResult } from "@4djs/assistant";
|
|
184
282
|
|
|
185
283
|
const tools: AssistantToolDefinition[] = [
|
|
186
284
|
{
|
|
@@ -201,7 +299,6 @@ async function invokeTool(
|
|
|
201
299
|
name: string,
|
|
202
300
|
args: Record<string, unknown>,
|
|
203
301
|
): Promise<AssistantToolResult> {
|
|
204
|
-
// run tool, return text content for the model
|
|
205
302
|
return {
|
|
206
303
|
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
207
304
|
};
|
|
@@ -229,27 +326,7 @@ Array<{
|
|
|
229
326
|
}>
|
|
230
327
|
```
|
|
231
328
|
|
|
232
|
-
Use `parseSuggestedPromptsResponse` from `@
|
|
233
|
-
|
|
234
|
-
## Fallback mode (no LLM)
|
|
235
|
-
|
|
236
|
-
When `configUrl` reports `enabled: false`, the assistant skips the LLM and calls `fallbackHandler` instead:
|
|
237
|
-
|
|
238
|
-
```ts
|
|
239
|
-
fallbackHandler: async ({ message, tools }) => {
|
|
240
|
-
if (message === "catalog") {
|
|
241
|
-
return {
|
|
242
|
-
id: crypto.randomUUID(),
|
|
243
|
-
role: "assistant",
|
|
244
|
-
content: "Here is your catalog…",
|
|
245
|
-
timestamp: Date.now(),
|
|
246
|
-
};
|
|
247
|
-
}
|
|
248
|
-
return null;
|
|
249
|
-
},
|
|
250
|
-
```
|
|
251
|
-
|
|
252
|
-
Return `null` to show a generic “LLM disabled” message.
|
|
329
|
+
Use `parseSuggestedPromptsResponse` from `@4djs/assistant/core` to validate LLM JSON output.
|
|
253
330
|
|
|
254
331
|
## Custom composition
|
|
255
332
|
|
|
@@ -262,7 +339,7 @@ import {
|
|
|
262
339
|
Assistant,
|
|
263
340
|
useAssistant,
|
|
264
341
|
useAssistantActions,
|
|
265
|
-
} from "@
|
|
342
|
+
} from "@4djs/assistant";
|
|
266
343
|
|
|
267
344
|
function CustomShell() {
|
|
268
345
|
const messages = useAssistant((s) => s.messages);
|
|
@@ -275,7 +352,7 @@ export function App() {
|
|
|
275
352
|
<AssistantProvider config={config}>
|
|
276
353
|
<AssistantBootstrap>
|
|
277
354
|
<CustomShell />
|
|
278
|
-
</
|
|
355
|
+
</AssistantBootstrap>
|
|
279
356
|
</AssistantProvider>
|
|
280
357
|
);
|
|
281
358
|
}
|
|
@@ -285,7 +362,7 @@ Exported building blocks include `ChatComposer`, `ChatMessageView`, `ChatEmptySt
|
|
|
285
362
|
|
|
286
363
|
## Composer commands
|
|
287
364
|
|
|
288
|
-
The input supports slash commands (e.g. `/clear`). Extend commands
|
|
365
|
+
The input supports slash commands (e.g. `/clear`). Extend commands via `runAssistantChatCommand` and related helpers from `@4djs/assistant/core`, or handle custom logic before `sendChat` in your host app.
|
|
289
366
|
|
|
290
367
|
## Core package
|
|
291
368
|
|
|
@@ -298,7 +375,8 @@ import {
|
|
|
298
375
|
buildLlmHistory,
|
|
299
376
|
fetchLlmStatus,
|
|
300
377
|
runAssistantChatCommand,
|
|
301
|
-
|
|
378
|
+
isLlmConfigured,
|
|
379
|
+
} from "@4djs/assistant/core";
|
|
302
380
|
```
|
|
303
381
|
|
|
304
382
|
Useful for server routes, tests, or a fully custom UI.
|
|
@@ -307,9 +385,11 @@ Useful for server routes, tests, or a fully custom UI.
|
|
|
307
385
|
|
|
308
386
|
| Import | Contents |
|
|
309
387
|
| --- | --- |
|
|
310
|
-
| `@
|
|
311
|
-
| `@
|
|
312
|
-
| `@
|
|
388
|
+
| `@4djs/assistant` | React components, hooks, types, labels |
|
|
389
|
+
| `@4djs/assistant/core` | Store, LLM client, commands, interactive tools, labels |
|
|
390
|
+
| `@4djs/assistant/styles.css` | Component styles |
|
|
391
|
+
|
|
392
|
+
The published package ships compiled JavaScript and TypeScript declarations from `dist/`. Source is not included in the tarball.
|
|
313
393
|
|
|
314
394
|
## Features
|
|
315
395
|
|
|
@@ -317,6 +397,9 @@ Useful for server routes, tests, or a fully custom UI.
|
|
|
317
397
|
- Interactive tool UI (confirmations, choices, reply suggestions)
|
|
318
398
|
- Markdown + GFM + math (KaTeX) + Mermaid diagrams
|
|
319
399
|
- Model selector with searchable dropdown
|
|
400
|
+
- In-app LLM settings (cloud or local OpenAI-compatible endpoints)
|
|
320
401
|
- Persistent chat history and model preference (`localStorage`)
|
|
402
|
+
- Configurable UI labels for translation and branding
|
|
321
403
|
- Welcome screen with static or LLM-generated starter prompts
|
|
322
404
|
- Composer footer toolbar: model selector, generate suggestions, clear chat
|
|
405
|
+
- Structured error states with retry actions
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { AssistantLabels } from "../labels.js";
|
|
1
2
|
export type ChatActivityStatus = "active" | "done" | "error";
|
|
2
3
|
export interface ChatActivityStep {
|
|
3
4
|
id: string;
|
|
@@ -10,7 +11,7 @@ export interface ChatActivityStep {
|
|
|
10
11
|
error?: string;
|
|
11
12
|
}
|
|
12
13
|
export declare function summarizeActivityResult(result: unknown): unknown;
|
|
13
|
-
export declare function chatActivityStepLabel(step: ChatActivityStep): string;
|
|
14
|
+
export declare function chatActivityStepLabel(step: ChatActivityStep, labels?: AssistantLabels): string;
|
|
14
15
|
export declare function formatJsonIfLarge(raw: string): string;
|
|
15
16
|
export declare function formatActivityJson(raw?: string): string | null;
|
|
16
17
|
export declare function formatActivityJsonValue(value: unknown): string | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat-activity.d.ts","sourceRoot":"","sources":["../../src/core/chat-activity.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;AAE7D,MAAM,WAAW,gBAAgB;
|
|
1
|
+
{"version":3,"file":"chat-activity.d.ts","sourceRoot":"","sources":["../../src/core/chat-activity.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAGpD,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;AAE7D,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,kBAAkB,CAAC;IAC3B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAYhE;AAED,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,gBAAgB,EACtB,MAAM,GAAE,eAA0C,GACjD,MAAM,CAmBR;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAarD;AAED,wBAAgB,kBAAkB,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQ9D;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAQrE;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAuB3D;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAI9D"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { AssistantLabels } from "../labels.js";
|
|
1
2
|
export type ChatCommandSurface = "assistant";
|
|
2
3
|
export type ChatCommandRunResult = {
|
|
3
4
|
handled: boolean;
|
|
@@ -8,18 +9,19 @@ export type AssistantCommandDeps = {
|
|
|
8
9
|
clearMessages: () => void;
|
|
9
10
|
setError: (error: string | null) => void;
|
|
10
11
|
streaming: boolean;
|
|
12
|
+
labels?: AssistantLabels;
|
|
11
13
|
};
|
|
12
14
|
export type ChatCommandSuggestion = {
|
|
13
15
|
name: string;
|
|
14
16
|
description: string;
|
|
15
17
|
usage: string;
|
|
16
18
|
};
|
|
17
|
-
export declare function getChatCommandSuggestions(surface: ChatCommandSurface): ChatCommandSuggestion[];
|
|
19
|
+
export declare function getChatCommandSuggestions(surface: ChatCommandSurface, labels?: AssistantLabels): ChatCommandSuggestion[];
|
|
18
20
|
export declare function isChatCommandInput(value: string): boolean;
|
|
19
|
-
export declare function filterChatCommands(value: string, surface: ChatCommandSurface): ChatCommandSuggestion[];
|
|
20
|
-
export declare function shouldShowChatCommandMenu(value: string, surface: ChatCommandSurface): boolean;
|
|
21
|
+
export declare function filterChatCommands(value: string, surface: ChatCommandSurface, labels?: AssistantLabels): ChatCommandSuggestion[];
|
|
22
|
+
export declare function shouldShowChatCommandMenu(value: string, surface: ChatCommandSurface, labels?: AssistantLabels): boolean;
|
|
21
23
|
export declare function completionForChatCommand(command: ChatCommandSuggestion): string;
|
|
22
|
-
export declare function listChatCommands(surface?: ChatCommandSurface): Array<{
|
|
24
|
+
export declare function listChatCommands(surface?: ChatCommandSurface, labels?: AssistantLabels): Array<{
|
|
23
25
|
name: string;
|
|
24
26
|
description: string;
|
|
25
27
|
}>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat-commands.d.ts","sourceRoot":"","sources":["../../src/core/chat-commands.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,kBAAkB,GAAG,WAAW,CAAC;AAE7C,MAAM,MAAM,oBAAoB,GAAG;
|
|
1
|
+
{"version":3,"file":"chat-commands.d.ts","sourceRoot":"","sources":["../../src/core/chat-commands.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAGpD,MAAM,MAAM,kBAAkB,GAAG,WAAW,CAAC;AAE7C,MAAM,MAAM,oBAAoB,GAAG;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IACzC,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,eAAe,CAAC;CAC1B,CAAC;AA+BF,MAAM,MAAM,qBAAqB,GAAG;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAMF,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,kBAAkB,EAC3B,MAAM,CAAC,EAAE,eAAe,GACvB,qBAAqB,EAAE,CASzB;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,kBAAkB,EAC3B,MAAM,CAAC,EAAE,eAAe,GACvB,qBAAqB,EAAE,CAiBzB;AAED,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,kBAAkB,EAC3B,MAAM,CAAC,EAAE,eAAe,GACvB,OAAO,CAWT;AAED,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,qBAAqB,GAC7B,MAAM,CAER;AAED,wBAAgB,gBAAgB,CAC9B,OAAO,CAAC,EAAE,kBAAkB,EAC5B,MAAM,CAAC,EAAE,eAAe,GACvB,KAAK,CAAC;IACP,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC,CAQD;AAED,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,MAAM,GACZ;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAgBvC;AA4BD,wBAAsB,uBAAuB,CAC3C,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,oBAAoB,GACzB,OAAO,CAAC,oBAAoB,CAAC,CAO/B;AAED,sDAAsD;AACtD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEpD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat-history.d.ts","sourceRoot":"","sources":["../../src/core/chat-history.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAK5E,MAAM,WAAW,kBAAkB;
|
|
1
|
+
{"version":3,"file":"chat-history.d.ts","sourceRoot":"","sources":["../../src/core/chat-history.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAK5E,MAAM,WAAW,kBAAkB;IACjC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,CAAC,GAAG,EAAE,uBAAuB,KAAK,gBAAgB,CAAC;CACpE;AAyDD,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,kBAAkB;qBAI5C,gBAAgB,EAAE,GAAG,IAAI;wBAapB,gBAAgB,EAAE;;uBAYnB,uBAAuB,KAAG,gBAAgB,EAAE;EAYvE;AAED,YAAY,EAAE,gBAAgB,EAAE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat-reply-suggestions-parse.d.ts","sourceRoot":"","sources":["../../src/core/chat-reply-suggestions-parse.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GAAG;
|
|
1
|
+
{"version":3,"file":"chat-reply-suggestions-parse.d.ts","sourceRoot":"","sources":["../../src/core/chat-reply-suggestions-parse.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,gBAAgB,GACxB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACjC;IACE,IAAI,EAAE,YAAY,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,GAAG,EAAE,MAAM,CAAC;CACb,GACD;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAcrC,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,CAoClE;AA4CD,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAUvD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-assistant-store.d.ts","sourceRoot":"","sources":["../../src/core/create-assistant-store.ts"],"names":[],"mappings":"AAyBA,OAAO,
|
|
1
|
+
{"version":3,"file":"create-assistant-store.d.ts","sourceRoot":"","sources":["../../src/core/create-assistant-store.ts"],"names":[],"mappings":"AAyBA,OAAO,EAML,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,EAS3B,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAEV,gBAAgB,EAChB,0BAA0B,EAC3B,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAC7B,WAAW,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAE7B,aAAa,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,kBAAkB,EAAE,MAAM,OAAO,CAAC,oBAAoB,CAAC,CAAC;IACxD,eAAe,EAAE,CAAC,MAAM,EAAE,qBAAqB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAClE,gBAAgB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,eAAe,EAAE,CACf,MAAM,EAAE,qBAAqB,KAC1B,OAAO,CAAC;QAAE,EAAE,EAAE,IAAI,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG;QAAE,EAAE,EAAE,KAAK,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACzE,uBAAuB,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IAChD,gBAAgB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,aAAa,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,gBAAgB,EAAE,MAAM,IAAI,CAAC;IAC7B,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,2BAA2B,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IACvE,2BAA2B,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CACvD;AA8HD,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,0BAA0B,+EAsbpE;AAED,MAAM,MAAM,cAAc,GAAG,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetch-suggested-prompts.d.ts","sourceRoot":"","sources":["../../src/core/fetch-suggested-prompts.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,wBAAwB;
|
|
1
|
+
{"version":3,"file":"fetch-suggested-prompts.d.ts","sourceRoot":"","sources":["../../src/core/fetch-suggested-prompts.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,KAAK,CAAC;QACb,EAAE,EAAE,MAAM,CAAC;QACX,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC,CAAC;CACJ;AAED,wBAAgB,6BAA6B,CAC3C,IAAI,EAAE,OAAO,GACZ,wBAAwB,CAAC,SAAS,CAAC,CAwCrC"}
|
package/dist/core/index.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
export type { AssistantLabelKey, AssistantLabelOverrides, AssistantLabels, } from "../labels.js";
|
|
2
|
+
export { ASSISTANT_LABEL_KEYS, DEFAULT_ASSISTANT_LABELS, formatLabel, resolveAssistantLabels, } from "../labels.js";
|
|
1
3
|
export type { ChatActivityStep } from "./chat-activity.js";
|
|
2
4
|
export { chatActivityStepLabel, formatJsonIfLarge, summarizeActivityResult, } from "./chat-activity.js";
|
|
3
5
|
export type { AssistantCommandDeps, ChatCommandRunResult, ChatCommandSuggestion, ChatCommandSurface, } from "./chat-commands.js";
|
package/dist/core/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,iBAAiB,EACjB,uBAAuB,EACvB,eAAe,GAChB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,oBAAoB,EACpB,wBAAwB,EACxB,WAAW,EACX,sBAAsB,GACvB,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EACL,qBAAqB,EACrB,iBAAiB,EACjB,uBAAuB,GACxB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACV,oBAAoB,EACpB,oBAAoB,EACpB,qBAAqB,EACrB,kBAAkB,GACnB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,kBAAkB,EAClB,yBAAyB,EACzB,kBAAkB,EAClB,gBAAgB,EAChB,gBAAgB,EAChB,uBAAuB,EACvB,yBAAyB,GAC1B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,EACL,KAAK,cAAc,EACnB,oBAAoB,GACrB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,6BAA6B,EAC7B,KAAK,wBAAwB,GAC9B,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,YAAY,EACZ,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,iBAAiB,EACjB,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,EACrB,+BAA+B,EAC/B,4BAA4B,EAC5B,oBAAoB,GACrB,MAAM,8BAA8B,CAAC;AACtC,YAAY,EACV,eAAe,EACf,aAAa,EACb,cAAc,EACd,YAAY,GACb,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,qBAAqB,EACrB,gBAAgB,EAChB,oBAAoB,EACpB,WAAW,EACX,mBAAmB,GACpB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EACtB,cAAc,EACd,oBAAoB,EACpB,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,uBAAuB,EACvB,iBAAiB,EACjB,uBAAuB,GACxB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,uBAAuB,EACvB,mBAAmB,GACpB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,qBAAqB,EACrB,iBAAiB,EACjB,2BAA2B,EAC3B,iBAAiB,GAClB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,oBAAoB,EACpB,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,iBAAiB,EACjB,uBAAuB,EACvB,2BAA2B,EAC3B,0BAA0B,EAC1B,oCAAoC,EACpC,wBAAwB,EACxB,gCAAgC,EAChC,gBAAgB,EAChB,sBAAsB,EACtB,gBAAgB,EAChB,yBAAyB,EACzB,uBAAuB,EACvB,2BAA2B,EAC3B,eAAe,EACf,eAAe,EACf,2BAA2B,EAC3B,oBAAoB,EACpB,2BAA2B,EAC3B,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,2BAA2B,CAAC;AACnC,YAAY,EACV,oBAAoB,EACpB,cAAc,EACd,cAAc,GACf,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,YAAY,EACV,kBAAkB,EAClB,oBAAoB,EACpB,gBAAgB,EAChB,oBAAoB,EACpB,0BAA0B,EAC1B,wBAAwB,EACxB,oBAAoB,EACpB,uBAAuB,EACvB,mBAAmB,EACnB,uBAAuB,EACvB,UAAU,GACX,MAAM,YAAY,CAAC"}
|