From 30bb028a0951636c0fe273990c183ffb78760468 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Wang?= <52880665+RiverTwilight@users.noreply.github.com> Date: Fri, 29 Aug 2025 15:52:02 +0800 Subject: [PATCH 1/4] =?UTF-8?q?=F0=9F=93=9D=20docs:=20add=20agents=20md=20?= =?UTF-8?q?(#8971)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * build: Add agents.md * feat: Add agents md * 📝 docs: address tjx666's review comments on AGENTS.md - Fix build tools description to reflect actual Next.js setup (Turbopack/Webpack) - Remove incorrect Turborepo reference - Improve TypeScript practices description for clarity Co-authored-by: René Wang --------- Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com> Co-authored-by: René Wang --- AGENTS.md | 133 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000000..10eb15f20f3 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,133 @@ +# LobeChat Development Guidelines + +This document serves as a comprehensive guide for all team members when developing LobeChat. + +## Tech Stack + +Built with modern technologies: + +- **Frontend**: Next.js 15, React 19, TypeScript +- **UI Components**: Ant Design, @lobehub/ui, antd-style +- **State Management**: Zustand, SWR +- **Database**: PostgreSQL, PGLite, Drizzle ORM +- **Testing**: Vitest, Testing Library +- **Package Manager**: pnpm (monorepo structure) +- **Build Tools**: Next.js (Turbopack in dev, Webpack in prod), Vitest + +## Directory Structure + +The project follows a well-organized monorepo structure: + +- `apps/` - Main applications +- `packages/` - Shared packages and libraries +- `src/` - Main source code +- `docs/` - Documentation +- `.cursor/rules/` - Development rules and guidelines + +## Development Workflow + +### Git Workflow + +- Use rebase for git pull: `git pull --rebase` +- Git commit messages should prefix with gitmoji +- Git branch name format: `username/feat/feature-name` +- Use `.github/PULL_REQUEST_TEMPLATE.md` for PR descriptions + +### Package Management + +- Use `pnpm` as the primary package manager +- Use `bun` to run npm scripts +- Use `bunx` to run executable npm packages +- Navigate to specific packages using `cd packages/` + +### Code Style Guidelines + +#### TypeScript + +- Follow strict TypeScript practices for type safety and code quality +- Use proper type annotations +- Prefer interfaces over types for object shapes +- Use generics for reusable components + +#### React Components + +- Use functional components with hooks +- Follow the component structure guidelines +- Use antd-style & @lobehub/ui for styling +- Implement proper error boundaries + +#### Database Schema + +- Follow Drizzle ORM naming conventions +- Use plural snake_case for table names +- Implement proper foreign key relationships +- Follow the schema style guide + +### Testing Strategy + +**Required Rule**: `testing-guide/testing-guide.mdc` + +**Commands**: + +- Web: `bunx vitest run --silent='passed-only' '[file-path-pattern]'` +- Packages: `cd packages/[package-name] && bunx vitest run --silent='passed-only' '[file-path-pattern]'` + +**Important Notes**: + +- Wrap file paths in single quotes to avoid shell expansion +- Never run `bun run test` - this runs all tests and takes ~10 minutes +- If a test fails twice, stop and ask for help +- Always add tests for new code + +### Type Checking + +- Use `bun run type-check` to check for type errors +- Ensure all TypeScript errors are resolved before committing + +### Internationalization + +- Add new keys to `src/locales/default/namespace.ts` +- Translate at least `zh-CN` files for development preview +- Use hierarchical nested objects, not flat keys +- Don't run `pnpm i18n` manually (handled by CI) + +## Available Development Rules + +The project provides comprehensive rules in `.cursor/rules/` directory: + +### Core Development + +- `backend-architecture.mdc` - Three-layer architecture and data flow +- `react-component.mdc` - Component patterns and UI library usage +- `drizzle-schema-style-guide.mdc` - Database schema conventions +- `define-database-model.mdc` - Model templates and CRUD patterns +- `i18n.mdc` - Internationalization workflow + +### State Management & UI + +- `zustand-slice-organization.mdc` - Store organization patterns +- `zustand-action-patterns.mdc` - Action implementation patterns +- `packages/react-layout-kit.mdc` - Flex layout component usage + +### Testing & Quality + +- `testing-guide/testing-guide.mdc` - Comprehensive testing strategy +- `code-review.mdc` - Code review process and standards + +### Desktop (Electron) + +- `desktop-feature-implementation.mdc` - Main/renderer process patterns +- `desktop-local-tools-implement.mdc` - Tool integration workflow +- `desktop-menu-configuration.mdc` - Menu system configuration +- `desktop-window-management.mdc` - Window management patterns +- `desktop-controller-tests.mdc` - Controller testing guide + +## Best Practices + +- **Conservative for existing code, modern approaches for new features** +- **Code Language**: Use Chinese for files with existing Chinese comments, American English for new files +- Always add tests for new functionality +- Follow the established patterns in the codebase +- Use proper error handling and logging +- Implement proper accessibility features +- Consider internationalization from the start From 2f3bf0fedfd08f08b1e6c8141f86a719ffbcc8f8 Mon Sep 17 00:00:00 2001 From: sxjeru Date: Fri, 29 Aug 2025 15:53:57 +0800 Subject: [PATCH 2/4] =?UTF-8?q?=E2=9C=A8=20feat:=20Add=20new=20provider=20?= =?UTF-8?q?AkashChat=20(#8923)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 添加 AkashChat 模型及相关配置 * feat: 更新 AkashChat 模型处理逻辑,添加嵌入模型关键词支持 * fix test * Update akashchat.ts --- packages/model-runtime/src/akashchat/index.ts | 43 ++++++++++ packages/model-runtime/src/index.ts | 1 + .../openai/__snapshots__/index.test.ts.snap | 2 +- packages/model-runtime/src/runtimeMap.ts | 2 + packages/model-runtime/src/types/type.ts | 1 + .../model-runtime/src/utils/modelParse.ts | 15 +++- packages/types/src/user/settings/keyVaults.ts | 1 + .../settings/llm/ProviderList/providers.tsx | 2 + src/config/aiModels/akashchat.ts | 84 +++++++++++++++++++ src/config/aiModels/index.ts | 3 + src/config/llm.ts | 6 ++ src/config/modelProviders/akashchat.ts | 17 ++++ src/config/modelProviders/index.ts | 3 + 13 files changed, 178 insertions(+), 2 deletions(-) create mode 100644 packages/model-runtime/src/akashchat/index.ts create mode 100644 src/config/aiModels/akashchat.ts create mode 100644 src/config/modelProviders/akashchat.ts diff --git a/packages/model-runtime/src/akashchat/index.ts b/packages/model-runtime/src/akashchat/index.ts new file mode 100644 index 00000000000..00ce615d74d --- /dev/null +++ b/packages/model-runtime/src/akashchat/index.ts @@ -0,0 +1,43 @@ +import { ModelProvider } from '../types'; +import { processMultiProviderModelList } from '../utils/modelParse'; +import { createOpenAICompatibleRuntime } from '../utils/openaiCompatibleFactory'; + +export interface AkashChatModelCard { + id: string; +} + +export const LobeAkashChatAI = createOpenAICompatibleRuntime({ + baseURL: 'https://chatapi.akash.network/api/v1', + chatCompletion: { + handlePayload: (payload) => { + const { model, ...rest } = payload; + + return { + ...rest, + model, + stream: true, + } as any; + }, + }, + debug: { + chatCompletion: () => process.env.DEBUG_AKASH_CHAT_COMPLETION === '1', + }, + models: async ({ client }) => { + try { + const modelsPage = (await client.models.list()) as any; + const rawList: any[] = modelsPage.data || []; + + // Remove `created` field from each model item + const modelList: AkashChatModelCard[] = rawList.map(({ created, ...rest }) => rest); + + return await processMultiProviderModelList(modelList, 'akashchat'); + } catch (error) { + console.warn( + 'Failed to fetch AkashChat models. Please ensure your AkashChat API key is valid:', + error, + ); + return []; + } + }, + provider: ModelProvider.AkashChat, +}); diff --git a/packages/model-runtime/src/index.ts b/packages/model-runtime/src/index.ts index ff61def98b8..f6942b2a478 100644 --- a/packages/model-runtime/src/index.ts +++ b/packages/model-runtime/src/index.ts @@ -1,3 +1,4 @@ +export { LobeAkashChatAI } from './akashchat'; export { LobeAnthropicAI } from './anthropic'; export { LobeAzureAI } from './azureai'; export { LobeAzureOpenAI } from './azureOpenai'; diff --git a/packages/model-runtime/src/openai/__snapshots__/index.test.ts.snap b/packages/model-runtime/src/openai/__snapshots__/index.test.ts.snap index d850b172348..9a524b88dfc 100644 --- a/packages/model-runtime/src/openai/__snapshots__/index.test.ts.snap +++ b/packages/model-runtime/src/openai/__snapshots__/index.test.ts.snap @@ -366,7 +366,7 @@ exports[`LobeOpenAI > models > should get models 1`] = ` "maxOutput": undefined, "reasoning": false, "releasedAt": "2022-12-16", - "type": "chat", + "type": "embedding", "vision": false, }, { diff --git a/packages/model-runtime/src/runtimeMap.ts b/packages/model-runtime/src/runtimeMap.ts index 67e88c4519e..ca7882a1fdc 100644 --- a/packages/model-runtime/src/runtimeMap.ts +++ b/packages/model-runtime/src/runtimeMap.ts @@ -2,6 +2,7 @@ import { LobeAi21AI } from './ai21'; import { Lobe302AI } from './ai302'; import { LobeAi360AI } from './ai360'; import { LobeAiHubMixAI } from './aihubmix'; +import { LobeAkashChatAI } from './akashchat'; import { LobeAnthropicAI } from './anthropic'; import { LobeAzureOpenAI } from './azureOpenai'; import { LobeAzureAI } from './azureai'; @@ -61,6 +62,7 @@ export const providerRuntimeMap = { ai302: Lobe302AI, ai360: LobeAi360AI, aihubmix: LobeAiHubMixAI, + akashchat: LobeAkashChatAI, anthropic: LobeAnthropicAI, azure: LobeAzureOpenAI, azureai: LobeAzureAI, diff --git a/packages/model-runtime/src/types/type.ts b/packages/model-runtime/src/types/type.ts index 1c28cb11430..2fbb0a9c451 100644 --- a/packages/model-runtime/src/types/type.ts +++ b/packages/model-runtime/src/types/type.ts @@ -32,6 +32,7 @@ export enum ModelProvider { Ai302 = 'ai302', Ai360 = 'ai360', AiHubMix = 'aihubmix', + AkashChat = 'akashchat', Anthropic = 'anthropic', Azure = 'azure', AzureAI = 'azureai', diff --git a/packages/model-runtime/src/utils/modelParse.ts b/packages/model-runtime/src/utils/modelParse.ts index 53d535e403c..e9ccfbe77e1 100644 --- a/packages/model-runtime/src/utils/modelParse.ts +++ b/packages/model-runtime/src/utils/modelParse.ts @@ -118,6 +118,14 @@ export const IMAGE_MODEL_KEYWORDS = [ '^V_1', ] as const; +// 嵌入模型关键词配置 +export const EMBEDDING_MODEL_KEYWORDS = [ + 'embedding', + 'embed', + 'bge', + 'm3e', +] as const; + /** * 检测关键词列表是否匹配模型ID(支持多种匹配模式) * @param modelId 模型ID(小写) @@ -278,7 +286,12 @@ const processModelCard = ( IMAGE_MODEL_KEYWORDS.map((k) => k.toLowerCase()), ) ? 'image' - : 'chat'); + : isKeywordListMatch( + model.id.toLowerCase(), + EMBEDDING_MODEL_KEYWORDS.map((k) => k.toLowerCase()), + ) + ? 'embedding' + : 'chat'); // image model can't find parameters if (modelType === 'image' && !model.parameters && !knownModel?.parameters) { diff --git a/packages/types/src/user/settings/keyVaults.ts b/packages/types/src/user/settings/keyVaults.ts index 1276da61e29..d7cb8fb6b3b 100644 --- a/packages/types/src/user/settings/keyVaults.ts +++ b/packages/types/src/user/settings/keyVaults.ts @@ -41,6 +41,7 @@ export interface UserKeyVaults extends SearchEngineKeyVaults { ai302?: OpenAICompatibleKeyVault; ai360?: OpenAICompatibleKeyVault; aihubmix?: OpenAICompatibleKeyVault; + akashchat?: OpenAICompatibleKeyVault; anthropic?: OpenAICompatibleKeyVault; azure?: AzureOpenAIKeyVault; azureai?: AzureOpenAIKeyVault; diff --git a/src/app/[variants]/(main)/settings/llm/ProviderList/providers.tsx b/src/app/[variants]/(main)/settings/llm/ProviderList/providers.tsx index bf25f59abf3..bf76ad37d98 100644 --- a/src/app/[variants]/(main)/settings/llm/ProviderList/providers.tsx +++ b/src/app/[variants]/(main)/settings/llm/ProviderList/providers.tsx @@ -4,6 +4,7 @@ import { Ai21ProviderCard, Ai302ProviderCard, Ai360ProviderCard, + AkashChatProviderCard, AnthropicProviderCard, BaichuanProviderCard, CohereProviderCard, @@ -113,6 +114,7 @@ export const useProviderList = (): ProviderItem[] => { GiteeAIProviderCard, PPIOProviderCard, InfiniAIProviderCard, + AkashChatProviderCard, Ai302ProviderCard, ], [ diff --git a/src/config/aiModels/akashchat.ts b/src/config/aiModels/akashchat.ts new file mode 100644 index 00000000000..1d5b87cad14 --- /dev/null +++ b/src/config/aiModels/akashchat.ts @@ -0,0 +1,84 @@ +import { AIChatModelCard } from '@/types/aiModel'; + +const akashChatModels: AIChatModelCard[] = [ + { + abilities: { + functionCall: true, + reasoning: true, + }, + contextWindowTokens: 65_536, + description: + 'DeepSeek V3.1:下一代推理模型,提升了复杂推理与链路思考能力,适合需要深入分析的任务。', + displayName: 'DeepSeek V3.1', + enabled: true, + id: 'DeepSeek-V3-1', + type: 'chat', + }, + { + abilities: { + functionCall: true, + reasoning: true, + }, + contextWindowTokens: 65_536, + displayName: 'DeepSeek R1 Distill Qwen 32B', + id: 'DeepSeek-R1-Distill-Qwen-32B', + type: 'chat', + }, + { + abilities: { + functionCall: true, + reasoning: true, + }, + contextWindowTokens: 131_072, + description: 'GPT-OSS-120B MXFP4 量化的 Transformer 结构,在资源受限时仍能保持强劲性能。', + displayName: 'GPT-OSS-120B', + enabled: true, + id: 'gpt-oss-120b', + type: 'chat', + }, + { + abilities: { + functionCall: true, + }, + contextWindowTokens: 262_144, + description: + 'Qwen3 235B A22B Instruct 2507:面向高级推理与对话指令优化的模型,混合专家架构以在大规模参数下保持推理效率。', + displayName: 'Qwen3 235B A22B Instruct 2507', + id: 'Qwen3-235B-A22B-Instruct-2507-FP8', + type: 'chat', + }, + { + abilities: { + functionCall: true, + vision: true, + }, + contextWindowTokens: 131_072, + description: + 'Llama 4 Maverick:基于 Mixture-of-Experts 的大规模模型,提供高效的专家激活策略以在推理中表现优异。', + displayName: 'Llama 4 Maverick (17Bx128E)', + id: 'Meta-Llama-4-Maverick-17B-128E-Instruct-FP8', + type: 'chat', + }, + { + abilities: { + functionCall: true, + }, + contextWindowTokens: 131_072, + description: 'Llama 3.3 70B:通用性强的 Transformer 模型,适用于对话和生成任务。', + displayName: 'Llama 3.3 70B', + id: 'Meta-Llama-3-3-70B-Instruct', + type: 'chat', + }, + { + abilities: { + functionCall: true, + }, + contextWindowTokens: 131_072, + displayName: 'Llama 3.1 8B', + id: 'Meta-Llama-3-1-8B-Instruct-FP8', + type: 'chat', + }, +]; +export const allModels = [...akashChatModels]; + +export default allModels; diff --git a/src/config/aiModels/index.ts b/src/config/aiModels/index.ts index 64a7bfb666e..345ac176b2c 100644 --- a/src/config/aiModels/index.ts +++ b/src/config/aiModels/index.ts @@ -4,6 +4,7 @@ import { default as ai21 } from './ai21'; import { default as ai302 } from './ai302'; import { default as ai360 } from './ai360'; import { default as aihubmix } from './aihubmix'; +import { default as akashchat } from './akashchat'; import { default as anthropic } from './anthropic'; import { default as azure } from './azure'; import { default as azureai } from './azureai'; @@ -83,6 +84,7 @@ export const LOBE_DEFAULT_MODEL_LIST = buildDefaultModelList({ ai302, ai360, aihubmix, + akashchat, anthropic, azure, azureai, @@ -143,6 +145,7 @@ export { default as ai21 } from './ai21'; export { default as ai302 } from './ai302'; export { default as ai360 } from './ai360'; export { default as aihubmix } from './aihubmix'; +export { default as akashchat } from './akashchat'; export { default as anthropic } from './anthropic'; export { default as azure } from './azure'; export { default as azureai } from './azureai'; diff --git a/src/config/llm.ts b/src/config/llm.ts index da6dca0d0b4..09ad0af26dd 100644 --- a/src/config/llm.ts +++ b/src/config/llm.ts @@ -178,6 +178,9 @@ export const getLLMConfig = () => { ENABLED_AI302: z.boolean(), AI302_API_KEY: z.string().optional(), + ENABLED_AKASHCHAT: z.boolean(), + AKASHCHAT_API_KEY: z.string().optional(), + ENABLED_AIHUBMIX: z.boolean(), AIHUBMIX_API_KEY: z.string().optional(), }, @@ -356,6 +359,9 @@ export const getLLMConfig = () => { ENABLED_AI302: !!process.env.AI302_API_KEY, AI302_API_KEY: process.env.AI302_API_KEY, + ENABLED_AKASHCHAT: !!process.env.AKASHCHAT_API_KEY, + AKASHCHAT_API_KEY: process.env.AKASHCHAT_API_KEY, + ENABLED_AIHUBMIX: !!process.env.AIHUBMIX_API_KEY, AIHUBMIX_API_KEY: process.env.AIHUBMIX_API_KEY, }, diff --git a/src/config/modelProviders/akashchat.ts b/src/config/modelProviders/akashchat.ts new file mode 100644 index 00000000000..29ba2aead56 --- /dev/null +++ b/src/config/modelProviders/akashchat.ts @@ -0,0 +1,17 @@ +import { ModelProviderCard } from '@/types/llm'; + +const AkashChat: ModelProviderCard = { + chatModels: [], + checkModel: 'Meta-Llama-3-1-8B-Instruct-FP8', + description: 'Akash 是一个无需许可的云资源市场,与传统云提供商相比,其定价具有竞争力。', + id: 'akashchat', + modelsUrl: 'https://chatapi.akash.network/documentation', + name: 'AkashChat', + settings: { + sdkType: 'openai', + showModelFetcher: true, + }, + url: 'https://chatapi.akash.network/', +}; + +export default AkashChat; diff --git a/src/config/modelProviders/index.ts b/src/config/modelProviders/index.ts index b79eb1ff68c..44a68642cf8 100644 --- a/src/config/modelProviders/index.ts +++ b/src/config/modelProviders/index.ts @@ -4,6 +4,7 @@ import Ai21Provider from './ai21'; import Ai302Provider from './ai302'; import Ai360Provider from './ai360'; import AiHubMixProvider from './aihubmix'; +import AkashChatProvider from './akashchat'; import AnthropicProvider from './anthropic'; import AzureProvider from './azure'; import AzureAIProvider from './azureai'; @@ -172,6 +173,7 @@ export const DEFAULT_MODEL_PROVIDER_LIST = [ Ai360Provider, Search1APIProvider, InfiniAIProvider, + AkashChatProvider, QiniuProvider, ]; @@ -188,6 +190,7 @@ export { default as Ai21ProviderCard } from './ai21'; export { default as Ai302ProviderCard } from './ai302'; export { default as Ai360ProviderCard } from './ai360'; export { default as AiHubMixProviderCard } from './aihubmix'; +export { default as AkashChatProviderCard } from './akashchat'; export { default as AnthropicProviderCard } from './anthropic'; export { default as AzureProviderCard } from './azure'; export { default as AzureAIProviderCard } from './azureai'; From d9024085ede02145a002b4a7073bde0cf01bd3dd Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 29 Aug 2025 08:05:49 +0000 Subject: [PATCH 3/4] :bookmark: chore(release): v1.118.0 [skip ci] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## [Version 1.118.0](https://github.com/lobehub/lobe-chat/compare/v1.117.1...v1.118.0) Released on **2025-08-29** #### ✨ Features - **misc**: Add new provider AkashChat.
Improvements and Fixes #### What's improved * **misc**: Add new provider AkashChat, closes [#8923](https://github.com/lobehub/lobe-chat/issues/8923) ([2f3bf0f](https://github.com/lobehub/lobe-chat/commit/2f3bf0f))
[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
--- CHANGELOG.md | 25 +++++++++++++++++++++++++ package.json | 2 +- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 48c17f5a173..89b76835665 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,31 @@ # Changelog +## [Version 1.118.0](https://github.com/lobehub/lobe-chat/compare/v1.117.1...v1.118.0) + +Released on **2025-08-29** + +#### ✨ Features + +- **misc**: Add new provider AkashChat. + +
+ +
+Improvements and Fixes + +#### What's improved + +- **misc**: Add new provider AkashChat, closes [#8923](https://github.com/lobehub/lobe-chat/issues/8923) ([2f3bf0f](https://github.com/lobehub/lobe-chat/commit/2f3bf0f)) + +
+ +
+ +[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top) + +
+ ### [Version 1.117.1](https://github.com/lobehub/lobe-chat/compare/v1.117.0...v1.117.1) Released on **2025-08-29** diff --git a/package.json b/package.json index dde4dbc2f0d..eb98106505a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@lobehub/chat", - "version": "1.117.1", + "version": "1.118.0", "description": "Lobe Chat - an open-source, high-performance chatbot framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.", "keywords": [ "framework", From 0220e81a92edc363f90645d84cb76d975ce345ee Mon Sep 17 00:00:00 2001 From: lobehubbot Date: Fri, 29 Aug 2025 08:06:46 +0000 Subject: [PATCH 4/4] =?UTF-8?q?=F0=9F=93=9D=20docs(bot):=20Auto=20sync=20a?= =?UTF-8?q?gents=20&=20plugin=20to=20readme?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- changelog/v1.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/changelog/v1.json b/changelog/v1.json index 171ac2aeb18..58f5e836676 100644 --- a/changelog/v1.json +++ b/changelog/v1.json @@ -1,4 +1,11 @@ [ + { + "children": { + "features": ["Add new provider AkashChat."] + }, + "date": "2025-08-29", + "version": "1.118.0" + }, { "children": { "improvements": ["Move chat item into chat."]