murmur-rag 1.2.0 → 1.3.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 (43) hide show
  1. package/README.md +26 -17
  2. package/dist/cdn/{anthropic-ynz7717b.js → anthropic-tw416spz.js} +2 -2
  3. package/dist/cdn/chunk-xyp6nm65.js +1 -0
  4. package/dist/cdn/{embed-xtkxyrpe.js → embed-3am76qfd.js} +6 -6
  5. package/dist/cdn/embed-50pfy67v.js +83 -0
  6. package/dist/cdn/{embed-n5nzhrf2.js → embed-cx1r66ch.js} +6 -6
  7. package/dist/cdn/{embed-7pk91zq8.js → embed-g0p6yc29.js} +2 -2
  8. package/dist/cdn/{embed-krrjjyf5.js → embed-q81wdr1z.js} +4 -4
  9. package/dist/cdn/embed-rjpq8psf.js +10 -0
  10. package/dist/cdn/{embed-0m8xctqy.js → embed-yz75savs.js} +3 -3
  11. package/dist/cdn/{google-k5kwa54v.js → google-556tp13p.js} +8 -8
  12. package/dist/cdn/index-8r44b2wt.js +1 -0
  13. package/dist/cdn/index-a5j4aat5.js +1 -0
  14. package/dist/cdn/index-ft8r539a.js +1 -0
  15. package/dist/cdn/index-pjxy71n5.js +1 -0
  16. package/dist/cdn/{index-gyd02jvt.js → index-qpy1k923.js} +2 -2
  17. package/dist/cdn/{mistral-p2qcnn42.js → mistral-25w1nsx5.js} +2 -2
  18. package/dist/cdn/{murmur-d6t6cjc7.js → murmur-1a55et82.js} +3 -3
  19. package/dist/cdn/murmur.js +7 -7
  20. package/dist/cdn/{openai-d3q1d6cz.js → openai-bjrbem49.js} +12 -12
  21. package/dist/cdn/{openai-compatible-psnkrpxy.js → openai-compatible-sg25g0vj.js} +6 -6
  22. package/dist/cdn/retriever-06ybegpd.js +1 -0
  23. package/dist/cdn/{transformers.web-xn16v7pz.js → transformers.web-49m0ht4a.js} +7 -7
  24. package/dist/lib/chunks/{index-y3v46yjp.js → index-4ftk20yq.js} +143 -39
  25. package/dist/lib/embed.js +8 -2
  26. package/dist/lib/llm/index.js +23 -0
  27. package/dist/lib/local/index.js +38 -2
  28. package/dist/lib/widget/index.js +2 -2
  29. package/dist/types/llm/index.d.ts +8 -0
  30. package/dist/types/local/index.d.ts +12 -0
  31. package/dist/types/widget/element.d.ts +4 -0
  32. package/dist/types/widget/i18n.d.ts +1 -0
  33. package/dist/types/widget/session.d.ts +43 -7
  34. package/dist/types/widget/styles.d.ts +1 -1
  35. package/package.json +1 -1
  36. package/dist/cdn/chunk-hpx6rpea.js +0 -1
  37. package/dist/cdn/embed-dbkjhg16.js +0 -83
  38. package/dist/cdn/embed-rp9gb1qq.js +0 -10
  39. package/dist/cdn/index-db4ne93m.js +0 -1
  40. package/dist/cdn/index-qc8kgsdt.js +0 -1
  41. package/dist/cdn/index-t0qn2m4r.js +0 -1
  42. package/dist/cdn/index-y0faj89r.js +0 -1
  43. package/dist/cdn/retriever-6qvn2maq.js +0 -1
