llm_meta_widget 0.8.1 → 0.8.3
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.
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: fcfba551ebe519801ae61b03a7e960a90f990f62d6a80d4f0c047f795e1be80a
|
|
4
|
+
data.tar.gz: 58357c2fe24fb77a0b93a66b1c612afa6a9f59e52448f7b20aa97a9bbd9024c4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 41ed12fd2884710a5208fb7a64064960072bb0667ee0c45d842c79ebd86ecc3cdbd45ad925b4dada6067bffe69797c1454e2a32ad353e57c0f45c8c12da3cdc7
|
|
7
|
+
data.tar.gz: 30bc09dfbba4e0b1cba18ab3a56c2706b0f62a297f649a12e9547ede038d27509eaccf570e4bde04f2ac9f215d5c0bf658facbc59f1d88d978b95e959c50a061
|
data/README.md
CHANGED
|
@@ -2,9 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
Embeddable browser chat widget for the [llm_meta](https://github.com/pubannotation) ecosystem.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
The browser does the orchestrating. At boot the widget reads the tools your page
|
|
6
|
+
declares and any `.well-known/mcp.json` your host publishes. When the model calls
|
|
7
|
+
a tool, the widget runs it: in the page itself, or against an MCP endpoint
|
|
8
|
+
directly. Only the chat goes through the meta-server, over SSE.
|
|
6
9
|
|
|
7
|
-
|
|
10
|
+
It ships as a custom element in one self-contained ES module. The same file is on
|
|
11
|
+
npm for any host, and in a Rails gem whose helper serves it for you.
|
|
12
|
+
|
|
13
|
+
**No** Devise, DB migrations, ChatManager, or PromptNavigator. The gem adds only `rails >= 8.0` as a runtime dep — so hosts that haven't bumped to 8.1 can adopt it without a Rails upgrade — and hosts that do not use Rails do not need the gem.
|
|
8
14
|
|
|
9
15
|
## What you need first
|
|
10
16
|
|
|
@@ -37,7 +43,7 @@ that section.
|
|
|
37
43
|
| Your app | What you add | What you write |
|
|
38
44
|
|---|---|---|
|
|
39
45
|
| **Rails** | the gem, one line in your `Gemfile` | one helper call in a view. The helper writes the `<llm-meta-widget>` tag for you, so you never write that tag yourself |
|
|
40
|
-
| **Anything else** — Python, Go, PHP, plain HTML… | one `<script>` tag from the CDN | the `<llm-meta-widget>` tag yourself |
|
|
46
|
+
| **Anything else** — Python, Go, PHP, plain HTML… | one `<script>` tag from the CDN, or an npm dependency you bundle | the `<llm-meta-widget>` tag yourself |
|
|
41
47
|
|
|
42
48
|
Both ways load the same file and run the same widget.
|
|
43
49
|
|
|
@@ -108,7 +114,7 @@ Two more things worth knowing before you go further:
|
|
|
108
114
|
- The model name is the hub's name for it (`GET /api/llms` lists them), not
|
|
109
115
|
the provider's.
|
|
110
116
|
|
|
111
|
-
Once that works, the widget can
|
|
117
|
+
Once that works, the widget can talk, but it cannot *do* anything yet. To let the
|
|
112
118
|
LLM act on your page or call your own services, declare tools using any of the
|
|
113
119
|
**three tool classes** below.
|
|
114
120
|
|
|
@@ -135,37 +141,73 @@ instead of ERB. Both produce the same widget, so the advice in that section
|
|
|
135
141
|
— CORS, a reachable `llm_url`, the hub's name for the model — applies here
|
|
136
142
|
too.
|
|
137
143
|
|
|
138
|
-
**`@0.8` is a range, and it stops at 0.8.x on purpose.** You
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
144
|
+
**`@0.8` is a version range, and it stops at 0.8.x on purpose.** You receive bug
|
|
145
|
+
fixes without editing your page, and a release that breaks your page cannot
|
|
146
|
+
arrive on its own.
|
|
147
|
+
|
|
148
|
+
Moving to 0.9 is therefore a change you make yourself. Read
|
|
149
|
+
[CHANGELOG.md](CHANGELOG.md) before you do, because this is where what your page
|
|
150
|
+
must provide can change. For example, 0.8.0 changed the shape of
|
|
151
|
+
`window.aiState`. A page that used the new shape while still loading `@0.7`
|
|
152
|
+
would have shown an error string in place of every value, with no other warning.
|
|
153
|
+
|
|
154
|
+
A Rails app is protected from that mismatch, because the `Gemfile` will not
|
|
155
|
+
resolve a widget version the page cannot use. A page that loads the widget from
|
|
156
|
+
the CDN has no such check, so the version you write in that URL is the only
|
|
157
|
+
protection you have.
|
|
147
158
|
|
|
148
159
|
Nothing else is needed: the stylesheets and the markdown renderer are bundled
|
|
149
160
|
in, and the element injects its own styles. The host serves no CSS and no JS.
|
|
150
161
|
|
|
151
|
-
|
|
162
|
+
### If you have a JS build pipeline, install it instead
|
|
163
|
+
|
|
164
|
+
Vite, webpack, esbuild, Next.js, SvelteKit, Astro — if your app already builds
|
|
165
|
+
JavaScript, take the widget as a dependency rather than a script tag:
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
npm install @aibranch/llm-meta-widget
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
```js
|
|
172
|
+
// Once, at your app's entry point. Importing the package is all you need: it
|
|
173
|
+
// defines the custom element. There is no function to call and nothing to name.
|
|
174
|
+
import "@aibranch/llm-meta-widget";
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Then write the `<llm-meta-widget>` tag exactly as above — same attributes, same
|
|
178
|
+
behaviour.
|
|
179
|
+
|
|
180
|
+
**Why do this, when the script tag is only one line?** Because your build then
|
|
181
|
+
checks the version for you. The version is pinned in your lockfile and installed by `npm ci`
|
|
182
|
+
with integrity checking, so you know which widget your page runs and your
|
|
183
|
+
colleague's build runs the same one. On the CDN path the version lives in a URL
|
|
184
|
+
that nothing checks. That matters most at a breaking release: 0.8.0 changed the
|
|
185
|
+
shape of `window.aiState`, and a lockfile makes the upgrade a deliberate, visible
|
|
186
|
+
step instead of a URL someone edits.
|
|
187
|
+
|
|
188
|
+
The only cost is that this path needs a build pipeline. The CDN path needs none,
|
|
189
|
+
which is why it is listed first.
|
|
190
|
+
|
|
191
|
+
Four ways to get that one file, in descending order of convenience:
|
|
152
192
|
|
|
153
193
|
- **the CDN**, as above — `@aibranch/llm-meta-widget` on npm, no path needed
|
|
154
194
|
because the package's `main` is the bundle;
|
|
195
|
+
- **npm install plus your own bundler**, as above — the same package, resolved
|
|
196
|
+
through `exports` and pinned by your lockfile;
|
|
155
197
|
- **the gem**, which serves the identical file at
|
|
156
198
|
`/llm_meta_widget_assets/llm-meta-widget.js` for Rails hosts, and is what the
|
|
157
199
|
`llm_meta_widget` helper points at;
|
|
158
200
|
- **self-hosted** — copy it out of the package or the gem and serve it as a
|
|
159
201
|
static asset, if you would rather not depend on a CDN.
|
|
160
202
|
|
|
161
|
-
Going without the gem removes the Rails
|
|
162
|
-
|
|
163
|
-
page
|
|
164
|
-
`window.aiActions`
|
|
165
|
-
|
|
203
|
+
Going without the gem removes the Rails parts: the helper and the partial. It
|
|
204
|
+
does not change what your page itself must provide, because those parts belong to
|
|
205
|
+
the page, not to Rails. You declare the `#ai-actions` JSON block, `window.aiState`
|
|
206
|
+
and `window.aiActions` exactly as a Rails page does — see the three tool classes
|
|
207
|
+
below.
|
|
166
208
|
|
|
167
|
-
**Attributes**
|
|
168
|
-
|
|
209
|
+
**Attributes** match the helper's keyword options one to one. Three of them are
|
|
210
|
+
easy to get wrong:
|
|
169
211
|
|
|
170
212
|
| attribute | notes |
|
|
171
213
|
|---|---|
|
|
@@ -176,11 +218,11 @@ obvious and are the ones that bite:
|
|
|
176
218
|
| `actions-schema-id`, `state-global`, `actions-global`, `remote-tools-schema-id` | as the helper options |
|
|
177
219
|
| `models`, `hub-tools` | comma-separated. Omitted **or empty** means no allowlist — an allowlist permitting nothing is never what anyone meant |
|
|
178
220
|
| `enable-model-picker`, `enable-tool-picker` | **value attributes, not boolean attributes.** They default to true, so presence cannot mean true. Disable with `enable-tool-picker="false"`; any other value is true |
|
|
179
|
-
| `well-known-urls` | **
|
|
221
|
+
| `well-known-urls` | **Three different states**, because an attribute cannot tell "not set" from "set to empty": omitted = auto-discover same-origin `/.well-known/mcp.json`; `""` = discovery off; `"a,b"` = fetch those |
|
|
180
222
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
console.
|
|
223
|
+
The last one fails quietly. If you expect discovery to be off but leave the
|
|
224
|
+
attribute out, the widget fetches your own origin instead. Nothing appears to
|
|
225
|
+
happen, except a 404 in the browser console.
|
|
184
226
|
|
|
185
227
|
One widget per page. The panel uses fixed element ids, so a second
|
|
186
228
|
`<llm-meta-widget>` is ignored with a console warning rather than fighting the
|
|
@@ -42,7 +42,10 @@ const MARKUP = `
|
|
|
42
42
|
|
|
43
43
|
<div id="llm-meta-widget-chat" class="llm-meta-conversation">
|
|
44
44
|
<div class="lmw-header">
|
|
45
|
-
<span class="lmw-title">
|
|
45
|
+
<span class="lmw-title-group">
|
|
46
|
+
<span class="lmw-title">AI assistant</span>
|
|
47
|
+
<a class="lmw-powered" href="https://chat.aibranch.org/" target="_blank" rel="noopener noreferrer">(powered by AIbranch)</a>
|
|
48
|
+
</span>
|
|
46
49
|
<div class="lmw-header-right">
|
|
47
50
|
<button type="button" class="lmw-clear" title="Clear conversation">clear</button>
|
|
48
51
|
<button type="button" class="lmw-hide" title="Hide">−</button>
|
|
@@ -3272,6 +3272,18 @@ var panel_default = `/* The chat panel's own styles. Extracted from _chat_panel.
|
|
|
3272
3272
|
}
|
|
3273
3273
|
#llm-meta-widget-chat .lmw-title { font-weight: 600; color: #1f2937; }
|
|
3274
3274
|
|
|
3275
|
+
/* Attribution back to the service that answers these chats. The header is
|
|
3276
|
+
* \`space-between\` with two children, so the title and the link travel
|
|
3277
|
+
* together in one group \u2014 otherwise the link lands in the middle of the
|
|
3278
|
+
* bar, visually detached from the title it qualifies. */
|
|
3279
|
+
#llm-meta-widget-chat .lmw-title-group {
|
|
3280
|
+
display: flex; align-items: baseline; gap: 6px; min-width: 0;
|
|
3281
|
+
}
|
|
3282
|
+
#llm-meta-widget-chat .lmw-powered {
|
|
3283
|
+
font-size: 11px; color: #6b7280; text-decoration: none; white-space: nowrap;
|
|
3284
|
+
}
|
|
3285
|
+
#llm-meta-widget-chat .lmw-powered:hover { color: #2563eb; text-decoration: underline; }
|
|
3286
|
+
|
|
3275
3287
|
/* Level-1 model picker \u2014 compact <select> next to the title.
|
|
3276
3288
|
* Populated by JS on widget open from GET /api/llms (anon path
|
|
3277
3289
|
* returns Ollama-only). Hidden entirely if enable_model_picker
|
|
@@ -3557,7 +3569,10 @@ var MARKUP = `
|
|
|
3557
3569
|
|
|
3558
3570
|
<div id="llm-meta-widget-chat" class="llm-meta-conversation">
|
|
3559
3571
|
<div class="lmw-header">
|
|
3560
|
-
<span class="lmw-title">
|
|
3572
|
+
<span class="lmw-title-group">
|
|
3573
|
+
<span class="lmw-title">AI assistant</span>
|
|
3574
|
+
<a class="lmw-powered" href="https://chat.aibranch.org/" target="_blank" rel="noopener noreferrer">(powered by AIbranch)</a>
|
|
3575
|
+
</span>
|
|
3561
3576
|
<div class="lmw-header-right">
|
|
3562
3577
|
<button type="button" class="lmw-clear" title="Clear conversation">clear</button>
|
|
3563
3578
|
<button type="button" class="lmw-hide" title="Hide">\u2212</button>
|
|
@@ -89,6 +89,18 @@
|
|
|
89
89
|
}
|
|
90
90
|
#llm-meta-widget-chat .lmw-title { font-weight: 600; color: #1f2937; }
|
|
91
91
|
|
|
92
|
+
/* Attribution back to the service that answers these chats. The header is
|
|
93
|
+
* `space-between` with two children, so the title and the link travel
|
|
94
|
+
* together in one group — otherwise the link lands in the middle of the
|
|
95
|
+
* bar, visually detached from the title it qualifies. */
|
|
96
|
+
#llm-meta-widget-chat .lmw-title-group {
|
|
97
|
+
display: flex; align-items: baseline; gap: 6px; min-width: 0;
|
|
98
|
+
}
|
|
99
|
+
#llm-meta-widget-chat .lmw-powered {
|
|
100
|
+
font-size: 11px; color: #6b7280; text-decoration: none; white-space: nowrap;
|
|
101
|
+
}
|
|
102
|
+
#llm-meta-widget-chat .lmw-powered:hover { color: #2563eb; text-decoration: underline; }
|
|
103
|
+
|
|
92
104
|
/* Level-1 model picker — compact <select> next to the title.
|
|
93
105
|
* Populated by JS on widget open from GET /api/llms (anon path
|
|
94
106
|
* returns Ollama-only). Hidden entirely if enable_model_picker
|