@4djs/assistant 0.0.1 → 0.1.0

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 (2) hide show
  1. package/README.md +49 -68
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,17 +1,13 @@
1
- # @4d/assistant
1
+ # @4djs/assistant
2
2
 
3
- Embeddable React chat assistant with LLM tool-calling, streaming, markdown rendering, and optional fallback mode when no LLM is configured.
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
- This package lives in the monorepo as a workspace dependency:
8
-
9
- ```json
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 "@4d/assistant/styles.css";
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 "@4d/assistant";
28
+ import { AssistantRoot, type AssistantConfig } from "@4djs/assistant";
33
29
 
34
30
  const config: AssistantConfig = {
35
31
  llm: {
36
- enabled: Boolean(import.meta.env.LLM_KEY),
37
- baseUrl: import.meta.env.LLM_BASE_URL ?? "https://api.openai.com/v1",
38
- apiKey: import.meta.env.LLM_KEY ?? null,
39
- model: import.meta.env.LLM_MODEL ?? "gpt-4o-mini",
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! LLM is disabled try `/clear` or use fallback commands.",
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
- See [`apps/web/src/assistant/config.ts`](../../apps/web/src/assistant/config.ts) for a full production example wired to the 4D tool registry.
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,7 +76,6 @@ 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`). |
@@ -91,9 +86,9 @@ See [`apps/web/src/assistant/config.ts`](../../apps/web/src/assistant/config.ts)
91
86
  {
92
87
  header: {
93
88
  title: "Assistant",
94
- subtitle: "Query and explore your datastore",
95
- icon: Sparkles, // lucide-react icon
96
- showClearButton: true, // footer toolbar (default: true)
89
+ subtitle: "Query and explore your data",
90
+ icon: Sparkles, // lucide-react icon
91
+ showClearButton: true, // footer toolbar (default: true)
97
92
  showSuggestionsButton: true, // footer toolbar when fetchSuggestedPrompts is set
98
93
  },
99
94
  emptyState: {
@@ -108,7 +103,7 @@ See [`apps/web/src/assistant/config.ts`](../../apps/web/src/assistant/config.ts)
108
103
  composerPlaceholder: "Ask the assistant…",
109
104
  showModelSelector: true,
110
105
  maxWidth: "56rem",
111
- className: "panel", // extra class on the root panel
106
+ className: "panel", // extra class on the root panel
112
107
  },
113
108
  }
114
109
  ```
@@ -122,12 +117,12 @@ The assistant calls an **OpenAI-compatible** chat completions API directly from
122
117
  Pass `llm` on `AssistantConfig`:
123
118
 
124
119
  ```ts
125
- import type { AssistantLlmSettings } from "@4d/assistant/core";
120
+ import type { AssistantLlmSettings } from "@4djs/assistant/core";
126
121
 