@@ -30,6 +30,20 @@ export interface WidgetOptions {
30
30
  storageKey?: string;
31
31
  /** Open the panel on load. */
32
32
  open?: boolean;
33
+ /**
34
+ * How the widget answers. `auto` (default): the owner's proxy or key if set, else the model in
35
+ * the visitor's browser with their own key as an option. `proxy`: only `llm.endpoint`. `local`:
36
+ * only the in-browser model, no key settings. `key`: only a key, the owner's `llm.apiKey` or
37
+ * else each visitor's own.
38
+ */
39
+ mode?: WidgetMode;
40
+ /**
41
+ * When the in-browser model downloads (about 1.1 GB, once; then it loads from the browser's
42
+ * cache): `question` (default) on the first question, `open` when the panel opens, `idle` as
43
+ * soon as the page is idle, `consent` after the visitor agrees on a prompt. A model already in
44
+ * the cache is prepared in the background whatever this says, without network.
45
+ */
46
+ preload?: Preload;
33
47
  /**
34
48
  * The model that runs in the visitor's browser on WebGPU, the default way to answer when there
35
49
  * is no proxy: LFM3 1.7B, about 1.1 GB downloaded once after the visitor agrees. Visitors can
@@ -43,7 +57,14 @@ export interface ChatTurn extends Turn {
43
57
  cited?: number[];
44
58
  error?: string;
45
59
  }
46
- type Mode = "custom" | "local" | "proxy" | "visitor";
60
+ export type WidgetMode = "auto" | "proxy" | "local" | "key";
61
+ export type Preload = "question" | "open" | "idle" | "consent";
62
+ /** Where the in-browser model is: not started, downloading or compiling, ready, or failed. */
63
+ export interface LocalState {
64
+ status: "idle" | "loading" | "ready" | "error";
65
+ progress?: LoadProgress;
66
+ }
67
+ type Mode = "custom" | "local" | "owner" | "proxy" | "visitor";
47
68
  /** Everything the widget does except drawing: index, model settings, history. */
48
69
  export declare class ChatSession {
49
70
  readonly options: WidgetOptions;
@@ -52,16 +73,31 @@ export declare class ChatSession {
52
73
  private storePromise;
53
74
  private readonly historyKey;
54
75
  private readonly key;
55
- /** Called while the in-browser model downloads. */
56
- onProgress: ((progress: LoadProgress) => void) | null;
76
+ private local;
77
+ private readonly localListeners;
57
78
  constructor(options: WidgetOptions);
79
+ private get configured();
58
80
  /**
59
- * How this session answers: your own model, then the owner's proxy, then the visitor's own
60
- * key if they chose one, else the model in the browser.
81
+ * How this session answers: your own model; then the owner's proxy, then the owner's key;
82
+ * then the visitor's own key if they chose one; else the model in the browser.
61
83
  */
62
84
  get mode(): Mode;
63
- /** Whether the in-browser model is offered: not with your own model or a proxy, nor `local: false`. */
85
+ /** Whether the in-browser model is offered at all. */
64
86
  get localAllowed(): boolean;
87
+ /** Whether visitors may connect their own key (the AI settings). */
88
+ get keyAllowed(): boolean;
89
+ /** Where the in-browser model is, and a way to follow it. */
90
+ get localState(): LocalState;
91
+ onLocalState(listener: (state: LocalState) => void): () => void;
92
+ private setLocal;
93
+ /**
94
+ * Starts loading the in-browser model now, in the background: downloads it if needed, then
95
+ * compiles it. Does nothing outside the local mode or without WebGPU. Safe to call often.
96
+ */
97
+ warmUp(): Promise<void>;
98
+ /** A model already in the browser's cache is prepared right away: no network, no prompt. */
99
+ warmUpIfCached(): Promise<void>;
100
+ get preload(): Preload;
65
101
  /**
66
102
  * Before a question: a visitor who saved a key before the in-browser model became the default,
67
103
  * and never chose between the two, keeps their key.
@@ -71,7 +107,7 @@ export declare class ChatSession {
71
107
  localSpec(): Promise<LocalModelSpec>;
72
108
  /** The visitor picks the in-browser model, or their own key. */
73
109
  useLocal(on: boolean): void;
74
- /** Whether the visitor must still agree to download the in-browser model. */
110
+ /** Whether the visitor must still agree to download the in-browser model (`preload: "consent"`). */
75
111
  get needsDownloadConsent(): boolean;
76
112
  agreeToDownload(): void;
77
113
  persist(): void;
@@ -3,4 +3,4 @@
3
3
  * custom properties on the element: --murmur-accent, --murmur-accent-ink, --murmur-font,
4
4
  * --murmur-radius, --murmur-z.
5
5
  */
6
- export declare const STYLES = "\n:host {\n --accent: var(--murmur-accent, #211c17);\n --accent-ink: var(--murmur-accent-ink, #f6efe0);\n --lamp: var(--murmur-lamp, #e0a032);\n --surface: #fbf8f1;\n --raised: #f2ece0;\n --ink: #211c17;\n --muted: #675c4f;\n --line: #e2d8c5;\n --focus: #b4541d;\n --danger: #a1301f;\n --radius: var(--murmur-radius, 16px);\n --shadow: 0 18px 48px -12px rgb(33 28 23 / 0.28), 0 4px 12px -4px rgb(33 28 23 / 0.16);\n --ease: cubic-bezier(0.16, 1, 0.3, 1);\n all: initial;\n position: fixed;\n z-index: var(--murmur-z, 2147483000);\n inset: auto 20px 20px auto;\n font-family: var(--murmur-font, inherit);\n font-size: 15px;\n line-height: 1.5;\n color: var(--ink);\n color-scheme: light;\n -webkit-font-smoothing: antialiased;\n}\n:host([position=\"bottom-left\"]) { inset: auto auto 20px 20px; }\n:host([inline]) { position: relative; inset: auto; z-index: auto; display: block; height: 100%; }\n:host([theme=\"dark\"]) { --surface: #1c1814; --raised: #26211b; --ink: #f2ead9; --muted: #b8ab95; --line: #3b342b; --focus: #f0a35c; --danger: #f08a73; color-scheme: dark; }\n@media (prefers-color-scheme: dark) {\n :host(:not([theme=\"light\"])) { --surface: #1c1814; --raised: #26211b; --ink: #f2ead9; --muted: #b8ab95; --line: #3b342b; --focus: #f0a35c; --danger: #f08a73; color-scheme: dark; }\n :host(:not([theme=\"light\"])) { --murmur-accent-default: #f2ead9; }\n}\n@media print { :host { display: none !important; } }\n* { box-sizing: border-box; }\n[hidden] { display: none !important; }\n::selection { background: color-mix(in oklab, var(--lamp) 45%, transparent); color: inherit; }\nbutton, input, select, textarea { font: inherit; color: inherit; }\nbutton { cursor: pointer; }\n:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }\na { color: inherit; text-underline-offset: 0.2em; text-decoration-thickness: 1px; }\n\n/* Launcher */\n.launcher {\n display: inline-flex; align-items: center; gap: 10px;\n height: 52px; padding: 0 20px 0 16px; border: 0; border-radius: 26px;\n background: var(--accent); color: var(--accent-ink);\n box-shadow: var(--shadow); font-weight: 600; letter-spacing: 0.01em;\n transition: transform 220ms var(--ease), box-shadow 220ms var(--ease);\n}\n.launcher:hover { transform: translateY(-2px); }\n.launcher:active { transform: translateY(0); }\n.launcher[aria-expanded=\"true\"] { display: none; }\n.lamp {\n width: 8px; height: 8px; border-radius: 50%; flex: none;\n background: var(--lamp); box-shadow: 0 0 0 3px color-mix(in oklab, var(--lamp) 28%, transparent);\n}\n.lamp.off { background: transparent; box-shadow: inset 0 0 0 1.5px var(--muted); }\n.lamp.busy { animation: blink 1.1s steps(2, jump-none) infinite; }\n@keyframes blink { 50% { opacity: 0.25; } }\n\n/* Panel */\n.panel {\n position: absolute; right: 0; bottom: 0;\n display: flex; flex-direction: column;\n width: min(400px, calc(100vw - 40px)); height: min(640px, calc(100dvh - 40px));\n background: var(--surface); border-radius: var(--radius); box-shadow: var(--shadow);\n overflow: hidden; transform-origin: bottom right;\n animation: rise 320ms var(--ease);\n}\n:host([position=\"bottom-left\"]) .panel { right: auto; left: 0; transform-origin: bottom left; }\n:host([inline]) .panel { position: static; width: 100%; height: 100%; box-shadow: none; animation: none; border-radius: inherit; }\n@keyframes rise { from { opacity: 0; transform: translateY(12px) scale(0.98); } }\n@media (max-width: 480px) {\n :host(:not([inline])) { inset: auto 12px 12px auto; }\n :host(:not([inline])[position=\"bottom-left\"]) { inset: auto auto 12px 12px; }\n :host(:not([inline])) .panel { position: fixed; inset: 0; width: 100%; height: 100dvh; border-radius: 0; }\n}\n\nheader {\n display: flex; align-items: center; gap: 10px;\n padding: 14px 10px 14px 18px; background: var(--accent); color: var(--accent-ink);\n}\nheader h2 { flex: 1; margin: 0; font-size: 16px; font-weight: 650; letter-spacing: 0.005em; line-height: 1.25; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.icon-btn {\n display: inline-grid; place-items: center; width: 36px; height: 36px; flex: none;\n border: 0; border-radius: 10px; background: transparent; color: inherit;\n transition: background 160ms;\n}\n.icon-btn:hover { background: color-mix(in oklab, currentColor 14%, transparent); }\nheader .icon-btn:focus-visible { outline-color: var(--accent-ink); }\n\n/* Conversation */\n.log {\n flex: 1; overflow-y: auto; overscroll-behavior: contain;\n padding: 18px 18px 8px; display: flex; flex-direction: column; gap: 16px;\n scrollbar-width: thin; scrollbar-color: var(--line) transparent;\n}\n.msg { max-width: 100%; overflow-wrap: anywhere; }\n.msg p { margin: 0 0 0.6em; }\n.msg p:last-child { margin-bottom: 0; }\n.msg ul, .msg ol { margin: 0 0 0.6em; padding-left: 1.3em; }\n.msg li + li { margin-top: 0.2em; }\n.msg code { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 0.88em; background: var(--raised); padding: 0.1em 0.35em; border-radius: 5px; }\n.msg pre { margin: 0 0 0.6em; padding: 10px 12px; background: var(--raised); border-radius: 10px; overflow-x: auto; }\n.msg pre code { background: none; padding: 0; }\n.msg .table { margin: 0 0 0.6em; overflow-x: auto; border-radius: 10px; box-shadow: inset 0 0 0 1px var(--line); }\n.msg table { width: 100%; border-collapse: collapse; font-size: 14px; }\n.msg th, .msg td { padding: 6px 10px; text-align: left; vertical-align: top; border-bottom: 1px solid var(--line); }\n.msg tr:last-child td { border-bottom: 0; }\n.msg th { font-weight: 650; background: var(--raised); }\n.msg blockquote { margin: 0 0 0.6em; padding: 2px 0 2px 12px; color: var(--muted); box-shadow: inset 1px 0 0 var(--line); }\n.msg hr { margin: 0.8em 0; border: 0; border-top: 1px solid var(--line); }\n.user {\n align-self: flex-end; max-width: 85%;\n padding: 9px 14px; border-radius: 16px 16px 4px 16px;\n background: var(--accent); color: var(--accent-ink); white-space: pre-wrap;\n}\n.bot { align-self: stretch; }\n.greeting { color: var(--muted); }\n\n.cite {\n display: inline-grid; place-items: center; min-width: 1.45em; height: 1.45em; padding: 0 0.3em;\n margin: 0 0.1em; vertical-align: 0.12em;\n border-radius: 1em; box-shadow: inset 0 0 0 1.25px currentColor;\n font-size: 0.72em; font-weight: 700; line-height: 1; text-decoration: none;\n font-variant-numeric: tabular-nums; color: var(--muted);\n transition: background 160ms, color 160ms;\n}\n.cite:hover, .cite:focus-visible { background: var(--lamp); color: #211c17; box-shadow: none; }\n\n.sources { margin: 12px 0 0; padding: 0; list-style: none; display: grid; gap: 2px; }\n.sources-label { margin: 18px 0 2px; font-size: 12px; font-weight: 650; letter-spacing: 0.06em; text-transform: uppercase; color: var(--muted); }\n.sources a {\n display: grid; grid-template-columns: auto 1fr; align-items: baseline; gap: 10px;\n padding: 7px 10px; margin: 0 -10px; border-radius: 10px; text-decoration: none;\n}\n.sources a:hover { background: var(--raised); }\n.sources .cite { margin: 0; }\n.sources .where { min-width: 0; font-size: 14px; line-height: 1.35; }\n.sources .where span { color: var(--muted); }\n\n.status { display: flex; align-items: center; gap: 10px; color: var(--muted); font-size: 14px; }\n.error { color: var(--danger); }\n.error p { margin: 0 0 8px; }\n.text-btn {\n display: inline-flex; align-items: center; gap: 6px; padding: 6px 12px; border-radius: 9px;\n border: 0; background: var(--raised); color: var(--ink); font-size: 14px; font-weight: 600;\n}\n.text-btn:hover { background: var(--line); }\n\n/* Composer */\nform.composer {\n display: flex; align-items: flex-end; gap: 8px; margin: 8px 12px 0; padding: 6px 6px 6px 14px;\n border-radius: 14px; background: var(--raised);\n box-shadow: inset 0 0 0 1px var(--line); transition: box-shadow 160ms;\n}\nform.composer:focus-within { box-shadow: inset 0 0 0 1.5px var(--focus); }\ntextarea {\n flex: 1; min-height: 38px; max-height: 140px; padding: 8px 0; resize: none;\n border: 0; background: transparent; outline: none; line-height: 1.4;\n}\ntextarea:focus-visible { outline: none; }\ntextarea::placeholder, input::placeholder { color: var(--muted); opacity: 1; }\n.send {\n display: inline-grid; place-items: center; width: 38px; height: 38px; flex: none;\n border: 0; border-radius: 10px; background: var(--accent); color: var(--accent-ink);\n transition: opacity 160ms;\n}\n.send:disabled { opacity: 0.35; cursor: default; }\nfooter { padding: 8px 18px 12px; font-size: 12px; color: var(--muted); text-align: center; }\nfooter a { text-decoration: none; }\nfooter a:hover { text-decoration: underline; }\n\n/* Settings */\n.setup { flex: 1; overflow-y: auto; padding: 18px; display: grid; gap: 16px; align-content: start; }\n.setup p.intro { margin: 0; color: var(--muted); font-size: 14px; }\n.field { display: grid; gap: 6px; }\n.field > span { font-size: 13px; font-weight: 650; }\n.field small { color: var(--muted); font-size: 12.5px; }\n.field input:not([type=\"checkbox\"]), .field select {\n width: 100%; height: 40px; padding: 0 12px; border-radius: 10px;\n border: 0; background: var(--raised); box-shadow: inset 0 0 0 1px var(--line);\n}\n.field input:focus-visible, .field select:focus-visible { outline: none; box-shadow: inset 0 0 0 1.5px var(--focus); }\n.check { display: flex; align-items: center; gap: 10px; font-size: 14px; }\n.check input { width: 18px; height: 18px; accent-color: var(--accent); margin: 0; }\n.presets { display: flex; gap: 8px; flex-wrap: wrap; }\n.row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }\n.primary {\n display: inline-flex; align-items: center; justify-content: center; gap: 8px;\n height: 42px; padding: 0 18px; border: 0; border-radius: 11px;\n background: var(--accent); color: var(--accent-ink); font-weight: 650;\n}\n.primary:disabled { opacity: 0.4; cursor: default; }\n.result { font-size: 14px; }\n.result.ok { color: inherit; }\n.result.ok::before { content: \"\"; display: inline-block; width: 8px; height: 8px; margin-right: 8px; border-radius: 50%; background: var(--lamp); }\n.result.fail { color: var(--danger); }\n.local-choice { display: grid; gap: 6px; padding: 14px; border-radius: 12px; background: var(--raised); }\n.local-choice small { color: var(--muted); font-size: 12.5px; }\n.local-choice .link-btn { margin-top: 2px; }\np.or { margin: 0; color: var(--muted); font-size: 13px; text-align: center; }\n.consent { display: grid; gap: 10px; padding: 14px; border-radius: 12px; background: var(--raised); }\n.consent p { margin: 0; }\n.status .grow { display: grid; gap: 6px; flex: 1; }\nprogress { width: 100%; height: 6px; appearance: none; border: 0; border-radius: 3px; background: var(--line); overflow: hidden; }\nprogress::-webkit-progress-bar { background: var(--line); }\nprogress::-webkit-progress-value { background: var(--lamp); }\nprogress::-moz-progress-bar { background: var(--lamp); }\n.link-btn { padding: 0; border: 0; background: none; color: var(--muted); font-size: 13px; text-decoration: underline; text-underline-offset: 0.2em; justify-self: start; }\n\n.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }\n\n@media (prefers-reduced-motion: reduce) {\n *, .panel { animation: none !important; transition: none !important; }\n}\n";
6
+ export declare const STYLES = "\n:host {\n --accent: var(--murmur-accent, #211c17);\n --accent-ink: var(--murmur-accent-ink, #f6efe0);\n --lamp: var(--murmur-lamp, #e0a032);\n --surface: #fbf8f1;\n --raised: #f2ece0;\n --ink: #211c17;\n --muted: #675c4f;\n --line: #e2d8c5;\n --focus: #b4541d;\n --danger: #a1301f;\n --radius: var(--murmur-radius, 16px);\n --shadow: 0 18px 48px -12px rgb(33 28 23 / 0.28), 0 4px 12px -4px rgb(33 28 23 / 0.16);\n --ease: cubic-bezier(0.16, 1, 0.3, 1);\n all: initial;\n position: fixed;\n z-index: var(--murmur-z, 2147483000);\n inset: auto 20px 20px auto;\n font-family: var(--murmur-font, inherit);\n font-size: 15px;\n line-height: 1.5;\n color: var(--ink);\n color-scheme: light;\n -webkit-font-smoothing: antialiased;\n}\n:host([position=\"bottom-left\"]) { inset: auto auto 20px 20px; }\n:host([inline]) { position: relative; inset: auto; z-index: auto; display: block; height: 100%; }\n:host([theme=\"dark\"]) { --surface: #1c1814; --raised: #26211b; --ink: #f2ead9; --muted: #b8ab95; --line: #3b342b; --focus: #f0a35c; --danger: #f08a73; color-scheme: dark; }\n@media (prefers-color-scheme: dark) {\n :host(:not([theme=\"light\"])) { --surface: #1c1814; --raised: #26211b; --ink: #f2ead9; --muted: #b8ab95; --line: #3b342b; --focus: #f0a35c; --danger: #f08a73; color-scheme: dark; }\n :host(:not([theme=\"light\"])) { --murmur-accent-default: #f2ead9; }\n}\n@media print { :host { display: none !important; } }\n* { box-sizing: border-box; }\n[hidden] { display: none !important; }\n::selection { background: color-mix(in oklab, var(--lamp) 45%, transparent); color: inherit; }\nbutton, input, select, textarea { font: inherit; color: inherit; }\nbutton { cursor: pointer; }\n:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }\na { color: inherit; text-underline-offset: 0.2em; text-decoration-thickness: 1px; }\n\n/* Launcher */\n.launcher {\n display: inline-flex; align-items: center; gap: 10px;\n height: 52px; padding: 0 20px 0 16px; border: 0; border-radius: 26px;\n background: var(--accent); color: var(--accent-ink);\n box-shadow: var(--shadow); font-weight: 600; letter-spacing: 0.01em;\n transition: transform 220ms var(--ease), box-shadow 220ms var(--ease);\n}\n.launcher:hover { transform: translateY(-2px); }\n.launcher:active { transform: translateY(0); }\n.launcher[aria-expanded=\"true\"] { display: none; }\n.lamp {\n width: 8px; height: 8px; border-radius: 50%; flex: none;\n background: var(--lamp); box-shadow: 0 0 0 3px color-mix(in oklab, var(--lamp) 28%, transparent);\n}\n.lamp.off { background: transparent; box-shadow: inset 0 0 0 1.5px var(--muted); }\n.lamp.busy { animation: blink 1.1s steps(2, jump-none) infinite; }\n@keyframes blink { 50% { opacity: 0.25; } }\n\n/* Panel */\n.panel {\n position: absolute; right: 0; bottom: 0;\n display: flex; flex-direction: column;\n width: min(400px, calc(100vw - 40px)); height: min(640px, calc(100dvh - 40px));\n background: var(--surface); border-radius: var(--radius); box-shadow: var(--shadow);\n overflow: hidden; transform-origin: bottom right;\n animation: rise 320ms var(--ease);\n}\n:host([position=\"bottom-left\"]) .panel { right: auto; left: 0; transform-origin: bottom left; }\n:host([inline]) .panel { position: static; width: 100%; height: 100%; box-shadow: none; animation: none; border-radius: inherit; }\n@keyframes rise { from { opacity: 0; transform: translateY(12px) scale(0.98); } }\n@media (max-width: 480px) {\n :host(:not([inline])) { inset: auto 12px 12px auto; }\n :host(:not([inline])[position=\"bottom-left\"]) { inset: auto auto 12px 12px; }\n :host(:not([inline])) .panel { position: fixed; inset: 0; width: 100%; height: 100dvh; border-radius: 0; }\n}\n\nheader {\n display: flex; align-items: center; gap: 10px;\n padding: 14px 10px 14px 18px; background: var(--accent); color: var(--accent-ink);\n}\nheader h2 { flex: 1; margin: 0; font-size: 16px; font-weight: 650; letter-spacing: 0.005em; line-height: 1.25; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.icon-btn {\n display: inline-grid; place-items: center; width: 36px; height: 36px; flex: none;\n border: 0; border-radius: 10px; background: transparent; color: inherit;\n transition: background 160ms;\n}\n.icon-btn:hover { background: color-mix(in oklab, currentColor 14%, transparent); }\nheader .icon-btn:focus-visible { outline-color: var(--accent-ink); }\n\n/* Conversation */\n.log {\n flex: 1; overflow-y: auto; overscroll-behavior: contain;\n padding: 18px 18px 8px; display: flex; flex-direction: column; gap: 16px;\n scrollbar-width: thin; scrollbar-color: var(--line) transparent;\n}\n.msg { max-width: 100%; overflow-wrap: anywhere; }\n.msg p { margin: 0 0 0.6em; }\n.msg p:last-child { margin-bottom: 0; }\n.msg ul, .msg ol { margin: 0 0 0.6em; padding-left: 1.3em; }\n.msg li + li { margin-top: 0.2em; }\n.msg code { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 0.88em; background: var(--raised); padding: 0.1em 0.35em; border-radius: 5px; }\n.msg pre { margin: 0 0 0.6em; padding: 10px 12px; background: var(--raised); border-radius: 10px; overflow-x: auto; }\n.msg pre code { background: none; padding: 0; }\n.msg .table { margin: 0 0 0.6em; overflow-x: auto; border-radius: 10px; box-shadow: inset 0 0 0 1px var(--line); }\n.msg table { width: 100%; border-collapse: collapse; font-size: 14px; }\n.msg th, .msg td { padding: 6px 10px; text-align: left; vertical-align: top; border-bottom: 1px solid var(--line); }\n.msg tr:last-child td { border-bottom: 0; }\n.msg th { font-weight: 650; background: var(--raised); }\n.msg blockquote { margin: 0 0 0.6em; padding: 2px 0 2px 12px; color: var(--muted); box-shadow: inset 1px 0 0 var(--line); }\n.msg hr { margin: 0.8em 0; border: 0; border-top: 1px solid var(--line); }\n.user {\n align-self: flex-end; max-width: 85%;\n padding: 9px 14px; border-radius: 16px 16px 4px 16px;\n background: var(--accent); color: var(--accent-ink); white-space: pre-wrap;\n}\n.bot { align-self: stretch; }\n.greeting { color: var(--muted); }\n\n.cite {\n display: inline-grid; place-items: center; min-width: 1.45em; height: 1.45em; padding: 0 0.3em;\n margin: 0 0.1em; vertical-align: 0.12em;\n border-radius: 1em; box-shadow: inset 0 0 0 1.25px currentColor;\n font-size: 0.72em; font-weight: 700; line-height: 1; text-decoration: none;\n font-variant-numeric: tabular-nums; color: var(--muted);\n transition: background 160ms, color 160ms;\n}\n.cite:hover, .cite:focus-visible { background: var(--lamp); color: #211c17; box-shadow: none; }\n\n.sources { margin: 12px 0 0; padding: 0; list-style: none; display: grid; gap: 2px; }\n.sources-label { margin: 18px 0 2px; font-size: 12px; font-weight: 650; letter-spacing: 0.06em; text-transform: uppercase; color: var(--muted); }\n.sources a {\n display: grid; grid-template-columns: auto 1fr; align-items: baseline; gap: 10px;\n padding: 7px 10px; margin: 0 -10px; border-radius: 10px; text-decoration: none;\n}\n.sources a:hover { background: var(--raised); }\n.sources .cite { margin: 0; }\n.sources .where { min-width: 0; font-size: 14px; line-height: 1.35; }\n.sources .where span { color: var(--muted); }\n\n.status { display: flex; align-items: center; gap: 10px; color: var(--muted); font-size: 14px; }\n.error { color: var(--danger); }\n.error p { margin: 0 0 8px; }\n.text-btn {\n display: inline-flex; align-items: center; gap: 6px; padding: 6px 12px; border-radius: 9px;\n border: 0; background: var(--raised); color: var(--ink); font-size: 14px; font-weight: 600;\n}\n.text-btn:hover { background: var(--line); }\n\n/* Composer */\nform.composer {\n display: flex; align-items: flex-end; gap: 8px; margin: 8px 12px 0; padding: 6px 6px 6px 14px;\n border-radius: 14px; background: var(--raised);\n box-shadow: inset 0 0 0 1px var(--line); transition: box-shadow 160ms;\n}\nform.composer:focus-within { box-shadow: inset 0 0 0 1.5px var(--focus); }\ntextarea {\n flex: 1; min-height: 38px; max-height: 140px; padding: 8px 0; resize: none;\n border: 0; background: transparent; outline: none; line-height: 1.4;\n}\ntextarea:focus-visible { outline: none; }\ntextarea::placeholder, input::placeholder { color: var(--muted); opacity: 1; }\n.send {\n display: inline-grid; place-items: center; width: 38px; height: 38px; flex: none;\n border: 0; border-radius: 10px; background: var(--accent); color: var(--accent-ink);\n transition: opacity 160ms;\n}\n.send:disabled { opacity: 0.35; cursor: default; }\nfooter { padding: 8px 18px 12px; font-size: 12px; color: var(--muted); text-align: center; }\nfooter a { text-decoration: none; }\nfooter a:hover { text-decoration: underline; }\n\n/* Settings */\n.setup { flex: 1; overflow-y: auto; padding: 18px; display: grid; gap: 16px; align-content: start; }\n.setup p.intro { margin: 0; color: var(--muted); font-size: 14px; }\n.field { display: grid; gap: 6px; }\n.field > span { font-size: 13px; font-weight: 650; }\n.field small { color: var(--muted); font-size: 12.5px; }\n.field input:not([type=\"checkbox\"]), .field select {\n width: 100%; height: 40px; padding: 0 12px; border-radius: 10px;\n border: 0; background: var(--raised); box-shadow: inset 0 0 0 1px var(--line);\n}\n.field input:focus-visible, .field select:focus-visible { outline: none; box-shadow: inset 0 0 0 1.5px var(--focus); }\n.check { display: flex; align-items: center; gap: 10px; font-size: 14px; }\n.check input { width: 18px; height: 18px; accent-color: var(--accent); margin: 0; }\n.presets { display: flex; gap: 8px; flex-wrap: wrap; }\n.row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }\n.primary {\n display: inline-flex; align-items: center; justify-content: center; gap: 8px;\n height: 42px; padding: 0 18px; border: 0; border-radius: 11px;\n background: var(--accent); color: var(--accent-ink); font-weight: 650;\n}\n.primary:disabled { opacity: 0.4; cursor: default; }\n.result { font-size: 14px; }\n.result.ok { color: inherit; }\n.result.ok::before { content: \"\"; display: inline-block; width: 8px; height: 8px; margin-right: 8px; border-radius: 50%; background: var(--lamp); }\n.result.fail { color: var(--danger); }\n.local-choice { display: grid; gap: 6px; padding: 14px; border-radius: 12px; background: var(--raised); }\n.local-choice small { color: var(--muted); font-size: 12.5px; }\n.local-choice .link-btn { margin-top: 2px; }\np.or { margin: 0; color: var(--muted); font-size: 13px; text-align: center; }\n.consent { display: grid; gap: 10px; padding: 14px; border-radius: 12px; background: var(--raised); }\n.consent p { margin: 0; }\n.loadbar { display: grid; gap: 6px; margin: 4px 12px 0; padding: 8px 12px; border-radius: 10px; background: var(--raised); color: var(--muted); font-size: 13px; }\nprogress { width: 100%; height: 6px; appearance: none; border: 0; border-radius: 3px; background: var(--line); overflow: hidden; }\nprogress::-webkit-progress-bar { background: var(--line); }\nprogress::-webkit-progress-value { background: var(--lamp); }\nprogress::-moz-progress-bar { background: var(--lamp); }\n.link-btn { padding: 0; border: 0; background: none; color: var(--muted); font-size: 13px; text-decoration: underline; text-underline-offset: 0.2em; justify-self: start; }\n\n.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }\n\n@media (prefers-reduced-motion: reduce) {\n *, .panel { animation: none !important; transition: none !important; }\n}\n";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "murmur-rag",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "Embeddable AI chat for static sites: one script tag, a mini RAG over your own pages, any LLM through llm-connect (your proxy or the visitor's own key). No backend.",
5
5
  "author": "maxgfr",
6
6
  "license": "MIT",
@@ -1 +0,0 @@
1
- import{kt,mt,wn,Tt,vn}from"./embed-krrjjyf5.js";export{kt as MAX_CHUNK,Tt as buildIndex,vn as isMurmurIndex,wn as markdownSections,mt as slugify};