Skip to content

Commit 67fe332

Browse files
committed
Merge branch 'next' of github.com:devforth/adminforth into next
2 parents 729e8d9 + a37a845 commit 67fe332

18 files changed

Lines changed: 1071 additions & 7374 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
[![Ask AI](http://tluma.ai/badge)](http://tluma.ai/ask-ai/devforth/adminforth)
77

8-
* [Try live demo](https://demo.adminforth.dev/) (Read-only mode)
8+
* [Try live demo](https://demo.adminforth.dev/)
99

1010
* [Hello world in 5 minutes](https://adminforth.dev/docs/tutorial/gettingStarted) with AdminForth
1111

adminforth/documentation/docs/tutorial/08-Plugins/26-agent.md

Lines changed: 73 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
This plugin adds an AI agent with a chat surface to AdminForth which is capable of default skills like searching/editing data and extending with custom skills.
77

8-
It stores session history in your own resources and uses any AdminForth completion adapter to generate responses.
8+
It stores session history in your own resources and generates responses using one of the configured `modes`.
99

1010
## Installation
1111

@@ -21,17 +21,21 @@ Add your LLM credentials to `.env`:
2121
OPENAI_API_KEY=your_key
2222
```
2323

24-
You can replace the OpenAI adapter with any completion adapter from [List of adapters](/docs/tutorial/ListOfAdapters/).
24+
Each mode accepts any AdminForth completion adapter, so you can replace the OpenAI adapter with another adapter from [List of adapters](/docs/tutorial/ListOfAdapters/).
2525

2626
## Setup
2727

2828
First create two resources for sessions and turns:
2929

3030
```ts title="./resources/agent_resources/sessions.ts"
3131
import AdminForth, { AdminForthDataTypes } from 'adminforth';
32-
import type { AdminForthResourceInput } from 'adminforth';
32+
import type { AdminForthResourceInput, AdminUser } from 'adminforth';
3333
import { randomUUID } from 'crypto';
3434

35+
async function allowedForSuperAdmins({ adminUser }: { adminUser: AdminUser }): Promise<boolean> {
36+
return adminUser.dbUser.role === 'superadmin';
37+
}
38+
3539
export default {
3640
dataSource: 'sqlite',
3741
table: 'sessions',
@@ -70,14 +74,27 @@ export default {
7074
},
7175
},
7276
],
77+
options: {
78+
allowedActions: {
79+
list: allowedForSuperAdmins,
80+
show: allowedForSuperAdmins,
81+
create: false,
82+
edit: false,
83+
delete: false,
84+
},
85+
},
7386
} as AdminForthResourceInput;
7487
```
7588

7689
```ts title="./resources/agent_resources/turns.ts"
7790
import AdminForth, { AdminForthDataTypes } from 'adminforth';
78-
import type { AdminForthResourceInput } from 'adminforth';
91+
import type { AdminForthResourceInput, AdminUser } from 'adminforth';
7992
import { randomUUID } from 'crypto';
8093

94+
async function allowedForSuperAdmins({ adminUser }: { adminUser: AdminUser }): Promise<boolean> {
95+
return adminUser.dbUser.role === 'superadmin';
96+
}
97+
8198
export default {
8299
dataSource: 'sqlite',
83100
table: 'turns',
@@ -116,6 +133,15 @@ export default {
116133
type: AdminForthDataTypes.TEXT,
117134
},
118135
],
136+
options: {
137+
allowedActions: {
138+
list: allowedForSuperAdmins,
139+
show: allowedForSuperAdmins,
140+
create: false,
141+
edit: false,
142+
delete: false,
143+
},
144+
},
119145
} as AdminForthResourceInput;
120146
```
121147

@@ -166,6 +192,8 @@ export const admin = new AdminForth({
166192

167193
Then attach the plugin once, usually to your `adminuser` resource:
168194

195+
Configure the plugin with `modes`. The legacy top-level `completionAdapter` setup is no longer used.
196+
169197
```ts title="./resources/adminuser.ts"
170198
import AdminForthAgent from '@adminforth/agent';
171199
import CompletionAdapterOpenAIChatGPT from '@adminforth/completion-adapter-open-ai-chat-gpt';
@@ -175,12 +203,45 @@ import CompletionAdapterOpenAIChatGPT from '@adminforth/completion-adapter-open-
175203
plugins: [
176204
...
177205
new AdminForthAgent({
178-
completionAdapter: new CompletionAdapterOpenAIChatGPT({
179-
openAiApiKey: process.env.OPENAI_API_KEY as string,
180-
model: 'gpt-5.4-mini',
181-
}),
206+
modes: [
207+
{
208+
name: 'Balanced',
209+
completionAdapter: new CompletionAdapterOpenAIChatGPT({
210+
openAiApiKey: process.env.OPENAI_API_KEY as string,
211+
model: 'gpt-5.4-mini',
212+
extraRequestBodyParameters: {
213+
reasoning: {
214+
effort: 'medium',
215+
},
216+
},
217+
}),
218+
},
219+
{
220+
name: 'Fast',
221+
completionAdapter: new CompletionAdapterOpenAIChatGPT({
222+
openAiApiKey: process.env.OPENAI_API_KEY as string,
223+
model: 'gpt-5.4-mini',
224+
extraRequestBodyParameters: {
225+
reasoning: {
226+
effort: 'low',
227+
},
228+
},
229+
}),
230+
},
231+
{
232+
name: 'Smart Thinking',
233+
completionAdapter: new CompletionAdapterOpenAIChatGPT({
234+
openAiApiKey: process.env.OPENAI_API_KEY as string,
235+
model: 'gpt-5.4',
236+
extraRequestBodyParameters: {
237+
reasoning: {
238+
effort: 'xhigh',
239+
},
240+
},
241+
}),
242+
},
243+
],
182244
maxTokens: 10000,
183-
reasoning: 'none',
184245
sessionResource: {
185246
resourceId: 'sessions',
186247
idField: 'id',
@@ -203,7 +264,9 @@ plugins: [
203264
]
204265
```
205266

206-
The plugin adds a chat surface to the admin UI and keeps session history per admin user.
267+
Each item in `modes` defines a user-selectable preset in the chat UI. The selected mode is sent to the backend and the plugin uses that mode's `completionAdapter` for the response.
268+
269+
The plugin adds a chat surface to the admin UI, keeps session history per admin user, and shows a mode picker when `modes` are configured.
207270

208271
## Reverse proxy and CDN configuration for streaming
209272

@@ -270,5 +333,3 @@ In skills markdown file, merge which tool exactlu agent should load.
270333
Skill example:
271334

272335
// TODO
273-
274-

adminforth/documentation/src/css/custom.css

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -130,17 +130,17 @@ pre code:has(.code-block-diff-remove-line) {
130130
position: relative;
131131
z-index: 1;
132132
padding: 3%;
133+
overflow: hidden;
133134
border-radius: 2vw;
134135
background: #ecf1f7;
135136
background-image: linear-gradient(to bottom, #333, #111);
136137
box-shadow: 0 0.1rem 0 #cfcfcf;
137138
border: 2px solid #ccc;
138139
}
139-
.laptop .laptop__screen img {
140+
.laptop .laptop__screen img,
141+
.laptop .laptop__screen iframe {
140142
display: block;
141143
max-width: 100%;
142-
height: auto;
143-
aspect-ratio: attr(width) / attr(height);
144144
background: #000;
145145
}
146146
.laptop .laptop__bottom {

adminforth/documentation/src/pages/index.module.css

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,22 @@
3636
max-width: 500px;
3737
}
3838

39+
.demoFrame {
40+
display: block;
41+
width: 100%;
42+
aspect-ratio: 16 / 10;
43+
border: 0;
44+
border-radius: 1.2vw;
45+
background: #000;
46+
}
47+
3948
.cardsWrapper {
4049
display: grid;
41-
grid-template-columns: repeat(3, minmax(300px, 500px));
50+
grid-template-columns: repeat(2, minmax(300px, 500px));
4251
gap: 4rem;
4352
justify-content: center;
4453
padding: 1rem;
4554

46-
@media (max-width: 1200px) {
47-
grid-template-columns: repeat(2, minmax(300px, 500px));
48-
}
4955
@media (max-width: 768px) {
5056
grid-template-columns: repeat(1, minmax(300px, 500px));
5157
}

adminforth/documentation/src/pages/index.tsx

Lines changed: 43 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,17 @@ import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
44
import Layout from '@theme/Layout';
55
import HomepageFeatures from '@site/src/components/HomepageFeatures';
66
import Heading from '@theme/Heading';
7-
import { useState } from 'react';
8-
import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment';
97
import styles from './index.module.css';
108

9+
const LIVE_DEMO_IFRAME_URL = `https://demo.adminforth.dev/overview?autologin=${encodeURIComponent('demo@adminfoth.dev:demo')}`;
10+
1111

1212
const images = [
1313
{
1414
original: require('@site/static/img/previews/login_form.png').default,
1515
title: 'Authentication and Authorization',
1616
link: '/docs/tutorial/gettingStarted',
17-
description: 'OWASP-Compliant Sign-In already there'
18-
},
19-
{
20-
original: require('@site/static/img/previews/users_management.png').default,
21-
title: 'Users management',
22-
link: '/docs/tutorial/gettingStarted',
23-
description: 'Manage users and roles with ease, extend as you like'
17+
description: 'OWASP-Compliant Sign-In done for you'
2418
},
2519
{
2620
original: require('@site/static/img/previews/sso.png').default,
@@ -29,22 +23,46 @@ const images = [
2923
description: 'RFC 6749 SSO plugin with premade Google, Github, Facebook, Keycloak, Microsoft or any custom OAuth2 adapter'
3024
},
3125
{
32-
original: require('@site/static/img/previews/ai_complete.png').default,
33-
title: 'AI autocomplete Plugin - write with ChatGPT',
34-
link: '/docs/tutorial/Plugins/text-complete/',
35-
description: 'Provide your OpenAI API key to autocomplete plugin and AI will help you to write your content using record context'
26+
original: require('@site/static/img/previews/2fa_plugin.png').default,
27+
title: '2FA Plugin - secure your admin panel',
28+
link: '/docs/tutorial/Plugins/TwoFactorsAuth/',
29+
description: 'RFC 6238-Compliant TOTP-Based & WebAuthn PassKeys 2FA will add additional security layer (login and preferred actions)'
30+
},
31+
{
32+
original: require('@site/static/img/previews/branding.png').default,
33+
title: 'Branding and theming',
34+
link: '/docs/tutorial/Customization/branding/',
35+
description: 'Upload your logo, change colors, update titles, make the look to match your brand'
36+
},
37+
{
38+
original: require('@site/static/img/previews/dashboard.png').default,
39+
title: 'Custom Pages and Dashboards',
40+
link: '/docs/tutorial/Customization/customPages/',
41+
description: 'Create your own pages and dashboards with Vue3 components. Add any additional npm packages and extend your admin panel as you like'
42+
},
43+
{
44+
original: require('@site/static/img/previews/users_management.png').default,
45+
title: 'Users management',
46+
link: '/docs/tutorial/gettingStarted',
47+
description: 'Manage users and roles with ease, extend as you like'
48+
},
49+
{
50+
original: require('@site/static/img/previews/translate.png').default,
51+
title: 'LLM-based Translation Plugin - translate your admin and External apps',
52+
link: '/docs/tutorial/Plugins/i18n/',
53+
description: 'Use LLMs to translate any external apps (Mobile, Nuxt, etc.) OR/AND admin panel with minimal effort. Any language supported'
3654
},
3755
{
3856
original: require('@site/static/img/previews/auditlog.png').default,
3957
title: 'Audit log Plugin - know who did what',
4058
link: '/docs/tutorial/Plugins/AuditLog/',
41-
description: 'Attach Audit log plugin with couple of lines, create table for logs and track your users actions'
59+
description: 'Attach Audit log plugin with couple of lines, create table for logs and track full history of any data changes'
4260
},
4361
{
44-
original: require('@site/static/img/previews/2fa_plugin.png').default,
45-
title: '2FA Plugin - secure your admin panel',
46-
link: '/docs/tutorial/Plugins/TwoFactorsAuth/',
47-
description: 'RFC 6238-Compliant TOTP-Based 2FA will add additional security layer to your admin panel. Also supports passkeys'
62+
original: require('@site/static/img/previews/ai_complete.png').default,
63+
title: 'AI autocomplete Plugin - write with LLMs',
64+
link: '/docs/tutorial/Plugins/text-complete/',
65+
description: 'Provide your LLM API key to autocomplete plugin and AI will help you to write your content using record context'
4866
},
4967
{
5068
original: require('@site/static/img/previews/dark.png').default,
@@ -58,18 +76,7 @@ const images = [
5876
link: '/docs/tutorial/Plugins/05-0-upload/',
5977
description: 'Upload files to Amazon S3 with instantiating plugin and providing your S3 credentials'
6078
},
61-
{
62-
original: require('@site/static/img/previews/dashboard.png').default,
63-
title: 'Custom Pages and Dashboards',
64-
link: '/docs/tutorial/Customization/customPages/',
65-
description: 'Create your own pages and dashboards with Vue3 components. Add any additional npm packages and extend your admin panel as you like'
66-
},
67-
{
68-
original: require('@site/static/img/previews/branding.png').default,
69-
title: 'Branding and theming',
70-
link: '/docs/tutorial/Customization/branding/',
71-
description: 'Upload your logo, change colors, update titles, make the look to match your brand'
72-
},
79+
7380
{
7481
original: require('@site/static/img/previews/filters.png').default,
7582
title: 'Filters to query your data',
@@ -100,12 +107,6 @@ const images = [
100107
link: '/docs/tutorial/Plugins/import-export/',
101108
description: 'Export tables to CSV and import from CSV with one click. Move data between environments easily'
102109
},
103-
{
104-
original: require('@site/static/img/previews/translate.png').default,
105-
title: 'AI Translation Plugin - translate your admin and External apps',
106-
link: '/docs/tutorial/Plugins/i18n/',
107-
description: 'Use LLMs to translate any external apps (Mobile, Nuxt, etc.) OR/AND admin panel with minimal effort. Any language supported'
108-
},
109110
{
110111
original: require('@site/static/img/previews/bulk-ai-flow.png').default,
111112
title: 'Bulk AI Plugin - generate data for your resources',
@@ -129,21 +130,13 @@ const images = [
129130

130131
function HomepageHeader() {
131132
const {siteConfig} = useDocusaurusContext();
132-
// read theme from docusarus
133-
134-
const [theme, setTheme] = useState('light');
135-
136-
if (ExecutionEnvironment.canUseDOM) {
137-
138-
139-
}
140133

141134
return (
142135
<>
143136
<header className={clsx('hero', styles.heroBanner)}>
144137
<div className="container" >
145138
<Heading as="h1" className={clsx('hero__title', styles.heroBannerTitle)} >
146-
The Free, Open-Source Admin Framework for Node, Vue & Tailwind
139+
Open-Source Admin Framework with a native Agent
147140
</Heading>
148141
<p className="hero__subtitle">{siteConfig.tagline}</p>
149142

@@ -183,15 +176,11 @@ function HomepageHeader() {
183176
<div className="laptop_container">
184177
<div className="laptop">
185178
<div className="laptop__screen">
186-
<img
187-
src={{
188-
light: require('@site/static/img/preview_light.png').default,
189-
dark: require('@site/static/img/preview_dark.png').default,
190-
}[theme]
191-
} alt="Screen" />
192-
<div className="theme_switcher" onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
193-
194-
</div>
179+
<iframe
180+
className={styles.demoFrame}
181+
src={LIVE_DEMO_IFRAME_URL}
182+
title="AdminForth live demo"
183+
/>
195184
</div>
196185
<div className="laptop__bottom">
197186
<div className="laptop__under"></div>

0 commit comments

Comments
 (0)