From fc93b2dff07fd699d9f81f950fafd0b95a4b7e7d Mon Sep 17 00:00:00 2001 From: Pavlo Kulyk Date: Wed, 22 Apr 2026 13:41:13 +0300 Subject: [PATCH 1/7] docs: update apartments configuration --- .../docs/tutorial/001-gettingStarted.md | 75 ++++++++++++++++--- 1 file changed, 65 insertions(+), 10 deletions(-) diff --git a/adminforth/documentation/docs/tutorial/001-gettingStarted.md b/adminforth/documentation/docs/tutorial/001-gettingStarted.md index 301a06331..a49e49dfa 100644 --- a/adminforth/documentation/docs/tutorial/001-gettingStarted.md +++ b/adminforth/documentation/docs/tutorial/001-gettingStarted.md @@ -197,7 +197,7 @@ After the resource file is generated, extend it with display and validation sett To properly apply these changes, refer to the example below and adjust the configuration according to your settings ```ts title="./resources/apartments.ts" -import { AdminForthDataTypes, AdminForthResourceInput } from 'adminforth'; +import { AdminForthResourceInput, AdminForthDataTypes } from 'adminforth'; export default { dataSource: 'maindb', @@ -206,6 +206,7 @@ export default { resourceId: 'apartments' //diff-add resourceId: 'aparts', // resourceId is defaulted to table name but you can redefine it like this e.g. + //diff-add // in case of same table names from different data sources label: 'Apartments', // label is defaulted to table name but you can change it //diff-add @@ -213,25 +214,33 @@ export default { columns: [ { name: 'id', + //diff-add type: AdminForthDataTypes.STRING, //diff-add label: 'Identifier', // if you wish you can redefine label, defaulted to uppercased name showIn: { // show column in filter and in show page - //diff-add + //diff-remove + all:true, + //diff-add list: false, //diff-add edit: false, //diff-add create: false, }, + //diff-add primaryKey: true, //diff-add fillOnCreate: ({ initialRecord, adminUser }) => Math.random().toString(36).substring(7), // called during creation to generate content of field, initialRecord is values user entered, adminUser object of user who creates record }, { - name: 'title', + name: "title", + //diff-add required: true, - showIn: { all: true }, // all available options + showIn: { + all:true, // all available options + }, + //diff-add type: AdminForthDataTypes.STRING, //diff-add maxLength: 255, // you can set max length for string fields @@ -240,14 +249,24 @@ export default { }, { name: 'created_at', + //diff-add type: AdminForthDataTypes.DATETIME, + //diff-add allowMinMaxQuery: true, - showIn: { create: false }, + showIn: { + //diff-remove + all:true, + //diff-add + create: false, + }, //diff-add fillOnCreate: ({ initialRecord, adminUser }) => (new Date()).toISOString(), }, { name: 'price', + showIn: { + all:true, + }, //diff-add inputSuffix: 'USD', // you can add a suffix to an input field that will be displayed when creating or editing records //diff-add @@ -257,8 +276,13 @@ export default { }, { name: 'square_meter', + //diff-add label: 'Square', + //diff-add allowMinMaxQuery: true, + showIn: { + all:true, + }, //diff-add minValue: 1, // you can set min /max value for number columns so users will not be able to enter more/less //diff-add @@ -266,7 +290,11 @@ export default { }, { name: 'number_of_rooms', + //diff-add allowMinMaxQuery: true, + showIn: { + all:true, + }, //diff-add enum: [ //diff-add @@ -284,11 +312,20 @@ export default { }, { name: 'description', + //diff-add sortable: false, - showIn: { list: false }, + showIn: { + //diff-remove + all:true, + //diff-add + list: false, + } }, { name: 'country', + showIn: { + all:true, + }, //diff-add enum: [{ //diff-add @@ -362,18 +399,27 @@ export default { name: 'listed', //diff-add required: true, // will be required on create/edit + showIn: { + all:true, + } }, { name: 'realtor_id', + //diff-add foreignResource: { + //diff-add resourceId: 'adminuser', //diff-add searchableFields: ["id", "email"], // fields available for search in filter + //diff-add + }, + showIn: { + all:true, } } ], options: { - listPageSize: 12, + listPageSize: 10, //diff-add allowedActions: { //diff-add @@ -439,8 +485,17 @@ export const admin = new AdminForth({ }, { label: 'Users', - ... - } + icon: 'flowbite:user-solid', + resourceId: 'adminuser' + }, + { + label: "Apartments", + icon: "flowbite:user-solid", + //diff-remove + resourceId: "apartments", + //diff-add + resourceId: "aparts", + }, ], ... }); @@ -467,7 +522,7 @@ async function seedDatabase() { //diff-add title: `Apartment ${i}`, //diff-add - square_meter: (Math.random() * 100).toFixed(1), + square_meter: Number((Math.random() * 100).toFixed(1)), //diff-add price: (Math.random() * 10000).toFixed(2), //diff-add From 3c815a2a011b381be9afd8094186fe490af90a9d Mon Sep 17 00:00:00 2001 From: Vitalii Kulyk Date: Thu, 23 Apr 2026 12:22:12 +0300 Subject: [PATCH 2/7] feat: add median aggregate function support in SQLite connector --- adminforth/dataConnectors/sqlite.ts | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/adminforth/dataConnectors/sqlite.ts b/adminforth/dataConnectors/sqlite.ts index ef0e352bf..3f0e330b7 100644 --- a/adminforth/dataConnectors/sqlite.ts +++ b/adminforth/dataConnectors/sqlite.ts @@ -9,6 +9,20 @@ class SQLiteConnector extends AdminForthBaseConnector implements IAdminForthData async setupClient(url: string): Promise { this.client = betterSqlite3(url.replace('sqlite://', '')); + this.client.aggregate('median', { + start: (): number[] => [], + step: (acc: number[], val: any) => { + if (val != null) acc.push(Number(val)); + }, + result: (acc: number[]): number | null => { + if (acc.length === 0) return null; + const sorted = acc.slice().sort((a, b) => a - b); + const mid = Math.floor(sorted.length / 2); + return sorted.length % 2 === 0 + ? (sorted[mid - 1] + sorted[mid]) / 2 + : sorted[mid]; + }, + }); } async getAllTables(): Promise> { const stmt = this.client.prepare( @@ -358,7 +372,7 @@ class SQLiteConnector extends AdminForthBaseConnector implements IAdminForthData case 'avg': selectParts.push(`AVG("${rule.field}") AS "${alias}"`); break; case 'min': selectParts.push(`MIN("${rule.field}") AS "${alias}"`); break; case 'max': selectParts.push(`MAX("${rule.field}") AS "${alias}"`); break; - case 'median': throw new Error('Aggregates.median() with GroupBy.Field is not supported in SQLite.'); + case 'median': selectParts.push(`median("${rule.field}") AS "${alias}"`); break; } } From e27b8e4de37e8e38bba0c7556fc45c96dce2a2bc Mon Sep 17 00:00:00 2001 From: Ivan Borshchov Date: Thu, 23 Apr 2026 10:25:01 +0000 Subject: [PATCH 3/7] feat: replace OpenAI ChatGPT adapter with OpenAI Responses adapter across documentation and codebase Co-authored-by: Copilot --- AGENTS.md | 5 +++++ .../blog/2024-10-01-ai-blog/index.md | 6 ++--- .../docs/tutorial/05-ListOfAdapters.md | 18 ++++++++------- .../docs/tutorial/08-Plugins/04-RichEditor.md | 6 ++--- .../tutorial/08-Plugins/06-text-complete.md | 10 ++++----- .../docs/tutorial/08-Plugins/10-i18n.md | 8 +++---- .../tutorial/08-Plugins/17-bulk-ai-flow.md | 4 ++-- .../docs/tutorial/08-Plugins/26-agent.md | 10 ++++----- dev-demo/Taskfile.yaml | 8 +++++-- dev-demo/resources/adminuser.ts | 8 +++---- .../cars_resources/carsResourseTemplate.ts | 8 +++---- dev-demo/resources/translations.ts | 4 ++-- live-demo/app/package.json | 2 +- live-demo/app/pnpm-lock.yaml | 22 +++++++++---------- live-demo/app/resources/apartments.ts | 6 ++--- live-demo/app/resources/translations.ts | 4 ++-- live-demo/app/resources/users.ts | 4 ++-- 17 files changed, 72 insertions(+), 61 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 7381deeb3..0facbd614 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,6 +1,11 @@ # AGENTS.md +## Package manager + +All packages and projects in this repo use `pnpm` and not `npm`. +Howeverer internally (e.g. in `codeInjector`) adminforth still supports both `npm` and `pnpm` style install commands, so users of framework itself can use it with either package manager. But in all dev demo/live demo, plugins, adapters, and documentation, we use `pnpm` as the standard. + ## General engineering rules Write code as if the system contracts are already defined and trusted. diff --git a/adminforth/documentation/blog/2024-10-01-ai-blog/index.md b/adminforth/documentation/blog/2024-10-01-ai-blog/index.md index 291b4fcb7..5bb9ac193 100644 --- a/adminforth/documentation/blog/2024-10-01-ai-blog/index.md +++ b/adminforth/documentation/blog/2024-10-01-ai-blog/index.md @@ -47,7 +47,7 @@ Add modules: ```bash cd ai-blog -npm i @adminforth/upload @adminforth/rich-editor @adminforth/text-complete @adminforth/chat-gpt slugify http-proxy @adminforth/image-generation-adapter-openai @adminforth/completion-adapter-open-ai-chat-gpt +npm i @adminforth/upload @adminforth/rich-editor @adminforth/text-complete @adminforth/chat-gpt slugify http-proxy @adminforth/image-generation-adapter-openai @adminforth/completion-adapter-openai-responses ``` @@ -475,7 +475,7 @@ import UploadPlugin from '@adminforth/upload'; import RichEditorPlugin from '@adminforth/rich-editor'; import ChatGptPlugin from '@adminforth/chat-gpt'; import slugify from 'slugify'; -import CompletionAdapterOpenAIChatGPT from "@adminforth/completion-adapter-open-ai-chat-gpt"; +import CompletionAdapterOpenAIResponses from "@adminforth/completion-adapter-openai-responses"; import ImageGenerationAdapterOpenAI from '@adminforth/image-generation-adapter-openai'; export default { @@ -591,7 +591,7 @@ export default { new RichEditorPlugin({ htmlFieldName: 'content', completion: { - adapter: new CompletionAdapterOpenAIChatGPT({ + adapter: new CompletionAdapterOpenAIResponses({ openAiApiKey: process.env.OPENAI_API_KEY as string, model: 'gpt-4o', expert: { diff --git a/adminforth/documentation/docs/tutorial/05-ListOfAdapters.md b/adminforth/documentation/docs/tutorial/05-ListOfAdapters.md index 8682cbdb1..ad5790cd9 100644 --- a/adminforth/documentation/docs/tutorial/05-ListOfAdapters.md +++ b/adminforth/documentation/docs/tutorial/05-ListOfAdapters.md @@ -154,18 +154,20 @@ Not really recommended for production use, cause cloud storage is more reliable Is used for AI-powered text completion. Feel free to fork and implement other models including models from Anthropic, Google Gemini, or any other AI model that supports text completion. -### OpenAI Completion Adapter +### OpenAI Responses Completion Adapter ``` -pnpm i @adminforth/completion-adapter-open-ai-chat-gpt +pnpm i @adminforth/completion-adapter-openai-responses ``` -Integrates AdminForth with OpenAI’s ChatGPT models to provide AI-powered completion and conversational features. +Integrates AdminForth with OpenAI's Responses API to provide AI-powered completion and conversational features. + +The older `@adminforth/completion-adapter-open-ai-chat-gpt` package is deprecated. Use this package instead. ```ts -import CompletionAdapterOpenAIChatGPT from "@adminforth/completion-adapter-open-ai-chat-gpt"; +import CompletionAdapterOpenAIResponses from "@adminforth/completion-adapter-openai-responses"; -new CompletionAdapterOpenAIChatGPT({ +new CompletionAdapterOpenAIResponses({ openAiApiKey: process.env.OPENAI_API_KEY as string, model: 'gpt-5.2', extraRequestBodyParameters: { @@ -259,7 +261,7 @@ If you want to use a custom `json_schema` for completion response, pass it as `o ```ts -const openAi = new CompletionAdapterOpenAIChatGPT({ +const openAi = new CompletionAdapterOpenAIResponses({ openAiApiKey: process.env.OPENAI_API_KEY as string, model: 'gpt-5-mini', }); @@ -290,7 +292,7 @@ openAi.complete( If you want to explicitly test a reasoning-capable GPT-5 model, pass `reasoningEffort` as the 4th argument: ```ts -const openAi = new CompletionAdapterOpenAIChatGPT({ +const openAi = new CompletionAdapterOpenAIResponses({ openAiApiKey: process.env.OPENAI_API_KEY as string, model: "gpt-5-mini", }); @@ -310,7 +312,7 @@ console.log(resp.content); If you pass `onChunk`, adapter switches to streaming mode automatically: ```ts -const openAi = new CompletionAdapterOpenAIChatGPT({ +const openAi = new CompletionAdapterOpenAIResponses({ openAiApiKey: process.env.OPENAI_API_KEY as string, model: "gpt-5-mini", }); diff --git a/adminforth/documentation/docs/tutorial/08-Plugins/04-RichEditor.md b/adminforth/documentation/docs/tutorial/08-Plugins/04-RichEditor.md index c0c309022..99bf48829 100644 --- a/adminforth/documentation/docs/tutorial/08-Plugins/04-RichEditor.md +++ b/adminforth/documentation/docs/tutorial/08-Plugins/04-RichEditor.md @@ -106,21 +106,21 @@ If you need multiple fields in one resource which happens rarely, just add multi First, install the completion adapter: ```bash -pnpm i @adminforth/completion-adapter-open-ai-chat-gpt --save +pnpm i @adminforth/completion-adapter-openai-responses --save ``` To get completion suggestions for the text in the editor, you can use the `completion` option. This option is an object with the following properties: ```ts title="./resources/apartments.ts" //diff-add - import CompletionAdapterOpenAIChatGPT from "@adminforth/completion-adapter-open-ai-chat-gpt"; + import CompletionAdapterOpenAIResponses from "@adminforth/completion-adapter-openai-responses"; new RichEditorPlugin({ htmlFieldName: 'description', //diff-add completion: { //diff-add - adapter: new CompletionAdapterOpenAIChatGPT({ + adapter: new CompletionAdapterOpenAIResponses({ //diff-add openAiApiKey: process.env.OPENAI_API_KEY as string, //diff-add diff --git a/adminforth/documentation/docs/tutorial/08-Plugins/06-text-complete.md b/adminforth/documentation/docs/tutorial/08-Plugins/06-text-complete.md index b537c5d64..eb3871c52 100644 --- a/adminforth/documentation/docs/tutorial/08-Plugins/06-text-complete.md +++ b/adminforth/documentation/docs/tutorial/08-Plugins/06-text-complete.md @@ -1,12 +1,12 @@ # Text Complete -This plugin allows you to auto-complete text and string fields using OpenAI Chat GPT models. +This plugin allows you to auto-complete text and string fields using OpenAI GPT models via the Responses API. ## Installation ``` pnpm i @adminforth/text-complete --save -pnpm i @adminforth/completion-adapter-open-ai-chat-gpt --save +pnpm i @adminforth/completion-adapter-openai-responses --save ``` Go to https://platform.openai.com/, open `Dashboard` -> `API keys` -> `Create new secret key`. Paste value in your `.env` file: @@ -24,7 +24,7 @@ For example let's add it for title and description in `aparts` resource configur //diff-add import TextCompletePlugin from '@adminforth/text-complete'; //diff-add -import CompletionAdapterOpenAIChatGPT from "@adminforth/completion-adapter-open-ai-chat-gpt"; +import CompletionAdapterOpenAIResponses from "@adminforth/completion-adapter-openai-responses"; export const admin = new AdminForth({ @@ -40,7 +40,7 @@ export const admin = new AdminForth({ //diff-add fieldName: 'title', //diff-add - adapter: new CompletionAdapterOpenAIChatGPT({ + adapter: new CompletionAdapterOpenAIResponses({ //diff-add openAiApiKey: process.env.OPENAI_API_KEY as string, //diff-add @@ -60,7 +60,7 @@ export const admin = new AdminForth({ //diff-add fieldName: 'description', //diff-add - adapter: new CompletionAdapterOpenAIChatGPT({ + adapter: new CompletionAdapterOpenAIResponses({ //diff-add openAiApiKey: process.env.OPENAI_API_KEY as string, //diff-add diff --git a/adminforth/documentation/docs/tutorial/08-Plugins/10-i18n.md b/adminforth/documentation/docs/tutorial/08-Plugins/10-i18n.md index 5bc7dd536..7a8432963 100644 --- a/adminforth/documentation/docs/tutorial/08-Plugins/10-i18n.md +++ b/adminforth/documentation/docs/tutorial/08-Plugins/10-i18n.md @@ -3,7 +3,7 @@ This plugin allows you translate your AdminForth application to multiple languages. Main features: - Stores all translation strings in your application in a single AdminForth resource. You can set [allowed actions](/docs/tutorial/Customization/limitingAccess/) only to Developers/Translators role if you don't want other users to see/edit the translations. -- Supports AI completion adapters to help with translations. For example, you can use OpenAI ChatGPT to generate translations. Supports correct pluralization, even for Slavic languages. +- Supports AI completion adapters to help with translations. For example, you can use OpenAI via the Responses API to generate translations. Supports correct pluralization, even for Slavic languages. - Supports any number of languages. - Supports BCP47 language codes (e.g., `en-GB`, `pt-BR`) for regional language variants. - Configurable primary language. @@ -18,7 +18,7 @@ To install the plugin: ```bash pnpm install @adminforth/i18n --save -pnpm install @adminforth/completion-adapter-open-ai-chat-gpt --save +pnpm install @adminforth/completion-adapter-openai-responses --save ``` For example lets add translations to next 4 languages: Ukrainian, Japanese, French, Spanish. Also we will support basic translation for English. @@ -56,7 +56,7 @@ Next, add resource for translations: ```ts title='./resources/translations.ts' import AdminForth, { AdminForthDataTypes, AdminForthResourceInput } from "adminforth"; -import CompletionAdapterOpenAIChatGPT from "@adminforth/completion-adapter-open-ai-chat-gpt"; +import CompletionAdapterOpenAIResponses from "@adminforth/completion-adapter-openai-responses"; import I18nPlugin from "@adminforth/i18n"; import { randomUUID } from 'crypto'; @@ -96,7 +96,7 @@ export default { // optional: set primary language (defaults to 'en' if not specified) // primaryLanguage: 'fr', // Uncomment to set French as primary language - completeAdapter: new CompletionAdapterOpenAIChatGPT({ + completeAdapter: new CompletionAdapterOpenAIResponses({ openAiApiKey: process.env.OPENAI_API_KEY as string, model: 'gpt-5-nano', extraRequestBodyParameters: { diff --git a/adminforth/documentation/docs/tutorial/08-Plugins/17-bulk-ai-flow.md b/adminforth/documentation/docs/tutorial/08-Plugins/17-bulk-ai-flow.md index 998c65b8c..e685e5fee 100644 --- a/adminforth/documentation/docs/tutorial/08-Plugins/17-bulk-ai-flow.md +++ b/adminforth/documentation/docs/tutorial/08-Plugins/17-bulk-ai-flow.md @@ -199,12 +199,12 @@ This is the most basic plugin usage. You can connect any text completion adapter Normalize user names by translating them from any language to English for internal processing. ```ts -import CompletionAdapterOpenAIChatGPT from '@adminforth/completion-adapter-open-ai-chat-gpt/index.js'; +import CompletionAdapterOpenAIResponses from '@adminforth/completion-adapter-openai-responses'; // Add to your resource plugins array new BulkAiFlowPlugin({ actionName: 'Translate surnames', - textCompleteAdapter: new CompletionAdapterOpenAIChatGPT({ + textCompleteAdapter: new CompletionAdapterOpenAIResponses({ openAiApiKey: process.env.OPENAI_API_KEY as string, model: 'gpt-5-nano', extraRequestBodyParameters: { diff --git a/adminforth/documentation/docs/tutorial/08-Plugins/26-agent.md b/adminforth/documentation/docs/tutorial/08-Plugins/26-agent.md index 031b57fda..3350b00ce 100644 --- a/adminforth/documentation/docs/tutorial/08-Plugins/26-agent.md +++ b/adminforth/documentation/docs/tutorial/08-Plugins/26-agent.md @@ -11,7 +11,7 @@ It stores session history in your own resources and generates responses using on ```bash pnpm i @adminforth/agent --save -pnpm i @adminforth/completion-adapter-open-ai-chat-gpt --save +pnpm i @adminforth/completion-adapter-openai-responses --save ``` Add your LLM credentials to `.env`: @@ -196,7 +196,7 @@ Configure the plugin with `modes`. The legacy top-level `completionAdapter` setu ```ts title="./resources/adminuser.ts" import AdminForthAgent from '@adminforth/agent'; -import CompletionAdapterOpenAIChatGPT from '@adminforth/completion-adapter-open-ai-chat-gpt'; +import CompletionAdapterOpenAIResponses from '@adminforth/completion-adapter-openai-responses'; ... @@ -213,7 +213,7 @@ plugins: [ modes: [ { name: 'Balanced', - completionAdapter: new CompletionAdapterOpenAIChatGPT({ + completionAdapter: new CompletionAdapterOpenAIResponses({ openAiApiKey: process.env.OPENAI_API_KEY as string, model: 'gpt-5.4-mini', extraRequestBodyParameters: { @@ -225,7 +225,7 @@ plugins: [ }, { name: 'Fast', - completionAdapter: new CompletionAdapterOpenAIChatGPT({ + completionAdapter: new CompletionAdapterOpenAIResponses({ openAiApiKey: process.env.OPENAI_API_KEY as string, model: 'gpt-5.4-mini', extraRequestBodyParameters: { @@ -237,7 +237,7 @@ plugins: [ }, { name: 'Smart Thinking', - completionAdapter: new CompletionAdapterOpenAIChatGPT({ + completionAdapter: new CompletionAdapterOpenAIResponses({ openAiApiKey: process.env.OPENAI_API_KEY as string, model: 'gpt-5.4', extraRequestBodyParameters: { diff --git a/dev-demo/Taskfile.yaml b/dev-demo/Taskfile.yaml index 0d10376a7..c32cb7436 100644 --- a/dev-demo/Taskfile.yaml +++ b/dev-demo/Taskfile.yaml @@ -34,7 +34,6 @@ vars: - "adminforth-agent" ADAPTERS: - - "adminforth-completion-adapter-open-ai-chat-gpt" - "adminforth-email-adapter-aws-ses" - "adminforth-email-adapter-mailgun" - "adminforth-oauth-adapter-google" @@ -50,10 +49,15 @@ vars: - "adminforth-key-value-adapter-ram" - "adminforth-login-captcha-adapter-cloudflare" - "adminforth-login-captcha-adapter-recaptcha" - - "adminforth-completion-adapter-google-gemini" - "adminforth-key-value-adapter-redis" - "adminforth-key-value-adapter-leveldb" - "adminforth-image-generation-adapter-nano-banana" + # legacy + - "adminforth-completion-adapter-open-ai-chat-gpt" + + - "adminforth-completion-adapter-openai-responses" + - "adminforth-completion-adapter-antropic-messages" + - "adminforth-completion-adapter-google-gemini" tasks: diff --git a/dev-demo/resources/adminuser.ts b/dev-demo/resources/adminuser.ts index 8d25fca4d..0b39965de 100644 --- a/dev-demo/resources/adminuser.ts +++ b/dev-demo/resources/adminuser.ts @@ -11,7 +11,7 @@ import OpenSignupPlugin from '../../plugins/adminforth-open-signup/index.js'; import OAuthPlugin from '../../plugins/adminforth-oauth/index.js'; import KeyValueAdapterRam from '../../adapters/adminforth-key-value-adapter-ram/index.js'; import AdminForthAgent from '../../plugins/adminforth-agent/index.js'; -import CompletionAdapterOpenAIChatGPT from '../../adapters/adminforth-completion-adapter-open-ai-chat-gpt/index.js'; +import CompletionAdapterOpenAIResponses from '../../adapters/adminforth-completion-adapter-openai-responses/index.js'; async function allowedForSuperAdmin({ adminUser }: { adminUser: AdminUser }): Promise { return adminUser.dbUser.role === 'superadmin'; @@ -202,7 +202,7 @@ export default { modes: [ { name: 'Balanced', - completionAdapter: new CompletionAdapterOpenAIChatGPT({ + completionAdapter: new CompletionAdapterOpenAIResponses({ openAiApiKey: process.env.OPENAI_API_KEY as string, model: 'gpt-5.4-mini', extraRequestBodyParameters: { @@ -214,7 +214,7 @@ export default { }, { name: 'Fast', - completionAdapter: new CompletionAdapterOpenAIChatGPT({ + completionAdapter: new CompletionAdapterOpenAIResponses({ openAiApiKey: process.env.OPENAI_API_KEY as string, model: 'gpt-5.4-mini', extraRequestBodyParameters: { @@ -226,7 +226,7 @@ export default { }, { name: 'Smart Thinking', - completionAdapter: new CompletionAdapterOpenAIChatGPT({ + completionAdapter: new CompletionAdapterOpenAIResponses({ openAiApiKey: process.env.OPENAI_API_KEY as string, model: 'gpt-5.4', extraRequestBodyParameters: { diff --git a/dev-demo/resources/cars_resources/carsResourseTemplate.ts b/dev-demo/resources/cars_resources/carsResourseTemplate.ts index 0cb9c585f..1162a0888 100644 --- a/dev-demo/resources/cars_resources/carsResourseTemplate.ts +++ b/dev-demo/resources/cars_resources/carsResourseTemplate.ts @@ -15,7 +15,7 @@ import MarkdownPlugin from '../../../plugins/adminforth-markdown/index.js'; import QuickFiltersPlugin from '../../../plugins/adminforth-quick-filters/index.js'; import Many2ManyPlugin from '../../../plugins/adminforth-many2many/index.js'; -import CompletionAdapterOpenAIChatGPT from '../../../adapters/adminforth-completion-adapter-open-ai-chat-gpt/index.js'; +import CompletionAdapterOpenAIResponses from '../../../adapters/adminforth-completion-adapter-openai-responses/index.js'; import CompletionAdapterGoogleGemini from '../../../adapters/adminforth-completion-adapter-google-gemini/index.js'; import ImageGenerationAdapterOpenAI from '../../../adapters/adminforth-image-generation-adapter-openai/index.js'; import AdminForthStorageAdapterLocalFilesystem from "../../../adapters/adminforth-storage-adapter-local/index.js"; @@ -243,7 +243,7 @@ export default function carsResourseTemplate(resourceId: string, dataSource: Car }, ...(process.env.OPENAI_API_KEY ? { completion: { - adapter: new CompletionAdapterOpenAIChatGPT({ + adapter: new CompletionAdapterOpenAIResponses({ openAiApiKey: process.env.OPENAI_API_KEY as string, model: 'gpt-5-mini', }), @@ -325,7 +325,7 @@ export default function carsResourseTemplate(resourceId: string, dataSource: Car }), new TextCompletePlugin({ fieldName: 'model', - adapter: new CompletionAdapterOpenAIChatGPT({ + adapter: new CompletionAdapterOpenAIResponses({ openAiApiKey: process.env.OPENAI_API_KEY as string, model: 'gpt-5-nano', extraRequestBodyParameters: { @@ -336,7 +336,7 @@ export default function carsResourseTemplate(resourceId: string, dataSource: Car new BulkAiFlowPlugin({ actionName: 'Generate description and Price', askConfirmationBeforeGenerating: true, - textCompleteAdapter: new CompletionAdapterOpenAIChatGPT({ + textCompleteAdapter: new CompletionAdapterOpenAIResponses({ openAiApiKey: process.env.OPENAI_API_KEY as string, model: "gpt-5-mini", extraRequestBodyParameters: { diff --git a/dev-demo/resources/translations.ts b/dev-demo/resources/translations.ts index 60c448aab..901671037 100644 --- a/dev-demo/resources/translations.ts +++ b/dev-demo/resources/translations.ts @@ -1,5 +1,5 @@ -import CompletionAdapterOpenAIChatGPT from "../../adapters/adminforth-completion-adapter-open-ai-chat-gpt/index.js"; +import CompletionAdapterOpenAIResponses from "../../adapters/adminforth-completion-adapter-openai-responses/index.js"; import AdminForth, { AdminForthDataTypes, AdminForthResourceInput } from "../../adminforth/index.js"; import I18nPlugin from "../../plugins/adminforth-i18n/index.js"; import { randomUUID } from 'crypto'; @@ -38,7 +38,7 @@ export default { completedFieldName: 'completedLangs', ...(process.env.OPENAI_API_KEY ? { - completeAdapter: new CompletionAdapterOpenAIChatGPT({ + completeAdapter: new CompletionAdapterOpenAIResponses({ openAiApiKey: process.env.OPENAI_API_KEY as string, model: 'gpt-5-mini', }), diff --git a/live-demo/app/package.json b/live-demo/app/package.json index 3807324b1..5bb6175b5 100644 --- a/live-demo/app/package.json +++ b/live-demo/app/package.json @@ -21,7 +21,7 @@ "@adminforth/bulk-ai-flow": "^1.23.14", "@adminforth/chat-gpt": "^1.0.20", "@adminforth/clone-row": "^1.2.0", - "@adminforth/completion-adapter-open-ai-chat-gpt": "^2.0.19", + "@adminforth/completion-adapter-openai-responses": "^2.0.21", "@adminforth/email-password-reset": "^1.3.6", "@adminforth/foreign-inline-list": "^1.10.5", "@adminforth/i18n": "^1.6.7", diff --git a/live-demo/app/pnpm-lock.yaml b/live-demo/app/pnpm-lock.yaml index b674b7721..f61629998 100644 --- a/live-demo/app/pnpm-lock.yaml +++ b/live-demo/app/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@adminforth/agent': - specifier: ^1.18.1 - version: 1.18.4(@types/node@25.3.5)(openai@6.34.0(ws@8.19.0)(zod@4.3.6))(typescript@5.9.3)(ws@8.19.0) + specifier: ^1.18.5 + version: 1.21.0(@types/node@25.3.5)(openai@6.34.0(ws@8.19.0)(zod@4.3.6))(typescript@5.9.3)(ws@8.19.0) '@adminforth/audit-log': specifier: ^1.9.12 version: 1.9.15(adminforth@2.40.0(@types/node@25.3.5)(typescript@5.9.3)) @@ -23,9 +23,9 @@ importers: '@adminforth/clone-row': specifier: ^1.2.0 version: 1.2.3(adminforth@2.40.0(@types/node@25.3.5)(typescript@5.9.3)) - '@adminforth/completion-adapter-open-ai-chat-gpt': - specifier: ^2.0.19 - version: 2.0.19(adminforth@2.40.0(@types/node@25.3.5)(typescript@5.9.3))(ws@8.19.0)(zod@4.3.6) + '@adminforth/completion-adapter-openai-responses': + specifier: ^2.0.21 + version: 2.0.21(adminforth@2.40.0(@types/node@25.3.5)(typescript@5.9.3))(ws@8.19.0)(zod@4.3.6) '@adminforth/email-password-reset': specifier: ^1.3.6 version: 1.3.10(adminforth@2.40.0(@types/node@25.3.5)(typescript@5.9.3)) @@ -96,8 +96,8 @@ importers: packages: - '@adminforth/agent@1.18.4': - resolution: {integrity: sha512-ndWiyupBccJKuLnVJ+pOP95AisDRLVTBjv6AL6cudfvpyy6jRu0wrTGsXNCkp8mQZcVyHsTvIdOQkV968CYUEw==} + '@adminforth/agent@1.21.0': + resolution: {integrity: sha512-aCiuJB8Cj4kcpT/oZ8cPqWiyvNbEz95hyCB7WPCJBy2TaIn+tBacL4sR2+mh9Ll4T+kJRijC/XMBAdQ98kAiuw==} '@adminforth/audit-log@1.9.15': resolution: {integrity: sha512-do8vXCMlfvu6ToPcACs+YBwGaa/g3cc2GyseUZIoUmerqBe7Y5Lj3T6KLjVa9Fd69f27mLowORsfXrRpqfoTIA==} @@ -117,8 +117,8 @@ packages: peerDependencies: adminforth: ^2.24.0 - '@adminforth/completion-adapter-open-ai-chat-gpt@2.0.19': - resolution: {integrity: sha512-XePBl/POUHaDjxZO+SvESFIwEKqFo32ovLd16/IVFW/hEIpWUfUhMYrsv+RrvQsTinKB2YDtvG94fhRI6bKjLg==} + '@adminforth/completion-adapter-openai-responses@2.0.21': + resolution: {integrity: sha512-rodTqSb2YePCY8QgWVvclB1Txqjz59vvYA3u4MCvKp2xyGyjl1fOZzROGrS5Weminy3uK5oXR8hwCou+EQAAjA==} peerDependencies: adminforth: ^2.24.0 @@ -2667,7 +2667,7 @@ packages: snapshots: - '@adminforth/agent@1.18.4(@types/node@25.3.5)(openai@6.34.0(ws@8.19.0)(zod@4.3.6))(typescript@5.9.3)(ws@8.19.0)': + '@adminforth/agent@1.21.0(@types/node@25.3.5)(openai@6.34.0(ws@8.19.0)(zod@4.3.6))(typescript@5.9.3)(ws@8.19.0)': dependencies: '@langchain/core': 1.1.40(openai@6.34.0(ws@8.19.0)(zod@4.3.6))(ws@8.19.0) '@langchain/langgraph': 1.2.9(@langchain/core@1.1.40(openai@6.34.0(ws@8.19.0)(zod@4.3.6))(ws@8.19.0))(zod@4.3.6) @@ -2720,7 +2720,7 @@ snapshots: dependencies: adminforth: 2.40.0(@types/node@25.3.5)(typescript@5.9.3) - '@adminforth/completion-adapter-open-ai-chat-gpt@2.0.19(adminforth@2.40.0(@types/node@25.3.5)(typescript@5.9.3))(ws@8.19.0)(zod@4.3.6)': + '@adminforth/completion-adapter-openai-responses@2.0.21(adminforth@2.40.0(@types/node@25.3.5)(typescript@5.9.3))(ws@8.19.0)(zod@4.3.6)': dependencies: adminforth: 2.40.0(@types/node@25.3.5)(typescript@5.9.3) openai: 6.34.0(ws@8.19.0)(zod@4.3.6) diff --git a/live-demo/app/resources/apartments.ts b/live-demo/app/resources/apartments.ts index 37e463445..c73959311 100644 --- a/live-demo/app/resources/apartments.ts +++ b/live-demo/app/resources/apartments.ts @@ -4,7 +4,7 @@ import RichEditorPlugin from '@adminforth/rich-editor'; import TextCompletePlugin from '@adminforth/text-complete'; import UploadPlugin from '@adminforth/upload'; import { randomUUID } from 'crypto'; -import CompletionAdapterOpenAIChatGPT from "@adminforth/completion-adapter-open-ai-chat-gpt"; +import CompletionAdapterOpenAIResponses from "@adminforth/completion-adapter-openai-responses"; import AdminForthAdapterS3Storage from '@adminforth/storage-adapter-amazon-s3' import ImageGenerationAdapterOpenAI from '@adminforth/image-generation-adapter-openai'; import BulkAiFlowPlugin from '@adminforth/bulk-ai-flow'; @@ -167,7 +167,7 @@ export default { new RichEditorPlugin({ htmlFieldName: 'description', completion: { - adapter: new CompletionAdapterOpenAIChatGPT({ + adapter: new CompletionAdapterOpenAIResponses({ openAiApiKey: process.env.OPENAI_API_KEY as string, model: 'gpt-4o', // default "gpt-4o-mini" expert: { @@ -186,7 +186,7 @@ export default { }), new TextCompletePlugin({ fieldName: 'title', - adapter: new CompletionAdapterOpenAIChatGPT({ + adapter: new CompletionAdapterOpenAIResponses({ openAiApiKey: process.env.OPENAI_API_KEY as string, }), // expert: { diff --git a/live-demo/app/resources/translations.ts b/live-demo/app/resources/translations.ts index 4604f1b02..488b9d316 100644 --- a/live-demo/app/resources/translations.ts +++ b/live-demo/app/resources/translations.ts @@ -1,6 +1,6 @@ import AdminForth, { AdminForthDataTypes, AdminForthResourceInput } from "adminforth"; -import CompletionAdapterOpenAIChatGPT from "@adminforth/completion-adapter-open-ai-chat-gpt"; +import CompletionAdapterOpenAIResponses from "@adminforth/completion-adapter-openai-responses"; import I18nPlugin from "@adminforth/i18n"; import { randomUUID } from 'crypto'; @@ -52,7 +52,7 @@ export default { // will hel to filter out incomplete translations completedFieldName: 'completedLangs', - completeAdapter: new CompletionAdapterOpenAIChatGPT({ + completeAdapter: new CompletionAdapterOpenAIResponses({ openAiApiKey: process.env.OPENAI_API_KEY as string, model: 'gpt-4o-mini', expert: { diff --git a/live-demo/app/resources/users.ts b/live-demo/app/resources/users.ts index d6459e5c5..bf43e4949 100644 --- a/live-demo/app/resources/users.ts +++ b/live-demo/app/resources/users.ts @@ -1,7 +1,7 @@ import AdminForth, { AdminForthDataTypes, AdminForthResourceColumn } from 'adminforth'; import type { AdminForthResource } from 'adminforth'; import AdminForthAgent from '@adminforth/agent'; -import CompletionAdapterOpenAIChatGPT from '@adminforth/completion-adapter-open-ai-chat-gpt'; +import CompletionAdapterOpenAIResponses from '@adminforth/completion-adapter-openai-responses'; import ForeignInlineListPlugin from '@adminforth/foreign-inline-list'; import { randomUUID } from 'crypto'; import { getLocalizedPlaceholderMessages } from './agent_resources/placeholderMessages'; @@ -11,7 +11,7 @@ const openAiApiKey = process.env.OPENAI_API_KEY as string; const createCompletionAdapter = ( model: string, effort: 'low' | 'medium' | 'xhigh', -) => new CompletionAdapterOpenAIChatGPT({ +) => new CompletionAdapterOpenAIResponses({ openAiApiKey, model, extraRequestBodyParameters: { From 9b1316ba3452feee30d1baac837845ec3204c148 Mon Sep 17 00:00:00 2001 From: yaroslav8765 Date: Thu, 23 Apr 2026 14:25:04 +0300 Subject: [PATCH 4/7] fix: set data-theme atribute onMount --- adminforth/spa/src/App.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adminforth/spa/src/App.vue b/adminforth/spa/src/App.vue index 38ad14669..54921fdc4 100644 --- a/adminforth/spa/src/App.vue +++ b/adminforth/spa/src/App.vue @@ -333,7 +333,7 @@ onMounted(async () => { await loadMenu(); // and this // before init flowbite we have to wait router initialized because it affects dom(our v-ifs) and fetch menu await initRouter(); - + document.documentElement.setAttribute('data-theme', theme.value); menu.refreshMenuBadges = async () => { await coreStore.fetchMenuBadges(); } From 6e4cfdb6da2a6f8f36427a710870dbf2682deb0b Mon Sep 17 00:00:00 2001 From: Ivan Borshchov Date: Thu, 23 Apr 2026 11:26:38 +0000 Subject: [PATCH 5/7] feat: add various adapter documentation and update completion adapter interface Co-authored-by: Copilot --- .../tutorial/05-Adapters/01-email-adapters.md | 21 + .../05-Adapters/02-oauth2-adapters.md | 53 +++ .../03-image-generation-adapters.md | 25 + .../05-Adapters/04-storage-adapters.md | 21 + .../05-Adapters/05-ai-completion-adapters.md | 167 +++++++ .../05-Adapters/06-image-analysis-adapters.md | 15 + .../05-Adapters/07-key-value-adapters.md | 59 +++ .../05-Adapters/08-captcha-adapters.md | 17 + .../docs/tutorial/05-Adapters/_category_.json | 12 + .../docs/tutorial/05-ListOfAdapters.md | 445 ------------------ .../09-Advanced/01-plugin-development.md | 26 +- adminforth/documentation/docusaurus.config.ts | 3 +- .../types/adapters/CompletionAdapter.ts | 39 +- adminforth/types/adapters/index.ts | 8 +- .../agent_resources/placeholderMessages.ts | 10 +- 15 files changed, 447 insertions(+), 474 deletions(-) create mode 100644 adminforth/documentation/docs/tutorial/05-Adapters/01-email-adapters.md create mode 100644 adminforth/documentation/docs/tutorial/05-Adapters/02-oauth2-adapters.md create mode 100644 adminforth/documentation/docs/tutorial/05-Adapters/03-image-generation-adapters.md create mode 100644 adminforth/documentation/docs/tutorial/05-Adapters/04-storage-adapters.md create mode 100644 adminforth/documentation/docs/tutorial/05-Adapters/05-ai-completion-adapters.md create mode 100644 adminforth/documentation/docs/tutorial/05-Adapters/06-image-analysis-adapters.md create mode 100644 adminforth/documentation/docs/tutorial/05-Adapters/07-key-value-adapters.md create mode 100644 adminforth/documentation/docs/tutorial/05-Adapters/08-captcha-adapters.md create mode 100644 adminforth/documentation/docs/tutorial/05-Adapters/_category_.json delete mode 100644 adminforth/documentation/docs/tutorial/05-ListOfAdapters.md diff --git a/adminforth/documentation/docs/tutorial/05-Adapters/01-email-adapters.md b/adminforth/documentation/docs/tutorial/05-Adapters/01-email-adapters.md new file mode 100644 index 000000000..c92a64d58 --- /dev/null +++ b/adminforth/documentation/docs/tutorial/05-Adapters/01-email-adapters.md @@ -0,0 +1,21 @@ +# Email Adapters + +Used to send emails. + +[Email adapter base class](https://github.com/devforth/adminforth/blob/917d897c866975a4aee29273377f2c07cb6ddf81/adminforth/types/adapters/EmailAdapter.ts#L17) + +## AWS SES Email Adapter + +```bash +pnpm i @adminforth/email-adapter-aws-ses +``` + +Enables email delivery via [Amazon Simple Email Service (SES)](https://aws.amazon.com/ses/), suitable for high-volume, programmatic email sending. + +## Mailgun Email Adapter + +```bash +pnpm i @adminforth/email-adapter-mailgun +``` + +Allows sending transactional or marketing emails using [Mailgun](https://www.mailgun.com/), a developer-friendly email service. \ No newline at end of file diff --git a/adminforth/documentation/docs/tutorial/05-Adapters/02-oauth2-adapters.md b/adminforth/documentation/docs/tutorial/05-Adapters/02-oauth2-adapters.md new file mode 100644 index 000000000..8abe31772 --- /dev/null +++ b/adminforth/documentation/docs/tutorial/05-Adapters/02-oauth2-adapters.md @@ -0,0 +1,53 @@ +# OAuth2 Adapters + +Used to authenticate users via OAuth 2.0 providers. + +[OAuth2Adapter source class](https://github.com/devforth/adminforth/blob/917d897c866975a4aee29273377f2c07cb6ddf81/adminforth/types/adapters/OAuth2Adapter.ts#L9) + +## Google OAuth Adapter + +```bash +pnpm i @adminforth/google-oauth-adapter +``` + +Supports Google sign-in to allow users to authenticate using their Google or Google Workspaces accounts. + +## GitHub OAuth Adapter + +```bash +pnpm i @adminforth/github-oauth-adapter +``` + +Enables authentication via GitHub accounts, useful for developer tools and open-source apps. + +## Facebook OAuth Adapter + +```bash +pnpm i @adminforth/facebook-oauth-adapter +``` + +Allows users to log in with Facebook credentials. Facebook OAuth is commonly used for social media integrations. + +## Keycloak OAuth Adapter + +```bash +pnpm i @adminforth/keycloak-oauth-adapter +``` + +Connects AdminForth to an open-source [Keycloak](https://www.keycloak.org/) identity provider for enterprise-grade SSO (Single Sign-On). + +## Microsoft OAuth Adapter + +```bash +pnpm i @adminforth/microsoft-oauth-adapter +``` + +Supports login through Microsoft accounts including Azure AD, Office365, and Outlook.com. + +## Twitch OAuth Adapter + +```bash +pnpm i @adminforth/twitch-oauth-adapter +``` + +Adds support for Twitch authentication, useful for streaming or creator-oriented platforms. \ No newline at end of file diff --git a/adminforth/documentation/docs/tutorial/05-Adapters/03-image-generation-adapters.md b/adminforth/documentation/docs/tutorial/05-Adapters/03-image-generation-adapters.md new file mode 100644 index 000000000..db3874591 --- /dev/null +++ b/adminforth/documentation/docs/tutorial/05-Adapters/03-image-generation-adapters.md @@ -0,0 +1,25 @@ +# Image Generation Adapters + +Used for image-generating AI tools. + +[ImageGenerationAdapter source class](https://github.com/devforth/adminforth/blob/917d897c866975a4aee29273377f2c07cb6ddf81/adminforth/types/adapters/ImageGenerationAdapter.ts#L32) + +## OpenAI Image Generation Adapter + +```bash +pnpm i @adminforth/image-generation-adapter-openai +``` + +Uses OpenAI image generation models such as DALL·E, `gpt-image-1`, and `gpt-image-1.5` to generate images from text prompts. + +Up to the winter 2026 OpenAI models are one of the most powerful image generation models available, especially GPT-Image-1.5, which is why we started with them. + +## Gemini (Nano Banana) Image Generation Adapter + +```bash +pnpm i @adminforth/image-generation-adapter-nano-banana +``` + +Uses the latest `gemini-3.1-flash-image-preview` model for instant image generation with text descriptions. + +This model is the top of the Nano Banana line as of 2026, combining the speed of the Flash series with the improved detail of version 3.1. The adapter lets you integrate the advanced capabilities of previous models into your interface and generate precise visuals even for specific or complex prompts. \ No newline at end of file diff --git a/adminforth/documentation/docs/tutorial/05-Adapters/04-storage-adapters.md b/adminforth/documentation/docs/tutorial/05-Adapters/04-storage-adapters.md new file mode 100644 index 000000000..b1ed5ecc3 --- /dev/null +++ b/adminforth/documentation/docs/tutorial/05-Adapters/04-storage-adapters.md @@ -0,0 +1,21 @@ +# Storage Adapters + +Used for storing files. + +[StorageAdapter source class](https://github.com/devforth/adminforth/blob/917d897c866975a4aee29273377f2c07cb6ddf81/adminforth/types/adapters/StorageAdapter.ts#L8) + +## Amazon S3 Storage Adapter + +```bash +pnpm i @adminforth/storage-adapter-amazon-s3 +``` + +Stores uploaded files in [Amazon S3](https://aws.amazon.com/s3/), providing scalable cloud storage. It can be forked and customized to work with S3-compatible services such as MinIO, Wasabi, or other third-party S3 providers. + +## Local Storage Adapter + +```bash +pnpm i @adminforth/storage-adapter-local +``` + +Stores files locally on the server filesystem. It is suitable for development or small self-hosted setups, but cloud storage is generally a better production option for reliability and scalability. \ No newline at end of file diff --git a/adminforth/documentation/docs/tutorial/05-Adapters/05-ai-completion-adapters.md b/adminforth/documentation/docs/tutorial/05-Adapters/05-ai-completion-adapters.md new file mode 100644 index 000000000..0c4c49c98 --- /dev/null +++ b/adminforth/documentation/docs/tutorial/05-Adapters/05-ai-completion-adapters.md @@ -0,0 +1,167 @@ +# AI Completion Adapters + +Used for AI-powered text completion. + +[CompletionAdapter source class](https://github.com/devforth/adminforth/blob/917d897c866975a4aee29273377f2c07cb6ddf81/adminforth/types/adapters/CompletionAdapter.ts#L16) + +Feel free to fork and implement other models, including Anthropic, Google Gemini, or any other AI model that supports text completion. + +## Common `complete()` signature + +All completion adapters implement the same `complete()` method signature from the shared `CompletionAdapter` interface. + +```ts +complete({ + content: string, + maxTokens: number, + outputSchema?: any, + reasoningEffort?: 'none' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh', + tools?: CompletionTool[], + onChunk?: ( + chunk: string, + event?: { + type: 'output' | 'reasoning'; + delta: string; + text: string; + source?: 'summary' | 'text'; + }, + ) => void | Promise, +}) +``` + +`reasoningEffort` is optional and defaults to `low` in the adapter implementation. + +## Using `json_schema` + +All completion adapters accept structured output through the shared `outputSchema` field in the request object. The example below uses the OpenAI adapter, but the same request shape is common for all completion adapters. + +```ts +const adapter = new CompletionAdapterOpenAIResponses({ + openAiApiKey: process.env.OPENAI_API_KEY as string, + model: 'gpt-5-mini', +}); + +const prompt = 'What is the capital of France? return json'; + +adapter.complete({ + content: prompt, + maxTokens: 200, + outputSchema: { + name: 'capital_response', + schema: { + type: 'object', + properties: { + capital: { type: 'string' }, + }, + required: ['capital'], + }, + }, +}).then((resp) => { + console.log(resp); +}); +``` + + +## Using streaming output and reasoning events + +All completion adapters accept `onChunk` inside the request object. The example below uses the OpenAI adapter, but the callback signature is common for all completion adapters. + +Streaming reasoning events depend on the selected model and provider response. + +```ts +const adapter = new CompletionAdapterOpenAIResponses({ + openAiApiKey: process.env.OPENAI_API_KEY as string, + model: 'gpt-5-mini', +}); + +await adapter.complete({ + content: 'Think step by step and write a short answer about how ABS brakes work', + maxTokens: 300, + reasoningEffort: 'medium', + onChunk: async (chunk, event) => { + if (!event) return; + + if (event.type === 'reasoning') { + console.log('Reasoning chunk:', event.delta); + return; + } + + console.log('Output chunk:', event.delta); + }, +}); +``` + +Then output will be like: + +```ts +{ content: '{"capital":"Paris"}', finishReason: 'stop' } +``` + + +## OpenAI Responses Completion Adapter + +```bash +pnpm i @adminforth/completion-adapter-openai-responses +``` + +Integrates AdminForth with OpenAI's Responses API to provide AI-powered completion and conversational features. + +The older `@adminforth/completion-adapter-open-ai-chat-gpt` package is deprecated. Use this package instead. + +```ts +import CompletionAdapterOpenAIResponses from '@adminforth/completion-adapter-openai-responses'; + +new CompletionAdapterOpenAIResponses({ + openAiApiKey: process.env.OPENAI_API_KEY as string, + model: 'gpt-5.2', + extraRequestBodyParameters: { + temperature: 0.7, + reasoning: { + effort: 'medium', + }, + }, +}), +``` + +You can specify any GPT model you need. The default is `gpt-5-nano`. + +This adapter uses the OpenAI `responses` API. + +## Google Gemini Completion Adapter + +```bash +pnpm i @adminforth/completion-adapter-google-gemini +``` + +Integrates AdminForth with Google Gemini models to provide AI-powered completion and conversational features. + +```ts +import CompletionAdapterGoogleGemini from '@adminforth/completion-adapter-google-gemini'; + +new CompletionAdapterGoogleGemini({ + geminiApiKey: process.env.GEMINI_API_KEY as string, + model: 'gemini-3-pro-preview', + extraRequestBodyParameters: { + temperature: 0.7, + }, +}), +``` + +You can specify any Gemini model you need. The default is `gemini-3-flash-preview`. + +## Adding extra request body params + +There might be cases where you want to add extra body params to the request sent to the AI provider. For those cases you can use `extraRequestBodyParameters`: + +```ts +import CompletionAdapterGoogleGemini from '@adminforth/completion-adapter-google-gemini'; + +new CompletionAdapterGoogleGemini({ + geminiApiKey: process.env.GEMINI_API_KEY as string, + model: 'gemini-3-pro-preview', + extraRequestBodyParameters: { + temperature: 0.7, + responseMimeType: 'application/json', + }, +}), +``` \ No newline at end of file diff --git a/adminforth/documentation/docs/tutorial/05-Adapters/06-image-analysis-adapters.md b/adminforth/documentation/docs/tutorial/05-Adapters/06-image-analysis-adapters.md new file mode 100644 index 000000000..8fa27ba6e --- /dev/null +++ b/adminforth/documentation/docs/tutorial/05-Adapters/06-image-analysis-adapters.md @@ -0,0 +1,15 @@ +# Image Analysis Adapters + +Used for AI-powered image analysis. + +[ImageVisionAdapter source class](https://github.com/devforth/adminforth/blob/1efdc19e3bb7a5fc3b19106704e4ae8bb7c73276/adminforth/types/adapters/ImageVisionAdapter.ts#L1) + +These adapters can analyze image content, extract text from images, identify objects, describe scenes, and provide detailed image insights. + +## OpenAI Vision Adapter + +```bash +pnpm install @adminforth/image-vision-adapter-openai --save +``` + +Integrates AdminForth with OpenAI to provide advanced AI-powered image analysis. It can describe image content, read and extract text from images, identify objects and people, and provide detailed visual insights. \ No newline at end of file diff --git a/adminforth/documentation/docs/tutorial/05-Adapters/07-key-value-adapters.md b/adminforth/documentation/docs/tutorial/05-Adapters/07-key-value-adapters.md new file mode 100644 index 000000000..8f71f6119 --- /dev/null +++ b/adminforth/documentation/docs/tutorial/05-Adapters/07-key-value-adapters.md @@ -0,0 +1,59 @@ +# Key-value Adapters + +Key-value adapters are used to store data in a key-value format. They provide a simple and efficient way to manage data where quick access to values based on unique keys is required. + +[Key-value adapter source class](https://github.com/devforth/adminforth/blob/86bb9236fed9e844fdb07688318c050641f9eb1c/adminforth/types/adapters/KeyValueAdapter.ts#L6) + +## RAM Adapter + +```bash +pnpm i @adminforth/key-value-adapter-ram +``` + +The RAM adapter is a simple in-memory key-value store. It keeps data in process memory, so it is not suitable for multi-process deployments because each process would have its own isolated store. In that case you need a centralized KV adapter such as Redis. + +Pros: + +- Simplest to use and does not require an external daemon. + +Cons: + +- Suitable for single-process installations only. + +## Redis Adapter + +```bash +pnpm i @adminforth/key-value-adapter-redis +``` + +Redis uses in-memory storage with $O(1)$ get complexity. It is a great fit for lightweight workloads that fit in RAM, and it also works well for multi-process or replica-based installations as a centralized store. If persistence across restarts is important, configure Redis persistence separately. + +```ts +import RedisKeyValueAdapter from '@adminforth/key-value-adapter-redis'; + +const adapter = new RedisKeyValueAdapter({ + redisUrl: '127.0.0.1:6379', +}); + +adapter.set('test-key', 'test-value', 120); +``` + +## LevelDB Adapter + +```bash +pnpm i @adminforth/key-value-adapter-leveldb +``` + +LevelDB uses disk storage with $O(\log n)$ get complexity. It is a good fit for large or persistent KV datasets that still require fast lookups but do not efficiently fit in RAM. This is a single-process adapter only, so multiple admin processes should not point to the same LevelDB directory. + +You can use replicas with isolated disks, but in that case the state will also be isolated between replicas. + +```ts +import LevelDBKeyValueAdapter from '@adminforth/key-value-adapter-leveldb'; + +const adapter = new LevelDBKeyValueAdapter({ + dbPath: './testdb', +}); + +adapter.set('test-key', 'test-value', 120); +``` \ No newline at end of file diff --git a/adminforth/documentation/docs/tutorial/05-Adapters/08-captcha-adapters.md b/adminforth/documentation/docs/tutorial/05-Adapters/08-captcha-adapters.md new file mode 100644 index 000000000..b63c442b5 --- /dev/null +++ b/adminforth/documentation/docs/tutorial/05-Adapters/08-captcha-adapters.md @@ -0,0 +1,17 @@ +# Captcha Adapters + +Used to add captcha to the login screen. + +[Captcha adapter source class](https://github.com/devforth/adminforth/blob/65153408a119314dad339f452700e0937952034a/adminforth/types/adapters/CaptchaAdapter.ts#L5) + +## Cloudflare Adapter + +```bash +pnpm i @adminforth/login-captcha-adapter-cloudflare +``` + +## reCaptcha Adapter + +```bash +pnpm i @adminforth/login-captcha-adapter-recaptcha +``` \ No newline at end of file diff --git a/adminforth/documentation/docs/tutorial/05-Adapters/_category_.json b/adminforth/documentation/docs/tutorial/05-Adapters/_category_.json new file mode 100644 index 000000000..0e50c219f --- /dev/null +++ b/adminforth/documentation/docs/tutorial/05-Adapters/_category_.json @@ -0,0 +1,12 @@ +{ + "label": "Adapters", + "position": 5, + "collapsible": true, + "collapsed": true, + "link": { + "type": "generated-index", + "title": "AdminForth Adapters", + "slug": "/tutorial/ListOfAdapters", + "description": "This section contains the available adapters in the AdminForth ecosystem. Adapters are used by AdminForth plugins to connect to third-party services and APIs, and each adapter can be forked and customized for a new service or provider." + } +} \ No newline at end of file diff --git a/adminforth/documentation/docs/tutorial/05-ListOfAdapters.md b/adminforth/documentation/docs/tutorial/05-ListOfAdapters.md deleted file mode 100644 index ad5790cd9..000000000 --- a/adminforth/documentation/docs/tutorial/05-ListOfAdapters.md +++ /dev/null @@ -1,445 +0,0 @@ -# AdminForth Adapters - -This page has a list of all available adapters in the AdminForth ecosystem. -Adapters are used by AdminForth plugins to implement connections to various 3rd-party services and APIs. -Every adapter could be easily forked and customized for any new service or API. - ---- - -## 📧 Email Adapters - -Used to send emails - -[🔗Email adapter base class](https://github.com/devforth/adminforth/blob/917d897c866975a4aee29273377f2c07cb6ddf81/adminforth/types/adapters/EmailAdapter.ts#L17) - -### AWS SES Email Adapter - -``` -pnpm i @adminforth/email-adapter-aws-ses -``` - -Enables email delivery via [Amazon Simple Email Service (SES)](https://aws.amazon.com/ses/), suitable for high-volume, programmatic email sending. - -### Mailgun Email Adapter - -``` -pnpm i @adminforth/email-adapter-mailgun -``` - -Allows sending transactional or marketing emails using [Mailgun](https://www.mailgun.com/), a developer-friendly email service. - ---- - -## 🔐 OAuth2 Adapters - -Used to authenticate users via OAuth 2.0 providers - -[🔗OAuth2Adapter source class](https://github.com/devforth/adminforth/blob/917d897c866975a4aee29273377f2c07cb6ddf81/adminforth/types/adapters/OAuth2Adapter.ts#L9) - - -### Google OAuth Adapter - -``` -pnpm i @adminforth/google-oauth-adapter -``` - -Supports Google sign-in to allow users to authenticate using their Google or Google Workspaces accounts. - -### GitHub OAuth Adapter - -``` -pnpm i @adminforth/github-oauth-adapter -``` - -Enables authentication via GitHub accounts, useful for developer tools and open-source apps. - -### Facebook OAuth Adapter - -``` -pnpm i @adminforth/facebook-oauth-adapter -``` - -Allows users to log in with Facebook credentials. Facebook OAuth is commonly used for social media integrations. - -### Keycloak OAuth Adapter - -``` -pnpm i @adminforth/keycloak-oauth-adapter -``` - -Connects AdminForth to an Open-Source [Keycloak](https://www.keycloak.org/) - generally self-hosted - identity provider for enterprise-grade SSO (Single Sign-On). - -### Microsoft OAuth Adapter - -``` -pnpm i @adminforth/microsoft-oauth-adapter -``` - -Supports login through Microsoft accounts including Azure AD, Office365, and Outlook.com. - -### Twitch OAuth Adapter - -``` -pnpm i @adminforth/twitch-oauth-adapter -``` - -Adds support for Twitch authentication, useful for streaming or creator-oriented platforms. - ---- - -## 🎨 Image Generation Adapters - -Is used for image generating AI tools. - -[🔗ImageGenerationAdapter source class](https://github.com/devforth/adminforth/blob/917d897c866975a4aee29273377f2c07cb6ddf81/adminforth/types/adapters/ImageGenerationAdapter.ts#L32) - - -### OpenAI Image Generation Adapter - -``` -pnpm i @adminforth/image-generation-adapter-openai -``` - -Uses OpenAI’s image generation models (like DALL·E, gpt-image-1, gpt-image-1.5) to generate images from text prompts. - -Up to the winter 2026 OpenAI models are one of the most powerful image generation models available (Especially GPT-Image-1.5), that is why we started with them. - ---- - -### Gemini (Nano Banana) Image Generation Adapter - -``` -pnpm i @adminforth/image-generation-adapter-nano-banana -``` - -Uses the latest gemini-3.1-flash-image-preview model for instant image generation with text descriptions. - -This model is the top of the Nano Banana line as of 2026, combining the lightning-fast speed of the Flash series with the improved detail of version 3.1. The adapter allows you to integrate the advanced capabilities of previous models into your interface, providing high-precision visualization for even the most specific and complex queries. - ---- - -## 💾 Storage Adapters - - -[🔗StorageAdapter source class](https://github.com/devforth/adminforth/blob/917d897c866975a4aee29273377f2c07cb6ddf81/adminforth/types/adapters/StorageAdapter.ts#L8) - -Is used for storing files - -### Amazon S3 Storage Adapter - -``` -pnpm i @adminforth/storage-adapter-amazon-s3 -``` - -Stores uploaded files in [Amazon S3](https://aws.amazon.com/s3/), providing scalable cloud storage. -Can be easily forked and customized to work with any S3-compatible storage service like MinIO or Wasabi or 3rd-party S3-capable services. - - -### Local Storage Adapter - -``` -pnpm i @adminforth/storage-adapter-local -``` - -Stores files locally on the server’s filesystem. Suitable for development or small-scale self-hosted setups. -Not really recommended for production use, cause cloud storage is more reliable and scalable. - ---- - -## 🧠 AI Completion Adapters - -[🔗CompletionAdapter source class](https://github.com/devforth/adminforth/blob/917d897c866975a4aee29273377f2c07cb6ddf81/adminforth/types/adapters/CompletionAdapter.ts#L16) - - -Is used for AI-powered text completion. -Feel free to fork and implement other models including models from Anthropic, Google Gemini, or any other AI model that supports text completion. - -### OpenAI Responses Completion Adapter - -``` -pnpm i @adminforth/completion-adapter-openai-responses -``` - -Integrates AdminForth with OpenAI's Responses API to provide AI-powered completion and conversational features. - -The older `@adminforth/completion-adapter-open-ai-chat-gpt` package is deprecated. Use this package instead. - -```ts -import CompletionAdapterOpenAIResponses from "@adminforth/completion-adapter-openai-responses"; - -new CompletionAdapterOpenAIResponses({ - openAiApiKey: process.env.OPENAI_API_KEY as string, - model: 'gpt-5.2', - extraRequestBodyParameters: { - temperature: 0.7 - } -}), - -``` -You can specify any gpt model you need. Default is `gpt-5-nano` - -This adapter uses the OpenAI `responses` API and supports: - -- regular text completion -- `json_schema` structured output -- reasoning effort control -- streaming output chunks -- streaming reasoning chunks - -### OpenAI adapter `complete()` signature - -```ts -complete( - content: string, - maxTokens?: number, - outputSchema?: any, - reasoningEffort?: "none" | "minimal" | "low" | "medium" | "high" | "xhigh", - onChunk?: ( - chunk: string, - event?: { - type: "output" | "reasoning"; - delta: string; - text: string; - source?: "summary" | "text"; - }, - ) => void | Promise, -) -``` - -`reasoningEffort` is optional and defaults to `low` in the adapter implementation. - ---- - -### Google Gemini Completion Adapter - -``` -pnpm i @adminforth/completion-adapter-google-gemini -``` - -Integrates AdminForth with Google Gemini models to provide AI-powered completion and conversational features. - -```ts -import CompletionAdapterGoogleGemini from '@adminforth/completion-adapter-google-gemini'; - -new CompletionAdapterGoogleGemini({ - geminiApiKey: process.env.GEMINI_API_KEY as string, - model: "gemini-3-pro-preview", - extraRequestBodyParameters: { - temperature: 0.7 - } -}), -``` - -You can specify any gemini model you need. Default is `gemini-3-flash-preview` - -### Adding extra request body params - -There might be cases, whe you want to add extra body params in request, that sent to the AI provider. For those cases you can use `extraRequestBodyParameters`: - - -```ts -import CompletionAdapterGoogleGemini from '@adminforth/completion-adapter-google-gemini'; - -new CompletionAdapterGoogleGemini({ - geminiApiKey: process.env.GEMINI_API_KEY as string, - model: "gemini-3-pro-preview", - extraRequestBodyParameters: { - temperature: 0.7 - } - //diff-add - extraRequestBodyParameters: { - //diff-add - responseMimeType: "application/json", - //diff-add - } -}), -``` - -### Using json_schema with adapter - -If you want to use a custom `json_schema` for completion response, pass it as `outputSchema`: - - -```ts -const openAi = new CompletionAdapterOpenAIResponses({ - openAiApiKey: process.env.OPENAI_API_KEY as string, - model: 'gpt-5-mini', -}); - -const prompt = 'What is the capital of France? return json'; - -openAi.complete( - prompt, - 200, - { - name: "capital_response", - schema: { - type: "object", - properties: { - capital: { type: "string" }, - }, - required: ["capital"], - }, - }, -).then((resp) => { - console.log(resp); -}); - -``` - -### Using reasoning effort - -If you want to explicitly test a reasoning-capable GPT-5 model, pass `reasoningEffort` as the 4th argument: - -```ts -const openAi = new CompletionAdapterOpenAIResponses({ - openAiApiKey: process.env.OPENAI_API_KEY as string, - model: "gpt-5-mini", -}); - -const resp = await openAi.complete( - "Explain why the sky looks blue in 3 short paragraphs", - 300, - undefined, - "medium", -); - -console.log(resp.content); -``` - -### Using streaming output and reasoning events - -If you pass `onChunk`, adapter switches to streaming mode automatically: - -```ts -const openAi = new CompletionAdapterOpenAIResponses({ - openAiApiKey: process.env.OPENAI_API_KEY as string, - model: "gpt-5-mini", -}); - -await openAi.complete( - "Think step by step and write a short answer about how ABS brakes work", - 300, - undefined, - "medium", - async (chunk, event) => { - if (!event) return; - - if (event.type === "reasoning") { - console.log("Reasoning chunk:", event.delta); - return; - } - - console.log("Output chunk:", event.delta); - }, -); -``` - -Note: - -- `event.type === "reasoning"` means a reasoning chunk -- `event.type === "output"` means visible output text chunk -- `event.text` contains accumulated text for that stream type -- reasoning events depend on the selected OpenAI model and provider response - -Then output will be like: -``` -{ content: '{"capital":"Paris"}', finishReason: 'stop' } -``` - -## 🔎 Image Analysis - -[🔗ImageVisionAdapter source class](https://github.com/devforth/adminforth/blob/1efdc19e3bb7a5fc3b19106704e4ae8bb7c73276/adminforth/types/adapters/ImageVisionAdapter.ts#L1) - -Used for AI-powered image analysis. These adapters can automatically analyze image content, extract text from images, identify objects, describe scenes, and provide detailed image insights. - -### OpenAI Vision Adapter - -``` -pnpm install @adminforth/image-vision-adapter-openai --save -``` - -Integrates AdminForth with OpenAI to provide advanced AI-powered image analysis. Can describe image content, read and extract text from images, identify objects and people, and provide detailed visual insights. - ---- - -## 🗄️Key-value Adapters - -[🔗Key-value adapter source class](https://github.com/devforth/adminforth/blob/86bb9236fed9e844fdb07688318c050641f9eb1c/adminforth/types/adapters/KeyValueAdapter.ts#L6) - -Key-value adapters are used to store data in a key-value format. They provide a simple and efficient way to manage data where quick access to values based on unique keys is required. - -### RAM Adapter - -``` -pnpm i @adminforth/key-value-adapter-ram -``` - -The RAM adapter is a simplest in-memory key-value storage. Stores data in process RAM memory. Not sutable if you run application with several processes because each process will have own RAM. In last case you need centralized KV adapter, e.g. Redis. - -Pros: -* Simplest in use - does not reqauire any external daemon. - -Cones: -* In production sutable for single-process installations only - - -### Redis adapter - -```bash -pnpm i @adminforth/key-value-adapter-redis -``` - -Redis adapter uses in-memory RAM-based Redis database with O(1) get complexity. It is great fit for most of lightweight tasks which fit in RAM. Also capable with multi-process or replica-based installations as centralized storage. Please note that Redis daemon might be not persisted to disk during restarts without additional settings, so if persistence is critical for your task - you might need to set up it separately (for many tasks like rate-limits ephemeral data are fine - - -```ts -import RedisKeyValueAdapter from '@adminforth/key-value-adapter-redis'; - -const adapter = new RedisKeyValueAdapter({ - redisUrl: '127.0.0.1:6379' -}) - -adapeter.set('test-key', 'test-value', 120); //expiry in 120 seconds - -``` - -### LevelDB adapter - -```bash -pnpm i @adminforth/key-value-adapter-leveldb -``` - -LebelDB uses disk storage with o(log(n)) get complexity. Good fit for large and/or persistent KV datasets which still require fast KV access but don't efficently fit into RAM. Please not that this is a single-process adapter only, so if you will run severall processes of admin - they will not be able to work with this adapter (>=2 processes which look at same level database might lead to unpredicted behaviour - exceptions or crashes). - -You can use replicas with isolated disks, however in this case state will be also separated between replicas. - -```ts -import LevelDBKeyValueAdapter from '@adminforth/key-value-adapter-leveldb' - -const adapter = new LevelDBKeyValueAdapter({ - dbPath: './testdb' -}); - -adapeter.set('test-key', 'test-value', 120); //expiry in 120 seconds - -``` - -## 🤖Captcha adapters - -Used to add capthca to the login screen - -[🔗Captcha adapter source class](https://github.com/devforth/adminforth/blob/65153408a119314dad339f452700e0937952034a/adminforth/types/adapters/CaptchaAdapter.ts#L5) - -### Cloudflare adapter - -``` -pnpm i @adminforth/login-captcha-adapter-cloudflare -``` - - -### reCaptcha adapter - -``` -pnpm i @adminforth/login-captcha-adapter-recaptcha -``` diff --git a/adminforth/documentation/docs/tutorial/09-Advanced/01-plugin-development.md b/adminforth/documentation/docs/tutorial/09-Advanced/01-plugin-development.md index 69947f97d..66f679c89 100644 --- a/adminforth/documentation/docs/tutorial/09-Advanced/01-plugin-development.md +++ b/adminforth/documentation/docs/tutorial/09-Advanced/01-plugin-development.md @@ -542,11 +542,22 @@ export interface CompletionAdapter { validate(); - complete( - content: string, - stop: string[], - maxTokens: number, - ): Promise<{ + complete(request: { + content: string; + maxTokens: number; + outputSchema?: any; + reasoningEffort?: 'none' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh'; + tools?: CompletionTool[]; + onChunk?: ( + chunk: string, + event?: { + type: 'output' | 'reasoning'; + delta: string; + text: string; + source?: 'summary' | 'text'; + }, + ) => void | Promise; + }): Promise<{ content?: string; finishReason?: string; error?: string; @@ -595,7 +606,10 @@ Now you can simply use adapter: ```ts title='./af-plugin-any-complete/index.ts' handler: async (a) => { ... - const resp = await this.options.adapter.complete(content, ['.'], this.options.expert?.maxTokens || 50); + const resp = await this.options.adapter.complete({ + content, + maxTokens: this.options.expert?.maxTokens || 50, + }); ... } ``` diff --git a/adminforth/documentation/docusaurus.config.ts b/adminforth/documentation/docusaurus.config.ts index 8944bb544..d235bc33f 100644 --- a/adminforth/documentation/docusaurus.config.ts +++ b/adminforth/documentation/docusaurus.config.ts @@ -50,7 +50,8 @@ const config: Config = { 'classic', { docs: { - sidebarCollapsible: false, + sidebarCollapsible: true, + sidebarCollapsed: false, sidebarPath: './sidebars.ts', // Please change this to your repo. // Remove this to remove the "edit this page" links. diff --git a/adminforth/types/adapters/CompletionAdapter.ts b/adminforth/types/adapters/CompletionAdapter.ts index 7c57b0fcb..fc89b89de 100644 --- a/adminforth/types/adapters/CompletionAdapter.ts +++ b/adminforth/types/adapters/CompletionAdapter.ts @@ -7,12 +7,33 @@ export type CompletionStreamEvent = { source?: "summary" | "text"; }; +export type CompletionReasoningEffort = + | "none" + | "minimal" + | "low" + | "medium" + | "high" + | "xhigh"; + export type CompletionTool, Output = any> = { name: string; input_schema: JSONSchemaType; description?: string; handler: (input: Input) => Promise | Output; }; + +export type CompletionRequest = { + content: string; + maxTokens: number; + outputSchema?: any; + reasoningEffort?: CompletionReasoningEffort; + tools?: CompletionTool[]; + onChunk?: ( + chunk: string, + event?: CompletionStreamEvent, + ) => void | Promise; +}; + export interface CompletionAdapter { /** @@ -23,24 +44,10 @@ export interface CompletionAdapter { /** * This method should return a text completion based on the provided content. - * @param content - The input text to complete - * @param maxTokens - The maximum number of tokens to generate - * @param outputSchema - Optional structured output schema for the response - * @param reasoningEffort - Optional parameter to indicate the level of reasoning effort for the completion - * @param onChunk - Optional callback invoked for each streamed chunk or reasoning event + * @param request - Completion request options * @returns A promise that resolves to an object containing the completed text and other metadata */ - complete( - content: string, - maxTokens: number, - outputSchema?: any, - reasoningEffort?: 'none' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh', - tools?: CompletionTool[], - onChunk?: ( - chunk: string, - event?: CompletionStreamEvent, - ) => void | Promise, - ): Promise<{ + complete(request: CompletionRequest): Promise<{ content?: string; finishReason?: string; error?: string; diff --git a/adminforth/types/adapters/index.ts b/adminforth/types/adapters/index.ts index f97679446..ca39fed31 100644 --- a/adminforth/types/adapters/index.ts +++ b/adminforth/types/adapters/index.ts @@ -1,5 +1,11 @@ export type { EmailAdapter } from './EmailAdapter.js'; -export type { CompletionAdapter, CompletionStreamEvent, CompletionTool } from './CompletionAdapter.js'; +export type { + CompletionAdapter, + CompletionReasoningEffort, + CompletionRequest, + CompletionStreamEvent, + CompletionTool, +} from './CompletionAdapter.js'; export type { ImageGenerationAdapter } from './ImageGenerationAdapter.js'; export type { KeyValueAdapter } from './KeyValueAdapter.js'; export type { ImageVisionAdapter } from './ImageVisionAdapter.js'; diff --git a/live-demo/app/resources/agent_resources/placeholderMessages.ts b/live-demo/app/resources/agent_resources/placeholderMessages.ts index ea5b7f9cc..61ef9d8b3 100644 --- a/live-demo/app/resources/agent_resources/placeholderMessages.ts +++ b/live-demo/app/resources/agent_resources/placeholderMessages.ts @@ -112,12 +112,12 @@ async function translatePlaceholderMessages({ }), ].join('\n\n'); - const result = await completionAdapter.complete( + const result = await completionAdapter.complete({ content, - 300, - LOCALIZED_PLACEHOLDER_MESSAGES_SCHEMA, - 'low', - ); + maxTokens: 300, + outputSchema: LOCALIZED_PLACEHOLDER_MESSAGES_SCHEMA, + reasoningEffort: 'low', + }); if (result.error) { throw new Error(result.error); From e1c5992a502a494c0d16af6ebc78b02becdebabc Mon Sep 17 00:00:00 2001 From: Ivan Borshchov Date: Thu, 23 Apr 2026 11:26:45 +0000 Subject: [PATCH 6/7] feat: add plugins category to documentation --- .../docs/tutorial/08-Plugins/_category_.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 adminforth/documentation/docs/tutorial/08-Plugins/_category_.json diff --git a/adminforth/documentation/docs/tutorial/08-Plugins/_category_.json b/adminforth/documentation/docs/tutorial/08-Plugins/_category_.json new file mode 100644 index 000000000..a17bb6840 --- /dev/null +++ b/adminforth/documentation/docs/tutorial/08-Plugins/_category_.json @@ -0,0 +1,12 @@ +{ + "label": "Plugins", + "position": 8, + "collapsible": true, + "collapsed": false, + "link": { + "type": "generated-index", + "title": "AdminForth Plugins", + "slug": "/tutorial/ListOfPlugins", + "description": "This section contains the available plugins in the AdminForth ecosystem. Plugins extend AdminForth resources and UI with common features like editors, auth flows, AI tooling, imports, uploads, and automation." + } +} \ No newline at end of file From f8d092aba26ca155534b5857a4edaec038c3f93b Mon Sep 17 00:00:00 2001 From: Maksym Pipkun Date: Thu, 23 Apr 2026 14:42:59 +0300 Subject: [PATCH 7/7] feat: enhance aggregation handler to support user-defined time zones --- adminforth/modules/restApi.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/adminforth/modules/restApi.ts b/adminforth/modules/restApi.ts index 015ada961..5b8001ccd 100644 --- a/adminforth/modules/restApi.ts +++ b/adminforth/modules/restApi.ts @@ -1572,7 +1572,7 @@ export default class AdminForthRestAPI implements IAdminForthRestAPI { description: 'Performs aggregation queries (sum, count, avg, min, max, median) on a resource, with optional grouping by field value or date truncation.', request_schema: aggregateRequestSchema, response_schema: aggregateResponseSchema, - handler: async ({ body, adminUser }) => { + handler: async ({ body, adminUser, headers }) => { const { resourceId, aggregations, filters, groupBy } = body; if (!this.adminforth.statuses.dbDiscover) { return { error: 'Database discovery not started' }; @@ -1618,11 +1618,16 @@ export default class AdminForthRestAPI implements IAdminForthRestAPI { } try { + const userTimeZone = headers['X-TimeZone']; + const aggregateGroupBy = groupBy?.type === 'date_trunc' && userTimeZone + ? { ...groupBy, timezone: userTimeZone } + : groupBy; + const data = await this.adminforth.connectors[resource.dataSource].aggregate({ resource, filters: normalizedFilters as IAdminForthAndOrFilter, aggregations, - groupBy, + groupBy: aggregateGroupBy, }); return { data }; } catch (e) {