127
122
  const llm: AssistantLlmSettings = {
128
123
  enabled: true,
129
124
  baseUrl: "https://api.openai.com/v1",
130
- apiKey: import.meta.env.LLM_KEY ?? null,
125
+ apiKey: process.env.LLM_KEY ?? null,
131
126
  model: "gpt-4o-mini",
132
127
  systemPrompt: "You are a helpful assistant with access to tools.",
133
128
  models: ["gpt-4o-mini", "gpt-4o"], // optional static list
@@ -136,9 +131,9 @@ const llm: AssistantLlmSettings = {
136
131
 
137
132
  | Field | Description |
138
133
  | --- | --- |
139
- | `enabled` | When `false`, or when `apiKey` is missing, fallback mode is used. |
140
- | `baseUrl` | Provider base URL (e.g. `https://api.openai.com/v1`). |
141
- | `apiKey` | Bearer token for the provider. |
134
+ | `enabled` | When `false`, chat is disabled until the user configures a provider. |
135
+ | `baseUrl` | Provider base URL (e.g. `https://api.openai.com/v1` or `http://127.0.0.1:11434/v1`). |
136
+ | `apiKey` | Bearer token for remote providers. Optional for local servers on `localhost`, `127.0.0.1`, or `*.local`. |
142
137
  | `model` | Default model when the user has not picked one. |
143
138
  | `models` | Optional static model list. When omitted, models are fetched from `{baseUrl}/models`. |
144
139
  | `systemPrompt` | Prepended system message for each completion. |
@@ -157,30 +152,32 @@ llm: async () => ({
157
152
  Configure globally outside React:
158
153
 
159
154
  ```ts
160
- import { configureAssistantLlm } from "@4d/assistant/core";
155
+ import { configureAssistantLlm } from "@4djs/assistant/core";
161
156
 
162
157
  configureAssistantLlm({ enabled: true, baseUrl: "…", apiKey: "…", model: "…" });
163
158
  ```
164
159
 
165
- ### Environment variables (4D web app)
160
+ Users can override provider settings in the built-in **LLM settings** panel. Values are persisted under `storageKeys.llmSettings` (default: `assistant-llm-settings`).
166
161
 
167
- The playground reads these from `.env.local` (exposed to the client via Vite `envPrefix`):
162
+ ### Environment variables
163
+
164
+ A typical Vite or Next.js app might expose provider defaults like this:
168
165
 
169
166
  | Variable | Description |
170
167
  | --- | --- |
171
- | `LLM_KEY` | API key (required to enable LLM) |
172
- | `LLM_BASE_URL` | Provider URL (default: OpenAI) |
173
- | `LLM_MODEL` | Default model |
174
- | `LLM_MODELS` | Comma-separated extra models for the selector |
168
+ | `VITE_LLM_KEY` / `LLM_KEY` | API key for remote providers |
169
+ | `VITE_LLM_BASE_URL` / `LLM_BASE_URL` | Provider URL (default: OpenAI) |
170
+ | `VITE_LLM_MODEL` / `LLM_MODEL` | Default model |
171
+ | `VITE_LLM_MODELS` / `LLM_MODELS` | Comma-separated extra models for the selector |
175
172
 
176
- **Note:** Because calls are made directly to the provider, the API key is available to the client bundle. Use this pattern for local/dev playgrounds or when the key is scoped and acceptable in the browser.
173
+ **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
174
 
178
175
  ## Wiring tools
179
176
 
180
177
  Tools must match the shape expected by the LLM agent:
181
178
 
182
179
  ```ts
183
- import type { AssistantToolDefinition, AssistantToolResult } from "@4d/assistant";
180
+ import type { AssistantToolDefinition, AssistantToolResult } from "@4djs/assistant";
184
181
 
185
182
  const tools: AssistantToolDefinition[] = [
186
183
  {
@@ -201,7 +198,6 @@ async function invokeTool(
201
198
  name: string,
202
199
  args: Record<string, unknown>,
203
200
  ): Promise<AssistantToolResult> {
204
- // run tool, return text content for the model
205
201
  return {
206
202
  content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
207
203
  };
@@ -229,27 +225,7 @@ Array<{
229
225
  }>
230
226
  ```
231
227
 
232
- Use `parseSuggestedPromptsResponse` from `@4d/assistant/core` to validate LLM JSON output.
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.
228
+ Use `parseSuggestedPromptsResponse` from `@4djs/assistant/core` to validate LLM JSON output.
253
229
 
254
230
  ## Custom composition
255
231
 
@@ -262,7 +238,7 @@ import {
262
238
  Assistant,
263
239
  useAssistant,
264
240
  useAssistantActions,
265
- } from "@4d/assistant";
241
+ } from "@4djs/assistant";
266
242
 
267
243
  function CustomShell() {
268
244
  const messages = useAssistant((s) => s.messages);
@@ -275,7 +251,7 @@ export function App() {
275
251
  <AssistantProvider config={config}>
276
252
  <AssistantBootstrap>
277
253
  <CustomShell />
278
- </AssistantProvider>
254
+ </AssistantBootstrap>
279
255
  </AssistantProvider>
280
256
  );
281
257
  }
@@ -285,7 +261,7 @@ Exported building blocks include `ChatComposer`, `ChatMessageView`, `ChatEmptySt
285
261
 
286
262
  ## Composer commands
287
263
 
288
- The input supports slash commands (e.g. `/clear`). Extend commands in `@4d/assistant/core` via `chat-commands.ts` or handle custom logic before `sendChat` in your host app.
264
+ 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
265
 
290
266
  ## Core package
291
267
 
@@ -298,7 +274,8 @@ import {
298
274
  buildLlmHistory,
299
275
  fetchLlmStatus,
300
276
  runAssistantChatCommand,
301
- } from "@4d/assistant/core";
277
+ isLlmConfigured,
278
+ } from "@4djs/assistant/core";
302
279
  ```
303
280
 
304
281
  Useful for server routes, tests, or a fully custom UI.
@@ -307,9 +284,11 @@ Useful for server routes, tests, or a fully custom UI.
307
284
 
308
285
  | Import | Contents |
309
286
  | --- | --- |
310
- | `@4d/assistant` | React components, hooks, types |
311
- | `@4d/assistant/core` | Store, LLM client, commands, interactive tools |
312
- | `@4d/assistant/styles.css` | Component styles |
287
+ | `@4djs/assistant` | React components, hooks, types |
288
+ | `@4djs/assistant/core` | Store, LLM client, commands, interactive tools |
289
+ | `@4djs/assistant/styles.css` | Component styles |
290
+
291
+ The published package ships compiled JavaScript and TypeScript declarations from `dist/`. Source is not included in the tarball.
313
292
 
314
293
  ## Features
315
294
 
@@ -317,6 +296,8 @@ Useful for server routes, tests, or a fully custom UI.
317
296
  - Interactive tool UI (confirmations, choices, reply suggestions)
318
297
  - Markdown + GFM + math (KaTeX) + Mermaid diagrams
319
298
  - Model selector with searchable dropdown
299
+ - In-app LLM settings (cloud or local OpenAI-compatible endpoints)
320
300
  - Persistent chat history and model preference (`localStorage`)
321
301
  - Welcome screen with static or LLM-generated starter prompts
322
302
  - Composer footer toolbar: model selector, generate suggestions, clear chat
303
+ - Structured error states with retry actions
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@4djs/assistant",
3
- "version": "0.0.1",
3
+ "version": "0.1.0",
4
4
  "type": "module",
5
5
  "types": "./dist/react/index.d.ts",
6
6
  "files": [