@mieweb/q 1.0.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.
- package/README.md +932 -0
- package/dist/AgentConfigGenerator-CQkFCXJI.cjs +4 -0
- package/dist/AgentConfigGenerator-DLoMdUYG.js +1903 -0
- package/dist/index.cjs +1 -0
- package/dist/index.js +67 -0
- package/dist/style.css +1 -0
- package/dist/universal.cjs +1 -0
- package/dist/universal.js +77 -0
- package/package.json +65 -0
- package/postcss.config.js +6 -0
- package/src/index.css +65 -0
- package/tailwind.config.js +27 -0
package/README.md
ADDED
|
@@ -0,0 +1,932 @@
|
|
|
1
|
+
# Q — Agent Config Generator
|
|
2
|
+
|
|
3
|
+
**Q** is a powerful, embeddable UI component for generating and editing AI Agent configuration files. It provides a form-based interface, a YAML/JSON code editor, and an MCP tool builder — all in one package. Built with React and [@mieweb/ui](https://www.npmjs.com/package/@mieweb/ui), Q can be dropped into any React application or used framework-agnostically in Vanilla JS, Vue, Angular, Svelte, or any other environment.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Features](#features)
|
|
8
|
+
- [Prerequisites](#prerequisites)
|
|
9
|
+
- [Installation](#installation)
|
|
10
|
+
- [Quick Start — React](#quick-start--react)
|
|
11
|
+
- [Quick Start — Universal (Vanilla JS / Any Framework)](#quick-start--universal-vanilla-js--any-framework)
|
|
12
|
+
- [API Reference](#api-reference)
|
|
13
|
+
- [React — `AgentConfigGenerator`](#react--agentconfiggenerator)
|
|
14
|
+
- [Universal — `UniversalAgentConfigGenerator`](#universal--universalagentconfiggenerator)
|
|
15
|
+
- [Exported Utilities](#exported-utilities)
|
|
16
|
+
- [Styling & CSS](#styling--css)
|
|
17
|
+
- [Theming & Brand Customization](#theming--brand-customization)
|
|
18
|
+
- [Custom Schemas](#custom-schemas)
|
|
19
|
+
- [Architecture & Flow Diagram](#architecture--flow-diagram)
|
|
20
|
+
- [Project Structure](#project-structure)
|
|
21
|
+
- [Development](#development)
|
|
22
|
+
- [Troubleshooting](#troubleshooting)
|
|
23
|
+
- [License](#license)
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Features
|
|
28
|
+
|
|
29
|
+
- **Form Builder** — Auto-generated form UI from a customizable JSON schema. Add, remove, and reorder fields visually with a built-in schema editor.
|
|
30
|
+
- **Config Editor** — Full-featured YAML/JSON editor powered by Monaco (the engine behind VS Code). Edit configs directly with syntax highlighting and validation.
|
|
31
|
+
- **Tool Builder** — Visual builder for defining MCP (Model Context Protocol) tools with parameter schemas, following the open standard.
|
|
32
|
+
- **Bidirectional Sync** — Changes in the form update the code editor and vice versa, always keeping the config in sync.
|
|
33
|
+
- **Download & Submit** — Download the generated config as YAML or JSON, or submit it programmatically via callbacks.
|
|
34
|
+
- **Schema Import/Export** — Import and export the form schema as JSON for portability and version control.
|
|
35
|
+
- **Customizable Theming** — Powered by `@mieweb/ui` CSS variables. Supports multiple built-in brands (Bluehive, MIEWeb, Enterprise Health, Ozwell, Waggleline, WebChart) or fully custom themes.
|
|
36
|
+
- **Framework Agnostic** — Use the React component directly or the Universal wrapper for any framework (Vue, Angular, Svelte, plain HTML).
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Prerequisites
|
|
41
|
+
|
|
42
|
+
| Requirement | Version | Notes |
|
|
43
|
+
| --------------- | ---------------- | ------------------------------------------------------------ |
|
|
44
|
+
| **Node.js** | 18+ | LTS recommended. [Download here](https://nodejs.org/). Check with `node -v` |
|
|
45
|
+
| **npm** | 9+ | Bundled with Node.js. Check with `npm -v` |
|
|
46
|
+
| **Bundler** | Vite 5+, Webpack 5+, or similar | Any modern bundler that supports ES modules |
|
|
47
|
+
| **React** _(React integration only)_ | 18+ or 19+ | The Universal wrapper includes React internally |
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Installation
|
|
52
|
+
|
|
53
|
+
Install Q directly from GitHub:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
npm install Q@github:avagu-mie/Q
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
This will:
|
|
60
|
+
1. Clone the repository
|
|
61
|
+
2. Run the `prepare` script (builds the library with Vite and compiles Tailwind CSS)
|
|
62
|
+
3. Install the generated `dist/` folder into your `node_modules/Q`
|
|
63
|
+
|
|
64
|
+
> **Note:** Because Q is installed from source (not a pre-built npm package), the `prepare` step builds the library on your machine. This requires all of Q's dependencies to be fetched and may take a minute or two on the first install. Subsequent installs will be faster if your npm cache is warm.
|
|
65
|
+
|
|
66
|
+
> **Tip:** Once published to npm, you can install with `npm install Q` instead.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Quick Start — React
|
|
71
|
+
|
|
72
|
+
This section walks through creating a brand-new React application that uses Q from scratch.
|
|
73
|
+
|
|
74
|
+
### 1. Scaffold the Application
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
# Create a new project folder
|
|
78
|
+
mkdir my-q-react-app && cd my-q-react-app
|
|
79
|
+
|
|
80
|
+
# Initialize package.json
|
|
81
|
+
npm init -y
|
|
82
|
+
|
|
83
|
+
# Make sure package.json has "type": "module"
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Edit your `package.json` so it looks like this:
|
|
87
|
+
|
|
88
|
+
```json
|
|
89
|
+
{
|
|
90
|
+
"name": "my-q-react-app",
|
|
91
|
+
"private": true,
|
|
92
|
+
"version": "1.0.0",
|
|
93
|
+
"type": "module",
|
|
94
|
+
"scripts": {
|
|
95
|
+
"dev": "vite",
|
|
96
|
+
"build": "vite build",
|
|
97
|
+
"preview": "vite preview"
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### 2. Install Dependencies
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
# Install Q from GitHub
|
|
106
|
+
npm install Q@github:avagu-mie/Q
|
|
107
|
+
|
|
108
|
+
# Install React (only if your app doesn't already have React)
|
|
109
|
+
npm install react react-dom
|
|
110
|
+
|
|
111
|
+
# Install Vite and the React plugin as dev dependencies
|
|
112
|
+
npm install -D vite @vitejs/plugin-react
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
> **Note:** Q includes `react` and `react-dom` as direct dependencies, so you don't need to install them separately. If your host app already has React installed, npm will deduplicate automatically. If you see "Invalid hook call" errors at runtime, ensure you only have **one copy** of React — run `npm ls react` to check. You can add a [resolution override](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#overrides) if needed.
|
|
116
|
+
|
|
117
|
+
### 3. Create Project Files
|
|
118
|
+
|
|
119
|
+
**`vite.config.js`**
|
|
120
|
+
```js
|
|
121
|
+
import { defineConfig } from 'vite';
|
|
122
|
+
import react from '@vitejs/plugin-react';
|
|
123
|
+
|
|
124
|
+
export default defineConfig({
|
|
125
|
+
plugins: [react()],
|
|
126
|
+
});
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
**`index.html`**
|
|
130
|
+
```html
|
|
131
|
+
<!doctype html>
|
|
132
|
+
<html lang="en">
|
|
133
|
+
<head>
|
|
134
|
+
<meta charset="UTF-8" />
|
|
135
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
136
|
+
<title>My Q App</title>
|
|
137
|
+
<style>
|
|
138
|
+
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
139
|
+
html, body, #root { height: 100%; }
|
|
140
|
+
</style>
|
|
141
|
+
</head>
|
|
142
|
+
<body>
|
|
143
|
+
<div id="root"></div>
|
|
144
|
+
<script type="module" src="/src/main.jsx"></script>
|
|
145
|
+
</body>
|
|
146
|
+
</html>
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
**`src/main.jsx`**
|
|
150
|
+
```jsx
|
|
151
|
+
import React, { useState } from 'react';
|
|
152
|
+
import ReactDOM from 'react-dom/client';
|
|
153
|
+
import { AgentConfigGenerator } from 'Q';
|
|
154
|
+
import 'Q/style.css'; // Required — loads all component styles
|
|
155
|
+
|
|
156
|
+
function App() {
|
|
157
|
+
const [submittedYaml, setSubmittedYaml] = useState('');
|
|
158
|
+
|
|
159
|
+
return (
|
|
160
|
+
<div style={{ height: '100%', display: 'flex', flexDirection: 'column' }}>
|
|
161
|
+
<AgentConfigGenerator
|
|
162
|
+
showEditor={true}
|
|
163
|
+
onConfigChange={(config) => {
|
|
164
|
+
console.log('Config changed:', config);
|
|
165
|
+
}}
|
|
166
|
+
onDownload={(content, mode) => {
|
|
167
|
+
// content = serialized config string, mode = 'yaml' or 'json'
|
|
168
|
+
console.log(`Download (${mode}):`, content);
|
|
169
|
+
}}
|
|
170
|
+
onSubmit={(yamlString) => {
|
|
171
|
+
console.log('Submitted YAML:', yamlString);
|
|
172
|
+
setSubmittedYaml(yamlString);
|
|
173
|
+
}}
|
|
174
|
+
/>
|
|
175
|
+
|
|
176
|
+
{submittedYaml && (
|
|
177
|
+
<pre style={{
|
|
178
|
+
margin: '1rem',
|
|
179
|
+
padding: '1rem',
|
|
180
|
+
background: '#f5f5f5',
|
|
181
|
+
borderRadius: '8px',
|
|
182
|
+
overflow: 'auto',
|
|
183
|
+
maxHeight: '300px',
|
|
184
|
+
fontSize: '0.85rem',
|
|
185
|
+
}}>
|
|
186
|
+
{submittedYaml}
|
|
187
|
+
</pre>
|
|
188
|
+
)}
|
|
189
|
+
</div>
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
ReactDOM.createRoot(document.getElementById('root')).render(<App />);
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### 4. Run the Application
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
npm run dev
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
Open the URL shown in your terminal (usually `http://localhost:5173`).
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
## Quick Start — Universal (Vanilla JS / Any Framework)
|
|
207
|
+
|
|
208
|
+
The Universal wrapper lets you use Q **without writing any React code**. It works with plain HTML, Vue, Angular, Svelte, or any framework. React is bundled internally.
|
|
209
|
+
|
|
210
|
+
### 1. Scaffold the Application
|
|
211
|
+
|
|
212
|
+
```bash
|
|
213
|
+
mkdir my-q-universal-app && cd my-q-universal-app
|
|
214
|
+
npm init -y
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
Edit your `package.json`:
|
|
218
|
+
|
|
219
|
+
```json
|
|
220
|
+
{
|
|
221
|
+
"name": "my-q-universal-app",
|
|
222
|
+
"private": true,
|
|
223
|
+
"version": "1.0.0",
|
|
224
|
+
"type": "module",
|
|
225
|
+
"scripts": {
|
|
226
|
+
"dev": "vite",
|
|
227
|
+
"build": "vite build",
|
|
228
|
+
"preview": "vite preview"
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### 2. Install Dependencies
|
|
234
|
+
|
|
235
|
+
```bash
|
|
236
|
+
# Install Q from GitHub (React is included as a dependency of Q)
|
|
237
|
+
npm install Q@github:avagu-mie/Q
|
|
238
|
+
|
|
239
|
+
# Install Vite as a dev dependency — no React plugin needed!
|
|
240
|
+
npm install -D vite
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### 3. Create Project Files
|
|
244
|
+
|
|
245
|
+
**`vite.config.js`**
|
|
246
|
+
```js
|
|
247
|
+
import { defineConfig } from 'vite';
|
|
248
|
+
|
|
249
|
+
export default defineConfig({});
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
**`index.html`**
|
|
253
|
+
```html
|
|
254
|
+
<!doctype html>
|
|
255
|
+
<html lang="en">
|
|
256
|
+
<head>
|
|
257
|
+
<meta charset="UTF-8" />
|
|
258
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
259
|
+
<title>My Q App</title>
|
|
260
|
+
<style>
|
|
261
|
+
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
262
|
+
html, body { height: 100%; }
|
|
263
|
+
#config-container { height: 100%; }
|
|
264
|
+
</style>
|
|
265
|
+
</head>
|
|
266
|
+
<body>
|
|
267
|
+
<div id="config-container"></div>
|
|
268
|
+
<script type="module" src="/src/main.js"></script>
|
|
269
|
+
</body>
|
|
270
|
+
</html>
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
**`src/main.js`**
|
|
274
|
+
```js
|
|
275
|
+
import { UniversalAgentConfigGenerator } from 'Q/universal';
|
|
276
|
+
import 'Q/style.css'; // Required — loads all component styles
|
|
277
|
+
|
|
278
|
+
// Mount Q into the container element
|
|
279
|
+
const generator = new UniversalAgentConfigGenerator('#config-container', {
|
|
280
|
+
showEditor: true,
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
const container = document.getElementById('config-container');
|
|
284
|
+
|
|
285
|
+
// Listen for config changes
|
|
286
|
+
container.addEventListener('config-change', (e) => {
|
|
287
|
+
console.log('Config changed:', e.detail);
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
// Listen for download requests
|
|
291
|
+
container.addEventListener('config-download', (e) => {
|
|
292
|
+
console.log('Download requested:', e.detail);
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
// Listen for submit
|
|
296
|
+
container.addEventListener('config-submit', (e) => {
|
|
297
|
+
console.log('Submit clicked:', e.detail);
|
|
298
|
+
// e.detail.yaml — the config as a YAML string
|
|
299
|
+
// e.detail.config — the config as a JS object
|
|
300
|
+
});
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
### 4. Run the Application
|
|
304
|
+
|
|
305
|
+
```bash
|
|
306
|
+
npm run dev
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
### Universal Wrapper in Vue
|
|
310
|
+
|
|
311
|
+
```vue
|
|
312
|
+
<template>
|
|
313
|
+
<div ref="container" style="height: 100%"></div>
|
|
314
|
+
</template>
|
|
315
|
+
|
|
316
|
+
<script>
|
|
317
|
+
import { UniversalAgentConfigGenerator } from 'Q/universal';
|
|
318
|
+
import 'Q/style.css';
|
|
319
|
+
|
|
320
|
+
export default {
|
|
321
|
+
mounted() {
|
|
322
|
+
this.generator = new UniversalAgentConfigGenerator(this.$refs.container, {
|
|
323
|
+
showEditor: true,
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
this.$refs.container.addEventListener('config-submit', (e) => {
|
|
327
|
+
this.$emit('submit', e.detail);
|
|
328
|
+
});
|
|
329
|
+
},
|
|
330
|
+
beforeUnmount() {
|
|
331
|
+
this.generator.destroy();
|
|
332
|
+
},
|
|
333
|
+
};
|
|
334
|
+
</script>
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
### Universal Wrapper in Angular
|
|
338
|
+
|
|
339
|
+
```typescript
|
|
340
|
+
import { Component, ElementRef, ViewChild, AfterViewInit, OnDestroy } from '@angular/core';
|
|
341
|
+
import { UniversalAgentConfigGenerator } from 'Q/universal';
|
|
342
|
+
import 'Q/style.css';
|
|
343
|
+
|
|
344
|
+
@Component({
|
|
345
|
+
selector: 'app-config-generator',
|
|
346
|
+
template: `<div #container style="height: 100%"></div>`,
|
|
347
|
+
})
|
|
348
|
+
export class ConfigGeneratorComponent implements AfterViewInit, OnDestroy {
|
|
349
|
+
@ViewChild('container') container!: ElementRef;
|
|
350
|
+
private generator!: UniversalAgentConfigGenerator;
|
|
351
|
+
|
|
352
|
+
ngAfterViewInit() {
|
|
353
|
+
this.generator = new UniversalAgentConfigGenerator(this.container.nativeElement, {
|
|
354
|
+
showEditor: true,
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
this.container.nativeElement.addEventListener('config-submit', (e: CustomEvent) => {
|
|
358
|
+
console.log('Submitted:', e.detail);
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
ngOnDestroy() {
|
|
363
|
+
this.generator.destroy();
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
---
|
|
369
|
+
|
|
370
|
+
## API Reference
|
|
371
|
+
|
|
372
|
+
### React — `AgentConfigGenerator`
|
|
373
|
+
|
|
374
|
+
```jsx
|
|
375
|
+
import { AgentConfigGenerator } from 'Q';
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
| Prop | Type | Default | Description |
|
|
379
|
+
| ---------------- | ------------------------------ | ---------------- | --------------------------------------------------------------------------- |
|
|
380
|
+
| `initialConfig` | `object` | auto-derived | Pre-populate with an existing agent config object |
|
|
381
|
+
| `schema` | `object` | built-in schema | Override the default questionnaire schema (MieForms v1.0 format) |
|
|
382
|
+
| `onConfigChange` | `(config: object) => void` | — | Callback fired on every config change |
|
|
383
|
+
| `onDownload` | `(content: string, mode: 'yaml' \| 'json') => void` | — | Callback when the user clicks Download. Receives the serialized config and the format. |
|
|
384
|
+
| `onSubmit` | `(yamlString: string) => void` | — | Callback when the user clicks Submit. Receives the config as a YAML string. Also shows the Submit button. |
|
|
385
|
+
| `showEditor` | `boolean` | `true` | Show/hide the Config Editor tab |
|
|
386
|
+
|
|
387
|
+
### Universal — `UniversalAgentConfigGenerator`
|
|
388
|
+
|
|
389
|
+
```js
|
|
390
|
+
import { UniversalAgentConfigGenerator } from 'Q/universal';
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
#### Constructor
|
|
394
|
+
|
|
395
|
+
```js
|
|
396
|
+
new UniversalAgentConfigGenerator(target, options?)
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
| Parameter | Type | Description |
|
|
400
|
+
| ------------------ | ----------------------- | ----------------------------------------------------------- |
|
|
401
|
+
| `target` | `string \| HTMLElement` | CSS selector or DOM element to mount into |
|
|
402
|
+
| `options.initialConfig` | `object` | Pre-populate with an existing agent config |
|
|
403
|
+
| `options.schema` | `object` | Override the default questionnaire schema |
|
|
404
|
+
| `options.showEditor` | `boolean` | Show the Config Editor tab (default: `true`) |
|
|
405
|
+
|
|
406
|
+
#### Methods
|
|
407
|
+
|
|
408
|
+
| Method | Description |
|
|
409
|
+
| ------------------- | ---------------------------------------- |
|
|
410
|
+
| `update(options)` | Merge new options and re-render |
|
|
411
|
+
| `destroy()` | Unmount the component and free resources |
|
|
412
|
+
|
|
413
|
+
#### DOM Events
|
|
414
|
+
|
|
415
|
+
Events are dispatched on the container element. Use `addEventListener` to listen:
|
|
416
|
+
|
|
417
|
+
| Event Name | `e.detail` | Description |
|
|
418
|
+
| ----------------- | -------------------------------------- | ------------------------------------------------ |
|
|
419
|
+
| `config-change` | `object` (the config) | Fired on every config change |
|
|
420
|
+
| `config-download` | `{ content: string, mode: 'yaml' \| 'json' }` | Fired when the user clicks Download |
|
|
421
|
+
| `config-submit` | `{ config: object, yaml: string }` | Fired when the user clicks Submit |
|
|
422
|
+
|
|
423
|
+
---
|
|
424
|
+
|
|
425
|
+
## Exported Utilities
|
|
426
|
+
|
|
427
|
+
In addition to the main components, Q exports several utilities:
|
|
428
|
+
|
|
429
|
+
```js
|
|
430
|
+
import {
|
|
431
|
+
// Components
|
|
432
|
+
AgentConfigGenerator,
|
|
433
|
+
FormBuilder,
|
|
434
|
+
ConfigEditor,
|
|
435
|
+
ToolBuilder,
|
|
436
|
+
Header,
|
|
437
|
+
|
|
438
|
+
// Schema / Config helpers
|
|
439
|
+
defaultSchema, // The built-in questionnaire JSON schema
|
|
440
|
+
deriveDefaultConfig, // (schema) => config object with defaults
|
|
441
|
+
questionnaireToConfig, // Convert schema answers to a config object
|
|
442
|
+
configToQuestionnaire, // Sync a config object back into a schema
|
|
443
|
+
validateConfig, // Validate a config object
|
|
444
|
+
configToYaml, // Convert config to YAML string
|
|
445
|
+
yamlToConfig, // Parse YAML string to config object
|
|
446
|
+
downloadConfig, // Trigger a file download
|
|
447
|
+
copyToClipboard, // Copy text to clipboard
|
|
448
|
+
|
|
449
|
+
// Constants
|
|
450
|
+
TIMEZONES, // Array of timezone strings
|
|
451
|
+
GENERIC_TOOLS, // Built-in MCP tool definitions
|
|
452
|
+
} from 'Q';
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
The Universal entry also re-exports branding helpers:
|
|
456
|
+
|
|
457
|
+
```js
|
|
458
|
+
import { brands, generateBrandCSS } from 'Q/universal';
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
---
|
|
462
|
+
|
|
463
|
+
## Styling & CSS
|
|
464
|
+
|
|
465
|
+
Q uses [Tailwind CSS](https://tailwindcss.com/) internally and ships a pre-built CSS file. **You must import the stylesheet** in your application for components to render correctly:
|
|
466
|
+
|
|
467
|
+
```js
|
|
468
|
+
import 'Q/style.css';
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
This single import includes:
|
|
472
|
+
- All Tailwind utility classes used by Q components
|
|
473
|
+
- All `@mieweb/ui` component styles
|
|
474
|
+
- Custom animations and hover-state overrides
|
|
475
|
+
|
|
476
|
+
### Full-Height Layout
|
|
477
|
+
|
|
478
|
+
Q is designed to fill its parent container. Make sure the mount target has a defined height:
|
|
479
|
+
|
|
480
|
+
```css
|
|
481
|
+
html, body, #root { height: 100%; }
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
### Using Q alongside your own Tailwind setup
|
|
485
|
+
|
|
486
|
+
If your host app also uses Tailwind, you can extend your own config with Q's preset:
|
|
487
|
+
|
|
488
|
+
```js
|
|
489
|
+
// your-app/tailwind.config.js
|
|
490
|
+
import miewebPreset from 'Q/tailwind-config';
|
|
491
|
+
|
|
492
|
+
export default {
|
|
493
|
+
presets: [miewebPreset],
|
|
494
|
+
content: [
|
|
495
|
+
'./src/**/*.{js,jsx,ts,tsx}',
|
|
496
|
+
'./node_modules/Q/dist/**/*.{js,cjs}', // Scan Q's built output
|
|
497
|
+
],
|
|
498
|
+
};
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
---
|
|
502
|
+
|
|
503
|
+
## Theming & Brand Customization
|
|
504
|
+
|
|
505
|
+
Q is styled entirely through **CSS custom properties** (variables) defined by `@mieweb/ui`. You can re-theme the entire component by setting these variables on a parent element.
|
|
506
|
+
|
|
507
|
+
### Built-in Brands
|
|
508
|
+
|
|
509
|
+
`@mieweb/ui` ships with 6 built-in brand themes. Import the desired brand CSS **before** Q's styles:
|
|
510
|
+
|
|
511
|
+
| Brand | Import |
|
|
512
|
+
| ------------------ | ------------------------------------------ |
|
|
513
|
+
| Bluehive (default) | `@mieweb/ui/brands/bluehive.css` |
|
|
514
|
+
| Enterprise Health | `@mieweb/ui/brands/enterprise-health.css` |
|
|
515
|
+
| MIEWeb | `@mieweb/ui/brands/mieweb.css` |
|
|
516
|
+
| Ozwell | `@mieweb/ui/brands/ozwell.css` |
|
|
517
|
+
| WebChart | `@mieweb/ui/brands/webchart.css` |
|
|
518
|
+
| Waggleline | `@mieweb/ui/brands/waggleline.css` |
|
|
519
|
+
|
|
520
|
+
Example (React):
|
|
521
|
+
|
|
522
|
+
```jsx
|
|
523
|
+
import '@mieweb/ui/brands/enterprise-health.css';
|
|
524
|
+
import 'Q/style.css';
|
|
525
|
+
import { AgentConfigGenerator } from 'Q';
|
|
526
|
+
```
|
|
527
|
+
|
|
528
|
+
### Custom Theme via CSS Variables
|
|
529
|
+
|
|
530
|
+
Create your own theme by setting the CSS variables on a parent element or `:root`:
|
|
531
|
+
|
|
532
|
+
```css
|
|
533
|
+
:root {
|
|
534
|
+
/* Colors */
|
|
535
|
+
--mieweb-background: #ffffff;
|
|
536
|
+
--mieweb-foreground: #0a0a0a;
|
|
537
|
+
--mieweb-card: #ffffff;
|
|
538
|
+
--mieweb-card-foreground: #0a0a0a;
|
|
539
|
+
--mieweb-primary: #2563eb;
|
|
540
|
+
--mieweb-primary-foreground: #ffffff;
|
|
541
|
+
--mieweb-secondary: #f5f5f5;
|
|
542
|
+
--mieweb-secondary-foreground: #171717;
|
|
543
|
+
--mieweb-muted: #f5f5f5;
|
|
544
|
+
--mieweb-muted-foreground: #737373;
|
|
545
|
+
--mieweb-accent: #f5f5f5;
|
|
546
|
+
--mieweb-accent-foreground: #171717;
|
|
547
|
+
--mieweb-destructive: #ef4444;
|
|
548
|
+
--mieweb-destructive-foreground: #ffffff;
|
|
549
|
+
--mieweb-border: #e5e5e5;
|
|
550
|
+
--mieweb-input: #e5e5e5;
|
|
551
|
+
--mieweb-ring: #2563eb;
|
|
552
|
+
|
|
553
|
+
/* Typography */
|
|
554
|
+
--mieweb-font-sans: 'Inter', system-ui, sans-serif;
|
|
555
|
+
|
|
556
|
+
/* Border Radius */
|
|
557
|
+
--mieweb-radius-sm: 0.375rem;
|
|
558
|
+
--mieweb-radius-md: 0.5rem;
|
|
559
|
+
--mieweb-radius-lg: 0.75rem;
|
|
560
|
+
}
|
|
561
|
+
```
|
|
562
|
+
|
|
563
|
+
### Scoped Theming
|
|
564
|
+
|
|
565
|
+
Apply different themes to different instances on the same page by scoping CSS variables to a wrapper element:
|
|
566
|
+
|
|
567
|
+
```html
|
|
568
|
+
<div class="theme-dark" style="
|
|
569
|
+
--mieweb-background: #1a1a1a;
|
|
570
|
+
--mieweb-foreground: #fafafa;
|
|
571
|
+
--mieweb-card: #262626;
|
|
572
|
+
--mieweb-border: #404040;
|
|
573
|
+
">
|
|
574
|
+
<div id="config-container"></div>
|
|
575
|
+
</div>
|
|
576
|
+
```
|
|
577
|
+
|
|
578
|
+
---
|
|
579
|
+
|
|
580
|
+
## Custom Schemas
|
|
581
|
+
|
|
582
|
+
Q uses a JSON schema format (MieForms v1.0) to define the form fields. You can pass a custom schema to control which fields appear in the Form Builder.
|
|
583
|
+
|
|
584
|
+
### Schema Structure
|
|
585
|
+
|
|
586
|
+
```json
|
|
587
|
+
{
|
|
588
|
+
"schemaType": "mieforms-v1.0",
|
|
589
|
+
"title": "My Custom Form",
|
|
590
|
+
"fields": [
|
|
591
|
+
{
|
|
592
|
+
"id": "section-1",
|
|
593
|
+
"fieldType": "section",
|
|
594
|
+
"title": "General Settings",
|
|
595
|
+
"fields": [
|
|
596
|
+
{
|
|
597
|
+
"id": "name",
|
|
598
|
+
"fieldType": "text",
|
|
599
|
+
"question": "Agent Name",
|
|
600
|
+
"answer": "My Agent",
|
|
601
|
+
"required": true
|
|
602
|
+
},
|
|
603
|
+
{
|
|
604
|
+
"id": "provider",
|
|
605
|
+
"fieldType": "dropdown",
|
|
606
|
+
"question": "LLM Provider",
|
|
607
|
+
"answer": "openai",
|
|
608
|
+
"options": ["openai", "anthropic", "google"]
|
|
609
|
+
},
|
|
610
|
+
{
|
|
611
|
+
"id": "enableLogging",
|
|
612
|
+
"fieldType": "check",
|
|
613
|
+
"question": "Enable Logging",
|
|
614
|
+
"answer": false
|
|
615
|
+
},
|
|
616
|
+
{
|
|
617
|
+
"id": "systemPrompt",
|
|
618
|
+
"fieldType": "longtext",
|
|
619
|
+
"question": "System Prompt",
|
|
620
|
+
"answer": ""
|
|
621
|
+
}
|
|
622
|
+
]
|
|
623
|
+
}
|
|
624
|
+
]
|
|
625
|
+
}
|
|
626
|
+
```
|
|
627
|
+
|
|
628
|
+
### Supported Field Types
|
|
629
|
+
|
|
630
|
+
| Type | Description |
|
|
631
|
+
| ---------- | ----------------------------------------------- |
|
|
632
|
+
| `text` | Single-line text input |
|
|
633
|
+
| `longtext` | Multi-line textarea |
|
|
634
|
+
| `dropdown` | Select dropdown (requires `options` array) |
|
|
635
|
+
| `check` | Boolean checkbox |
|
|
636
|
+
| `section` | Grouping container (contains nested `fields`) |
|
|
637
|
+
|
|
638
|
+
### Using Nested Keys
|
|
639
|
+
|
|
640
|
+
Use dot-notation in the field `id` to map to nested config keys:
|
|
641
|
+
|
|
642
|
+
```json
|
|
643
|
+
{
|
|
644
|
+
"id": "twilio.phoneNumber",
|
|
645
|
+
"fieldType": "text",
|
|
646
|
+
"question": "Twilio Phone Number"
|
|
647
|
+
}
|
|
648
|
+
```
|
|
649
|
+
|
|
650
|
+
This produces:
|
|
651
|
+
|
|
652
|
+
```yaml
|
|
653
|
+
twilio:
|
|
654
|
+
phoneNumber: "+1234567890"
|
|
655
|
+
```
|
|
656
|
+
|
|
657
|
+
### Passing a Custom Schema
|
|
658
|
+
|
|
659
|
+
```jsx
|
|
660
|
+
import customSchema from './my-schema.json';
|
|
661
|
+
|
|
662
|
+
<AgentConfigGenerator
|
|
663
|
+
schema={customSchema}
|
|
664
|
+
onSubmit={(yaml) => console.log(yaml)}
|
|
665
|
+
/>
|
|
666
|
+
```
|
|
667
|
+
|
|
668
|
+
---
|
|
669
|
+
|
|
670
|
+
## Architecture & Flow Diagram
|
|
671
|
+
|
|
672
|
+
```mermaid
|
|
673
|
+
flowchart TB
|
|
674
|
+
subgraph Host["Host Application"]
|
|
675
|
+
direction TB
|
|
676
|
+
R["React App"]
|
|
677
|
+
U["Universal Wrapper<br/>(Vanilla JS / Vue / Angular)"]
|
|
678
|
+
end
|
|
679
|
+
|
|
680
|
+
subgraph Q["Q Package"]
|
|
681
|
+
direction TB
|
|
682
|
+
|
|
683
|
+
subgraph Entry["Entry Points"]
|
|
684
|
+
RE["Q (React)<br/>import from 'Q'"]
|
|
685
|
+
UE["Q/universal<br/>import from 'Q/universal'"]
|
|
686
|
+
end
|
|
687
|
+
|
|
688
|
+
subgraph Core["Core Components"]
|
|
689
|
+
ACG["AgentConfigGenerator<br/>(orchestrator)"]
|
|
690
|
+
FB["FormBuilder<br/>(questionnaire UI)"]
|
|
691
|
+
CE["ConfigEditor<br/>(Monaco YAML/JSON)"]
|
|
692
|
+
TB["ToolBuilder<br/>(MCP tool editor)"]
|
|
693
|
+
end
|
|
694
|
+
|
|
695
|
+
subgraph Data["Data Layer"]
|
|
696
|
+
CFG["Config State<br/>(React useState)"]
|
|
697
|
+
SCH["Schema State<br/>(MieForms v1.0)"]
|
|
698
|
+
YAML["YAML/JSON<br/>Output Sync"]
|
|
699
|
+
end
|
|
700
|
+
|
|
701
|
+
subgraph Style["Styling"]
|
|
702
|
+
CSS["Q/style.css<br/>(Tailwind bundle)"]
|
|
703
|
+
VAR["CSS Variables<br/>(--mieweb-*)"]
|
|
704
|
+
BRAND["Brand Themes<br/>(@mieweb/ui)"]
|
|
705
|
+
end
|
|
706
|
+
end
|
|
707
|
+
|
|
708
|
+
R -->|"import { AgentConfigGenerator }"| RE
|
|
709
|
+
U -->|"new UniversalAgentConfigGenerator()"| UE
|
|
710
|
+
UE -->|"wraps with createRoot"| ACG
|
|
711
|
+
RE --> ACG
|
|
712
|
+
|
|
713
|
+
ACG --> FB
|
|
714
|
+
ACG --> CE
|
|
715
|
+
ACG --> TB
|
|
716
|
+
|
|
717
|
+
FB -->|"form answers"| CFG
|
|
718
|
+
CE -->|"editor changes"| CFG
|
|
719
|
+
TB -->|"tool definitions"| CFG
|
|
720
|
+
CFG -->|"sync"| YAML
|
|
721
|
+
CFG <-->|"bidirectional"| SCH
|
|
722
|
+
|
|
723
|
+
BRAND --> VAR
|
|
724
|
+
VAR --> CSS
|
|
725
|
+
|
|
726
|
+
ACG -->|"onConfigChange"| Host
|
|
727
|
+
ACG -->|"onSubmit (YAML)"| Host
|
|
728
|
+
ACG -->|"onDownload"| Host
|
|
729
|
+
```
|
|
730
|
+
|
|
731
|
+
### Data Flow
|
|
732
|
+
|
|
733
|
+
```mermaid
|
|
734
|
+
sequenceDiagram
|
|
735
|
+
participant User
|
|
736
|
+
participant FormBuilder
|
|
737
|
+
participant ConfigState
|
|
738
|
+
participant ConfigEditor
|
|
739
|
+
participant HostApp
|
|
740
|
+
|
|
741
|
+
User->>FormBuilder: Fill out form fields
|
|
742
|
+
FormBuilder->>ConfigState: Update config object
|
|
743
|
+
ConfigState->>ConfigEditor: Sync YAML/JSON strings
|
|
744
|
+
ConfigState->>HostApp: onConfigChange(config)
|
|
745
|
+
|
|
746
|
+
User->>ConfigEditor: Edit YAML/JSON directly
|
|
747
|
+
ConfigEditor->>ConfigState: Parse & update config
|
|
748
|
+
ConfigState->>FormBuilder: Re-render with new values
|
|
749
|
+
|
|
750
|
+
User->>HostApp: Click Submit
|
|
751
|
+
HostApp->>ConfigState: Read yamlOutput
|
|
752
|
+
ConfigState-->>HostApp: onSubmit(yamlString)
|
|
753
|
+
```
|
|
754
|
+
|
|
755
|
+
### Component Tabs
|
|
756
|
+
|
|
757
|
+
```mermaid
|
|
758
|
+
stateDiagram-v2
|
|
759
|
+
[*] --> FormBuilder
|
|
760
|
+
|
|
761
|
+
FormBuilder --> ConfigEditor: Switch tab
|
|
762
|
+
FormBuilder --> ToolBuilder: Switch tab
|
|
763
|
+
ConfigEditor --> FormBuilder: Switch tab
|
|
764
|
+
ConfigEditor --> ToolBuilder: Switch tab
|
|
765
|
+
ToolBuilder --> FormBuilder: Switch tab
|
|
766
|
+
ToolBuilder --> ConfigEditor: Switch tab
|
|
767
|
+
|
|
768
|
+
FormBuilder --> SchemaEditor: Click "Customize Form"
|
|
769
|
+
SchemaEditor --> FormBuilder: Click "Back to Form"
|
|
770
|
+
|
|
771
|
+
state FormBuilder {
|
|
772
|
+
[*] --> RenderForm
|
|
773
|
+
RenderForm: Questionnaire UI
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
state ConfigEditor {
|
|
777
|
+
[*] --> YAML
|
|
778
|
+
YAML --> JSON: Toggle
|
|
779
|
+
JSON --> YAML: Toggle
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
state ToolBuilder {
|
|
783
|
+
[*] --> ToolList
|
|
784
|
+
ToolList: MCP Tool Definitions
|
|
785
|
+
}
|
|
786
|
+
```
|
|
787
|
+
|
|
788
|
+
---
|
|
789
|
+
|
|
790
|
+
## Project Structure
|
|
791
|
+
|
|
792
|
+
```
|
|
793
|
+
Q/
|
|
794
|
+
├── dist/ # Built output (generated)
|
|
795
|
+
│ ├── index.js / index.cjs # React component library
|
|
796
|
+
│ ├── universal.js / .cjs # Framework-agnostic wrapper
|
|
797
|
+
│ └── style.css # Pre-built Tailwind CSS
|
|
798
|
+
├── src/
|
|
799
|
+
│ ├── index.js # React entry — public exports
|
|
800
|
+
│ ├── universal.jsx # Universal wrapper class
|
|
801
|
+
│ ├── index.css # Tailwind directives + custom styles
|
|
802
|
+
│ ├── components/
|
|
803
|
+
│ │ ├── AgentConfigGenerator.jsx # Main orchestrator component
|
|
804
|
+
│ │ ├── FormBuilder.jsx # Questionnaire form renderer
|
|
805
|
+
│ │ ├── ConfigEditor.jsx # Monaco-based YAML/JSON editor
|
|
806
|
+
│ │ └── ToolBuilder.jsx # MCP tool definition editor
|
|
807
|
+
│ ├── schemas/
|
|
808
|
+
│ │ └── agent-config-questionnaire.json # Default form schema
|
|
809
|
+
│ ├── constants/
|
|
810
|
+
│ │ └── defaults.js # Timezones, generic tools
|
|
811
|
+
│ └── utils/
|
|
812
|
+
│ ├── configHelpers.js # YAML/JSON conversion, download, clipboard
|
|
813
|
+
│ └── transformers.js # Schema ↔ config transformations
|
|
814
|
+
├── package.json
|
|
815
|
+
├── vite.config.js # Dev server config
|
|
816
|
+
├── vite.lib.config.js # Library build config
|
|
817
|
+
├── tailwind.config.js # Tailwind CSS config with @mieweb/ui preset
|
|
818
|
+
├── postcss.config.js # PostCSS config (Tailwind + Autoprefixer)
|
|
819
|
+
└── .npmrc # npm config (legacy-peer-deps)
|
|
820
|
+
```
|
|
821
|
+
|
|
822
|
+
---
|
|
823
|
+
|
|
824
|
+
## Development
|
|
825
|
+
|
|
826
|
+
### Running the Dev Server
|
|
827
|
+
|
|
828
|
+
```bash
|
|
829
|
+
# Clone the repo
|
|
830
|
+
git clone https://github.com/avagu-mie/Q.git && cd Q
|
|
831
|
+
|
|
832
|
+
# Install dependencies
|
|
833
|
+
npm install
|
|
834
|
+
|
|
835
|
+
# Start the dev server with both React and Universal demo pages
|
|
836
|
+
npm run dev # Opens index.html (default demo)
|
|
837
|
+
npm run dev:react # Opens the React-specific demo page
|
|
838
|
+
npm run dev:universal # Opens the Universal demo page
|
|
839
|
+
```
|
|
840
|
+
|
|
841
|
+
### Building the Library
|
|
842
|
+
|
|
843
|
+
```bash
|
|
844
|
+
# Build the distributable library files
|
|
845
|
+
npm run build:lib
|
|
846
|
+
|
|
847
|
+
# Full prepare (build + CSS) — runs automatically on npm install from GitHub
|
|
848
|
+
npm run prepare
|
|
849
|
+
```
|
|
850
|
+
|
|
851
|
+
### Key Scripts
|
|
852
|
+
|
|
853
|
+
| Script | Description |
|
|
854
|
+
| ----------------- | ------------------------------------------------------------- |
|
|
855
|
+
| `npm run dev` | Start Vite dev server with HMR |
|
|
856
|
+
| `npm run build` | Production build of the demo app |
|
|
857
|
+
| `npm run build:lib` | Build the library (`dist/index.js`, `dist/universal.js`) |
|
|
858
|
+
| `npm run prepare` | Full library build + Tailwind CSS compilation |
|
|
859
|
+
| `npm run storybook` | Start Storybook for component development |
|
|
860
|
+
|
|
861
|
+
---
|
|
862
|
+
|
|
863
|
+
## Troubleshooting
|
|
864
|
+
|
|
865
|
+
### `npm install` fails with peer dependency errors
|
|
866
|
+
|
|
867
|
+
Q uses `legacy-peer-deps=true` in its `.npmrc` to handle peer dependency conflicts between Storybook (which expects React 18) and the library (which supports React 19). If you encounter peer dep issues in your host app, create an `.npmrc` in your project root:
|
|
868
|
+
|
|
869
|
+
```
|
|
870
|
+
legacy-peer-deps=true
|
|
871
|
+
```
|
|
872
|
+
|
|
873
|
+
### Styles not loading / unstyled components
|
|
874
|
+
|
|
875
|
+
Make sure you import the CSS file:
|
|
876
|
+
|
|
877
|
+
```js
|
|
878
|
+
import 'Q/style.css';
|
|
879
|
+
```
|
|
880
|
+
|
|
881
|
+
This import is **required**. Without it, components will render without any styling.
|
|
882
|
+
|
|
883
|
+
### Component doesn't fill the page
|
|
884
|
+
|
|
885
|
+
Q renders to fill its parent container. Ensure the parent element has an explicit height:
|
|
886
|
+
|
|
887
|
+
```css
|
|
888
|
+
html, body, #root { height: 100%; }
|
|
889
|
+
```
|
|
890
|
+
|
|
891
|
+
### Monaco Editor not loading
|
|
892
|
+
|
|
893
|
+
The Monaco editor (used in the Config Editor tab) is loaded asynchronously. Ensure your bundler supports dynamic imports (all modern bundlers do). If using a CSP (Content Security Policy), make sure `worker-src` allows blob URLs.
|
|
894
|
+
|
|
895
|
+
### Build errors with `ERR_PACKAGE_PATH_NOT_EXPORTED`
|
|
896
|
+
|
|
897
|
+
If you see export map errors, check that you're importing from the correct path:
|
|
898
|
+
|
|
899
|
+
```js
|
|
900
|
+
// ✅ Correct
|
|
901
|
+
import { AgentConfigGenerator } from 'Q';
|
|
902
|
+
import { UniversalAgentConfigGenerator } from 'Q/universal';
|
|
903
|
+
import 'Q/style.css';
|
|
904
|
+
|
|
905
|
+
// ❌ Wrong — don't import from dist/ directly
|
|
906
|
+
import { AgentConfigGenerator } from 'Q/dist/index.js';
|
|
907
|
+
```
|
|
908
|
+
|
|
909
|
+
---
|
|
910
|
+
|
|
911
|
+
## Sample Output
|
|
912
|
+
|
|
913
|
+
Here's an example of the YAML config that Q generates with the default schema:
|
|
914
|
+
|
|
915
|
+
```yaml
|
|
916
|
+
_id: ""
|
|
917
|
+
name: New Agent Config
|
|
918
|
+
timezone: America/New_York
|
|
919
|
+
description: Agent Assistant Description
|
|
920
|
+
twilio:
|
|
921
|
+
phoneNumber: ""
|
|
922
|
+
accountSid: ""
|
|
923
|
+
authToken: ""
|
|
924
|
+
officeOpeningTime: 8
|
|
925
|
+
officeClosingTime: 17
|
|
926
|
+
systemPrompt: ""
|
|
927
|
+
tools: []
|
|
928
|
+
```
|
|
929
|
+
|
|
930
|
+
Each field in the form maps directly to a key in this output. Nested keys (like `twilio.phoneNumber`) are expanded into nested YAML objects. The Tool Builder tab adds entries to the `tools` array using the MCP `inputSchema` format.
|
|
931
|
+
|
|
932
|
+
|