Skip to content

Commit da5960d

Browse files
committed
start v3 docs
1 parent 747c18e commit da5960d

14 files changed

Lines changed: 784 additions & 11 deletions

content/docs/extensions/server.mdx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
title: Server Extensions API
3+
description: This guide provides a walkthrough of the LLM Server Extensions API
4+
---

content/docs/extensions/ui.mdx

Lines changed: 241 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,241 @@
1+
---
2+
title: UI Extensions API
3+
description: This guide provides a walkthrough of the LLM UI Extensions API (`ctx.mjs`), using the `xmas` extension as a practical example. The Extensions API allows you to customize the UI, add new pages, modify the layout, and intercept chat functionality.
4+
---
5+
6+
7+
## Extension Entry Point
8+
9+
Every UI extension must export an object with an `install(ctx)` method. `ctx` is the `AppContext` instance which provides access to the core UI functionality.
10+
11+
```js
12+
export default {
13+
install(ctx) {
14+
// Registration logic goes here
15+
},
16+
async load(ctx) {
17+
// Optional async loading logic
18+
// e.g., fetching initial data
19+
}
20+
}
21+
```
22+
23+
## 1. Registering Components
24+
25+
You can register custom Vue components to be used throughout the application or to replace existing ones. This is done using `ctx.components()`.
26+
27+
### Replacing Core Components
28+
Overrides default components like `Brand`, `Welcome`, or `HomeTools` by registering components with the same name.
29+
30+
```js
31+
// Replace Brand component with a custom Christmas theme
32+
const Brand = {
33+
template: `
34+
<div class="flex-shrink-0 p-2 border-b border-gray-200 dark:border-gray-700 select-none">
35+
<button type="button" @click="$router.push('/')" class="...">
36+
🎄 {{ $state.title }} 🎄
37+
</button>
38+
</div>`
39+
}
40+
41+
const Welcome = {
42+
template: `<!-- Custom Welcome Screen -->`,
43+
setup() { /* ... */ }
44+
}
45+
46+
const HomeTools = {
47+
template: `<DarkModeToggle class="mt-4" />`,
48+
}
49+
50+
export default {
51+
install(ctx) {
52+
ctx.components({
53+
Brand,
54+
Welcome,
55+
HomeTools,
56+
// Register other custom components
57+
XmasPage,
58+
XmasTopPanel,
59+
})
60+
}
61+
}
62+
```
63+
64+
## 2. Adding Navigation Icons
65+
66+
### Left Sidebar Icons
67+
Use `ctx.setLeftIcons(icons)` to add icons to the left sidebar.
68+
69+
* `component`: The Vue component for the icon button.
70+
* `isActive`: A function receiving `{ path }` to determine active state.
71+
72+
```js
73+
ctx.setLeftIcons({
74+
xmas: {
75+
component: {
76+
template: `<button @click="$ctx.togglePath('/xmas')" class="...">🎄</button>`
77+
},
78+
isActive({ path }) { return path === '/xmas' }
79+
}
80+
})
81+
```
82+
83+
### Top Bar Icons
84+
Use `ctx.setTopIcons(icons)` to add icons to the top navigation bar.
85+
86+
* `component`: The Vue component for the icon button.
87+
* `isActive`: A function receiving `{ top }` to determine active state.
88+
89+
```js
90+
ctx.setTopIcons({
91+
xmas: {
92+
component: {
93+
template: `<button @click="toggle" class="...">🎁</button>`,
94+
setup() {
95+
const ctx = inject('ctx')
96+
async function toggle() {
97+
// Toggles the Top Panel named 'XmasTopPanel'
98+
if (ctx.toggleTop('XmasTopPanel')) {
99+
// Start a new thread when opened
100+
ctx.threads.startNewThread({ title: 'Ask Santa' })
101+
}
102+
}
103+
return { toggle }
104+
}
105+
},
106+
isActive({ top }) {
107+
return top === 'XmasTopPanel'
108+
}
109+
}
110+
})
111+
```
112+
113+
## 3. Adding New Pages & Routes
114+
115+
You can push new route definitions directly to `ctx.routes`.
116+
117+
```js
118+
const XmasPage = {
119+
template: `<div>Merry Christmas!</div>`
120+
}
121+
122+
ctx.routes.push({
123+
path: '/xmas',
124+
component: XmasPage,
125+
meta: { title: `Merry Christmas!` }
126+
})
127+
```
128+
129+
## 4. Controlling Layout & Logic
130+
131+
### Router Hooks
132+
Intercept navigation changes using `ctx.onRouterBeforeEach`. This is useful for managing UI state based on the current page.
133+
134+
```js
135+
// Auto hide top panel on non-chat pages
136+
ctx.onRouterBeforeEach((to, from) => {
137+
if (to.path !== '/' && !to.path.startsWith('/c/')) {
138+
ctx.toggleTop('XmasTopPanel', false)
139+
}
140+
})
141+
```
142+
143+
### Styling Interception
144+
Use `ctx.onClass` to dynamically modify CSS classes for layout elements (like `body` or `page`).
145+
146+
```js
147+
ctx.onClass((id, cls) => {
148+
// Only apply custom styles on the home page
149+
if (ctx.router.currentRoute.value?.path !== '/') return
150+
151+
// Add festive background colors to the page container
152+
if (id == 'page') {
153+
return cls + ' bg-slate-50! dark:bg-slate-950!'
154+
}
155+
})
156+
```
157+
158+
## 5. Chat & Thread Integration
159+
160+
You can intercept and modify chat behavior to create custom personas or functionality.
161+
162+
### Thread Creation Filters
163+
Use `ctx.createThreadFilters` to modify new threads as they are created.
164+
165+
```js
166+
const santaSystemPrompt = `You are Santa Claus...`
167+
const isTopOpen = () => ctx.layout.top === 'XmasTopPanel'
168+
169+
ctx.createThreadFilters.push(thread => {
170+
// Only apply if our specific UI panel is open
171+
if (!isTopOpen()) return
172+
thread.systemPrompt = santaSystemPrompt
173+
})
174+
```
175+
176+
### Chat Request Filters
177+
Use `ctx.chatRequestFilters` to modify the request body before it is sent to the LLM.
178+
179+
```js
180+
ctx.chatRequestFilters.push(({ request, thread }) => {
181+
if (!isTopOpen()) return
182+
183+
// Enforce the system prompt for every request
184+
request.messages = request.messages.filter(x => x.role !== 'system')
185+
request.messages.unshift({
186+
role: 'system',
187+
content: santaSystemPrompt
188+
})
189+
})
190+
```
191+
192+
## 6. Backend Integration
193+
194+
### Extension Scope
195+
Use `ctx.scope(id)` to create a scoped helper for standard API interactions. It handles base URLs and state injection.
196+
197+
```js
198+
export default {
199+
install(ctx) {
200+
// Create scope for 'xmas' extension
201+
let ext = ctx.scope('xmas')
202+
203+
// ...
204+
205+
// Use 'ext' to make requests to /api/ext/xmas/greet
206+
async function onSubmit(e) {
207+
const form = new FormData(e.target)
208+
const res = await ext.postForm('/greet', {
209+
body: form
210+
})
211+
// ...
212+
}
213+
},
214+
async load(ctx) {
215+
// Load initial data
216+
let ext = ctx.scope('xmas')
217+
ctx.state.greetings = await ext.getJson("/greetings.json")
218+
}
219+
}
220+
```
221+
222+
## Full Example Component: Top Panel
223+
224+
This is how you define a complex UI component like a Top Panel. It's just a standard Vue 3 component.
225+
226+
```js
227+
const XmasTopPanel = {
228+
template: `
229+
<div class="w-full bg-red-800 ...">
230+
<!-- Panel Content -->
231+
<h1>Ask Santa</h1>
232+
<p>Chat directly with Santa Claus...</p>
233+
</div>
234+
`,
235+
setup() {
236+
return {
237+
// ... setup logic
238+
}
239+
}
240+
}
241+
```

content/docs/meta.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@
22
"title": "Documentation",
33
"pages": [
44
"index",
5+
"v3",
56
"getting-started",
67
"features",
78
"multimodal",
9+
"extensions",
810
"configuration",
911
"cli",
1012
"deployment"

0 commit comments

Comments
 (0)