@kpritam/grimoire-output-docusaurus 0.1.8
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/LICENSE +21 -0
- package/README.md +25 -0
- package/dist/.tsbuildinfo +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/internal/assets.d.ts +9 -0
- package/dist/internal/assets.js +50 -0
- package/dist/internal/docusaurusConfig.d.ts +9 -0
- package/dist/internal/docusaurusConfig.js +259 -0
- package/dist/internal/spellbookAssets.d.ts +39 -0
- package/dist/internal/spellbookAssets.js +68 -0
- package/dist/layer.d.ts +3 -0
- package/dist/layer.js +6 -0
- package/dist/shared.d.ts +10 -0
- package/dist/shared.js +36 -0
- package/dist/upstream.d.ts +6 -0
- package/dist/upstream.js +84 -0
- package/package.json +59 -0
- package/src/index.ts +1 -0
- package/src/internal/assets.ts +66 -0
- package/src/internal/docusaurusConfig.ts +281 -0
- package/src/internal/spellbookAssets.ts +80 -0
- package/src/layer.ts +12 -0
- package/src/shared.ts +43 -0
- package/src/upstream.ts +119 -0
- package/templates/spellbook/spellbookPlugin.ts +156 -0
- package/templates/spellbook/src/components/SpellbookChat/ChatEngine.ts +79 -0
- package/templates/spellbook/src/components/SpellbookChat/ChatErrorBoundary.tsx +65 -0
- package/templates/spellbook/src/components/SpellbookChat/Markdown.tsx +259 -0
- package/templates/spellbook/src/components/SpellbookChat/README.md +111 -0
- package/templates/spellbook/src/components/SpellbookChat/SettingsPanel.tsx +376 -0
- package/templates/spellbook/src/components/SpellbookChat/VoiceMode.tsx +867 -0
- package/templates/spellbook/src/components/SpellbookChat/index.tsx +744 -0
- package/templates/spellbook/src/components/SpellbookChat/markdown.module.css +343 -0
- package/templates/spellbook/src/components/SpellbookChat/secretStore.ts +106 -0
- package/templates/spellbook/src/components/SpellbookChat/streamProviders/anthropic.ts +36 -0
- package/templates/spellbook/src/components/SpellbookChat/streamProviders/createCloudProvider.ts +112 -0
- package/templates/spellbook/src/components/SpellbookChat/streamProviders/google.ts +33 -0
- package/templates/spellbook/src/components/SpellbookChat/streamProviders/index.ts +32 -0
- package/templates/spellbook/src/components/SpellbookChat/streamProviders/mapFinishReason.ts +23 -0
- package/templates/spellbook/src/components/SpellbookChat/streamProviders/ollama.ts +44 -0
- package/templates/spellbook/src/components/SpellbookChat/streamProviders/openai.ts +34 -0
- package/templates/spellbook/src/components/SpellbookChat/streamProviders/openaiRealtime.ts +320 -0
- package/templates/spellbook/src/components/SpellbookChat/streamProviders/types.ts +172 -0
- package/templates/spellbook/src/components/SpellbookChat/streamProviders/webllm.ts +214 -0
- package/templates/spellbook/src/components/SpellbookChat/styles.module.css +852 -0
- package/templates/spellbook/src/components/SpellbookChat/systemPrompt.ts +107 -0
- package/templates/spellbook/src/components/SpellbookChat/transformers-ssr-stub.ts +16 -0
- package/templates/spellbook/src/components/SpellbookChat/types.ts +52 -0
- package/templates/spellbook/src/components/SpellbookChat/useBundleLoader.ts +46 -0
- package/templates/spellbook/src/components/SpellbookChat/useChatEngine.ts +524 -0
- package/templates/spellbook/src/components/SpellbookChat/useEmbeddings.ts +147 -0
- package/templates/spellbook/src/components/SpellbookChat/useRetrieval.ts +377 -0
- package/templates/spellbook/src/components/SpellbookChat/useSileroVAD.ts +236 -0
- package/templates/spellbook/src/components/SpellbookChat/useSpeechRecognition.ts +271 -0
- package/templates/spellbook/src/components/SpellbookChat/useSpeechSynthesis.ts +229 -0
- package/templates/spellbook/src/components/SpellbookChat/useUnifiedSTT.ts +134 -0
- package/templates/spellbook/src/components/SpellbookChat/useWhisperSTT.ts +411 -0
- package/templates/spellbook/src/components/SpellbookChat/vad-ssr-stub.ts +25 -0
- package/templates/spellbook/src/components/SpellbookChat/voiceDebug.ts +60 -0
- package/templates/spellbook/src/components/SpellbookChat/voiceFsm.ts +196 -0
- package/templates/spellbook/src/components/SpellbookChat/voiceStyles.module.css +334 -0
- package/templates/spellbook/src/components/SpellbookChat/webllm-ssr-stub.ts +8 -0
- package/templates/spellbook/src/components/SpellbookChatDisabled.tsx +20 -0
- package/templates/spellbook/src/theme/Root.tsx +29 -0
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
/* Spellbook voice mode — dark / purple / mystical; respects reduced motion */
|
|
2
|
+
|
|
3
|
+
.wrap {
|
|
4
|
+
display: flex;
|
|
5
|
+
flex-direction: column;
|
|
6
|
+
align-items: center;
|
|
7
|
+
gap: 1rem;
|
|
8
|
+
padding: 0.75rem 0;
|
|
9
|
+
font-family: var(--ifm-font-family-base, "Georgia", serif);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.status {
|
|
13
|
+
font-size: 0.8125rem;
|
|
14
|
+
color: rgba(230, 220, 255, 0.75);
|
|
15
|
+
text-align: center;
|
|
16
|
+
max-width: 22rem;
|
|
17
|
+
line-height: 1.45;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.transcript {
|
|
21
|
+
width: 100%;
|
|
22
|
+
max-width: 22rem;
|
|
23
|
+
min-height: 2.5rem;
|
|
24
|
+
padding: 0.65rem 0.85rem;
|
|
25
|
+
border-radius: 10px;
|
|
26
|
+
background: rgba(40, 24, 72, 0.45);
|
|
27
|
+
border: 1px solid rgba(167, 139, 250, 0.25);
|
|
28
|
+
color: rgba(248, 244, 255, 0.92);
|
|
29
|
+
font-size: 0.875rem;
|
|
30
|
+
line-height: 1.5;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.transcriptLabel {
|
|
34
|
+
display: block;
|
|
35
|
+
font-size: 0.6875rem;
|
|
36
|
+
letter-spacing: 0.06em;
|
|
37
|
+
text-transform: uppercase;
|
|
38
|
+
color: rgba(196, 181, 253, 0.65);
|
|
39
|
+
margin-bottom: 0.35rem;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.controls {
|
|
43
|
+
display: flex;
|
|
44
|
+
flex-direction: column;
|
|
45
|
+
align-items: center;
|
|
46
|
+
gap: 0.75rem;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.micOuter {
|
|
50
|
+
position: relative;
|
|
51
|
+
width: 5.5rem;
|
|
52
|
+
height: 5.5rem;
|
|
53
|
+
display: grid;
|
|
54
|
+
place-items: center;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.micRing {
|
|
58
|
+
position: absolute;
|
|
59
|
+
inset: -4px;
|
|
60
|
+
border-radius: 50%;
|
|
61
|
+
pointer-events: none;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.micRingListening {
|
|
65
|
+
border: 2px solid rgba(248, 113, 113, 0.85);
|
|
66
|
+
animation: voicePulse 1.4s ease-in-out infinite;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.micButton {
|
|
70
|
+
position: relative;
|
|
71
|
+
z-index: 1;
|
|
72
|
+
width: 4.5rem;
|
|
73
|
+
height: 4.5rem;
|
|
74
|
+
border-radius: 50%;
|
|
75
|
+
border: none;
|
|
76
|
+
cursor: pointer;
|
|
77
|
+
display: grid;
|
|
78
|
+
place-items: center;
|
|
79
|
+
color: #f5f3ff;
|
|
80
|
+
background: radial-gradient(
|
|
81
|
+
circle at 30% 25%,
|
|
82
|
+
rgba(192, 132, 252, 0.95),
|
|
83
|
+
rgba(88, 28, 135, 0.98) 55%,
|
|
84
|
+
rgba(49, 10, 80, 1) 100%
|
|
85
|
+
);
|
|
86
|
+
box-shadow:
|
|
87
|
+
0 0 0 1px rgba(216, 180, 254, 0.35),
|
|
88
|
+
0 0 28px rgba(167, 139, 250, 0.45),
|
|
89
|
+
inset 0 1px 0 rgba(255, 255, 255, 0.12);
|
|
90
|
+
transition:
|
|
91
|
+
transform 0.15s ease,
|
|
92
|
+
box-shadow 0.2s ease;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.micButton:hover:not(:disabled) {
|
|
96
|
+
transform: scale(1.04);
|
|
97
|
+
box-shadow:
|
|
98
|
+
0 0 0 1px rgba(216, 180, 254, 0.5),
|
|
99
|
+
0 0 36px rgba(192, 132, 252, 0.55),
|
|
100
|
+
inset 0 1px 0 rgba(255, 255, 255, 0.15);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.micButton:active:not(:disabled) {
|
|
104
|
+
transform: scale(0.98);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.micButton:focus-visible {
|
|
108
|
+
outline: 2px solid rgba(196, 181, 253, 0.9);
|
|
109
|
+
outline-offset: 3px;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.micButton:disabled {
|
|
113
|
+
cursor: not-allowed;
|
|
114
|
+
opacity: 0.45;
|
|
115
|
+
filter: grayscale(0.35);
|
|
116
|
+
box-shadow: none;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.micButtonIdle {
|
|
120
|
+
animation: voiceGlow 3.2s ease-in-out infinite;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.micButtonListening {
|
|
124
|
+
background: radial-gradient(
|
|
125
|
+
circle at 35% 28%,
|
|
126
|
+
rgba(252, 165, 165, 0.35),
|
|
127
|
+
rgba(88, 28, 135, 0.98) 50%,
|
|
128
|
+
rgba(49, 10, 80, 1) 100%
|
|
129
|
+
);
|
|
130
|
+
box-shadow:
|
|
131
|
+
0 0 0 1px rgba(248, 113, 113, 0.45),
|
|
132
|
+
0 0 32px rgba(248, 113, 113, 0.35);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
.micButtonSpeaking {
|
|
136
|
+
background: radial-gradient(
|
|
137
|
+
circle at 30% 25%,
|
|
138
|
+
rgba(129, 140, 248, 0.95),
|
|
139
|
+
rgba(49, 46, 129, 0.98) 55%,
|
|
140
|
+
rgba(30, 27, 75, 1) 100%
|
|
141
|
+
);
|
|
142
|
+
box-shadow:
|
|
143
|
+
0 0 0 1px rgba(165, 180, 252, 0.45),
|
|
144
|
+
0 0 28px rgba(99, 102, 241, 0.4);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.micIcon {
|
|
148
|
+
width: 1.65rem;
|
|
149
|
+
height: 1.65rem;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
.caption {
|
|
153
|
+
font-size: 0.8125rem;
|
|
154
|
+
color: rgba(216, 211, 244, 0.88);
|
|
155
|
+
text-align: center;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
.thinking {
|
|
159
|
+
display: flex;
|
|
160
|
+
flex-direction: column;
|
|
161
|
+
align-items: center;
|
|
162
|
+
gap: 0.5rem;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
.spinner {
|
|
166
|
+
width: 1.75rem;
|
|
167
|
+
height: 1.75rem;
|
|
168
|
+
border: 2px solid rgba(167, 139, 250, 0.25);
|
|
169
|
+
border-top-color: rgba(196, 181, 253, 0.95);
|
|
170
|
+
border-radius: 50%;
|
|
171
|
+
animation: voiceSpin 0.85s linear infinite;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
.stopButton {
|
|
175
|
+
font: inherit;
|
|
176
|
+
font-size: 0.8125rem;
|
|
177
|
+
padding: 0.45rem 1rem;
|
|
178
|
+
border-radius: 999px;
|
|
179
|
+
border: 1px solid rgba(248, 113, 113, 0.45);
|
|
180
|
+
background: rgba(127, 29, 29, 0.35);
|
|
181
|
+
color: #fecaca;
|
|
182
|
+
cursor: pointer;
|
|
183
|
+
transition:
|
|
184
|
+
background 0.15s ease,
|
|
185
|
+
border-color 0.15s ease;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.stopButton:hover {
|
|
189
|
+
background: rgba(153, 27, 27, 0.45);
|
|
190
|
+
border-color: rgba(252, 165, 165, 0.55);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
.stopButton:focus-visible {
|
|
194
|
+
outline: 2px solid rgba(252, 165, 165, 0.85);
|
|
195
|
+
outline-offset: 2px;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
.wave {
|
|
199
|
+
display: flex;
|
|
200
|
+
align-items: flex-end;
|
|
201
|
+
justify-content: center;
|
|
202
|
+
gap: 4px;
|
|
203
|
+
height: 28px;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
.waveBar {
|
|
207
|
+
width: 4px;
|
|
208
|
+
border-radius: 2px;
|
|
209
|
+
background: linear-gradient(
|
|
210
|
+
180deg,
|
|
211
|
+
rgba(165, 180, 252, 0.95),
|
|
212
|
+
rgba(79, 70, 229, 0.6)
|
|
213
|
+
);
|
|
214
|
+
animation: voiceWave 0.9s ease-in-out infinite;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
.waveBar:nth-child(2) {
|
|
218
|
+
animation-delay: 0.08s;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
.waveBar:nth-child(3) {
|
|
222
|
+
animation-delay: 0.16s;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
.waveBar:nth-child(4) {
|
|
226
|
+
animation-delay: 0.24s;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
.waveBar:nth-child(5) {
|
|
230
|
+
animation-delay: 0.32s;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
@keyframes voiceGlow {
|
|
234
|
+
0%,
|
|
235
|
+
100% {
|
|
236
|
+
box-shadow:
|
|
237
|
+
0 0 0 1px rgba(216, 180, 254, 0.35),
|
|
238
|
+
0 0 22px rgba(167, 139, 250, 0.38);
|
|
239
|
+
}
|
|
240
|
+
50% {
|
|
241
|
+
box-shadow:
|
|
242
|
+
0 0 0 1px rgba(233, 213, 255, 0.55),
|
|
243
|
+
0 0 36px rgba(192, 132, 252, 0.55);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
@keyframes voicePulse {
|
|
248
|
+
0%,
|
|
249
|
+
100% {
|
|
250
|
+
transform: scale(1);
|
|
251
|
+
opacity: 0.85;
|
|
252
|
+
}
|
|
253
|
+
50% {
|
|
254
|
+
transform: scale(1.08);
|
|
255
|
+
opacity: 1;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
@keyframes voiceSpin {
|
|
260
|
+
to {
|
|
261
|
+
transform: rotate(360deg);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
@keyframes voiceWave {
|
|
266
|
+
0%,
|
|
267
|
+
100% {
|
|
268
|
+
height: 8px;
|
|
269
|
+
opacity: 0.65;
|
|
270
|
+
}
|
|
271
|
+
50% {
|
|
272
|
+
height: 26px;
|
|
273
|
+
opacity: 1;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
@media (prefers-reduced-motion: reduce) {
|
|
278
|
+
.micRingListening,
|
|
279
|
+
.micButtonIdle,
|
|
280
|
+
.spinner,
|
|
281
|
+
.waveBar {
|
|
282
|
+
animation: none;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
.micRingListening {
|
|
286
|
+
opacity: 0.95;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
.micButtonIdle {
|
|
290
|
+
box-shadow:
|
|
291
|
+
0 0 0 1px rgba(216, 180, 254, 0.35),
|
|
292
|
+
0 0 22px rgba(167, 139, 250, 0.38);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
.waveBar {
|
|
296
|
+
height: 14px;
|
|
297
|
+
opacity: 0.85;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/* =============================================================
|
|
302
|
+
LIGHT THEME OVERRIDES — voice mode was built dark-first;
|
|
303
|
+
all hardcoded dark rgba() values are corrected here for the
|
|
304
|
+
parchment theme. The mic button stays purple (brand accent).
|
|
305
|
+
============================================================= */
|
|
306
|
+
|
|
307
|
+
:global([data-theme="light"]) .status {
|
|
308
|
+
color: oklch(0.48 0.08 295);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
:global([data-theme="light"]) .transcript {
|
|
312
|
+
background: color-mix(in oklch, oklch(0.5 0.22 298) 8%, oklch(0.945 0.012 80));
|
|
313
|
+
border-color: oklch(0.5 0.22 298 / 0.25);
|
|
314
|
+
color: oklch(0.185 0.028 290);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
:global([data-theme="light"]) .transcriptLabel {
|
|
318
|
+
color: oklch(0.48 0.12 295);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
:global([data-theme="light"]) .caption {
|
|
322
|
+
color: oklch(0.45 0.06 285);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
:global([data-theme="light"]) .stopButton {
|
|
326
|
+
background: oklch(0.97 0.015 25);
|
|
327
|
+
border-color: oklch(0.65 0.18 25 / 0.45);
|
|
328
|
+
color: oklch(0.38 0.2 25);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
:global([data-theme="light"]) .stopButton:hover {
|
|
332
|
+
background: oklch(0.94 0.03 25);
|
|
333
|
+
border-color: oklch(0.6 0.2 25 / 0.55);
|
|
334
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Docusaurus SSR build must not import `@mlc-ai/web-llm` (WebGPU / browser-only).
|
|
3
|
+
* Webpack aliases the real package to this stub on the server target.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export function CreateMLCEngine(): Promise<never> {
|
|
7
|
+
throw new Error("WebLLM is browser-only");
|
|
8
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Compile-time replacement for `SpellbookChat` when the chat feature is
|
|
5
|
+
* disabled (`index.enabled: false` in `.grimoire/config.yml`, or an
|
|
6
|
+
* explicit `SPELLBOOK_ENABLED=false` at site-build time).
|
|
7
|
+
*
|
|
8
|
+
* `docusaurus.config.ts` swaps this stub in via webpack's
|
|
9
|
+
* `NormalModuleReplacementPlugin`, which short-circuits webpack's import
|
|
10
|
+
* graph traversal at the module-resolution step. That breaks the chain to
|
|
11
|
+
* `react-markdown`, `@huggingface/transformers`, `@mlc-ai/web-llm`, `ai`,
|
|
12
|
+
* `@ai-sdk/*`, `highlight.js`, … so none of those heavy deps end up in
|
|
13
|
+
* any chunk of the production bundle.
|
|
14
|
+
*
|
|
15
|
+
* The component renders nothing — `Root.tsx` lazy-imports it inside a
|
|
16
|
+
* `<Suspense fallback={null}>`, so the chat slot stays empty.
|
|
17
|
+
*/
|
|
18
|
+
export default function SpellbookChatDisabled(): ReactNode {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Suspense, lazy, type ReactNode } from "react";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Lazy-loaded Spellbook chat dialog.
|
|
5
|
+
*
|
|
6
|
+
* When the feature is disabled (`index.enabled: false` in
|
|
7
|
+
* `.grimoire/config.yml`, or `SPELLBOOK_ENABLED=false` at site-build
|
|
8
|
+
* time), `spellbookWebpackPlugin` swaps this import target for
|
|
9
|
+
* `SpellbookChatDisabled.tsx` via `NormalModuleReplacementPlugin`. That
|
|
10
|
+
* happens at module-resolution time, so webpack tree-shakes the entire
|
|
11
|
+
* SpellbookChat dependency tree (`@huggingface/transformers`,
|
|
12
|
+
* `@mlc-ai/web-llm`, `ai`, `@ai-sdk/*`, `react-markdown`, `highlight.js`,
|
|
13
|
+
* …) out of the production bundle — the resulting chunk is just an empty
|
|
14
|
+
* stub. We pre-load this lazy module unconditionally; the cost when
|
|
15
|
+
* disabled is essentially zero.
|
|
16
|
+
*/
|
|
17
|
+
const SpellbookChat = lazy(() => import("../components/SpellbookChat"));
|
|
18
|
+
|
|
19
|
+
export default function Root(props: { readonly children: ReactNode }): ReactNode {
|
|
20
|
+
const { children } = props;
|
|
21
|
+
return (
|
|
22
|
+
<>
|
|
23
|
+
{children}
|
|
24
|
+
<Suspense fallback={null}>
|
|
25
|
+
<SpellbookChat />
|
|
26
|
+
</Suspense>
|
|
27
|
+
</>
|
|
28
|
+
);
|
|
29
|
+
}
|