@mieweb/ui 0.10.0-dev.20 → 0.10.0-dev.22

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.
@@ -198,3 +198,80 @@ abstraction solely to make it contributable.
198
198
  Follow the repository's permissions and approval requirements for commits,
199
199
  pushes, and PR creation. Do not treat these instructions as authorization to
200
200
  publish changes.
201
+
202
+ ## Rule 16: Embedding the Ozwell assistant that acts on the page
203
+
204
+ Two different things share the "Ozwell" name — pick deliberately:
205
+
206
+ - **`OzwellChat` / `AIChat` (this library)** — the *chat UI shell*. You own the
207
+ transport and render messages you already have. Use it when the assistant is
208
+ part of your own product and you wire the answers yourself (see the
209
+ [Chat family](https://ui.mieweb.org/?path=/docs/modules-chat-overview--docs)
210
+ and the [Ozwell backend guide](https://github.com/mieweb/ui/blob/main/src/components/AI/OZWELL-BACKEND.md)).
211
+ - **The embedded Ozwell assistant (`@ozwell/react`, from ozwellai-api)** — a
212
+ drop-in, page-aware assistant that can **read and act on your page** through
213
+ tool calls. Use this when the user says things like "add Ozwell" or "let
214
+ Ozwell click / read / fill something on the page."
215
+
216
+ To add the page-aware assistant to a `@mieweb/ui` app:
217
+
218
+ - Install `@ozwell/react` alongside `@mieweb/ui`.
219
+ - Render `OzwellChat` from `@ozwell/react` and declare one tool in `tools` for
220
+ each page action the user wants Ozwell to perform (click, read, fill, …).
221
+ - Authenticate with a **site-approved agent key** (`agnt_key-…`) via
222
+ `VITE_OZWELL_AGENT_KEY`. Vite inlines every `VITE_*` value into the browser
223
+ bundle — this is **not** secret storage, so never expose a parent (`ozw_…`),
224
+ admin, or model-provider key this way; use a server-side integration when a
225
+ credential must stay private.
226
+ - Handle each call in `onToolCall(name, args, respond)`: perform the DOM action
227
+ and **always** `respond(...)`. Return `isError: true` for an unknown tool name
228
+ or a missing target, so the assistant never claims an action that did not happen.
229
+ - Follow the canonical guide — a full **Vite + MIE UI "Click Hello World"**
230
+ example — at <https://mieweb.github.io/ozwellai-api/frontend/react/>.
231
+
232
+ Example — let Ozwell fill a field on the page (adapt the tool to your app's own actions):
233
+
234
+ ```tsx
235
+ import { useState } from 'react';
236
+ import { Input } from '@mieweb/ui';
237
+ import { OzwellChat, type OzwellTool } from '@ozwell/react';
238
+
239
+ const tools: OzwellTool[] = [{
240
+ type: 'function',
241
+ function: {
242
+ name: 'set_note',
243
+ description: 'Write text into the Note field when the user asks.',
244
+ parameters: {
245
+ type: 'object',
246
+ properties: { text: { type: 'string', description: 'Text to put in the Note field' } },
247
+ required: ['text'],
248
+ },
249
+ },
250
+ }];
251
+
252
+ export default function App() {
253
+ const [note, setNote] = useState('');
254
+ return (
255
+ <>
256
+ <Input label="Note" value={note} onChange={(e) => setNote(e.target.value)} />
257
+ <output aria-live="polite">Note: {note}</output>
258
+ <OzwellChat
259
+ apiKey={import.meta.env.VITE_OZWELL_AGENT_KEY}
260
+ tools={tools}
261
+ onToolCall={(name, args, respond) => {
262
+ if (name !== 'set_note' || typeof args.text !== 'string') {
263
+ respond({ isError: true, content: [{ type: 'text', text: 'Tool unavailable' }] });
264
+ return;
265
+ }
266
+ setNote(args.text);
267
+ respond({ content: [{ type: 'text', text: `Note set to "${args.text}"` }] });
268
+ }}
269
+ />
270
+ </>
271
+ );
272
+ }
273
+ ```
274
+
275
+ Privacy: conversation content stays between the user and Ozwell and is never
276
+ relayed to the host page. The host receives only the tool calls it declares,
277
+ lifecycle/error events, and any data the user explicitly shares (opt-in).
package/dist/kerebron.css CHANGED
@@ -119,6 +119,34 @@
119
119
  color: var(--kb-menu-dropdown-text) !important;
120
120
  }
121
121
 
122
+ /*
123
+ * Kerebron leaves headings, lists, links and code to browser defaults, which
124
+ * Tailwind's preflight strips (headings `inherit`, lists `list-style: none`,
125
+ * links `color: inherit`) — so "# " and "- " produced real h1/ul nodes that
126
+ * rendered as plain text while editing. `revert` hands these back to the
127
+ * browser. (Adapted from mieweb/timehuddle#620.)
128
+ *
129
+ * Deliberately NOT in `@layer base`: @mieweb/q ships an *unlayered* preflight
130
+ * copy, and unlayered author rules beat any layered rule. Unlayered here with
131
+ * `:where()` keeps specificity at 0,1,0 — above preflight's bare element
132
+ * selectors (0,0,1) but below Kerebron's own `.kb-editor pre` / `.kb-editor
133
+ * ul` rules (0,1,1), so its pre-wrap and list padding stay in charge.
134
+ */
135
+ .kb-editor :where(h1, h2, h3, h4, h5, h6, ol, ul, a, code, pre) {
136
+ all: revert;
137
+ }
138
+ /* The browser's default link blue is unreadable on the dark editor surface,
139
+ and the brand blue fails 4.5:1 on white, so each theme gets its own shade.
140
+ Dark uses primary-400: primary-500 (#64748b) is only ~3.9:1 on the default
141
+ brand's #0f172a background, while primary-400 (#94a3b8) is ~7:1. */
142
+ .kb-editor :where(a) {
143
+ color: var(--mieweb-primary-800, #0f749c);
144
+ }
145
+ [data-theme='dark'] .kb-editor :where(a),
146
+ .dark .kb-editor :where(a) {
147
+ color: var(--mieweb-primary-400, #94a3b8);
148
+ }
149
+
122
150
  /*
123
151
  * Kerebron's base.css paints inline shortcode pills green without setting a
124
152
  * text color, so the inherited foreground fails WCAG AA contrast. Pin an
@@ -129,6 +157,93 @@
129
157
  color: #ffffff;
130
158
  }
131
159
 
160
+ /*
161
+ * codecrock's light syntax palette fails WCAG AA on white: keyword #d73 is
162
+ * 3.1:1, number #099 3.5:1, string #690 3.4:1, comment #998 2.9:1, etc.
163
+ * (axe color-contrast, caught by the Storybook a11y CI job). Darken each
164
+ * failing token to a hue-preserving shade ≥4.5:1; tokens already passing
165
+ * (property, function, type, variable, tag) are left to upstream.
166
+ */
167
+ .kb-editor .ts-keyword,
168
+ .kb-editor .ts-keyword_operator,
169
+ .kb-editor .ts-function_builtin {
170
+ color: #b03a00; /* was #d73 (3.1:1) → 6.1:1 */
171
+ }
172
+ .kb-editor .ts-number {
173
+ color: #007272; /* was #099 (3.5:1) → 5.8:1 */
174
+ }
175
+ .kb-editor .ts-string {
176
+ color: #557700; /* was #690 (3.4:1) → 5.2:1 */
177
+ }
178
+ .kb-editor .ts-string_special {
179
+ color: #c22f2f; /* was #d44 (4.2:1) → 5.6:1 */
180
+ }
181
+ .kb-editor .ts-comment {
182
+ color: #716d5e; /* was #998 (2.9:1) → 5.2:1 */
183
+ }
184
+ .kb-editor .ts-operator {
185
+ color: #637226; /* upstream #9a6 (2.5:1, misspelt .ts-perator) → 5.3:1 */
186
+ }
187
+ .kb-editor .ts-punctuation,
188
+ .kb-editor .ts-punctuation_bracket {
189
+ color: #707070; /* was #999 (2.9:1) → 5.0:1 */
190
+ }
191
+ .kb-editor .ts-attribute {
192
+ color: #8a5c00; /* was #e90 (2.3:1) → 5.8:1 */
193
+ }
194
+ .kb-editor .ts-constant,
195
+ .kb-editor .ts-constant_builtin {
196
+ color: #006a8e; /* was #0086b3 (4.2:1) → 6.1:1 */
197
+ }
198
+ /*
199
+ * Dark: codecrock only switches its palette via prefers-color-scheme, which
200
+ * a class-based dark toggle never matches — so dark surfaces were showing
201
+ * the light tokens. Re-assert codecrock's own dark (VS Code) palette for
202
+ * the tokens overridden above under the app's dark selectors.
203
+ */
204
+ [data-theme='dark'] .kb-editor .ts-keyword,
205
+ [data-theme='dark'] .kb-editor .ts-keyword_operator,
206
+ .dark .kb-editor .ts-keyword,
207
+ .dark .kb-editor .ts-keyword_operator {
208
+ color: #c586c0;
209
+ }
210
+ [data-theme='dark'] .kb-editor .ts-function_builtin,
211
+ .dark .kb-editor .ts-function_builtin {
212
+ color: #dcdcaa;
213
+ }
214
+ [data-theme='dark'] .kb-editor .ts-number,
215
+ .dark .kb-editor .ts-number {
216
+ color: #b5cea8;
217
+ }
218
+ [data-theme='dark'] .kb-editor .ts-string,
219
+ [data-theme='dark'] .kb-editor .ts-string_special,
220
+ .dark .kb-editor .ts-string,
221
+ .dark .kb-editor .ts-string_special {
222
+ color: #ce9178;
223
+ }
224
+ [data-theme='dark'] .kb-editor .ts-comment,
225
+ .dark .kb-editor .ts-comment {
226
+ color: #6a9955;
227
+ }
228
+ [data-theme='dark'] .kb-editor .ts-operator,
229
+ [data-theme='dark'] .kb-editor .ts-punctuation,
230
+ [data-theme='dark'] .kb-editor .ts-punctuation_bracket,
231
+ .dark .kb-editor .ts-operator,
232
+ .dark .kb-editor .ts-punctuation,
233
+ .dark .kb-editor .ts-punctuation_bracket {
234
+ color: #d4d4d4;
235
+ }
236
+ [data-theme='dark'] .kb-editor .ts-attribute,
237
+ .dark .kb-editor .ts-attribute {
238
+ color: #9cdcfe;
239
+ }
240
+ [data-theme='dark'] .kb-editor .ts-constant,
241
+ [data-theme='dark'] .kb-editor .ts-constant_builtin,
242
+ .dark .kb-editor .ts-constant,
243
+ .dark .kb-editor .ts-constant_builtin {
244
+ color: #4fc1ff;
245
+ }
246
+
132
247
  /* Overflow-menu icons declare min sizes that burst their compact buttons. */
133
248
  .kb-custom-menu__overflow-menu .kb-icon {
134
249
  display: inline-flex !important;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mieweb/ui",
3
- "version": "0.10.0-dev.20",
3
+ "version": "0.10.0-dev.22",
4
4
  "description": "A themeable, accessible React component library built with Tailwind CSS",
5
5
  "author": "Medical Informatics Engineering, Inc.",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -286,11 +286,11 @@
286
286
  "prepublishOnly": "npm run build"
287
287
  },
288
288
  "peerDependencies": {
289
- "@kerebron/editor": ">=0.8.6",
290
- "@kerebron/editor-kits": ">=0.8.6",
291
- "@kerebron/extension-basic-editor": ">=0.8.6",
292
- "@kerebron/extension-yjs": ">=0.8.6",
293
- "@kerebron/wasm": ">=0.8.6",
289
+ "@kerebron/editor": ">=0.8.12",
290
+ "@kerebron/editor-kits": ">=0.8.12",
291
+ "@kerebron/extension-basic-editor": ">=0.8.12",
292
+ "@kerebron/extension-yjs": ">=0.8.12",
293
+ "@kerebron/wasm": ">=0.8.12",
294
294
  "@mieweb/q": "1.0.0",
295
295
  "ag-grid-community": ">=32.0.0",
296
296
  "ag-grid-react": ">=32.0.0",
@@ -423,11 +423,11 @@
423
423
  "@esheet/fields": "0.0.5",
424
424
  "@esheet/renderer": "0.0.5",
425
425
  "@eslint/js": "^9.39.3",
426
- "@kerebron/editor": "^0.8.6",
427
- "@kerebron/editor-kits": "^0.8.6",
428
- "@kerebron/extension-basic-editor": "^0.8.6",
429
- "@kerebron/extension-yjs": "^0.8.6",
430
- "@kerebron/wasm": "^0.8.6",
426
+ "@kerebron/editor": "^0.8.12",
427
+ "@kerebron/editor-kits": "^0.8.12",
428
+ "@kerebron/extension-basic-editor": "^0.8.12",
429
+ "@kerebron/extension-yjs": "^0.8.12",
430
+ "@kerebron/wasm": "^0.8.12",
431
431
  "@mieweb/datavis": "link:./packages/datavis",
432
432
  "@mieweb/q": "1.0.0",
433
433
  "@monaco-editor/react": "^4.7.0",