mirror of
https://github.com/lobehub/lobe-chat.git
synced 2026-06-21 14:39:34 +00:00
Compare commits
124 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 263ba692cb | |||
| 28245be7f3 | |||
| f723b38fa8 | |||
| 5382df8cf8 | |||
| 4c313ced5e | |||
| b6f1fc4a14 | |||
| 0dc112436b | |||
| 24c42f6025 | |||
| 48ee38cf9b | |||
| 654064ff7d | |||
| b5219c220a | |||
| b59ee0aabe | |||
| d481315a66 | |||
| 4f5d1ff6af | |||
| 1bd46e0346 | |||
| a8be073b65 | |||
| 2e911ea9f5 | |||
| a89f4c73b4 | |||
| ebf5a8f649 | |||
| 80b0999467 | |||
| be952f95fd | |||
| d46bb9ad8b | |||
| 8e7f541a0b | |||
| 0eb02ca1c5 | |||
| b90436421b | |||
| e284330678 | |||
| ea9da27e72 | |||
| e99f12f840 | |||
| bbc037912c | |||
| 9881b7b303 | |||
| e9de9e3b52 | |||
| 69f21da3e1 | |||
| 2b7761c36e | |||
| 6734a47759 | |||
| 7f7dcfbff9 | |||
| af33543cba | |||
| 8b619f0a8e | |||
| b81d8f79a4 | |||
| 15ffe289f5 | |||
| 2606f93146 | |||
| c882e75580 | |||
| 6334f62aa1 | |||
| 0af13ca057 | |||
| 68d6457659 | |||
| 3466055968 | |||
| d99a3a80f8 | |||
| cc37acb30b | |||
| eb708e04fe | |||
| 11df190f36 | |||
| a094d5c04c | |||
| f6daefb0a2 | |||
| b8c59be3a7 | |||
| 284faf799b | |||
| 88d194c3b6 | |||
| 6c53a5f026 | |||
| d430836f20 | |||
| 7571b66284 | |||
| 3ec394d77a | |||
| 778dea3853 | |||
| f599617042 | |||
| cc8f5d0639 | |||
| 32d365b544 | |||
| 0ff41dba9c | |||
| fd68cc364c | |||
| ce7a74242f | |||
| 7f9bfda652 | |||
| 5f10aace5b | |||
| 6d14dfe50d | |||
| 12f54759df | |||
| b43d4b27ad | |||
| dab987f64b | |||
| 2e24f72b2a | |||
| 5ebcfa531e | |||
| 1b3f88346b | |||
| 808cb21b99 | |||
| c6dd22eea6 | |||
| da5427ccdf | |||
| d1c7f41bd4 | |||
| 6681989fe6 | |||
| 48a7a08110 | |||
| 0596692e95 | |||
| 59ea77d746 | |||
| 4aa570c904 | |||
| c9ea5336d3 | |||
| ceffce27c3 | |||
| b56c9c51b8 | |||
| 97a6c8e172 | |||
| 727c92ad5b | |||
| 25e45a4cd4 | |||
| 296bad9fa4 | |||
| d8d28371d6 | |||
| a588319cf1 | |||
| 527ab0add7 | |||
| f2230ae536 | |||
| c83fe13d7c | |||
| f4b9d6795b | |||
| 77bc2614a4 | |||
| a02b301904 | |||
| 846a7a5986 | |||
| bc7aa88a8f | |||
| 85c4553821 | |||
| 03c28385e5 | |||
| e525cb2ed6 | |||
| ea44ef1b4c | |||
| 1cfbc878bd | |||
| 61bbd596f0 | |||
| 6508e2fcaf | |||
| 7cef9d88ea | |||
| 16de38ae32 | |||
| c6257f1dba | |||
| b2c28d0810 | |||
| d17b50c6dc | |||
| 0a8c80dfd2 | |||
| 6fd337de18 | |||
| 6266a85cf1 | |||
| 2f7317b98f | |||
| 317df489ce | |||
| ff41f4bb82 | |||
| 60f43d90e5 | |||
| b8136ac17b | |||
| f0e387fa29 | |||
| 8dcb00e2c9 | |||
| 790d8fd498 | |||
| 3719bf4d52 |
@@ -0,0 +1,38 @@
|
||||
---
|
||||
allowed-tools: Bash(gh issue view:*), Bash(gh search:*), Bash(gh issue list:*), Bash(gh api:*), Bash(gh issue comment:*)
|
||||
description: Find duplicate GitHub issues
|
||||
---
|
||||
|
||||
Find up to 3 likely duplicate issues for a given GitHub issue.
|
||||
|
||||
To do this, follow these steps precisely:
|
||||
|
||||
1. Use an agent to check if the Github issue (a) is closed, (b) does not need to be deduped (eg. because it is broad product feedback without a specific solution, or positive feedback), or (c) already has a duplicates comment that you made earlier. If so, do not proceed.
|
||||
2. Use an agent to view a Github issue, and ask the agent to return a summary of the issue
|
||||
3. Then, launch 5 parallel agents to search Github for duplicates of this issue, using diverse keywords and search approaches, using the summary from #1
|
||||
4. Next, feed the results from #1 and #2 into another agent, so that it can filter out false positives, that are likely not actually duplicates of the original issue. If there are no duplicates remaining, do not proceed.
|
||||
5. Finally, comment back on the issue with a list of up to three duplicate issues (or zero, if there are no likely duplicates)
|
||||
|
||||
Notes (be sure to tell this to your agents, too):
|
||||
|
||||
- Use `gh` to interact with Github, rather than web fetch
|
||||
- Do not use other tools, beyond `gh` (eg. don't use other MCP servers, file edit, etc.)
|
||||
- Make a todo list first
|
||||
- For your comment, follow the following format precisely (assuming for this example that you found 3 suspected duplicates):
|
||||
|
||||
---
|
||||
|
||||
Found 3 possible duplicate issues:
|
||||
|
||||
1. <link to issue>
|
||||
2. <link to issue>
|
||||
3. <link to issue>
|
||||
|
||||
This issue will be automatically closed as a duplicate in 3 days.
|
||||
|
||||
- If your issue is a duplicate, please close it and 👍 the existing issue instead
|
||||
- To prevent auto-closure, add a comment or 👎 this comment
|
||||
|
||||
> 🤖 Generated with Claude Code
|
||||
|
||||
---
|
||||
@@ -0,0 +1,253 @@
|
||||
# Issue Triage Guide
|
||||
|
||||
This guide is used for batch triaging GitHub issues - analyzing issues and applying appropriate labels.
|
||||
|
||||
## Workflow
|
||||
|
||||
For EACH issue, follow these steps:
|
||||
|
||||
### Step 1: Get Available Labels (run once per batch)
|
||||
|
||||
```bash
|
||||
gh label list --json name,description --limit 300
|
||||
```
|
||||
|
||||
### Step 2: Get Issue Details
|
||||
|
||||
For each issue number, run:
|
||||
|
||||
```bash
|
||||
gh issue view [ISSUE_NUMBER] --json number,title,body,labels,comments
|
||||
```
|
||||
|
||||
### Step 3: Analyze and Select Labels
|
||||
|
||||
Extract information from the issue template and content:
|
||||
|
||||
#### Template Fields Mapping
|
||||
|
||||
- 📦 Platform field → `platform:web/desktop/mobile`
|
||||
- 💻 Operating System → `os:windows/macos/linux/ios`
|
||||
- 🌐 Browser → `device:pc/mobile`
|
||||
- 📦 Deployment mode → `deployment:server/client/pglite`
|
||||
- Platform (hosting) → `hosting:cloud/self-host/vercel/zeabur/railway`
|
||||
|
||||
#### Provider Detection
|
||||
|
||||
**IMPORTANT**: Always check issue title and body for provider mentions!
|
||||
|
||||
**Official Providers** (check for these keywords in title/body):
|
||||
|
||||
- `openai`, `gpt` → `provider:openai`
|
||||
- `gemini` → `provider:gemini`
|
||||
- `claude`, `anthropic` → `provider:claude`
|
||||
- `deepseek` → `provider:deepseek`
|
||||
- `google` → `provider:google`
|
||||
- `ollama` → `provider:ollama`
|
||||
- `azure` → `provider:azure`
|
||||
- `bedrock` → `provider:bedrock`
|
||||
- `vertex` → `provider:vertex`
|
||||
- `groq`, `grok` → `provider:groq`
|
||||
- `mistral` → `provider:mistral`
|
||||
- `moonshot` → `provider:moonshot`
|
||||
- `zhipu` → `provider:zhipu`
|
||||
- `minimax` → `provider:minimax`
|
||||
- `doubao` → `provider:doubao`
|
||||
|
||||
**Third-party Aggregation Providers**:
|
||||
|
||||
- `aihubmix`, `AIHubMix`, `AIHUBMIX` → `provider:aihubmix`
|
||||
- Check environment variables like `AIHUBMIX_*` in issue body
|
||||
|
||||
**Multiple Providers**: If issue mentions multiple providers, add ALL applicable provider labels.
|
||||
|
||||
### Label Categories
|
||||
|
||||
#### a) Issue Type (select ONE if applicable)
|
||||
|
||||
- `💄 Design` - UI/UX design issues
|
||||
- `📝 Documentation` - Documentation improvements
|
||||
- `⚡️ Performance` - Performance optimization
|
||||
|
||||
#### b) Priority (select ONE if applicable)
|
||||
|
||||
- `priority:high` - Critical issues, data loss, security, maintainer mentions "urgent"/"serious"/"critical"
|
||||
- `priority:medium` - Important issues affecting multiple users, significant functionality impact
|
||||
- `priority:low` - Nice to have, minor issues, edge cases
|
||||
|
||||
**Priority Guidelines**:
|
||||
|
||||
- Set `priority:high` for: data loss, authentication failures, deployment blockers, critical bugs
|
||||
- Set `priority:medium` for: feature bugs affecting multiple users, workflow issues
|
||||
- Set `priority:low` for: cosmetic issues, feature requests, configuration questions
|
||||
|
||||
#### c) Platform (select ALL applicable)
|
||||
|
||||
- `platform:web`
|
||||
- `platform:desktop`
|
||||
- `platform:mobile`
|
||||
|
||||
#### d) Device (for platform:web, select ONE)
|
||||
|
||||
- `device:pc`
|
||||
- `device:mobile`
|
||||
|
||||
#### e) Operating System (select ALL applicable)
|
||||
|
||||
- `os:windows`
|
||||
- `os:macos`
|
||||
- `os:linux`
|
||||
- `os:ios`
|
||||
- `os:android`
|
||||
|
||||
#### f) Hosting Platform (select ONE)
|
||||
|
||||
- `hosting:cloud` - Official LobeHub Cloud
|
||||
- `hosting:self-host` - Self-hosted deployment
|
||||
- `hosting:vercel` - Vercel deployment
|
||||
- `hosting:zeabur` - Zeabur deployment
|
||||
- `hosting:railway` - Railway deployment
|
||||
|
||||
#### g) Deployment Mode (select ONE if mentioned)
|
||||
|
||||
- `deployment:server` - Server-side database mode
|
||||
- `deployment:client` - Client-side database mode
|
||||
- `deployment:pglite` - PGLite mode
|
||||
|
||||
**Additional deployment tags**:
|
||||
|
||||
- `docker` - If using Docker deployment
|
||||
- `electron` - If desktop/Electron specific
|
||||
|
||||
#### h) Model Provider (select ALL applicable)
|
||||
|
||||
See "Provider Detection" section above for complete list.
|
||||
|
||||
**IMPORTANT**: Always scan issue title and body for provider keywords!
|
||||
|
||||
#### i) Feature/Component (select ALL applicable)
|
||||
|
||||
Core Features:
|
||||
|
||||
- `feature:settings` - Settings and configuration
|
||||
- `feature:agent` - Agent/Assistant functionality
|
||||
- `feature:topic` - Topic/Conversation management
|
||||
- `feature:marketplace` - Agent marketplace
|
||||
|
||||
File & Knowledge:
|
||||
|
||||
- `feature:files` - File upload/management
|
||||
- `feature:knowledge-base` - Knowledge base and RAG
|
||||
- `feature:export` - Export functionality
|
||||
|
||||
Model Capabilities:
|
||||
|
||||
- `feature:streaming` - Streaming responses
|
||||
- `feature:tool` - Tool calling
|
||||
- `feature:vision` - Vision/multimodal capabilities
|
||||
- `feature:image` - AI image generation
|
||||
- `feature:dalle` - DALL-E specific
|
||||
- `feature:tts` - Text-to-speech
|
||||
|
||||
Technical:
|
||||
|
||||
- `feature:api` - Backend API
|
||||
- `feature:auth` - Authentication/authorization
|
||||
- `feature:sync` - Cloud sync functionality
|
||||
- `feature:search` - Search functionality
|
||||
- `feature:mcp` - MCP integration
|
||||
- `feature:editor` - Lobe Editor
|
||||
- `feature:markdown` - Markdown rendering
|
||||
- `feature:thread` - Thread/Subtopic functionality
|
||||
|
||||
Collaboration:
|
||||
|
||||
- `feature:group-chat` - Group chat functionality
|
||||
- `feature:memory` - Memory feature
|
||||
- `feature:team-workspace` - Team workspace
|
||||
|
||||
#### j) Workflow/Status
|
||||
|
||||
- `Duplicate` - Only if duplicate of an OPEN issue (mention issue number)
|
||||
- `needs-reproduction` - Cannot reproduce, needs more information
|
||||
- `good-first-issue` - Good for first-time contributors
|
||||
- `🤔 Need Reproduce` - Needs reproduction steps
|
||||
|
||||
### Step 4: Apply Labels
|
||||
|
||||
Add labels (comma-separated, no spaces after commas):
|
||||
|
||||
```bash
|
||||
gh issue edit [ISSUE_NUMBER] --add-label "label1,label2,label3"
|
||||
```
|
||||
|
||||
Remove "unconfirm" label if adding other labels:
|
||||
|
||||
```bash
|
||||
gh issue edit [ISSUE_NUMBER] --remove-label "unconfirm"
|
||||
```
|
||||
|
||||
**Important**: Combine both commands when possible for efficiency.
|
||||
|
||||
### Step 5: Log Summary
|
||||
|
||||
For each issue, provide reasoning (2-4 sentences):
|
||||
|
||||
- Labels applied and why
|
||||
- Key factors from issue template/comments
|
||||
- Provider detection reasoning (if applicable)
|
||||
|
||||
## Important Rules
|
||||
|
||||
1. **Read Carefully**: Read issue template fields AND issue body/title for complete context
|
||||
2. **Provider Detection**: ALWAYS check title and body for provider keywords (including aihubmix, etc.)
|
||||
3. **Multiple Categories**: Use ALL applicable labels from different categories
|
||||
4. **Label Prefixes**: Always use proper prefixes (`feature:`, `provider:`, `os:`, `platform:`, etc.)
|
||||
5. **Maintainer Comments**: Check maintainer comments for priority/status hints
|
||||
6. **No Comments**: Only apply labels, DO NOT post comments to issues
|
||||
7. **Batch Efficiency**: Process issues in parallel when possible
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Provider in Environment Variables
|
||||
|
||||
If issue body contains `AIHUBMIX_*`, add `provider:aihubmix`
|
||||
|
||||
### Multiple Provider Issues
|
||||
|
||||
If comparing providers (e.g., "works with OpenAI but not Gemini"), add both provider labels
|
||||
|
||||
### Desktop Issues
|
||||
|
||||
Desktop issues often need: `platform:desktop`, `electron`, specific `os:*`, and `deployment:client` or `deployment:server`
|
||||
|
||||
### Knowledge Base Issues
|
||||
|
||||
Usually need: `feature:knowledge-base`, often with `feature:files`, may need `provider:*` for embedding models
|
||||
|
||||
### Tool Calling Issues
|
||||
|
||||
Usually need: `feature:tool`, specific `provider:*`, may need `feature:mcp` if MCP-related
|
||||
|
||||
### Streaming Issues
|
||||
|
||||
Usually need: `feature:streaming`, specific `provider:*`, check for timeout/performance issues
|
||||
|
||||
## Example Triage
|
||||
|
||||
**Issue #8850**: "aihubmix 的优惠 app 没有生效"
|
||||
|
||||
**Analysis**:
|
||||
|
||||
- Title contains "aihubmix" → `provider:aihubmix`
|
||||
- Template shows: Windows, Chrome, Docker, Client mode
|
||||
- About API discount codes not working
|
||||
|
||||
**Labels Applied**:
|
||||
|
||||
```bash
|
||||
gh issue edit 8850 --add-label "provider:aihubmix,platform:web,os:windows,deployment:client,hosting:self-host,docker"
|
||||
gh issue edit 8850 --remove-label "unconfirm"
|
||||
```
|
||||
|
||||
**Reasoning**: AIHubMix provider discount feature not working. Client mode deployment on Windows with Docker. Provider detection from title keyword "aihubmix".
|
||||
@@ -0,0 +1,135 @@
|
||||
# Team Assignment Guide
|
||||
|
||||
## Quick Reference by Name
|
||||
|
||||
- **@arvinxx**: Last resort only, mention for priority:high issues, tool calling , mcp
|
||||
- **@canisminor1990**: Design, UI components, editor
|
||||
- **@tjx666**: Image/video generation, vision, cloud, documentation, TTS
|
||||
- **@ONLY-yours**: Performance, streaming, settings, general bugs, web platform, marketplace
|
||||
- **@RiverTwilight**: Knowledge base, files (KB-related), group chat
|
||||
- **@nekomeowww**: Memory, backend, deployment, DevOps
|
||||
- **@sudongyuer**: Mobile app (React Native)
|
||||
- **@sxjeru**: Model providers and configuration
|
||||
- **@cy948**: Auth Modules
|
||||
- **@rdmclin2**: Team workspace
|
||||
|
||||
Quick reference for assigning issues based on labels.
|
||||
|
||||
## Label to Team Member Mapping
|
||||
|
||||
### Provider Labels (provider:\*)
|
||||
|
||||
| Label | Owner | Notes |
|
||||
| ---------------- | ------- | -------------------------------------------- |
|
||||
| All `provider:*` | @sxjeru | Model configuration and provider integration |
|
||||
|
||||
### Platform Labels (platform:\*)
|
||||
|
||||
| Label | Owner | Notes |
|
||||
| ------------------ | ----------- | -------------------------------------- |
|
||||
| `platform:mobile` | @sudongyuer | React Native mobile app |
|
||||
| `platform:desktop` | @ONLY-yours | Electron desktop client (general) |
|
||||
| `platform:web` | @ONLY-yours | Web platform (unless specific feature) |
|
||||
|
||||
### Feature Labels (feature:\*)
|
||||
|
||||
| Label | Owner | Notes |
|
||||
| ------------------------ | --------------- | ----------------------------------------------------------------------- |
|
||||
| `feature:image` | @tjx666 | AI image generation |
|
||||
| `feature:dalle` | @tjx666 | DALL-E related |
|
||||
| `feature:vision` | @tjx666 | Vision/multimodal generation |
|
||||
| `feature:knowledge-base` | @RiverTwilight | Knowledge base and RAG |
|
||||
| `feature:files` | @RiverTwilight | File upload/management (when KB-related)<br>@ONLY-yours (general files) |
|
||||
| `feature:editor` | @canisminor1990 | Lobe Editor |
|
||||
| `feature:auth` | @cy948 | Authentication/authorization |
|
||||
| `feature:api` | @nekomeowww | Backend API |
|
||||
| `feature:streaming` | @arvinxx | Streaming response |
|
||||
| `feature:settings` | @ONLY-yours | Settings and configuration |
|
||||
| `feature:agent` | @ONLY-yours | Agent/Assistant |
|
||||
| `feature:topic` | @ONLY-yours | Topic/Conversation management |
|
||||
| `feature:thread` | @arvinxx | Thread/Subtopic |
|
||||
| `feature:marketplace` | @ONLY-yours | Agent marketplace |
|
||||
| `feature:tool` | @arvinxx | Tool calling |
|
||||
| `feature:mcp` | @arvinxx | MCP integration |
|
||||
| `feature:search` | @ONLY-yours | Search functionality |
|
||||
| `feature:tts` | @tjx666 | Text-to-speech |
|
||||
| `feature:export` | @ONLY-yours | Export functionality |
|
||||
| `feature:group-chat` | @RiverTwilight | Group chat functionality |
|
||||
| `feature:memory` | @nekomeowww | Memory feature |
|
||||
| `feature:team-workspace` | @rdmclin2 | Team workspace application |
|
||||
|
||||
### Deployment Labels (deployment:\*)
|
||||
|
||||
| Label | Owner | Notes |
|
||||
| ------------------ | ----------- | -------------------------- |
|
||||
| All `deployment:*` | @nekomeowww | Server/client/pglite modes |
|
||||
|
||||
### Hosting Labels (hosting:\*)
|
||||
|
||||
| Label | Owner | Notes |
|
||||
| ------------------- | ----------- | ---------------------- |
|
||||
| `hosting:cloud` | @tjx666 | Official LobeHub Cloud |
|
||||
| `hosting:self-host` | @nekomeowww | Self-hosting issues |
|
||||
| `hosting:vercel` | @nekomeowww | Vercel deployment |
|
||||
| `hosting:zeabur` | @nekomeowww | Zeabur deployment |
|
||||
| `hosting:railway` | @nekomeowww | Railway deployment |
|
||||
|
||||
### Issue Type Labels
|
||||
|
||||
| Label | Owner | Notes |
|
||||
| ------------------ | -------------------- | ---------------------------- |
|
||||
| 💄 Design | @canisminor1990 | Design and styling |
|
||||
| 📝 Documentation | @tjx666 | Documentation |
|
||||
| ⚡️ Performance | @ONLY-yours | Performance optimization |
|
||||
| 🐛 Bug | (depends on feature) | Assign based on other labels |
|
||||
| 🌠 Feature Request | (depends on feature) | Assign based on other labels |
|
||||
|
||||
## Assignment Rules
|
||||
|
||||
### Priority Order (apply in order)
|
||||
|
||||
1. **Specific feature owner** - e.g., `feature:knowledge-base` → @RiverTwilight
|
||||
2. **Platform owner** - e.g., `platform:mobile` → @sudongyuer
|
||||
3. **Provider owner** - e.g., `provider:*` → @sxjeru
|
||||
4. **Component owner** - e.g., 💄 Design → @canisminor1990
|
||||
5. **Infrastructure owner** - e.g., `deployment:*` → @nekomeowww
|
||||
6. **General maintainer** - @ONLY-yours for general bugs/issues
|
||||
7. **Last resort** - @arvinxx (only if no clear owner)
|
||||
|
||||
### Special Cases
|
||||
|
||||
**Multiple labels with different owners:**
|
||||
|
||||
- Mention the **most specific** feature owner first
|
||||
- Mention secondary owners if their input is valuable
|
||||
- Example: `feature:knowledge-base` + `deployment:server` → @RiverTwilight (primary), @nekomeowww (secondary)
|
||||
|
||||
**Priority:high issues:**
|
||||
|
||||
- Mention feature owner + @arvinxx
|
||||
- Example: `priority:high` + `feature:image` → @tjx666 @arvinxx
|
||||
|
||||
**No clear owner:**
|
||||
|
||||
- Assign to @ONLY-yours for general issues
|
||||
- Only mention @arvinxx if critical and truly unclear
|
||||
|
||||
## Comment Templates
|
||||
|
||||
**Single owner:**
|
||||
|
||||
```
|
||||
@username - This is a [feature/component] issue. Please take a look.
|
||||
```
|
||||
|
||||
**Multiple owners:**
|
||||
|
||||
```
|
||||
@primary @secondary - This involves [features]. Please coordinate.
|
||||
```
|
||||
|
||||
**High priority:**
|
||||
|
||||
```
|
||||
@owner @arvinxx - High priority [feature] issue.
|
||||
```
|
||||
@@ -0,0 +1,579 @@
|
||||
---
|
||||
description: Best practices for testing Zustand store actions
|
||||
globs: "src/store/**/*.test.ts"
|
||||
alwaysApply: false
|
||||
---
|
||||
|
||||
# Zustand Store Action Testing Guide
|
||||
|
||||
This guide provides best practices for testing Zustand store actions, based on our proven testing patterns.
|
||||
|
||||
## Basic Test Structure
|
||||
|
||||
```typescript
|
||||
import { act, renderHook } from '@testing-library/react';
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
import { messageService } from '@/services/message';
|
||||
import { useChatStore } from '../../store';
|
||||
|
||||
// Keep zustand mock as it's needed globally
|
||||
vi.mock('zustand/traditional');
|
||||
|
||||
beforeEach(() => {
|
||||
// Reset store state
|
||||
vi.clearAllMocks();
|
||||
useChatStore.setState(
|
||||
{
|
||||
activeId: 'test-session-id',
|
||||
messagesMap: {},
|
||||
loadingIds: [],
|
||||
},
|
||||
false,
|
||||
);
|
||||
|
||||
// ✅ Setup only spies that MOST tests need
|
||||
vi.spyOn(messageService, 'createMessage').mockResolvedValue('new-message-id');
|
||||
// ❌ Don't setup spies that only few tests need - spy only when needed
|
||||
|
||||
// Setup common mock methods
|
||||
act(() => {
|
||||
useChatStore.setState({
|
||||
refreshMessages: vi.fn(),
|
||||
internal_coreProcessMessage: vi.fn(),
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
describe('action name', () => {
|
||||
describe('validation', () => {
|
||||
// Validation tests
|
||||
});
|
||||
|
||||
describe('normal flow', () => {
|
||||
// Happy path tests
|
||||
});
|
||||
|
||||
describe('error handling', () => {
|
||||
// Error case tests
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
## Testing Best Practices
|
||||
|
||||
### 1. Test Layering - Spy Direct Dependencies Only
|
||||
|
||||
✅ **Good**: Spy on the direct dependency
|
||||
|
||||
```typescript
|
||||
// When testing internal_coreProcessMessage, spy its direct dependency
|
||||
const fetchAIChatSpy = vi
|
||||
.spyOn(result.current, 'internal_fetchAIChatMessage')
|
||||
.mockResolvedValue({ isFunctionCall: false, content: 'AI response' });
|
||||
```
|
||||
|
||||
❌ **Bad**: Spy on lower-level implementation details
|
||||
|
||||
```typescript
|
||||
// Don't spy on services that internal_fetchAIChatMessage uses
|
||||
const streamSpy = vi
|
||||
.spyOn(chatService, 'createAssistantMessageStream')
|
||||
.mockImplementation(...);
|
||||
```
|
||||
|
||||
**Why**: Each test should only mock its direct dependencies, not the entire call chain. This makes tests more maintainable and less brittle.
|
||||
|
||||
### 2. Mock Management - Minimize Global Spies
|
||||
|
||||
✅ **Good**: Spy only when needed
|
||||
|
||||
```typescript
|
||||
beforeEach(() => {
|
||||
// ✅ Only spy services that most tests need
|
||||
vi.spyOn(messageService, 'createMessage').mockResolvedValue('new-message-id');
|
||||
// ✅ Don't spy chatService globally
|
||||
});
|
||||
|
||||
it('should process message', async () => {
|
||||
// ✅ Spy chatService only in tests that need it
|
||||
const streamSpy = vi.spyOn(chatService, 'createAssistantMessageStream')
|
||||
.mockImplementation(...);
|
||||
|
||||
// test logic
|
||||
|
||||
streamSpy.mockRestore();
|
||||
});
|
||||
```
|
||||
|
||||
❌ **Bad**: Setup all spies globally
|
||||
|
||||
```typescript
|
||||
beforeEach(() => {
|
||||
vi.spyOn(messageService, 'createMessage').mockResolvedValue('id');
|
||||
vi.spyOn(chatService, 'createAssistantMessageStream').mockResolvedValue({}); // ❌ Not all tests need this
|
||||
vi.spyOn(fileService, 'uploadFile').mockResolvedValue({}); // ❌ Creates implicit coupling
|
||||
});
|
||||
```
|
||||
|
||||
### 3. Service Mocking - Mock the Correct Layer
|
||||
|
||||
✅ **Good**: Mock the service method
|
||||
|
||||
```typescript
|
||||
it('should fetch AI chat response', async () => {
|
||||
const streamSpy = vi
|
||||
.spyOn(chatService, 'createAssistantMessageStream')
|
||||
.mockImplementation(async ({ onMessageHandle, onFinish }) => {
|
||||
await onMessageHandle?.({ type: 'text', text: 'Hello' } as any);
|
||||
await onFinish?.('Hello', {});
|
||||
});
|
||||
|
||||
// test logic
|
||||
});
|
||||
```
|
||||
|
||||
❌ **Bad**: Mock global fetch
|
||||
|
||||
```typescript
|
||||
it('should fetch AI chat response', async () => {
|
||||
global.fetch = vi.fn().mockResolvedValue(...); // ❌ Too low level
|
||||
});
|
||||
```
|
||||
|
||||
### 4. Test Organization - Use Descriptive Nesting
|
||||
|
||||
✅ **Good**: Clear nested structure
|
||||
|
||||
```typescript
|
||||
describe('sendMessage', () => {
|
||||
describe('validation', () => {
|
||||
it('should not send when session is inactive', async () => {});
|
||||
it('should not send when message is empty', async () => {});
|
||||
});
|
||||
|
||||
describe('message creation', () => {
|
||||
it('should create user message and trigger AI processing', async () => {});
|
||||
it('should send message with files attached', async () => {});
|
||||
});
|
||||
|
||||
describe('error handling', () => {
|
||||
it('should handle message creation errors gracefully', async () => {});
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
❌ **Bad**: Flat structure
|
||||
|
||||
```typescript
|
||||
describe('sendMessage', () => {
|
||||
it('test 1', async () => {});
|
||||
it('test 2', async () => {});
|
||||
it('test 3', async () => {});
|
||||
});
|
||||
```
|
||||
|
||||
### 5. Testing Async Actions
|
||||
|
||||
Always wrap async operations in `act()`:
|
||||
|
||||
```typescript
|
||||
it('should send message', async () => {
|
||||
const { result } = renderHook(() => useChatStore());
|
||||
|
||||
await act(async () => {
|
||||
await result.current.sendMessage({ message: 'Hello' });
|
||||
});
|
||||
|
||||
expect(messageService.createMessage).toHaveBeenCalled();
|
||||
});
|
||||
```
|
||||
|
||||
### 6. State Setup - Use act() for setState
|
||||
|
||||
```typescript
|
||||
it('should handle disabled state', async () => {
|
||||
act(() => {
|
||||
useChatStore.setState({ activeId: undefined });
|
||||
});
|
||||
|
||||
const { result } = renderHook(() => useChatStore());
|
||||
// test logic
|
||||
});
|
||||
```
|
||||
|
||||
### 7. Testing Complex Flows
|
||||
|
||||
For complex flows with multiple steps, use clear spy setup:
|
||||
|
||||
```typescript
|
||||
it('should handle topic creation flow', async () => {
|
||||
// Setup store state
|
||||
act(() => {
|
||||
useChatStore.setState({
|
||||
activeTopicId: undefined,
|
||||
messagesMap: {
|
||||
'test-session-id': [
|
||||
{ id: 'msg-1', role: 'user', content: 'Message 1' },
|
||||
{ id: 'msg-2', role: 'assistant', content: 'Response 1' },
|
||||
{ id: 'msg-3', role: 'user', content: 'Message 2' },
|
||||
],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
const { result } = renderHook(() => useChatStore());
|
||||
|
||||
// Spy on action dependencies
|
||||
const createTopicSpy = vi.spyOn(result.current, 'createTopic')
|
||||
.mockResolvedValue('new-topic-id');
|
||||
const toggleLoadingSpy = vi.spyOn(result.current, 'internal_toggleMessageLoading');
|
||||
|
||||
// Execute
|
||||
await act(async () => {
|
||||
await result.current.sendMessage({ message: 'Test message' });
|
||||
});
|
||||
|
||||
// Assert
|
||||
expect(createTopicSpy).toHaveBeenCalled();
|
||||
expect(toggleLoadingSpy).toHaveBeenCalledWith(true, expect.any(String));
|
||||
});
|
||||
```
|
||||
|
||||
### 8. Streaming Response Mocking
|
||||
|
||||
When testing streaming responses, simulate the flow properly:
|
||||
|
||||
```typescript
|
||||
it('should handle streaming chunks', async () => {
|
||||
const { result } = renderHook(() => useChatStore());
|
||||
const messages = [
|
||||
{ id: 'msg-1', role: 'user', content: 'Hello', sessionId: 'test-session' },
|
||||
];
|
||||
|
||||
const streamSpy = vi
|
||||
.spyOn(chatService, 'createAssistantMessageStream')
|
||||
.mockImplementation(async ({ onMessageHandle, onFinish }) => {
|
||||
// Simulate streaming chunks
|
||||
await onMessageHandle?.({ type: 'text', text: 'Hello' } as any);
|
||||
await onMessageHandle?.({ type: 'text', text: ' World' } as any);
|
||||
await onFinish?.('Hello World', {});
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
await result.current.internal_fetchAIChatMessage({
|
||||
messages,
|
||||
messageId: 'test-message-id',
|
||||
model: 'gpt-4o-mini',
|
||||
provider: 'openai',
|
||||
});
|
||||
});
|
||||
|
||||
expect(result.current.internal_dispatchMessage).toHaveBeenCalled();
|
||||
|
||||
streamSpy.mockRestore();
|
||||
});
|
||||
```
|
||||
|
||||
### 9. Error Handling Tests
|
||||
|
||||
Always test error scenarios:
|
||||
|
||||
```typescript
|
||||
it('should handle errors gracefully', async () => {
|
||||
const { result } = renderHook(() => useChatStore());
|
||||
|
||||
vi.spyOn(messageService, 'createMessage').mockRejectedValue(
|
||||
new Error('create message error'),
|
||||
);
|
||||
|
||||
await act(async () => {
|
||||
try {
|
||||
await result.current.sendMessage({ message: 'Test message' });
|
||||
} catch {
|
||||
// Expected to throw
|
||||
}
|
||||
});
|
||||
|
||||
expect(result.current.internal_coreProcessMessage).not.toHaveBeenCalled();
|
||||
});
|
||||
```
|
||||
|
||||
### 10. Cleanup After Tests
|
||||
|
||||
Always restore mocks after each test:
|
||||
|
||||
```typescript
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
// For individual test cleanup:
|
||||
it('should test something', async () => {
|
||||
const spy = vi.spyOn(service, 'method').mockImplementation(...);
|
||||
|
||||
// test logic
|
||||
|
||||
spy.mockRestore(); // Optional: cleanup immediately after test
|
||||
});
|
||||
```
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Testing Store Methods That Call Other Store Methods
|
||||
|
||||
```typescript
|
||||
it('should call internal methods', async () => {
|
||||
const { result } = renderHook(() => useChatStore());
|
||||
|
||||
const internalMethodSpy = vi.spyOn(result.current, 'internal_method')
|
||||
.mockResolvedValue();
|
||||
|
||||
await act(async () => {
|
||||
await result.current.publicMethod();
|
||||
});
|
||||
|
||||
expect(internalMethodSpy).toHaveBeenCalledWith(
|
||||
expect.any(String),
|
||||
expect.objectContaining({ key: 'value' }),
|
||||
);
|
||||
});
|
||||
```
|
||||
|
||||
### Testing Conditional Logic
|
||||
|
||||
```typescript
|
||||
describe('conditional behavior', () => {
|
||||
it('should execute when condition is true', async () => {
|
||||
const { result } = renderHook(() => useChatStore());
|
||||
vi.spyOn(result.current, 'internal_shouldUseRAG').mockReturnValue(true);
|
||||
|
||||
await act(async () => {
|
||||
await result.current.sendMessage({ message: 'test' });
|
||||
});
|
||||
|
||||
expect(result.current.internal_retrieveChunks).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not execute when condition is false', async () => {
|
||||
const { result } = renderHook(() => useChatStore());
|
||||
vi.spyOn(result.current, 'internal_shouldUseRAG').mockReturnValue(false);
|
||||
|
||||
await act(async () => {
|
||||
await result.current.sendMessage({ message: 'test' });
|
||||
});
|
||||
|
||||
expect(result.current.internal_retrieveChunks).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### Testing AbortController
|
||||
|
||||
```typescript
|
||||
it('should abort generation and clear loading state', () => {
|
||||
const abortController = new AbortController();
|
||||
|
||||
act(() => {
|
||||
useChatStore.setState({ chatLoadingIdsAbortController: abortController });
|
||||
});
|
||||
|
||||
const { result } = renderHook(() => useChatStore());
|
||||
const toggleLoadingSpy = vi.spyOn(result.current, 'internal_toggleChatLoading');
|
||||
|
||||
act(() => {
|
||||
result.current.stopGenerateMessage();
|
||||
});
|
||||
|
||||
expect(abortController.signal.aborted).toBe(true);
|
||||
expect(toggleLoadingSpy).toHaveBeenCalledWith(false, undefined, expect.any(String));
|
||||
});
|
||||
```
|
||||
|
||||
## Anti-Patterns to Avoid
|
||||
|
||||
❌ **Don't**: Mock the entire store
|
||||
|
||||
```typescript
|
||||
vi.mock('../../store', () => ({
|
||||
useChatStore: vi.fn(() => ({
|
||||
sendMessage: vi.fn(),
|
||||
})),
|
||||
}));
|
||||
```
|
||||
|
||||
❌ **Don't**: Test implementation details
|
||||
|
||||
```typescript
|
||||
// Bad: testing internal state structure
|
||||
expect(result.current.messagesMap).toHaveProperty('test-session');
|
||||
|
||||
// Good: testing behavior
|
||||
expect(result.current.refreshMessages).toHaveBeenCalled();
|
||||
```
|
||||
|
||||
❌ **Don't**: Create tight coupling between tests
|
||||
|
||||
```typescript
|
||||
// Bad: Tests depend on order
|
||||
let messageId: string;
|
||||
|
||||
it('test 1', () => {
|
||||
messageId = 'some-id'; // Side effect
|
||||
});
|
||||
|
||||
it('test 2', () => {
|
||||
expect(messageId).toBeDefined(); // Depends on test 1
|
||||
});
|
||||
```
|
||||
|
||||
❌ **Don't**: Over-mock services
|
||||
|
||||
```typescript
|
||||
// Bad: Mocking everything
|
||||
beforeEach(() => {
|
||||
vi.mock('@/services/chat');
|
||||
vi.mock('@/services/message');
|
||||
vi.mock('@/services/file');
|
||||
vi.mock('@/services/agent');
|
||||
// ... too many global mocks
|
||||
});
|
||||
```
|
||||
|
||||
## Testing SWR Hooks in Zustand Stores
|
||||
|
||||
Some Zustand store slices use SWR hooks for data fetching. These require a different testing approach.
|
||||
|
||||
### Basic SWR Hook Test Structure
|
||||
|
||||
```typescript
|
||||
import { renderHook, waitFor } from '@testing-library/react';
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
import { discoverService } from '@/services/discover';
|
||||
import { globalHelpers } from '@/store/global/helpers';
|
||||
import { useDiscoverStore as useStore } from '../../store';
|
||||
|
||||
vi.mock('zustand/traditional');
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('SWR Hook Actions', () => {
|
||||
it('should fetch data and return correct response', async () => {
|
||||
const mockData = [{ id: '1', name: 'Item 1' }];
|
||||
|
||||
// Mock the service call (the fetcher)
|
||||
vi.spyOn(discoverService, 'getPluginCategories').mockResolvedValue(mockData as any);
|
||||
vi.spyOn(globalHelpers, 'getCurrentLanguage').mockReturnValue('en-US');
|
||||
|
||||
const params = {} as any;
|
||||
const { result } = renderHook(() => useStore.getState().usePluginCategories(params));
|
||||
|
||||
// Use waitFor to wait for async data loading
|
||||
await waitFor(() => {
|
||||
expect(result.current.data).toEqual(mockData);
|
||||
});
|
||||
|
||||
expect(discoverService.getPluginCategories).toHaveBeenCalledWith(params);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
**Key points**:
|
||||
- **DO NOT mock useSWR** - let it use the real implementation
|
||||
- Only mock the **service methods** (fetchers)
|
||||
- Use `waitFor` from `@testing-library/react` to wait for async operations
|
||||
- Check `result.current.data` directly after waitFor completes
|
||||
|
||||
### Testing SWR Key Generation
|
||||
|
||||
```typescript
|
||||
it('should generate correct SWR key with locale and params', () => {
|
||||
vi.spyOn(globalHelpers, 'getCurrentLanguage').mockReturnValue('zh-CN');
|
||||
|
||||
const useSWRMock = vi.mocked(useSWR);
|
||||
let capturedKey: string | null = null;
|
||||
useSWRMock.mockImplementation(((key: string) => {
|
||||
capturedKey = key;
|
||||
return { data: undefined, error: undefined, isValidating: false, mutate: vi.fn() };
|
||||
}) as any);
|
||||
|
||||
const params = { page: 2, category: 'tools' } as any;
|
||||
renderHook(() => useStore.getState().usePluginList(params));
|
||||
|
||||
expect(capturedKey).toBe('plugin-list-zh-CN-2-tools');
|
||||
});
|
||||
```
|
||||
|
||||
### Testing SWR Configuration
|
||||
|
||||
```typescript
|
||||
it('should have correct SWR configuration', () => {
|
||||
const useSWRMock = vi.mocked(useSWR);
|
||||
let capturedOptions: any = null;
|
||||
useSWRMock.mockImplementation(((key: string, fetcher: any, options: any) => {
|
||||
capturedOptions = options;
|
||||
return { data: undefined, error: undefined, isValidating: false, mutate: vi.fn() };
|
||||
}) as any);
|
||||
|
||||
renderHook(() => useStore.getState().usePluginIdentifiers());
|
||||
|
||||
expect(capturedOptions).toMatchObject({ revalidateOnFocus: false });
|
||||
});
|
||||
```
|
||||
|
||||
### Testing Conditional Fetching
|
||||
|
||||
```typescript
|
||||
it('should not fetch when required parameter is missing', () => {
|
||||
const useSWRMock = vi.mocked(useSWR);
|
||||
let capturedKey: string | null = null;
|
||||
useSWRMock.mockImplementation(((key: string | null) => {
|
||||
capturedKey = key;
|
||||
return { data: undefined, error: undefined, isValidating: false, mutate: vi.fn() };
|
||||
}) as any);
|
||||
|
||||
// When identifier is undefined, SWR key should be null
|
||||
renderHook(() => useStore.getState().usePluginDetail({ identifier: undefined }));
|
||||
|
||||
expect(capturedKey).toBeNull();
|
||||
});
|
||||
```
|
||||
|
||||
### Key Differences from Regular Action Tests
|
||||
|
||||
1. **Mock useSWR globally**: Use `vi.mock('swr')` at the top level
|
||||
2. **Mock the fetcher, not the result**:
|
||||
- ✅ **Correct**: `const data = fetcher?.()` - call fetcher and return its Promise
|
||||
- ❌ **Wrong**: `return { data: mockData }` - hardcode the result
|
||||
3. **Await Promise results**: The `data` field is a Promise, use `await result.current.data`
|
||||
4. **No act() wrapper needed**: SWR hooks don't trigger React state updates in these tests
|
||||
5. **Test SWR key generation**: Verify keys include locale and parameters
|
||||
6. **Test configuration**: Verify revalidation and other SWR options
|
||||
7. **Type assertions**: Use `as any` for test mock data where type definitions are strict
|
||||
|
||||
**Why this matters**:
|
||||
- The fetcher (service method) is what we're testing - it must be called
|
||||
- Hardcoding the return value bypasses the actual fetcher logic
|
||||
- SWR returns Promises in real usage, tests should mirror this behavior
|
||||
|
||||
## Benefits of This Approach
|
||||
|
||||
✅ **Clear test layers** - Each test only spies on direct dependencies
|
||||
✅ **Correct mocks** - Mocks match actual implementation
|
||||
✅ **Better maintainability** - Changes to implementation require fewer test updates
|
||||
✅ **Improved coverage** - Structured approach ensures all branches are tested
|
||||
✅ **Reduced coupling** - Tests are independent and can run in any order
|
||||
|
||||
## Reference
|
||||
|
||||
See example implementation in:
|
||||
- `src/store/chat/slices/aiChat/actions/__tests__/generateAIChat.test.ts` (Regular actions)
|
||||
- `src/store/discover/slices/plugin/action.test.ts` (SWR hooks)
|
||||
- `src/store/discover/slices/mcp/action.test.ts` (SWR hooks)
|
||||
@@ -5,34 +5,17 @@ type: Bug
|
||||
body:
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: '📦 Platform'
|
||||
label: '📱 Client Type'
|
||||
description: 'Select how you are accessing LobeChat'
|
||||
multiple: true
|
||||
options:
|
||||
- 'Official Preview'
|
||||
- 'Official Cloud'
|
||||
- 'Vercel'
|
||||
- 'Zeabur'
|
||||
- 'Sealos'
|
||||
- 'Netlify'
|
||||
- 'Self hosting Docker'
|
||||
- 'Web (Desktop Browser)'
|
||||
- 'Web (Mobile Browser)'
|
||||
- 'Desktop App (Electron)'
|
||||
- 'Mobile App (React Native)'
|
||||
- 'Other'
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: '📦 Deploymenet mode'
|
||||
multiple: true
|
||||
options:
|
||||
- 'client db (lobe-chat image)'
|
||||
- 'client pgelite db (lobe-chat-pglite image)'
|
||||
- 'server db(lobe-chat-database image)'
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
attributes:
|
||||
label: '📌 Version'
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
attributes:
|
||||
@@ -48,6 +31,39 @@ body:
|
||||
- 'Other'
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: '📦 Deployment Platform'
|
||||
multiple: true
|
||||
options:
|
||||
- 'Official Cloud'
|
||||
- 'Vercel'
|
||||
- 'Zeabur'
|
||||
- 'Sealos'
|
||||
- 'Netlify'
|
||||
- 'Self hosting Docker'
|
||||
- 'Other'
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: '🔧 Deployment Mode'
|
||||
multiple: true
|
||||
options:
|
||||
- 'client db (lobe-chat image)'
|
||||
- 'client pgelite db (lobe-chat-pglite image)'
|
||||
- 'server db (lobe-chat-database image)'
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: '📌 Version'
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: '🌐 Browser'
|
||||
@@ -60,21 +76,49 @@ body:
|
||||
- 'Other'
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: '🐛 Bug Description'
|
||||
description: A clear and concise description of the bug, if the above option is `Other`, please also explain in detail.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: '📷 Recurrence Steps'
|
||||
description: A clear and concise description of how to recurrence.
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: '🚦 Expected Behavior'
|
||||
description: A clear and concise description of what you expected to happen.
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: '📝 Additional Information'
|
||||
description: If your problem needs further explanation, or if the issue you're seeing cannot be reproduced in a gist, please add more information here.
|
||||
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: '🛠️ Willing to Submit a PR?'
|
||||
description: Would you be willing to submit a pull request to fix this bug?
|
||||
options:
|
||||
- 'Yes, I am willing to submit a PR'
|
||||
- 'No, but I am happy to help test the fix'
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: '✅ Validations'
|
||||
description: Before submitting the issue, please make sure you do the following
|
||||
options:
|
||||
- label: Read the [docs](https://lobehub.com/zh/docs).
|
||||
required: true
|
||||
- label: Check that there isn't [already an issue](https://github.com/lobehub/lobe-chat/issues) that reports the same bug to avoid creating a duplicate.
|
||||
required: true
|
||||
- label: Make sure this is a LobeChat issue and not a third-party library or provider issue.
|
||||
required: true
|
||||
- label: Check that this is a concrete bug. For Q&A, please use [GitHub Discussions](https://github.com/lobehub/lobe-chat/discussions) or join our [Discord Server](https://discord.gg/rGHwKq4R).
|
||||
required: true
|
||||
|
||||
@@ -12,10 +12,36 @@
|
||||
- [ ] 📝 docs
|
||||
- [ ] 🔨 chore
|
||||
|
||||
#### 🔗 Related Issue
|
||||
|
||||
<!-- Link to the issue that is fixed by this PR -->
|
||||
|
||||
<!-- Example: Fixes #123, Closes #456, Related to #789 -->
|
||||
|
||||
#### 🔀 Description of Change
|
||||
|
||||
<!-- Thank you for your Pull Request. Please provide a description above. -->
|
||||
|
||||
#### 🧪 How to Test
|
||||
|
||||
<!-- Please describe how you tested your changes -->
|
||||
|
||||
<!-- For AI features, please include test prompts or scenarios -->
|
||||
|
||||
- [ ] Tested locally
|
||||
- [ ] Added/updated tests
|
||||
- [ ] No tests needed
|
||||
|
||||
#### 📸 Screenshots / Videos
|
||||
|
||||
<!-- If this PR includes UI changes, please provide screenshots or videos -->
|
||||
|
||||
| Before | After |
|
||||
| ------ | ----- |
|
||||
| ... | ... |
|
||||
|
||||
#### 📝 Additional Information
|
||||
|
||||
<!-- Add any other context about the Pull Request here. -->
|
||||
|
||||
<!-- Breaking changes? Migration guide? Performance impact? -->
|
||||
|
||||
@@ -0,0 +1,260 @@
|
||||
#!/usr/bin/env bun
|
||||
|
||||
declare global {
|
||||
// @ts-ignore
|
||||
// eslint-disable-next-line no-var
|
||||
var process: {
|
||||
env: Record<string, string | undefined>;
|
||||
};
|
||||
}
|
||||
|
||||
interface GitHubIssue {
|
||||
created_at: string;
|
||||
number: number;
|
||||
title: string;
|
||||
user: { id: number };
|
||||
}
|
||||
|
||||
interface GitHubComment {
|
||||
body: string;
|
||||
created_at: string;
|
||||
id: number;
|
||||
user: { id: number; type: string };
|
||||
}
|
||||
|
||||
interface GitHubReaction {
|
||||
content: string;
|
||||
user: { id: number };
|
||||
}
|
||||
|
||||
async function githubRequest<T>(
|
||||
endpoint: string,
|
||||
token: string,
|
||||
method: string = 'GET',
|
||||
body?: any,
|
||||
): Promise<T> {
|
||||
const response = await fetch(`https://api.github.com${endpoint}`, {
|
||||
headers: {
|
||||
'Accept': 'application/vnd.github.v3+json',
|
||||
'Authorization': `Bearer ${token}`,
|
||||
'User-Agent': 'auto-close-duplicates-script',
|
||||
...(body && { 'Content-Type': 'application/json' }),
|
||||
},
|
||||
method,
|
||||
...(body && { body: JSON.stringify(body) }),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`GitHub API request failed: ${response.status} ${response.statusText}`);
|
||||
}
|
||||
|
||||
return response.json();
|
||||
}
|
||||
|
||||
function extractDuplicateIssueNumber(commentBody: string): number | null {
|
||||
// Try to match #123 format first
|
||||
let match = commentBody.match(/#(\d+)/);
|
||||
if (match) {
|
||||
return parseInt(match[1], 10);
|
||||
}
|
||||
|
||||
// Try to match GitHub issue URL format: https://github.com/owner/repo/issues/123
|
||||
match = commentBody.match(/github\.com\/[^/]+\/[^/]+\/issues\/(\d+)/);
|
||||
if (match) {
|
||||
return parseInt(match[1], 10);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
async function closeIssueAsDuplicate(
|
||||
owner: string,
|
||||
repo: string,
|
||||
issueNumber: number,
|
||||
duplicateOfNumber: number,
|
||||
token: string,
|
||||
): Promise<void> {
|
||||
await githubRequest(`/repos/${owner}/${repo}/issues/${issueNumber}`, token, 'PATCH', {
|
||||
labels: ['duplicate'],
|
||||
state: 'closed',
|
||||
state_reason: 'duplicate',
|
||||
});
|
||||
|
||||
await githubRequest(`/repos/${owner}/${repo}/issues/${issueNumber}/comments`, token, 'POST', {
|
||||
body: `This issue has been automatically closed as a duplicate of #${duplicateOfNumber}.
|
||||
|
||||
If this is incorrect, please re-open this issue or create a new one.
|
||||
|
||||
🤖 Generated with [Claude Code](https://claude.ai/code)`,
|
||||
});
|
||||
}
|
||||
|
||||
async function autoCloseDuplicates(): Promise<void> {
|
||||
console.log('[DEBUG] Starting auto-close duplicates script');
|
||||
|
||||
const token = process.env.GITHUB_TOKEN;
|
||||
if (!token) {
|
||||
throw new Error('GITHUB_TOKEN environment variable is required');
|
||||
}
|
||||
console.log('[DEBUG] GitHub token found');
|
||||
|
||||
const owner = process.env.GITHUB_REPOSITORY_OWNER || 'lobehub';
|
||||
const repo = process.env.GITHUB_REPOSITORY_NAME || 'lobe-chat';
|
||||
console.log(`[DEBUG] Repository: ${owner}/${repo}`);
|
||||
|
||||
const threeDaysAgo = new Date();
|
||||
threeDaysAgo.setDate(threeDaysAgo.getDate() - 3);
|
||||
console.log(`[DEBUG] Checking for duplicate comments older than: ${threeDaysAgo.toISOString()}`);
|
||||
|
||||
console.log('[DEBUG] Fetching open issues created more than 3 days ago...');
|
||||
const allIssues: GitHubIssue[] = [];
|
||||
let page = 1;
|
||||
const perPage = 100;
|
||||
|
||||
// eslint-disable-next-line no-constant-condition
|
||||
while (true) {
|
||||
const pageIssues: GitHubIssue[] = await githubRequest(
|
||||
`/repos/${owner}/${repo}/issues?state=open&per_page=${perPage}&page=${page}`,
|
||||
token,
|
||||
);
|
||||
|
||||
if (pageIssues.length === 0) break;
|
||||
|
||||
// Filter for issues created more than 3 days ago
|
||||
const oldEnoughIssues = pageIssues.filter(
|
||||
(issue) => new Date(issue.created_at) <= threeDaysAgo,
|
||||
);
|
||||
|
||||
allIssues.push(...oldEnoughIssues);
|
||||
page++;
|
||||
|
||||
// Safety limit to avoid infinite loops
|
||||
if (page > 20) break;
|
||||
}
|
||||
|
||||
const issues = allIssues;
|
||||
console.log(`[DEBUG] Found ${issues.length} open issues`);
|
||||
|
||||
let processedCount = 0;
|
||||
let candidateCount = 0;
|
||||
|
||||
for (const issue of issues) {
|
||||
processedCount++;
|
||||
console.log(
|
||||
`[DEBUG] Processing issue #${issue.number} (${processedCount}/${issues.length}): ${issue.title}`,
|
||||
);
|
||||
|
||||
console.log(`[DEBUG] Fetching comments for issue #${issue.number}...`);
|
||||
const comments: GitHubComment[] = await githubRequest(
|
||||
`/repos/${owner}/${repo}/issues/${issue.number}/comments`,
|
||||
token,
|
||||
);
|
||||
console.log(`[DEBUG] Issue #${issue.number} has ${comments.length} comments`);
|
||||
|
||||
const dupeComments = comments.filter(
|
||||
(comment) =>
|
||||
comment.body.includes('Found') &&
|
||||
comment.body.includes('possible duplicate') &&
|
||||
comment.user.type === 'Bot',
|
||||
);
|
||||
console.log(
|
||||
`[DEBUG] Issue #${issue.number} has ${dupeComments.length} duplicate detection comments`,
|
||||
);
|
||||
|
||||
if (dupeComments.length === 0) {
|
||||
console.log(`[DEBUG] Issue #${issue.number} - no duplicate comments found, skipping`);
|
||||
continue;
|
||||
}
|
||||
|
||||
const lastDupeComment = dupeComments.at(-1);
|
||||
// @ts-ignore
|
||||
const dupeCommentDate = new Date(lastDupeComment.created_at);
|
||||
console.log(
|
||||
`[DEBUG] Issue #${
|
||||
issue.number
|
||||
} - most recent duplicate comment from: ${dupeCommentDate.toISOString()}`,
|
||||
);
|
||||
|
||||
if (dupeCommentDate > threeDaysAgo) {
|
||||
console.log(`[DEBUG] Issue #${issue.number} - duplicate comment is too recent, skipping`);
|
||||
continue;
|
||||
}
|
||||
console.log(
|
||||
`[DEBUG] Issue #${issue.number} - duplicate comment is old enough (${Math.floor(
|
||||
(Date.now() - dupeCommentDate.getTime()) / (1000 * 60 * 60 * 24),
|
||||
)} days)`,
|
||||
);
|
||||
|
||||
const commentsAfterDupe = comments.filter(
|
||||
(comment) => new Date(comment.created_at) > dupeCommentDate,
|
||||
);
|
||||
console.log(
|
||||
`[DEBUG] Issue #${issue.number} - ${commentsAfterDupe.length} comments after duplicate detection`,
|
||||
);
|
||||
|
||||
if (commentsAfterDupe.length > 0) {
|
||||
console.log(
|
||||
`[DEBUG] Issue #${issue.number} - has activity after duplicate comment, skipping`,
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
console.log(`[DEBUG] Issue #${issue.number} - checking reactions on duplicate comment...`);
|
||||
const reactions: GitHubReaction[] = await githubRequest(
|
||||
// @ts-ignore
|
||||
`/repos/${owner}/${repo}/issues/comments/${lastDupeComment.id}/reactions`,
|
||||
token,
|
||||
);
|
||||
console.log(
|
||||
`[DEBUG] Issue #${issue.number} - duplicate comment has ${reactions.length} reactions`,
|
||||
);
|
||||
|
||||
const authorThumbsDown = reactions.some(
|
||||
(reaction) => reaction.user.id === issue.user.id && reaction.content === '-1',
|
||||
);
|
||||
console.log(
|
||||
`[DEBUG] Issue #${issue.number} - author thumbs down reaction: ${authorThumbsDown}`,
|
||||
);
|
||||
|
||||
if (authorThumbsDown) {
|
||||
console.log(
|
||||
`[DEBUG] Issue #${issue.number} - author disagreed with duplicate detection, skipping`,
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
const duplicateIssueNumber = extractDuplicateIssueNumber(lastDupeComment.body);
|
||||
if (!duplicateIssueNumber) {
|
||||
console.log(
|
||||
`[DEBUG] Issue #${issue.number} - could not extract duplicate issue number from comment, skipping`,
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
candidateCount++;
|
||||
const issueUrl = `https://github.com/${owner}/${repo}/issues/${issue.number}`;
|
||||
|
||||
try {
|
||||
console.log(
|
||||
`[INFO] Auto-closing issue #${issue.number} as duplicate of #${duplicateIssueNumber}: ${issueUrl}`,
|
||||
);
|
||||
await closeIssueAsDuplicate(owner, repo, issue.number, duplicateIssueNumber, token);
|
||||
console.log(
|
||||
`[SUCCESS] Successfully closed issue #${issue.number} as duplicate of #${duplicateIssueNumber}`,
|
||||
);
|
||||
} catch (error) {
|
||||
console.error(`[ERROR] Failed to close issue #${issue.number} as duplicate: ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
console.log(
|
||||
`[DEBUG] Script completed. Processed ${processedCount} issues, found ${candidateCount} candidates for auto-close`,
|
||||
);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line unicorn/prefer-top-level-await
|
||||
autoCloseDuplicates().catch(console.error);
|
||||
|
||||
// Make it a module
|
||||
export {};
|
||||
@@ -0,0 +1,33 @@
|
||||
name: Claude Issue Dedupe
|
||||
description: Automatically dedupe GitHub issues using Claude Code
|
||||
on:
|
||||
issues:
|
||||
types: [opened]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
issue_number:
|
||||
description: 'Issue number to process for duplicate detection'
|
||||
required: true
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
claude-dedupe-issues:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Run Claude Code slash command
|
||||
uses: anthropics/claude-code-action@main
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
allowed_non_write_users: "*"
|
||||
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
|
||||
prompt: '/dedupe ${{ github.repository }}/issues/${{ github.event.issue.number || inputs.issue_number }}'
|
||||
@@ -0,0 +1,65 @@
|
||||
name: Claude Issue Triage
|
||||
description: Automatically triage GitHub issues using Claude Code
|
||||
on:
|
||||
issues:
|
||||
types: [opened, labeled]
|
||||
|
||||
jobs:
|
||||
triage-issue:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
# Only run on issue opened, or when "trigger:triage" label is added
|
||||
if: github.event.action == 'opened' || (github.event.action == 'labeled' && github.event.label.name == 'trigger:triage')
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Copy triage prompts
|
||||
run: |
|
||||
mkdir -p /tmp/claude-prompts
|
||||
cp .claude/prompts/team-assignment.md /tmp/claude-prompts/
|
||||
cp .claude/prompts/issue-triage.md /tmp/claude-prompts/
|
||||
|
||||
- name: Run Claude Code for Issue Triage
|
||||
uses: anthropics/claude-code-action@main
|
||||
with:
|
||||
github_token: ${{ secrets.GH_TOKEN }}
|
||||
allowed_non_write_users: "*"
|
||||
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
|
||||
claude_args: "--allowed-tools Bash(gh *),Read"
|
||||
prompt: |
|
||||
You're an issue triage assistant for GitHub issues. Your task is to analyze issues, apply appropriate labels, and mention the responsible team member.
|
||||
|
||||
REPOSITORY: ${{ github.repository }}
|
||||
ISSUE_NUMBER: ${{ github.event.issue.number }}
|
||||
|
||||
## Instructions
|
||||
|
||||
Follow the complete triage guide located at:
|
||||
```bash
|
||||
cat /tmp/claude-prompts/issue-triage.md
|
||||
```
|
||||
|
||||
Read the team assignment guide for determining team members:
|
||||
```bash
|
||||
cat /tmp/claude-prompts/team-assignment.md
|
||||
```
|
||||
|
||||
**IMPORTANT**:
|
||||
- Follow ALL steps in the issue-triage.md guide
|
||||
- Apply labels according to the guide's rules
|
||||
- Post a mention comment to the appropriate team member(s) based on team-assignment.md
|
||||
- Replace [ISSUE_NUMBER] with: ${{ github.event.issue.number }}
|
||||
|
||||
**Start the triage process now.**
|
||||
|
||||
- name: Remove trigger label
|
||||
if: github.event.action == 'labeled' && github.event.label.name == 'trigger:triage'
|
||||
run: |
|
||||
gh issue edit ${{ github.event.issue.number }} --remove-label "trigger:triage"
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
||||
@@ -18,8 +18,8 @@ env:
|
||||
jobs:
|
||||
test:
|
||||
name: Code quality check
|
||||
# 添加 PR label 触发条件,只有添加了 Build Desktop 标签的 PR 才会触发构建
|
||||
if: contains(github.event.pull_request.labels.*.name, 'Build Desktop')
|
||||
# 添加 PR label 触发条件,只有添加了 trigger:build-desktop 标签的 PR 才会触发构建
|
||||
if: contains(github.event.pull_request.labels.*.name, 'trigger:build-desktop')
|
||||
runs-on: ubuntu-latest # 只在 ubuntu 上运行一次检查
|
||||
steps:
|
||||
- name: Checkout base
|
||||
@@ -51,7 +51,7 @@ jobs:
|
||||
version:
|
||||
name: Determine version
|
||||
# 与 test job 相同的触发条件
|
||||
if: contains(github.event.pull_request.labels.*.name, 'Build Desktop')
|
||||
if: contains(github.event.pull_request.labels.*.name, 'trigger:build-desktop')
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
# 输出版本信息,供后续 job 使用
|
||||
@@ -238,7 +238,7 @@ jobs:
|
||||
|
||||
# 下载所有平台的构建产物
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
path: release
|
||||
pattern: release-*
|
||||
@@ -287,7 +287,7 @@ jobs:
|
||||
|
||||
# 下载合并后的构建产物
|
||||
- name: Download merged artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
name: merged-release-pr
|
||||
path: release
|
||||
|
||||
@@ -22,7 +22,7 @@ jobs:
|
||||
# 添加 PR label 触发条件
|
||||
if: |
|
||||
(github.event_name == 'pull_request' &&
|
||||
contains(github.event.pull_request.labels.*.name, 'Build Docker')) ||
|
||||
contains(github.event.pull_request.labels.*.name, 'trigger:build-docker')) ||
|
||||
github.event_name != 'pull_request'
|
||||
|
||||
strategy:
|
||||
@@ -118,7 +118,7 @@ jobs:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Download digests
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
path: /tmp/digests
|
||||
pattern: digest-*
|
||||
|
||||
@@ -22,7 +22,7 @@ jobs:
|
||||
# 添加 PR label 触发条件
|
||||
if: |
|
||||
(github.event_name == 'pull_request' &&
|
||||
contains(github.event.pull_request.labels.*.name, 'Build Docker')) ||
|
||||
contains(github.event.pull_request.labels.*.name, 'trigger:build-docker')) ||
|
||||
github.event_name != 'pull_request'
|
||||
|
||||
strategy:
|
||||
@@ -118,7 +118,7 @@ jobs:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Download digests
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
path: /tmp/digests
|
||||
pattern: digest-*
|
||||
|
||||
@@ -22,7 +22,7 @@ jobs:
|
||||
# 添加 PR label 触发条件
|
||||
if: |
|
||||
(github.event_name == 'pull_request' &&
|
||||
contains(github.event.pull_request.labels.*.name, 'Build Docker')) ||
|
||||
contains(github.event.pull_request.labels.*.name, 'trigger:build-docker')) ||
|
||||
github.event_name != 'pull_request'
|
||||
|
||||
strategy:
|
||||
@@ -118,7 +118,7 @@ jobs:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Download digests
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
path: /tmp/digests
|
||||
pattern: digest-*
|
||||
|
||||
@@ -22,7 +22,7 @@ jobs:
|
||||
- name: Setup Bun
|
||||
uses: oven-sh/setup-bun@v2
|
||||
with:
|
||||
bun-version: latest
|
||||
bun-version: 1.2.23
|
||||
|
||||
- name: Install dependencies (bun)
|
||||
run: bun install
|
||||
@@ -35,18 +35,18 @@ jobs:
|
||||
PORT: 3010
|
||||
run: bun run e2e
|
||||
|
||||
- name: Upload Playwright HTML report (on failure)
|
||||
- name: Upload Cucumber HTML report (on failure)
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: playwright-report
|
||||
path: playwright-report
|
||||
name: cucumber-report
|
||||
path: e2e/reports
|
||||
if-no-files-found: ignore
|
||||
|
||||
- name: Upload Playwright traces (on failure)
|
||||
- name: Upload screenshots (on failure)
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: test-results
|
||||
path: test-results
|
||||
name: test-screenshots
|
||||
path: e2e/screenshots
|
||||
if-no-files-found: ignore
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
name: Auto-close duplicate issues
|
||||
description: Auto-closes issues that are duplicates of existing issues
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 2 * * *"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
auto-close-duplicates:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Setup Bun
|
||||
uses: oven-sh/setup-bun@v2
|
||||
with:
|
||||
bun-version: latest
|
||||
|
||||
- name: Auto-close duplicate issues
|
||||
run: bun run .github/scripts/auto-close-duplicates.ts
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
|
||||
GITHUB_REPOSITORY_OWNER: ${{ github.repository_owner }}
|
||||
GITHUB_REPOSITORY_NAME: ${{ github.event.repository.name }}
|
||||
@@ -15,7 +15,7 @@ permissions: read-all
|
||||
jobs:
|
||||
test:
|
||||
name: Code quality check
|
||||
# 添加 PR label 触发条件,只有添加了 Build Desktop 标签的 PR 才会触发构建
|
||||
# 添加 PR label 触发条件,只有添加了 trigger:build-desktop 标签的 PR 才会触发构建
|
||||
runs-on: ubuntu-latest # 只在 ubuntu 上运行一次检查
|
||||
steps:
|
||||
- name: Checkout base
|
||||
@@ -220,7 +220,7 @@ jobs:
|
||||
|
||||
# 下载所有平台的构建产物
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
path: release
|
||||
pattern: release-*
|
||||
@@ -262,7 +262,7 @@ jobs:
|
||||
steps:
|
||||
# 下载合并后的构建产物
|
||||
- name: Download merged artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
name: merged-release
|
||||
path: release
|
||||
|
||||
@@ -50,5 +50,5 @@ jobs:
|
||||

|
||||
|
||||
[lobechat]: https://github.com/lobehub/lobe-chat
|
||||
[tutorial-zh-CN]: https://github.com/lobehub/lobe-chat/wiki/Upstream-Sync.zh-CN
|
||||
[tutorial-en-US]: https://github.com/lobehub/lobe-chat/wiki/Upstream-Sync
|
||||
[tutorial-zh-CN]: https://lobehub.com/zh/docs/self-hosting/advanced/upstream-sync
|
||||
[tutorial-en-US]: https://lobehub.com/docs/self-hosting/advanced/upstream-sync
|
||||
|
||||
@@ -145,26 +145,24 @@ jobs:
|
||||
node-version: 22
|
||||
package-manager-cache: false
|
||||
|
||||
- name: Install bun
|
||||
uses: oven-sh/setup-bun@v2
|
||||
with:
|
||||
bun-version: 1.2.23
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
|
||||
- name: Install deps
|
||||
run: bun i
|
||||
run: pnpm i
|
||||
|
||||
- name: Lint
|
||||
run: bun run lint
|
||||
run: npm run lint
|
||||
|
||||
- name: Test Client DB
|
||||
run: bun run --filter @lobechat/database test:client-db
|
||||
run: pnpm --filter @lobechat/database test:client-db
|
||||
env:
|
||||
KEY_VAULTS_SECRET: LA7n9k3JdEcbSgml2sxfw+4TV1AzaaFU5+R176aQz4s=
|
||||
S3_PUBLIC_DOMAIN: https://example.com
|
||||
APP_URL: https://home.com
|
||||
|
||||
- name: Test Coverage
|
||||
run: bun run --filter @lobechat/database test:coverage
|
||||
run: pnpm --filter @lobechat/database test:coverage
|
||||
env:
|
||||
DATABASE_TEST_URL: postgresql://postgres:postgres@localhost:5432/postgres
|
||||
DATABASE_DRIVER: node
|
||||
|
||||
@@ -117,3 +117,4 @@ CLAUDE.local.md
|
||||
|
||||
prd
|
||||
GEMINI.md
|
||||
e2e/reports
|
||||
|
||||
@@ -4,8 +4,6 @@ resolution-mode=highest
|
||||
ignore-workspace-root-check=true
|
||||
enable-pre-post-scripts=true
|
||||
|
||||
# Load dotenv files for all the npm scripts
|
||||
node-options="--require dotenv-expand/config"
|
||||
|
||||
public-hoist-pattern[]=*@umijs/lint*
|
||||
public-hoist-pattern[]=*changelog*
|
||||
|
||||
+702
@@ -2,6 +2,708 @@
|
||||
|
||||
# Changelog
|
||||
|
||||
### [Version 1.141.8](https://github.com/lobehub/lobe-chat/compare/v1.141.7...v1.141.8)
|
||||
|
||||
<sup>Released on **2025-10-23**</sup>
|
||||
|
||||
#### 💄 Styles
|
||||
|
||||
- **misc**: Improvement for Agent Team After Alpha Launch \[LOB-517].
|
||||
|
||||
<br/>
|
||||
|
||||
<details>
|
||||
<summary><kbd>Improvements and Fixes</kbd></summary>
|
||||
|
||||
#### Styles
|
||||
|
||||
- **misc**: Improvement for Agent Team After Alpha Launch \[LOB-517], closes [#9748](https://github.com/lobehub/lobe-chat/issues/9748) ([28245be](https://github.com/lobehub/lobe-chat/commit/28245be))
|
||||
|
||||
</details>
|
||||
|
||||
<div align="right">
|
||||
|
||||
[](#readme-top)
|
||||
|
||||
</div>
|
||||
|
||||
### [Version 1.141.7](https://github.com/lobehub/lobe-chat/compare/v1.141.6...v1.141.7)
|
||||
|
||||
<sup>Released on **2025-10-23**</sup>
|
||||
|
||||
#### 💄 Styles
|
||||
|
||||
- **misc**: Allow removal of `top_p` and similar request parameters.
|
||||
|
||||
<br/>
|
||||
|
||||
<details>
|
||||
<summary><kbd>Improvements and Fixes</kbd></summary>
|
||||
|
||||
#### Styles
|
||||
|
||||
- **misc**: Allow removal of `top_p` and similar request parameters, closes [#9498](https://github.com/lobehub/lobe-chat/issues/9498) ([4c313ce](https://github.com/lobehub/lobe-chat/commit/4c313ce))
|
||||
|
||||
</details>
|
||||
|
||||
<div align="right">
|
||||
|
||||
[](#readme-top)
|
||||
|
||||
</div>
|
||||
|
||||
### [Version 1.141.6](https://github.com/lobehub/lobe-chat/compare/v1.141.5...v1.141.6)
|
||||
|
||||
<sup>Released on **2025-10-22**</sup>
|
||||
|
||||
<br/>
|
||||
|
||||
<details>
|
||||
<summary><kbd>Improvements and Fixes</kbd></summary>
|
||||
|
||||
</details>
|
||||
|
||||
<div align="right">
|
||||
|
||||
[](#readme-top)
|
||||
|
||||
</div>
|
||||
|
||||
### [Version 1.141.5](https://github.com/lobehub/lobe-chat/compare/v1.141.4...v1.141.5)
|
||||
|
||||
<sup>Released on **2025-10-22**</sup>
|
||||
|
||||
#### ♻ Code Refactoring
|
||||
|
||||
- **misc**: Change discover page from RSC to SPA to improve performance.
|
||||
|
||||
<br/>
|
||||
|
||||
<details>
|
||||
<summary><kbd>Improvements and Fixes</kbd></summary>
|
||||
|
||||
#### Code refactoring
|
||||
|
||||
- **misc**: Change discover page from RSC to SPA to improve performance, closes [#9828](https://github.com/lobehub/lobe-chat/issues/9828) ([b59ee0a](https://github.com/lobehub/lobe-chat/commit/b59ee0a))
|
||||
|
||||
</details>
|
||||
|
||||
<div align="right">
|
||||
|
||||
[](#readme-top)
|
||||
|
||||
</div>
|
||||
|
||||
### [Version 1.141.4](https://github.com/lobehub/lobe-chat/compare/v1.141.3...v1.141.4)
|
||||
|
||||
<sup>Released on **2025-10-22**</sup>
|
||||
|
||||
#### ♻ Code Refactoring
|
||||
|
||||
- **misc**: Fix model runtime cost calculate with CNY.
|
||||
|
||||
<br/>
|
||||
|
||||
<details>
|
||||
<summary><kbd>Improvements and Fixes</kbd></summary>
|
||||
|
||||
#### Code refactoring
|
||||
|
||||
- **misc**: Fix model runtime cost calculate with CNY, closes [#9834](https://github.com/lobehub/lobe-chat/issues/9834) ([2e911ea](https://github.com/lobehub/lobe-chat/commit/2e911ea))
|
||||
|
||||
</details>
|
||||
|
||||
<div align="right">
|
||||
|
||||
[](#readme-top)
|
||||
|
||||
</div>
|
||||
|
||||
### [Version 1.141.3](https://github.com/lobehub/lobe-chat/compare/v1.141.2...v1.141.3)
|
||||
|
||||
<sup>Released on **2025-10-22**</sup>
|
||||
|
||||
#### 💄 Styles
|
||||
|
||||
- **misc**: Update i18n.
|
||||
|
||||
<br/>
|
||||
|
||||
<details>
|
||||
<summary><kbd>Improvements and Fixes</kbd></summary>
|
||||
|
||||
#### Styles
|
||||
|
||||
- **misc**: Update i18n, closes [#9832](https://github.com/lobehub/lobe-chat/issues/9832) ([80b0999](https://github.com/lobehub/lobe-chat/commit/80b0999))
|
||||
|
||||
</details>
|
||||
|
||||
<div align="right">
|
||||
|
||||
[](#readme-top)
|
||||
|
||||
</div>
|
||||
|
||||
### [Version 1.141.2](https://github.com/lobehub/lobe-chat/compare/v1.141.1...v1.141.2)
|
||||
|
||||
<sup>Released on **2025-10-21**</sup>
|
||||
|
||||
#### 💄 Styles
|
||||
|
||||
- **settings**: Broadcast locale changes and update switchLocale action.
|
||||
|
||||
<br/>
|
||||
|
||||
<details>
|
||||
<summary><kbd>Improvements and Fixes</kbd></summary>
|
||||
|
||||
#### Styles
|
||||
|
||||
- **settings**: Broadcast locale changes and update switchLocale action, closes [#9620](https://github.com/lobehub/lobe-chat/issues/9620) ([0eb02ca](https://github.com/lobehub/lobe-chat/commit/0eb02ca))
|
||||
|
||||
</details>
|
||||
|
||||
<div align="right">
|
||||
|
||||
[](#readme-top)
|
||||
|
||||
</div>
|
||||
|
||||
### [Version 1.141.1](https://github.com/lobehub/lobe-chat/compare/v1.141.0...v1.141.1)
|
||||
|
||||
<sup>Released on **2025-10-21**</sup>
|
||||
|
||||
#### ♻ Code Refactoring
|
||||
|
||||
- **misc**: Refactor context engine.
|
||||
|
||||
<br/>
|
||||
|
||||
<details>
|
||||
<summary><kbd>Improvements and Fixes</kbd></summary>
|
||||
|
||||
#### Code refactoring
|
||||
|
||||
- **misc**: Refactor context engine, closes [#9821](https://github.com/lobehub/lobe-chat/issues/9821) ([e99f12f](https://github.com/lobehub/lobe-chat/commit/e99f12f))
|
||||
|
||||
</details>
|
||||
|
||||
<div align="right">
|
||||
|
||||
[](#readme-top)
|
||||
|
||||
</div>
|
||||
|
||||
## [Version 1.141.0](https://github.com/lobehub/lobe-chat/compare/v1.140.0...v1.141.0)
|
||||
|
||||
<sup>Released on **2025-10-21**</sup>
|
||||
|
||||
#### ✨ Features
|
||||
|
||||
- **misc**: Add PDF export functionality to share modal.
|
||||
|
||||
#### 🐛 Bug Fixes
|
||||
|
||||
- **misc**: Ignore abort signal errors in TRPC client, slove when pwa user info have code cannot be viewed in full.
|
||||
|
||||
#### 💄 Styles
|
||||
|
||||
- **misc**: Add knowledge base mansory layout \[LOB-496], improve rich text link display.
|
||||
|
||||
<br/>
|
||||
|
||||
<details>
|
||||
<summary><kbd>Improvements and Fixes</kbd></summary>
|
||||
|
||||
#### What's improved
|
||||
|
||||
- **misc**: Add PDF export functionality to share modal, closes [#9300](https://github.com/lobehub/lobe-chat/issues/9300) [#9299](https://github.com/lobehub/lobe-chat/issues/9299) ([2b7761c](https://github.com/lobehub/lobe-chat/commit/2b7761c))
|
||||
|
||||
#### What's fixed
|
||||
|
||||
- **misc**: Ignore abort signal errors in TRPC client, closes [#9809](https://github.com/lobehub/lobe-chat/issues/9809) [#9401](https://github.com/lobehub/lobe-chat/issues/9401) ([7f7dcfb](https://github.com/lobehub/lobe-chat/commit/7f7dcfb))
|
||||
- **misc**: Slove when pwa user info have code cannot be viewed in full, closes [#9817](https://github.com/lobehub/lobe-chat/issues/9817) ([6734a47](https://github.com/lobehub/lobe-chat/commit/6734a47))
|
||||
|
||||
#### Styles
|
||||
|
||||
- **misc**: Add knowledge base mansory layout \[LOB-496], closes [#9722](https://github.com/lobehub/lobe-chat/issues/9722) ([69f21da](https://github.com/lobehub/lobe-chat/commit/69f21da))
|
||||
- **misc**: Improve rich text link display, closes [#9816](https://github.com/lobehub/lobe-chat/issues/9816) ([af33543](https://github.com/lobehub/lobe-chat/commit/af33543))
|
||||
|
||||
</details>
|
||||
|
||||
<div align="right">
|
||||
|
||||
[](#readme-top)
|
||||
|
||||
</div>
|
||||
|
||||
## [Version 1.140.0](https://github.com/lobehub/lobe-chat/compare/v1.139.5...v1.140.0)
|
||||
|
||||
<sup>Released on **2025-10-21**</sup>
|
||||
|
||||
#### ✨ Features
|
||||
|
||||
- **misc**: Add ComfyUI integration Phase1(RFC-128).
|
||||
|
||||
<br/>
|
||||
|
||||
<details>
|
||||
<summary><kbd>Improvements and Fixes</kbd></summary>
|
||||
|
||||
#### What's improved
|
||||
|
||||
- **misc**: Add ComfyUI integration Phase1(RFC-128), closes [#9043](https://github.com/lobehub/lobe-chat/issues/9043) ([15ffe28](https://github.com/lobehub/lobe-chat/commit/15ffe28))
|
||||
|
||||
</details>
|
||||
|
||||
<div align="right">
|
||||
|
||||
[](#readme-top)
|
||||
|
||||
</div>
|
||||
|
||||
### [Version 1.139.5](https://github.com/lobehub/lobe-chat/compare/v1.139.4...v1.139.5)
|
||||
|
||||
<sup>Released on **2025-10-21**</sup>
|
||||
|
||||
#### 🐛 Bug Fixes
|
||||
|
||||
- **desktop**: Fix desktop open error in some edge cases.
|
||||
|
||||
<br/>
|
||||
|
||||
<details>
|
||||
<summary><kbd>Improvements and Fixes</kbd></summary>
|
||||
|
||||
#### What's fixed
|
||||
|
||||
- **desktop**: Fix desktop open error in some edge cases, closes [#9813](https://github.com/lobehub/lobe-chat/issues/9813) ([6334f62](https://github.com/lobehub/lobe-chat/commit/6334f62))
|
||||
|
||||
</details>
|
||||
|
||||
<div align="right">
|
||||
|
||||
[](#readme-top)
|
||||
|
||||
</div>
|
||||
|
||||
### [Version 1.139.4](https://github.com/lobehub/lobe-chat/compare/v1.139.3...v1.139.4)
|
||||
|
||||
<sup>Released on **2025-10-21**</sup>
|
||||
|
||||
#### 🐛 Bug Fixes
|
||||
|
||||
- **misc**: Pass threadId to messages in sendMessageInServer.
|
||||
|
||||
<br/>
|
||||
|
||||
<details>
|
||||
<summary><kbd>Improvements and Fixes</kbd></summary>
|
||||
|
||||
#### What's fixed
|
||||
|
||||
- **misc**: Pass threadId to messages in sendMessageInServer, closes [#9808](https://github.com/lobehub/lobe-chat/issues/9808) ([d99a3a8](https://github.com/lobehub/lobe-chat/commit/d99a3a8))
|
||||
|
||||
</details>
|
||||
|
||||
<div align="right">
|
||||
|
||||
[](#readme-top)
|
||||
|
||||
</div>
|
||||
|
||||
### [Version 1.139.3](https://github.com/lobehub/lobe-chat/compare/v1.139.2...v1.139.3)
|
||||
|
||||
<sup>Released on **2025-10-21**</sup>
|
||||
|
||||
#### 💄 Styles
|
||||
|
||||
- **misc**: Show message author in minimap.
|
||||
|
||||
<br/>
|
||||
|
||||
<details>
|
||||
<summary><kbd>Improvements and Fixes</kbd></summary>
|
||||
|
||||
#### Styles
|
||||
|
||||
- **misc**: Show message author in minimap, closes [#9797](https://github.com/lobehub/lobe-chat/issues/9797) ([f6daefb](https://github.com/lobehub/lobe-chat/commit/f6daefb))
|
||||
|
||||
</details>
|
||||
|
||||
<div align="right">
|
||||
|
||||
[](#readme-top)
|
||||
|
||||
</div>
|
||||
|
||||
### [Version 1.139.2](https://github.com/lobehub/lobe-chat/compare/v1.139.1...v1.139.2)
|
||||
|
||||
<sup>Released on **2025-10-20**</sup>
|
||||
|
||||
#### 💄 Styles
|
||||
|
||||
- **misc**: Solve when desktop the sider agent list too long.
|
||||
|
||||
<br/>
|
||||
|
||||
<details>
|
||||
<summary><kbd>Improvements and Fixes</kbd></summary>
|
||||
|
||||
#### Styles
|
||||
|
||||
- **misc**: Solve when desktop the sider agent list too long, closes [#9792](https://github.com/lobehub/lobe-chat/issues/9792) ([778dea3](https://github.com/lobehub/lobe-chat/commit/778dea3))
|
||||
|
||||
</details>
|
||||
|
||||
<div align="right">
|
||||
|
||||
[](#readme-top)
|
||||
|
||||
</div>
|
||||
|
||||
### [Version 1.139.1](https://github.com/lobehub/lobe-chat/compare/v1.139.0...v1.139.1)
|
||||
|
||||
<sup>Released on **2025-10-20**</sup>
|
||||
|
||||
#### ♻ Code Refactoring
|
||||
|
||||
- **i18n**: Rm qa.
|
||||
|
||||
#### 💄 Styles
|
||||
|
||||
- **misc**: Update i18n.
|
||||
|
||||
<br/>
|
||||
|
||||
<details>
|
||||
<summary><kbd>Improvements and Fixes</kbd></summary>
|
||||
|
||||
#### Code refactoring
|
||||
|
||||
- **i18n**: Rm qa, closes [#9783](https://github.com/lobehub/lobe-chat/issues/9783) ([6d14dfe](https://github.com/lobehub/lobe-chat/commit/6d14dfe))
|
||||
|
||||
#### Styles
|
||||
|
||||
- **misc**: Update i18n, closes [#9787](https://github.com/lobehub/lobe-chat/issues/9787) ([b43d4b2](https://github.com/lobehub/lobe-chat/commit/b43d4b2))
|
||||
|
||||
</details>
|
||||
|
||||
<div align="right">
|
||||
|
||||
[](#readme-top)
|
||||
|
||||
</div>
|
||||
|
||||
## [Version 1.139.0](https://github.com/lobehub/lobe-chat/compare/v1.138.5...v1.139.0)
|
||||
|
||||
<sup>Released on **2025-10-19**</sup>
|
||||
|
||||
#### ✨ Features
|
||||
|
||||
- **misc**: Support image generation for siliconcloud.
|
||||
|
||||
<br/>
|
||||
|
||||
<details>
|
||||
<summary><kbd>Improvements and Fixes</kbd></summary>
|
||||
|
||||
#### What's improved
|
||||
|
||||
- **misc**: Support image generation for siliconcloud, closes [#9447](https://github.com/lobehub/lobe-chat/issues/9447) ([5ebcfa5](https://github.com/lobehub/lobe-chat/commit/5ebcfa5))
|
||||
|
||||
</details>
|
||||
|
||||
<div align="right">
|
||||
|
||||
[](#readme-top)
|
||||
|
||||
</div>
|
||||
|
||||
### [Version 1.138.5](https://github.com/lobehub/lobe-chat/compare/v1.138.4...v1.138.5)
|
||||
|
||||
<sup>Released on **2025-10-18**</sup>
|
||||
|
||||
#### ♻ Code Refactoring
|
||||
|
||||
- **misc**: Refactor upload router into lambda and decide to remove it in V2.
|
||||
|
||||
<br/>
|
||||
|
||||
<details>
|
||||
<summary><kbd>Improvements and Fixes</kbd></summary>
|
||||
|
||||
#### Code refactoring
|
||||
|
||||
- **misc**: Refactor upload router into lambda and decide to remove it in V2, closes [#9766](https://github.com/lobehub/lobe-chat/issues/9766) ([d1c7f41](https://github.com/lobehub/lobe-chat/commit/d1c7f41))
|
||||
|
||||
</details>
|
||||
|
||||
<div align="right">
|
||||
|
||||
[](#readme-top)
|
||||
|
||||
</div>
|
||||
|
||||
### [Version 1.138.4](https://github.com/lobehub/lobe-chat/compare/v1.138.3...v1.138.4)
|
||||
|
||||
<sup>Released on **2025-10-18**</sup>
|
||||
|
||||
#### 🐛 Bug Fixes
|
||||
|
||||
- **misc**: Fix response API tools calling issue.
|
||||
|
||||
<br/>
|
||||
|
||||
<details>
|
||||
<summary><kbd>Improvements and Fixes</kbd></summary>
|
||||
|
||||
#### What's fixed
|
||||
|
||||
- **misc**: Fix response API tools calling issue, closes [#9760](https://github.com/lobehub/lobe-chat/issues/9760) ([0596692](https://github.com/lobehub/lobe-chat/commit/0596692))
|
||||
|
||||
</details>
|
||||
|
||||
<div align="right">
|
||||
|
||||
[](#readme-top)
|
||||
|
||||
</div>
|
||||
|
||||
### [Version 1.138.3](https://github.com/lobehub/lobe-chat/compare/v1.138.2...v1.138.3)
|
||||
|
||||
<sup>Released on **2025-10-18**</sup>
|
||||
|
||||
#### 🐛 Bug Fixes
|
||||
|
||||
- **misc**: Fix topic fetch not correct in custom agent.
|
||||
|
||||
<br/>
|
||||
|
||||
<details>
|
||||
<summary><kbd>Improvements and Fixes</kbd></summary>
|
||||
|
||||
#### What's fixed
|
||||
|
||||
- **misc**: Fix topic fetch not correct in custom agent, closes [#9761](https://github.com/lobehub/lobe-chat/issues/9761) ([ceffce2](https://github.com/lobehub/lobe-chat/commit/ceffce2))
|
||||
|
||||
</details>
|
||||
|
||||
<div align="right">
|
||||
|
||||
[](#readme-top)
|
||||
|
||||
</div>
|
||||
|
||||
### [Version 1.138.2](https://github.com/lobehub/lobe-chat/compare/v1.138.1...v1.138.2)
|
||||
|
||||
<sup>Released on **2025-10-16**</sup>
|
||||
|
||||
#### 💄 Styles
|
||||
|
||||
- **misc**: Improve welcome message.
|
||||
|
||||
<br/>
|
||||
|
||||
<details>
|
||||
<summary><kbd>Improvements and Fixes</kbd></summary>
|
||||
|
||||
#### Styles
|
||||
|
||||
- **misc**: Improve welcome message, closes [#9747](https://github.com/lobehub/lobe-chat/issues/9747) ([c83fe13](https://github.com/lobehub/lobe-chat/commit/c83fe13))
|
||||
|
||||
</details>
|
||||
|
||||
<div align="right">
|
||||
|
||||
[](#readme-top)
|
||||
|
||||
</div>
|
||||
|
||||
### [Version 1.138.1](https://github.com/lobehub/lobe-chat/compare/v1.138.0...v1.138.1)
|
||||
|
||||
<sup>Released on **2025-10-16**</sup>
|
||||
|
||||
#### 🐛 Bug Fixes
|
||||
|
||||
- **misc**: Automatic topic creation switch does not work.
|
||||
|
||||
<br/>
|
||||
|
||||
<details>
|
||||
<summary><kbd>Improvements and Fixes</kbd></summary>
|
||||
|
||||
#### What's fixed
|
||||
|
||||
- **misc**: Automatic topic creation switch does not work, closes [#9693](https://github.com/lobehub/lobe-chat/issues/9693) ([a02b301](https://github.com/lobehub/lobe-chat/commit/a02b301))
|
||||
|
||||
</details>
|
||||
|
||||
<div align="right">
|
||||
|
||||
[](#readme-top)
|
||||
|
||||
</div>
|
||||
|
||||
## [Version 1.138.0](https://github.com/lobehub/lobe-chat/compare/v1.137.10...v1.138.0)
|
||||
|
||||
<sup>Released on **2025-10-16**</sup>
|
||||
|
||||
#### ✨ Features
|
||||
|
||||
- **misc**: Support Group Chat, Mention, and Multi-Agent Orchestration with feature flag.
|
||||
|
||||
<br/>
|
||||
|
||||
<details>
|
||||
<summary><kbd>Improvements and Fixes</kbd></summary>
|
||||
|
||||
#### What's improved
|
||||
|
||||
- **misc**: Support Group Chat, Mention, and Multi-Agent Orchestration with feature flag, closes [#8976](https://github.com/lobehub/lobe-chat/issues/8976) ([03c2838](https://github.com/lobehub/lobe-chat/commit/03c2838))
|
||||
|
||||
</details>
|
||||
|
||||
<div align="right">
|
||||
|
||||
[](#readme-top)
|
||||
|
||||
</div>
|
||||
|
||||
### [Version 1.137.10](https://github.com/lobehub/lobe-chat/compare/v1.137.9...v1.137.10)
|
||||
|
||||
<sup>Released on **2025-10-16**</sup>
|
||||
|
||||
#### 💄 Styles
|
||||
|
||||
- **misc**: Add Claude Haiku 4.5 model.
|
||||
|
||||
<br/>
|
||||
|
||||
<details>
|
||||
<summary><kbd>Improvements and Fixes</kbd></summary>
|
||||
|
||||
#### Styles
|
||||
|
||||
- **misc**: Add Claude Haiku 4.5 model, closes [#9735](https://github.com/lobehub/lobe-chat/issues/9735) ([1cfbc87](https://github.com/lobehub/lobe-chat/commit/1cfbc87))
|
||||
|
||||
</details>
|
||||
|
||||
<div align="right">
|
||||
|
||||
[](#readme-top)
|
||||
|
||||
</div>
|
||||
|
||||
### [Version 1.137.9](https://github.com/lobehub/lobe-chat/compare/v1.137.8...v1.137.9)
|
||||
|
||||
<sup>Released on **2025-10-15**</sup>
|
||||
|
||||
#### 💄 Styles
|
||||
|
||||
- **misc**: Improve update notification.
|
||||
|
||||
<br/>
|
||||
|
||||
<details>
|
||||
<summary><kbd>Improvements and Fixes</kbd></summary>
|
||||
|
||||
#### Styles
|
||||
|
||||
- **misc**: Improve update notification, closes [#9717](https://github.com/lobehub/lobe-chat/issues/9717) ([16de38a](https://github.com/lobehub/lobe-chat/commit/16de38a))
|
||||
|
||||
</details>
|
||||
|
||||
<div align="right">
|
||||
|
||||
[](#readme-top)
|
||||
|
||||
</div>
|
||||
|
||||
### [Version 1.137.8](https://github.com/lobehub/lobe-chat/compare/v1.137.7...v1.137.8)
|
||||
|
||||
<sup>Released on **2025-10-15**</sup>
|
||||
|
||||
#### 🐛 Bug Fixes
|
||||
|
||||
- **misc**: Fix duplicate tools id issue and fix link dialog issue.
|
||||
|
||||
#### 💄 Styles
|
||||
|
||||
- **misc**: Add region support for Vertex AI provider.
|
||||
|
||||
<br/>
|
||||
|
||||
<details>
|
||||
<summary><kbd>Improvements and Fixes</kbd></summary>
|
||||
|
||||
#### What's fixed
|
||||
|
||||
- **misc**: Fix duplicate tools id issue and fix link dialog issue, closes [#9731](https://github.com/lobehub/lobe-chat/issues/9731) ([0a8c80d](https://github.com/lobehub/lobe-chat/commit/0a8c80d))
|
||||
|
||||
#### Styles
|
||||
|
||||
- **misc**: Add region support for Vertex AI provider, closes [#9720](https://github.com/lobehub/lobe-chat/issues/9720) ([d17b50c](https://github.com/lobehub/lobe-chat/commit/d17b50c))
|
||||
|
||||
</details>
|
||||
|
||||
<div align="right">
|
||||
|
||||
[](#readme-top)
|
||||
|
||||
</div>
|
||||
|
||||
### [Version 1.137.7](https://github.com/lobehub/lobe-chat/compare/v1.137.6...v1.137.7)
|
||||
|
||||
<sup>Released on **2025-10-15**</sup>
|
||||
|
||||
#### 💄 Styles
|
||||
|
||||
- **misc**: Use different favicon.ico in dev mode.
|
||||
|
||||
<br/>
|
||||
|
||||
<details>
|
||||
<summary><kbd>Improvements and Fixes</kbd></summary>
|
||||
|
||||
#### Styles
|
||||
|
||||
- **misc**: Use different favicon.ico in dev mode, closes [#9723](https://github.com/lobehub/lobe-chat/issues/9723) ([2f7317b](https://github.com/lobehub/lobe-chat/commit/2f7317b))
|
||||
|
||||
</details>
|
||||
|
||||
<div align="right">
|
||||
|
||||
[](#readme-top)
|
||||
|
||||
</div>
|
||||
|
||||
### [Version 1.137.6](https://github.com/lobehub/lobe-chat/compare/v1.137.5...v1.137.6)
|
||||
|
||||
<sup>Released on **2025-10-14**</sup>
|
||||
|
||||
#### 🐛 Bug Fixes
|
||||
|
||||
- **misc**: Update Claude workflows to use oauth token, vertext ai create image.
|
||||
|
||||
<br/>
|
||||
|
||||
<details>
|
||||
<summary><kbd>Improvements and Fixes</kbd></summary>
|
||||
|
||||
#### What's fixed
|
||||
|
||||
- **misc**: Update Claude workflows to use oauth token, closes [#9711](https://github.com/lobehub/lobe-chat/issues/9711) ([8dcb00e](https://github.com/lobehub/lobe-chat/commit/8dcb00e))
|
||||
- **misc**: Vertext ai create image, closes [#9710](https://github.com/lobehub/lobe-chat/issues/9710) ([790d8fd](https://github.com/lobehub/lobe-chat/commit/790d8fd))
|
||||
|
||||
</details>
|
||||
|
||||
<div align="right">
|
||||
|
||||
[](#readme-top)
|
||||
|
||||
</div>
|
||||
|
||||
### [Version 1.137.5](https://github.com/lobehub/lobe-chat/compare/v1.137.4...v1.137.5)
|
||||
|
||||
<sup>Released on **2025-10-14**</sup>
|
||||
|
||||
@@ -165,6 +165,9 @@ ENV \
|
||||
CLOUDFLARE_API_KEY="" CLOUDFLARE_BASE_URL_OR_ACCOUNT_ID="" CLOUDFLARE_MODEL_LIST="" \
|
||||
# Cohere
|
||||
COHERE_API_KEY="" COHERE_MODEL_LIST="" COHERE_PROXY_URL="" \
|
||||
# ComfyUI
|
||||
COMFYUI_BASE_URL="" COMFYUI_AUTH_TYPE="" \
|
||||
COMFYUI_API_KEY="" COMFYUI_USERNAME="" COMFYUI_PASSWORD="" COMFYUI_CUSTOM_HEADERS="" \
|
||||
# DeepSeek
|
||||
DEEPSEEK_API_KEY="" DEEPSEEK_MODEL_LIST="" \
|
||||
# Fireworks AI
|
||||
|
||||
@@ -218,6 +218,9 @@ ENV \
|
||||
CLOUDFLARE_API_KEY="" CLOUDFLARE_BASE_URL_OR_ACCOUNT_ID="" CLOUDFLARE_MODEL_LIST="" \
|
||||
# Cohere
|
||||
COHERE_API_KEY="" COHERE_MODEL_LIST="" COHERE_PROXY_URL="" \
|
||||
# ComfyUI
|
||||
COMFYUI_BASE_URL="" COMFYUI_AUTH_TYPE="" \
|
||||
COMFYUI_API_KEY="" COMFYUI_USERNAME="" COMFYUI_PASSWORD="" COMFYUI_CUSTOM_HEADERS="" \
|
||||
# DeepSeek
|
||||
DEEPSEEK_API_KEY="" DEEPSEEK_MODEL_LIST="" \
|
||||
# Fireworks AI
|
||||
|
||||
@@ -167,6 +167,9 @@ ENV \
|
||||
CLOUDFLARE_API_KEY="" CLOUDFLARE_BASE_URL_OR_ACCOUNT_ID="" CLOUDFLARE_MODEL_LIST="" \
|
||||
# Cohere
|
||||
COHERE_API_KEY="" COHERE_MODEL_LIST="" COHERE_PROXY_URL="" \
|
||||
# ComfyUI
|
||||
COMFYUI_BASE_URL="" COMFYUI_AUTH_TYPE="" \
|
||||
COMFYUI_API_KEY="" COMFYUI_USERNAME="" COMFYUI_PASSWORD="" COMFYUI_CUSTOM_HEADERS="" \
|
||||
# DeepSeek
|
||||
DEEPSEEK_API_KEY="" DEEPSEEK_MODEL_LIST="" \
|
||||
# Fireworks AI
|
||||
|
||||
@@ -902,7 +902,7 @@ This project is [LobeHub Community License](./LICENSE) licensed.
|
||||
[github-release-shield]: https://img.shields.io/github/v/release/lobehub/lobe-chat?color=369eff&labelColor=black&logo=github&style=flat-square
|
||||
[github-releasedate-link]: https://github.com/lobehub/lobe-chat/releases
|
||||
[github-releasedate-shield]: https://img.shields.io/github/release-date/lobehub/lobe-chat?labelColor=black&style=flat-square
|
||||
[github-stars-link]: https://github.com/lobehub/lobe-chat/network/stargazers
|
||||
[github-stars-link]: https://github.com/lobehub/lobe-chat/stargazers
|
||||
[github-stars-shield]: https://img.shields.io/github/stars/lobehub/lobe-chat?color=ffcb47&labelColor=black&style=flat-square
|
||||
[github-trending-shield]: https://trendshift.io/api/badge/repositories/2256
|
||||
[github-trending-url]: https://trendshift.io/repositories/2256
|
||||
|
||||
+1
-1
@@ -923,7 +923,7 @@ This project is [LobeHub Community License](./LICENSE) licensed.
|
||||
[github-release-shield]: https://img.shields.io/github/v/release/lobehub/lobe-chat?color=369eff&labelColor=black&logo=github&style=flat-square
|
||||
[github-releasedate-link]: https://github.com/lobehub/lobe-chat/releases
|
||||
[github-releasedate-shield]: https://img.shields.io/github/release-date/lobehub/lobe-chat?labelColor=black&style=flat-square
|
||||
[github-stars-link]: https://github.com/lobehub/lobe-chat/network/stargazers
|
||||
[github-stars-link]: https://github.com/lobehub/lobe-chat/stargazers
|
||||
[github-stars-shield]: https://img.shields.io/github/stars/lobehub/lobe-chat?color=ffcb47&labelColor=black&style=flat-square
|
||||
[github-trending-shield]: https://trendshift.io/api/badge/repositories/2256
|
||||
[github-trending-url]: https://trendshift.io/repositories/2256
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
"@electron-toolkit/eslint-config-prettier": "^3.0.0",
|
||||
"@electron-toolkit/eslint-config-ts": "^3.0.0",
|
||||
"@electron-toolkit/preload": "^3.0.1",
|
||||
"@electron-toolkit/tsconfig": "^1.0.1",
|
||||
"@electron-toolkit/tsconfig": "^2.0.0",
|
||||
"@electron-toolkit/utils": "^4.0.0",
|
||||
"@lobechat/electron-client-ipc": "workspace:*",
|
||||
"@lobechat/electron-server-ipc": "workspace:*",
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
import { InterceptRouteParams } from '@lobechat/electron-client-ipc';
|
||||
import { InterceptRouteParams, OpenSettingsWindowOptions } from '@lobechat/electron-client-ipc';
|
||||
import { extractSubPath, findMatchingRoute } from '~common/routes';
|
||||
|
||||
import { AppBrowsersIdentifiers, BrowsersIdentifiers, WindowTemplateIdentifiers } from '@/appBrowsers';
|
||||
import {
|
||||
AppBrowsersIdentifiers,
|
||||
BrowsersIdentifiers,
|
||||
WindowTemplateIdentifiers,
|
||||
} from '@/appBrowsers';
|
||||
import { IpcClientEventSender } from '@/types/ipcClientEvent';
|
||||
|
||||
import { ControllerModule, ipcClientEvent, shortcut } from './index';
|
||||
@@ -14,11 +18,16 @@ export default class BrowserWindowsCtr extends ControllerModule {
|
||||
}
|
||||
|
||||
@ipcClientEvent('openSettingsWindow')
|
||||
async openSettingsWindow(tab?: string) {
|
||||
console.log('[BrowserWindowsCtr] Received request to open settings window', tab);
|
||||
async openSettingsWindow(options?: string | OpenSettingsWindowOptions) {
|
||||
const normalizedOptions: OpenSettingsWindowOptions =
|
||||
typeof options === 'string' || options === undefined
|
||||
? { tab: typeof options === 'string' ? options : undefined }
|
||||
: options;
|
||||
|
||||
console.log('[BrowserWindowsCtr] Received request to open settings window', normalizedOptions);
|
||||
|
||||
try {
|
||||
await this.app.browserManager.showSettingsWindowWithTab(tab);
|
||||
await this.app.browserManager.showSettingsWindowWithTab(normalizedOptions);
|
||||
|
||||
return { success: true };
|
||||
} catch (error) {
|
||||
@@ -68,15 +77,37 @@ export default class BrowserWindowsCtr extends ControllerModule {
|
||||
|
||||
try {
|
||||
if (matchedRoute.targetWindow === BrowsersIdentifiers.settings) {
|
||||
const subPath = extractSubPath(path, matchedRoute.pathPrefix);
|
||||
const extractedSubPath = extractSubPath(path, matchedRoute.pathPrefix);
|
||||
const sanitizedSubPath =
|
||||
extractedSubPath && !extractedSubPath.startsWith('?') ? extractedSubPath : undefined;
|
||||
let searchParams: Record<string, string> | undefined;
|
||||
try {
|
||||
const url = new URL(params.url);
|
||||
const entries = Array.from(url.searchParams.entries());
|
||||
if (entries.length > 0) {
|
||||
searchParams = entries.reduce<Record<string, string>>((acc, [key, value]) => {
|
||||
acc[key] = value;
|
||||
return acc;
|
||||
}, {});
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn(
|
||||
'[BrowserWindowsCtr] Failed to parse URL for settings route interception:',
|
||||
params.url,
|
||||
error,
|
||||
);
|
||||
}
|
||||
|
||||
await this.app.browserManager.showSettingsWindowWithTab(subPath);
|
||||
await this.app.browserManager.showSettingsWindowWithTab({
|
||||
searchParams,
|
||||
tab: sanitizedSubPath,
|
||||
});
|
||||
|
||||
return {
|
||||
intercepted: true,
|
||||
path,
|
||||
source,
|
||||
subPath,
|
||||
subPath: sanitizedSubPath,
|
||||
targetWindow: matchedRoute.targetWindow,
|
||||
};
|
||||
} else {
|
||||
@@ -105,8 +136,8 @@ export default class BrowserWindowsCtr extends ControllerModule {
|
||||
*/
|
||||
@ipcClientEvent('createMultiInstanceWindow')
|
||||
async createMultiInstanceWindow(params: {
|
||||
templateId: WindowTemplateIdentifiers;
|
||||
path: string;
|
||||
templateId: WindowTemplateIdentifiers;
|
||||
uniqueId?: string;
|
||||
}) {
|
||||
try {
|
||||
|
||||
@@ -77,6 +77,7 @@ export default class SystemController extends ControllerModule {
|
||||
|
||||
// 更新i18n实例的语言
|
||||
await this.app.i18n.changeLanguage(locale === 'auto' ? app.getLocale() : locale);
|
||||
this.app.browserManager.broadcastToAllWindows('localeChanged', { locale });
|
||||
|
||||
return { success: true };
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ describe('BrowserWindowsCtr', () => {
|
||||
it('should show the settings window with the specified tab', async () => {
|
||||
const tab = 'appearance';
|
||||
const result = await browserWindowsCtr.openSettingsWindow(tab);
|
||||
expect(mockShowSettingsWindowWithTab).toHaveBeenCalledWith(tab);
|
||||
expect(mockShowSettingsWindowWithTab).toHaveBeenCalledWith({ tab });
|
||||
expect(result).toEqual({ success: true });
|
||||
});
|
||||
|
||||
@@ -120,11 +120,11 @@ describe('BrowserWindowsCtr', () => {
|
||||
it('should show settings window if matched route target is settings', async () => {
|
||||
const params: InterceptRouteParams = {
|
||||
...baseParams,
|
||||
path: '/settings?active=common',
|
||||
url: 'app://host/settings?active=common',
|
||||
path: '/settings/provider',
|
||||
url: 'app://host/settings/provider?active=provider&provider=ollama',
|
||||
};
|
||||
const matchedRoute = { targetWindow: BrowsersIdentifiers.settings, pathPrefix: '/settings' };
|
||||
const subPath = 'common';
|
||||
const subPath = 'provider';
|
||||
(findMatchingRoute as Mock).mockReturnValue(matchedRoute);
|
||||
(extractSubPath as Mock).mockReturnValue(subPath);
|
||||
|
||||
@@ -132,7 +132,10 @@ describe('BrowserWindowsCtr', () => {
|
||||
|
||||
expect(findMatchingRoute).toHaveBeenCalledWith(params.path);
|
||||
expect(extractSubPath).toHaveBeenCalledWith(params.path, matchedRoute.pathPrefix);
|
||||
expect(mockShowSettingsWindowWithTab).toHaveBeenCalledWith(subPath);
|
||||
expect(mockShowSettingsWindowWithTab).toHaveBeenCalledWith({
|
||||
searchParams: { active: 'provider', provider: 'ollama' },
|
||||
tab: subPath,
|
||||
});
|
||||
expect(result).toEqual({
|
||||
intercepted: true,
|
||||
path: params.path,
|
||||
@@ -170,11 +173,11 @@ describe('BrowserWindowsCtr', () => {
|
||||
it('should return error if processing route interception fails for settings', async () => {
|
||||
const params: InterceptRouteParams = {
|
||||
...baseParams,
|
||||
path: '/settings?active=general',
|
||||
path: '/settings',
|
||||
url: 'app://host/settings?active=general',
|
||||
};
|
||||
const matchedRoute = { targetWindow: BrowsersIdentifiers.settings, pathPrefix: '/settings' };
|
||||
const subPath = 'general';
|
||||
const subPath = undefined;
|
||||
const errorMessage = 'Processing error for settings';
|
||||
(findMatchingRoute as Mock).mockReturnValue(matchedRoute);
|
||||
(extractSubPath as Mock).mockReturnValue(subPath);
|
||||
@@ -182,6 +185,10 @@ describe('BrowserWindowsCtr', () => {
|
||||
|
||||
const result = await browserWindowsCtr.interceptRoute(params);
|
||||
|
||||
expect(mockShowSettingsWindowWithTab).toHaveBeenCalledWith({
|
||||
searchParams: { active: 'general' },
|
||||
tab: subPath,
|
||||
});
|
||||
expect(result).toEqual({
|
||||
error: errorMessage,
|
||||
intercepted: false,
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { ElectronIPCEventHandler, ElectronIPCServer } from '@lobechat/electron-server-ipc';
|
||||
import { Session, app, ipcMain, protocol } from 'electron';
|
||||
import { macOS, windows } from 'electron-is';
|
||||
import { pathExistsSync, remove } from 'fs-extra';
|
||||
import os from 'node:os';
|
||||
import { join } from 'node:path';
|
||||
|
||||
import { name } from '@/../../package.json';
|
||||
import { buildDir, nextStandaloneDir } from '@/const/dir';
|
||||
import { buildDir, LOCAL_DATABASE_DIR, nextStandaloneDir } from '@/const/dir';
|
||||
import { isDev } from '@/const/env';
|
||||
import { IControlModule } from '@/controllers';
|
||||
import { IServiceModule } from '@/services';
|
||||
@@ -129,6 +130,9 @@ export class App {
|
||||
|
||||
this.initDevBranding();
|
||||
|
||||
// Clean up stale database lock file before starting IPC server
|
||||
await this.cleanupDatabaseLock();
|
||||
|
||||
// ==============
|
||||
await this.ipcServer.start();
|
||||
logger.debug('IPC server started');
|
||||
@@ -371,6 +375,27 @@ export class App {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Clean up stale database lock file from previous crashes or abnormal exits
|
||||
*/
|
||||
private cleanupDatabaseLock = async () => {
|
||||
try {
|
||||
const dbPath = join(this.appStoragePath, LOCAL_DATABASE_DIR);
|
||||
const lockPath = `${dbPath}.lock`;
|
||||
|
||||
if (pathExistsSync(lockPath)) {
|
||||
logger.info(`Cleaning up stale database lock file: ${lockPath}`);
|
||||
await remove(lockPath);
|
||||
logger.info('Database lock file removed successfully');
|
||||
} else {
|
||||
logger.debug('No database lock file found, skipping cleanup');
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error('Failed to cleanup database lock file:', error);
|
||||
// Non-fatal error, allow application to continue
|
||||
}
|
||||
};
|
||||
|
||||
private registerNextHandler() {
|
||||
logger.debug('Registering Next.js handler');
|
||||
const handler = createHandler({
|
||||
|
||||
@@ -0,0 +1,282 @@
|
||||
import { app } from 'electron';
|
||||
import { pathExistsSync, remove } from 'fs-extra';
|
||||
import { join } from 'node:path';
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
import { LOCAL_DATABASE_DIR } from '@/const/dir';
|
||||
|
||||
// Mock electron modules
|
||||
vi.mock('electron', () => ({
|
||||
app: {
|
||||
getAppPath: vi.fn(() => '/mock/app/path'),
|
||||
getLocale: vi.fn(() => 'en-US'),
|
||||
getPath: vi.fn(() => '/mock/user/path'),
|
||||
requestSingleInstanceLock: vi.fn(() => true),
|
||||
whenReady: vi.fn(() => Promise.resolve()),
|
||||
on: vi.fn(),
|
||||
commandLine: {
|
||||
appendSwitch: vi.fn(),
|
||||
},
|
||||
dock: {
|
||||
setIcon: vi.fn(),
|
||||
},
|
||||
exit: vi.fn(),
|
||||
},
|
||||
ipcMain: {
|
||||
handle: vi.fn(),
|
||||
},
|
||||
nativeTheme: {
|
||||
on: vi.fn(),
|
||||
shouldUseDarkColors: false,
|
||||
},
|
||||
protocol: {
|
||||
registerSchemesAsPrivileged: vi.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
// Mock logger
|
||||
vi.mock('@/utils/logger', () => ({
|
||||
createLogger: () => ({
|
||||
debug: vi.fn(),
|
||||
info: vi.fn(),
|
||||
warn: vi.fn(),
|
||||
error: vi.fn(),
|
||||
}),
|
||||
}));
|
||||
|
||||
// Mock fs-extra module
|
||||
vi.mock('fs-extra', async () => {
|
||||
const actual = await vi.importActual('fs-extra');
|
||||
return {
|
||||
...actual,
|
||||
pathExistsSync: vi.fn(),
|
||||
remove: vi.fn(),
|
||||
};
|
||||
});
|
||||
|
||||
// Mock common/routes
|
||||
vi.mock('~common/routes', () => ({
|
||||
findMatchingRoute: vi.fn(),
|
||||
extractSubPath: vi.fn(),
|
||||
}));
|
||||
|
||||
// Mock other dependencies
|
||||
vi.mock('electron-is', () => ({
|
||||
macOS: vi.fn(() => false),
|
||||
windows: vi.fn(() => false),
|
||||
}));
|
||||
|
||||
vi.mock('fix-path', () => ({
|
||||
default: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('@/const/env', () => ({
|
||||
isDev: false,
|
||||
}));
|
||||
|
||||
vi.mock('@/const/dir', () => ({
|
||||
buildDir: '/mock/build',
|
||||
nextStandaloneDir: '/mock/standalone',
|
||||
LOCAL_DATABASE_DIR: 'lobehub-local-db',
|
||||
appStorageDir: '/mock/storage/path',
|
||||
userDataDir: '/mock/user/data',
|
||||
DB_SCHEMA_HASH_FILENAME: 'lobehub-local-db-schema-hash',
|
||||
FILE_STORAGE_DIR: 'file-storage',
|
||||
INSTALL_PLUGINS_DIR: 'plugins',
|
||||
LOCAL_STORAGE_URL_PREFIX: '/lobe-desktop-file',
|
||||
}));
|
||||
|
||||
vi.mock('@lobechat/electron-server-ipc', () => ({
|
||||
ElectronIPCServer: vi.fn().mockImplementation(() => ({
|
||||
start: vi.fn().mockResolvedValue(undefined),
|
||||
})),
|
||||
}));
|
||||
|
||||
// Mock all infrastructure managers
|
||||
vi.mock('../infrastructure/I18nManager', () => ({
|
||||
I18nManager: vi.fn().mockImplementation(() => ({
|
||||
init: vi.fn().mockResolvedValue(undefined),
|
||||
})),
|
||||
}));
|
||||
|
||||
vi.mock('../infrastructure/StoreManager', () => ({
|
||||
StoreManager: vi.fn().mockImplementation(() => ({
|
||||
get: vi.fn((key) => {
|
||||
if (key === 'storagePath') return '/mock/storage/path';
|
||||
return undefined;
|
||||
}),
|
||||
set: vi.fn(),
|
||||
})),
|
||||
}));
|
||||
|
||||
vi.mock('../infrastructure/StaticFileServerManager', () => ({
|
||||
StaticFileServerManager: vi.fn().mockImplementation(() => ({
|
||||
initialize: vi.fn().mockResolvedValue(undefined),
|
||||
destroy: vi.fn(),
|
||||
})),
|
||||
}));
|
||||
|
||||
vi.mock('../infrastructure/UpdaterManager', () => ({
|
||||
UpdaterManager: vi.fn().mockImplementation(() => ({
|
||||
initialize: vi.fn().mockResolvedValue(undefined),
|
||||
})),
|
||||
}));
|
||||
|
||||
vi.mock('../infrastructure/ProtocolManager', () => ({
|
||||
ProtocolManager: vi.fn().mockImplementation(() => ({
|
||||
initialize: vi.fn(),
|
||||
processPendingUrls: vi.fn().mockResolvedValue(undefined),
|
||||
})),
|
||||
}));
|
||||
|
||||
vi.mock('../browser/BrowserManager', () => ({
|
||||
BrowserManager: vi.fn().mockImplementation(() => ({
|
||||
initializeBrowsers: vi.fn(),
|
||||
getIdentifierByWebContents: vi.fn(),
|
||||
})),
|
||||
}));
|
||||
|
||||
vi.mock('../ui/MenuManager', () => ({
|
||||
MenuManager: vi.fn().mockImplementation(() => ({
|
||||
initialize: vi.fn(),
|
||||
})),
|
||||
}));
|
||||
|
||||
vi.mock('../ui/ShortcutManager', () => ({
|
||||
ShortcutManager: vi.fn().mockImplementation(() => ({
|
||||
initialize: vi.fn(),
|
||||
})),
|
||||
}));
|
||||
|
||||
vi.mock('../ui/TrayManager', () => ({
|
||||
TrayManager: vi.fn().mockImplementation(() => ({
|
||||
initializeTrays: vi.fn(),
|
||||
destroyAll: vi.fn(),
|
||||
})),
|
||||
}));
|
||||
|
||||
vi.mock('@/utils/next-electron-rsc', () => ({
|
||||
createHandler: vi.fn(() => ({
|
||||
createInterceptor: vi.fn(),
|
||||
registerCustomHandler: vi.fn(),
|
||||
})),
|
||||
}));
|
||||
|
||||
// Mock controllers and services
|
||||
vi.mock('../../controllers/*Ctr.ts', () => ({}));
|
||||
vi.mock('../../services/*Srv.ts', () => ({}));
|
||||
|
||||
// Import after mocks are set up
|
||||
import { App } from '../App';
|
||||
|
||||
describe('App - Database Lock Cleanup', () => {
|
||||
let appInstance: App;
|
||||
let mockLockPath: string;
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
|
||||
// Mock glob imports to return empty arrays
|
||||
(import.meta as any).glob = vi.fn(() => ({}));
|
||||
|
||||
mockLockPath = join('/mock/storage/path', LOCAL_DATABASE_DIR) + '.lock';
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('bootstrap - database lock cleanup', () => {
|
||||
it('should remove stale lock file if it exists during bootstrap', async () => {
|
||||
// Setup: simulate existing lock file
|
||||
vi.mocked(pathExistsSync).mockReturnValue(true);
|
||||
vi.mocked(remove).mockResolvedValue(undefined);
|
||||
|
||||
// Create app instance
|
||||
appInstance = new App();
|
||||
|
||||
// Call bootstrap which should trigger cleanup
|
||||
await appInstance.bootstrap();
|
||||
|
||||
// Verify: lock file check was called
|
||||
expect(pathExistsSync).toHaveBeenCalledWith(mockLockPath);
|
||||
|
||||
// Verify: lock file was removed
|
||||
expect(remove).toHaveBeenCalledWith(mockLockPath);
|
||||
});
|
||||
|
||||
it('should not attempt to remove lock file if it does not exist', async () => {
|
||||
// Setup: no lock file exists
|
||||
vi.mocked(pathExistsSync).mockReturnValue(false);
|
||||
|
||||
// Create app instance
|
||||
appInstance = new App();
|
||||
|
||||
// Call bootstrap
|
||||
await appInstance.bootstrap();
|
||||
|
||||
// Verify: lock file check was called
|
||||
expect(pathExistsSync).toHaveBeenCalledWith(mockLockPath);
|
||||
|
||||
// Verify: remove was NOT called since file doesn't exist
|
||||
expect(remove).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should continue bootstrap even if lock cleanup fails', async () => {
|
||||
// Setup: simulate lock file exists but cleanup fails
|
||||
vi.mocked(pathExistsSync).mockReturnValue(true);
|
||||
vi.mocked(remove).mockRejectedValue(new Error('Permission denied'));
|
||||
|
||||
// Create app instance
|
||||
appInstance = new App();
|
||||
|
||||
// Bootstrap should not throw even if cleanup fails
|
||||
await expect(appInstance.bootstrap()).resolves.not.toThrow();
|
||||
|
||||
// Verify: cleanup was attempted
|
||||
expect(pathExistsSync).toHaveBeenCalledWith(mockLockPath);
|
||||
expect(remove).toHaveBeenCalledWith(mockLockPath);
|
||||
});
|
||||
|
||||
it('should clean up lock file before starting IPC server', async () => {
|
||||
// Setup
|
||||
vi.mocked(pathExistsSync).mockReturnValue(true);
|
||||
const callOrder: string[] = [];
|
||||
|
||||
vi.mocked(remove).mockImplementation(async () => {
|
||||
callOrder.push('remove');
|
||||
});
|
||||
|
||||
// Mock IPC server start to track call order
|
||||
const { ElectronIPCServer } = await import('@lobechat/electron-server-ipc');
|
||||
const mockStart = vi.fn().mockImplementation(() => {
|
||||
callOrder.push('ipcServer.start');
|
||||
return Promise.resolve();
|
||||
});
|
||||
|
||||
vi.mocked(ElectronIPCServer).mockImplementation(
|
||||
() =>
|
||||
({
|
||||
start: mockStart,
|
||||
}) as any,
|
||||
);
|
||||
|
||||
// Create app instance and bootstrap
|
||||
appInstance = new App();
|
||||
await appInstance.bootstrap();
|
||||
|
||||
// Verify: cleanup happens before IPC server starts
|
||||
expect(callOrder).toEqual(['remove', 'ipcServer.start']);
|
||||
});
|
||||
});
|
||||
|
||||
describe('appStoragePath', () => {
|
||||
it('should return storage path from store manager', () => {
|
||||
appInstance = new App();
|
||||
|
||||
const storagePath = appInstance.appStoragePath;
|
||||
|
||||
expect(storagePath).toBe('/mock/storage/path');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,9 +1,18 @@
|
||||
import { MainBroadcastEventKey, MainBroadcastParams } from '@lobechat/electron-client-ipc';
|
||||
import {
|
||||
MainBroadcastEventKey,
|
||||
MainBroadcastParams,
|
||||
OpenSettingsWindowOptions,
|
||||
} from '@lobechat/electron-client-ipc';
|
||||
import { WebContents } from 'electron';
|
||||
|
||||
import { createLogger } from '@/utils/logger';
|
||||
|
||||
import { AppBrowsersIdentifiers, appBrowsers, WindowTemplate, WindowTemplateIdentifiers, windowTemplates } from '../../appBrowsers';
|
||||
import {
|
||||
AppBrowsersIdentifiers,
|
||||
WindowTemplateIdentifiers,
|
||||
appBrowsers,
|
||||
windowTemplates,
|
||||
} from '../../appBrowsers';
|
||||
import type { App } from '../App';
|
||||
import type { BrowserWindowOpts } from './Browser';
|
||||
import Browser from './Browser';
|
||||
@@ -63,14 +72,35 @@ export class BrowserManager {
|
||||
* Display the settings window and navigate to a specific tab
|
||||
* @param tab Settings window sub-path tab
|
||||
*/
|
||||
async showSettingsWindowWithTab(tab?: string) {
|
||||
logger.debug(`Showing settings window with tab: ${tab || 'default'}`);
|
||||
// common is the main path for settings route
|
||||
if (tab && tab !== 'common') {
|
||||
const browser = await this.redirectToPage('settings', tab);
|
||||
async showSettingsWindowWithTab(options?: OpenSettingsWindowOptions) {
|
||||
const tab = options?.tab;
|
||||
const searchParams = options?.searchParams;
|
||||
|
||||
const query = new URLSearchParams();
|
||||
if (searchParams) {
|
||||
Object.entries(searchParams).forEach(([key, value]) => {
|
||||
if (value !== undefined) query.set(key, value);
|
||||
});
|
||||
}
|
||||
|
||||
if (tab && tab !== 'common' && !query.has('active')) {
|
||||
query.set('active', tab);
|
||||
}
|
||||
|
||||
const queryString = query.toString();
|
||||
const activeTab = query.get('active') ?? tab;
|
||||
|
||||
logger.debug(
|
||||
`Showing settings window with navigation: active=${activeTab || 'default'}, query=${
|
||||
queryString || 'none'
|
||||
}`,
|
||||
);
|
||||
|
||||
if (queryString) {
|
||||
const browser = await this.redirectToPage('settings', undefined, queryString);
|
||||
|
||||
// make provider page more large
|
||||
if (tab.startsWith('provider/')) {
|
||||
if (activeTab?.startsWith('provider')) {
|
||||
logger.debug('Resizing window for provider settings');
|
||||
browser.setWindowSize({ height: 1000, width: 1400 });
|
||||
browser.moveToCenter();
|
||||
@@ -87,7 +117,7 @@ export class BrowserManager {
|
||||
* @param identifier Window identifier
|
||||
* @param subPath Sub-path, such as 'agent', 'about', etc.
|
||||
*/
|
||||
async redirectToPage(identifier: string, subPath?: string) {
|
||||
async redirectToPage(identifier: string, subPath?: string, search?: string) {
|
||||
try {
|
||||
// Ensure window is retrieved or created
|
||||
const browser = this.retrieveByIdentifier(identifier);
|
||||
@@ -105,11 +135,14 @@ export class BrowserManager {
|
||||
|
||||
// Build complete URL path
|
||||
const fullPath = subPath ? `${baseRoute}/${subPath}` : baseRoute;
|
||||
const normalizedSearch =
|
||||
search && search.length > 0 ? (search.startsWith('?') ? search : `?${search}`) : '';
|
||||
const fullUrl = `${fullPath}${normalizedSearch}`;
|
||||
|
||||
logger.debug(`Redirecting to: ${fullPath}`);
|
||||
logger.debug(`Redirecting to: ${fullUrl}`);
|
||||
|
||||
// Load URL and show window
|
||||
await browser.loadUrl(fullPath);
|
||||
await browser.loadUrl(fullUrl);
|
||||
browser.show();
|
||||
|
||||
return browser;
|
||||
@@ -143,14 +176,20 @@ export class BrowserManager {
|
||||
* @param uniqueId Optional unique identifier, will be generated if not provided
|
||||
* @returns The window identifier and Browser instance
|
||||
*/
|
||||
createMultiInstanceWindow(templateId: WindowTemplateIdentifiers, path: string, uniqueId?: string) {
|
||||
createMultiInstanceWindow(
|
||||
templateId: WindowTemplateIdentifiers,
|
||||
path: string,
|
||||
uniqueId?: string,
|
||||
) {
|
||||
const template = windowTemplates[templateId];
|
||||
if (!template) {
|
||||
throw new Error(`Window template ${templateId} not found`);
|
||||
}
|
||||
|
||||
// Generate unique identifier
|
||||
const windowId = uniqueId || `${template.baseIdentifier}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
||||
const windowId =
|
||||
uniqueId ||
|
||||
`${template.baseIdentifier}_${Date.now()}_${Math.random().toString(36).slice(2, 11)}`;
|
||||
|
||||
// Create browser options from template
|
||||
const browserOpts: BrowserWindowOpts = {
|
||||
@@ -164,8 +203,8 @@ export class BrowserManager {
|
||||
const browser = this.retrieveOrInitialize(browserOpts);
|
||||
|
||||
return {
|
||||
identifier: windowId,
|
||||
browser: browser,
|
||||
identifier: windowId,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -176,7 +215,7 @@ export class BrowserManager {
|
||||
*/
|
||||
getWindowsByTemplate(templateId: string): string[] {
|
||||
const prefix = `${templateId}_`;
|
||||
return Array.from(this.browsers.keys()).filter(id => id.startsWith(prefix));
|
||||
return Array.from(this.browsers.keys()).filter((id) => id.startsWith(prefix));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -185,7 +224,7 @@ export class BrowserManager {
|
||||
*/
|
||||
closeWindowsByTemplate(templateId: string): void {
|
||||
const windowIds = this.getWindowsByTemplate(templateId);
|
||||
windowIds.forEach(id => {
|
||||
windowIds.forEach((id) => {
|
||||
const browser = this.browsers.get(id);
|
||||
if (browser) {
|
||||
browser.close();
|
||||
@@ -235,8 +274,7 @@ export class BrowserManager {
|
||||
});
|
||||
|
||||
browser.browserWindow.on('show', () => {
|
||||
if (browser.webContents)
|
||||
this.webContentsMap.set(browser.webContents, browser.identifier);
|
||||
if (browser.webContents) this.webContentsMap.set(browser.webContents, browser.identifier);
|
||||
});
|
||||
|
||||
return browser;
|
||||
|
||||
@@ -1,4 +1,187 @@
|
||||
[
|
||||
{
|
||||
"children": {
|
||||
"improvements": ["Allow removal of top_p and similar request parameters."]
|
||||
},
|
||||
"date": "2025-10-23",
|
||||
"version": "1.141.7"
|
||||
},
|
||||
{
|
||||
"children": {},
|
||||
"date": "2025-10-22",
|
||||
"version": "1.141.6"
|
||||
},
|
||||
{
|
||||
"children": {
|
||||
"improvements": ["Change discover page from RSC to SPA to improve performance."]
|
||||
},
|
||||
"date": "2025-10-22",
|
||||
"version": "1.141.5"
|
||||
},
|
||||
{
|
||||
"children": {
|
||||
"improvements": ["Fix model runtime cost calculate with CNY."]
|
||||
},
|
||||
"date": "2025-10-22",
|
||||
"version": "1.141.4"
|
||||
},
|
||||
{
|
||||
"children": {
|
||||
"improvements": ["Update i18n."]
|
||||
},
|
||||
"date": "2025-10-22",
|
||||
"version": "1.141.3"
|
||||
},
|
||||
{
|
||||
"children": {},
|
||||
"date": "2025-10-21",
|
||||
"version": "1.141.2"
|
||||
},
|
||||
{
|
||||
"children": {
|
||||
"improvements": ["Refactor context engine."]
|
||||
},
|
||||
"date": "2025-10-21",
|
||||
"version": "1.141.1"
|
||||
},
|
||||
{
|
||||
"children": {
|
||||
"features": ["Add PDF export functionality to share modal."],
|
||||
"fixes": [
|
||||
"Ignore abort signal errors in TRPC client, slove when pwa user info have code cannot be viewed in full."
|
||||
],
|
||||
"improvements": [
|
||||
"Add knowledge base mansory layout [LOB-496], improve rich text link display."
|
||||
]
|
||||
},
|
||||
"date": "2025-10-21",
|
||||
"version": "1.141.0"
|
||||
},
|
||||
{
|
||||
"children": {
|
||||
"features": ["Add ComfyUI integration Phase1(RFC-128)."]
|
||||
},
|
||||
"date": "2025-10-21",
|
||||
"version": "1.140.0"
|
||||
},
|
||||
{
|
||||
"children": {},
|
||||
"date": "2025-10-21",
|
||||
"version": "1.139.5"
|
||||
},
|
||||
{
|
||||
"children": {
|
||||
"fixes": ["Pass threadId to messages in sendMessageInServer."]
|
||||
},
|
||||
"date": "2025-10-21",
|
||||
"version": "1.139.4"
|
||||
},
|
||||
{
|
||||
"children": {
|
||||
"improvements": ["Show message author in minimap."]
|
||||
},
|
||||
"date": "2025-10-21",
|
||||
"version": "1.139.3"
|
||||
},
|
||||
{
|
||||
"children": {
|
||||
"improvements": ["Solve when desktop the sider agent list too long."]
|
||||
},
|
||||
"date": "2025-10-20",
|
||||
"version": "1.139.2"
|
||||
},
|
||||
{
|
||||
"children": {
|
||||
"improvements": ["Update i18n."]
|
||||
},
|
||||
"date": "2025-10-20",
|
||||
"version": "1.139.1"
|
||||
},
|
||||
{
|
||||
"children": {
|
||||
"features": ["Support image generation for siliconcloud."]
|
||||
},
|
||||
"date": "2025-10-19",
|
||||
"version": "1.139.0"
|
||||
},
|
||||
{
|
||||
"children": {
|
||||
"improvements": ["Refactor upload router into lambda and decide to remove it in V2."]
|
||||
},
|
||||
"date": "2025-10-18",
|
||||
"version": "1.138.5"
|
||||
},
|
||||
{
|
||||
"children": {
|
||||
"fixes": ["Fix response API tools calling issue."]
|
||||
},
|
||||
"date": "2025-10-18",
|
||||
"version": "1.138.4"
|
||||
},
|
||||
{
|
||||
"children": {
|
||||
"fixes": ["Fix topic fetch not correct in custom agent."]
|
||||
},
|
||||
"date": "2025-10-18",
|
||||
"version": "1.138.3"
|
||||
},
|
||||
{
|
||||
"children": {
|
||||
"improvements": ["Improve welcome message."]
|
||||
},
|
||||
"date": "2025-10-16",
|
||||
"version": "1.138.2"
|
||||
},
|
||||
{
|
||||
"children": {
|
||||
"fixes": ["Automatic topic creation switch does not work."]
|
||||
},
|
||||
"date": "2025-10-16",
|
||||
"version": "1.138.1"
|
||||
},
|
||||
{
|
||||
"children": {
|
||||
"features": ["Support Group Chat, Mention, and Multi-Agent Orchestration with feature flag."]
|
||||
},
|
||||
"date": "2025-10-16",
|
||||
"version": "1.138.0"
|
||||
},
|
||||
{
|
||||
"children": {
|
||||
"improvements": ["Add Claude Haiku 4.5 model."]
|
||||
},
|
||||
"date": "2025-10-16",
|
||||
"version": "1.137.10"
|
||||
},
|
||||
{
|
||||
"children": {
|
||||
"improvements": ["Improve update notification."]
|
||||
},
|
||||
"date": "2025-10-15",
|
||||
"version": "1.137.9"
|
||||
},
|
||||
{
|
||||
"children": {
|
||||
"fixes": ["Fix duplicate tools id issue and fix link dialog issue."],
|
||||
"improvements": ["Add region support for Vertex AI provider."]
|
||||
},
|
||||
"date": "2025-10-15",
|
||||
"version": "1.137.8"
|
||||
},
|
||||
{
|
||||
"children": {
|
||||
"improvements": ["Use different favicon.ico in dev mode."]
|
||||
},
|
||||
"date": "2025-10-15",
|
||||
"version": "1.137.7"
|
||||
},
|
||||
{
|
||||
"children": {
|
||||
"fixes": ["Update Claude workflows to use oauth token, vertext ai create image."]
|
||||
},
|
||||
"date": "2025-10-14",
|
||||
"version": "1.137.6"
|
||||
},
|
||||
{
|
||||
"children": {
|
||||
"improvements": ["Add imagen model to vertex ai."]
|
||||
|
||||
@@ -230,7 +230,7 @@ services:
|
||||
otel-tracing-test:
|
||||
profiles:
|
||||
- otel-test
|
||||
image: ghcr.io/grafana/xk6-client-tracing:v0.0.7
|
||||
image: ghcr.io/grafana/xk6-client-tracing:v0.0.9
|
||||
container_name: lobe-otel-tracing-test
|
||||
network_mode: 'service:network-service'
|
||||
restart: always
|
||||
|
||||
@@ -151,7 +151,7 @@ services:
|
||||
otel-tracing-test:
|
||||
profiles:
|
||||
- otel-test
|
||||
image: ghcr.io/grafana/xk6-client-tracing:v0.0.7
|
||||
image: ghcr.io/grafana/xk6-client-tracing:v0.0.9
|
||||
container_name: lobe-otel-tracing-test
|
||||
network_mode: 'service:network-service'
|
||||
restart: always
|
||||
|
||||
@@ -149,7 +149,7 @@ services:
|
||||
otel-tracing-test:
|
||||
profiles:
|
||||
- otel-test
|
||||
image: ghcr.io/grafana/xk6-client-tracing:v0.0.7
|
||||
image: ghcr.io/grafana/xk6-client-tracing:v0.0.9
|
||||
container_name: lobe-otel-tracing-test
|
||||
network_mode: 'service:network-service'
|
||||
restart: always
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,998 @@
|
||||
---
|
||||
title: ComfyUI 扩展开发指南
|
||||
description: 学习如何为 LobeChat ComfyUI 集成添加新模型、工作流和功能扩展
|
||||
tags:
|
||||
- ComfyUI
|
||||
- 开发指南
|
||||
- 模型扩展
|
||||
- 工作流开发
|
||||
---
|
||||
|
||||
# ComfyUI 扩展开发指南
|
||||
|
||||
本指南基于实际代码实现,帮助开发者扩展 LobeChat 的 ComfyUI 集成功能。
|
||||
|
||||
## 架构概览
|
||||
|
||||
LobeChat ComfyUI 集成采用四层服务架构,围绕 `LobeComfyUI` 主类构建:
|
||||
|
||||
```plaintext
|
||||
packages/model-runtime/src/providers/comfyui/
|
||||
├── index.ts # LobeComfyUI 主类入口
|
||||
├── services/ # 四大核心服务
|
||||
│ ├── comfyuiClient.ts # ComfyUIClientService - 客户端和认证
|
||||
│ ├── modelResolver.ts # ModelResolverService - 模型解析
|
||||
│ ├── workflowBuilder.ts # WorkflowBuilderService - 工作流构建
|
||||
│ └── imageService.ts # ImageService - 图像生成
|
||||
├── config/ # 配置系统
|
||||
│ ├── modelRegistry.ts # 主模型注册表(222个模型)
|
||||
│ ├── fluxModelRegistry.ts # 130个FLUX模型配置
|
||||
│ ├── sdModelRegistry.ts # 92个SD系列模型配置
|
||||
│ ├── systemComponents.ts # VAE/CLIP/T5/LoRA/ControlNet组件
|
||||
│ └── workflowRegistry.ts # 工作流路由配置
|
||||
├── workflows/ # 工作流实现
|
||||
│ ├── flux-dev.ts # FLUX Dev 20步工作流
|
||||
│ ├── flux-schnell.ts # FLUX Schnell 4步快速工作流
|
||||
│ ├── flux-kontext.ts # FLUX Kontext 填充工作流
|
||||
│ ├── sd35.ts # SD3.5 外部编码器工作流
|
||||
│ ├── simple-sd.ts # 通用SD工作流
|
||||
│ └── index.ts # 工作流导出
|
||||
├── utils/ # 工具层
|
||||
│ ├── staticModelLookup.ts # 模型查找函数
|
||||
│ ├── workflowDetector.ts # 模型架构检测
|
||||
│ ├── promptSplitter.ts # FLUX双提示词分割
|
||||
│ ├── seedGenerator.ts # 随机种子生成
|
||||
│ ├── cacheManager.ts # TTL缓存管理
|
||||
│ └── workflowUtils.ts # 工作流工具函数
|
||||
└── errors/ # 错误处理
|
||||
├── base.ts # 基础错误类
|
||||
├── modelResolverError.ts # 模型解析错误
|
||||
├── workflowError.ts # 工作流错误
|
||||
└── servicesError.ts # 服务错误
|
||||
|
||||
src/server/services/comfyui/ # 服务端实现
|
||||
├── core/ # 核心服务器服务
|
||||
│ ├── comfyUIAuthService.ts # 认证服务
|
||||
│ ├── comfyUIClientService.ts # 客户端服务
|
||||
│ ├── comfyUIConnectionService.ts # 连接服务
|
||||
│ ├── errorHandlerService.ts # 错误处理服务
|
||||
│ ├── imageService.ts # 图像生成服务
|
||||
│ ├── modelResolverService.ts # 模型解析服务
|
||||
│ └── workflowBuilderService.ts # 工作流构建服务
|
||||
├── config/ # 服务器端配置
|
||||
│ ├── constants.ts # 常量和默认值
|
||||
│ ├── modelRegistry.ts # 模型注册表
|
||||
│ ├── fluxModelRegistry.ts # FLUX模型
|
||||
│ ├── sdModelRegistry.ts # SD模型
|
||||
│ ├── systemComponents.ts # 系统组件
|
||||
│ └── workflowRegistry.ts # 工作流注册表
|
||||
├── workflows/ # 服务端工作流实现
|
||||
│ ├── flux-dev.ts # FLUX Dev 工作流
|
||||
│ ├── flux-schnell.ts # FLUX Schnell 工作流
|
||||
│ ├── flux-kontext.ts # FLUX Kontext 工作流
|
||||
│ ├── sd35.ts # SD3.5 工作流
|
||||
│ └── simple-sd.ts # Simple SD 工作流
|
||||
├── utils/ # 服务器工具
|
||||
│ ├── cacheManager.ts # 缓存管理
|
||||
│ ├── componentInfo.ts # 组件信息
|
||||
│ ├── imageResizer.ts # 图像调整
|
||||
│ ├── promptSplitter.ts # 提示词分割
|
||||
│ ├── staticModelLookup.ts # 模型查找
|
||||
│ ├── weightDType.ts # 权重数据类型工具
|
||||
│ ├── workflowDetector.ts # 工作流检测
|
||||
│ └── workflowUtils.ts # 工作流工具
|
||||
└── errors/ # 服务器错误处理
|
||||
├── base.ts # 基础错误类
|
||||
├── configError.ts # 配置错误
|
||||
├── modelResolverError.ts # 模型解析器错误
|
||||
├── servicesError.ts # 服务错误
|
||||
├── utilsError.ts # 工具错误
|
||||
└── workflowError.ts # 工作流错误
|
||||
|
||||
packages/model-runtime/src/utils/ # 共享工具
|
||||
└── comfyuiErrorParser.ts # 客户端/服务器统一错误解析器
|
||||
```
|
||||
|
||||
### 核心服务架构
|
||||
|
||||
`LobeComfyUI` 主类初始化四个核心服务:
|
||||
|
||||
```typescript
|
||||
// packages/model-runtime/src/providers/comfyui/index.ts
|
||||
export class LobeComfyUI implements LobeRuntimeAI, AuthenticatedImageRuntime {
|
||||
constructor(options: ComfyUIKeyVault = {}) {
|
||||
// 1. 客户端服务 - 处理认证和API调用
|
||||
this.clientService = new ComfyUIClientService(options);
|
||||
|
||||
// 2. 模型解析服务 - 模型查找和组件选择
|
||||
const modelResolverService = new ModelResolverService(this.clientService);
|
||||
|
||||
// 3. 工作流构建服务 - 路由和构建工作流
|
||||
const workflowBuilderService = new WorkflowBuilderService({
|
||||
clientService: this.clientService,
|
||||
modelResolverService: modelResolverService,
|
||||
});
|
||||
|
||||
// 4. 图像服务 - 统一的图像生成入口
|
||||
this.imageService = new ImageService(
|
||||
this.clientService,
|
||||
modelResolverService,
|
||||
workflowBuilderService,
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 认证系统
|
||||
|
||||
ComfyUI 集成支持四种认证方式,由 `ComfyUIClientService` 内的 `AuthManager` 处理:
|
||||
|
||||
### 支持的认证类型
|
||||
|
||||
```typescript
|
||||
interface ComfyUIKeyVault {
|
||||
baseURL: string;
|
||||
authType?: 'none' | 'basic' | 'bearer' | 'custom';
|
||||
// Basic Auth
|
||||
username?: string;
|
||||
password?: string;
|
||||
// Bearer Token
|
||||
apiKey?: string;
|
||||
// Custom Headers
|
||||
customHeaders?: Record<string, string>;
|
||||
}
|
||||
```
|
||||
|
||||
### 认证配置示例
|
||||
|
||||
```typescript
|
||||
// 无认证
|
||||
const comfyUI = new LobeComfyUI({
|
||||
baseURL: 'http://localhost:8000',
|
||||
authType: 'none'
|
||||
});
|
||||
|
||||
// 基础认证
|
||||
const comfyUI = new LobeComfyUI({
|
||||
baseURL: 'https://your-comfyui-server.com',
|
||||
authType: 'basic',
|
||||
username: 'your-username',
|
||||
password: 'your-password'
|
||||
});
|
||||
|
||||
// Bearer Token
|
||||
const comfyUI = new LobeComfyUI({
|
||||
baseURL: 'https://your-comfyui-server.com',
|
||||
authType: 'bearer',
|
||||
apiKey: 'your-api-key'
|
||||
});
|
||||
|
||||
// 自定义头部
|
||||
const comfyUI = new LobeComfyUI({
|
||||
baseURL: 'https://your-comfyui-server.com',
|
||||
authType: 'custom',
|
||||
customHeaders: {
|
||||
'X-API-Key': 'your-custom-key',
|
||||
'Authorization': 'Custom your-token'
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## WebAPI 路由
|
||||
|
||||
ComfyUI 提供了用于图像生成的 REST WebAPI 路由,支持常规认证和内部服务认证:
|
||||
|
||||
### 路由详情
|
||||
|
||||
```typescript
|
||||
// src/app/(backend)/webapi/create-image/comfyui/route.ts
|
||||
export const runtime = 'nodejs';
|
||||
export const maxDuration = 300; // 最长5分钟
|
||||
|
||||
// POST /api/create-image/comfyui
|
||||
{
|
||||
model: string; // 模型标识符
|
||||
params: { // 生成参数
|
||||
prompt: string;
|
||||
width?: number;
|
||||
height?: number;
|
||||
// ... 其他参数
|
||||
};
|
||||
options?: { // 可选生成选项
|
||||
// ... 额外选项
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### 认证中间件
|
||||
|
||||
WebAPI 路由使用 `checkAuth` 中间件进行认证:
|
||||
|
||||
```typescript
|
||||
import { checkAuth } from '@/app/(backend)/middleware/auth';
|
||||
|
||||
// 路由自动验证 JWT 令牌
|
||||
// 并将认证上下文传递给 tRPC 调用器
|
||||
```
|
||||
|
||||
### 错误处理
|
||||
|
||||
WebAPI 路由提供结构化的错误响应:
|
||||
|
||||
```typescript
|
||||
// 从 TRPCError 的 cause 中提取 AgentRuntimeError
|
||||
if (agentError && 'errorType' in agentError) {
|
||||
// 将 errorType 转换为适当的 HTTP 状态码
|
||||
// 401 对应 InvalidProviderAPIKey
|
||||
// 403 对应 PermissionDenied
|
||||
// 404 对应 NotFound
|
||||
// 500+ 对应服务器错误
|
||||
}
|
||||
```
|
||||
|
||||
## 添加新模型
|
||||
|
||||
### 1. 理解模型注册表结构
|
||||
|
||||
模型配置存储在配置文件中:
|
||||
|
||||
```typescript
|
||||
// packages/model-runtime/src/providers/comfyui/config/modelRegistry.ts
|
||||
export interface ModelConfig {
|
||||
modelFamily: 'FLUX' | 'SD1' | 'SDXL' | 'SD3';
|
||||
priority: number; // 1=官方, 2=企业, 3=社区
|
||||
recommendedDtype?: 'default' | 'fp8_e4m3fn' | 'fp8_e5m2';
|
||||
variant: string; // 模型变体标识符
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 添加 FLUX 模型
|
||||
|
||||
在 `fluxModelRegistry.ts` 中添加新模型:
|
||||
|
||||
```typescript
|
||||
// packages/model-runtime/src/providers/comfyui/config/fluxModelRegistry.ts
|
||||
export const FLUX_MODEL_REGISTRY: Record<string, ModelConfig> = {
|
||||
// 现有模型...
|
||||
|
||||
// 添加新的FLUX Dev模型
|
||||
'your-custom-flux-dev.safetensors': {
|
||||
modelFamily: 'FLUX',
|
||||
priority: 2, // 企业级模型
|
||||
variant: 'dev',
|
||||
recommendedDtype: 'default',
|
||||
},
|
||||
|
||||
// 添加量化版本
|
||||
'your-custom-flux-dev-fp8.safetensors': {
|
||||
modelFamily: 'FLUX',
|
||||
priority: 2,
|
||||
variant: 'dev',
|
||||
recommendedDtype: 'fp8_e4m3fn',
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
### 3. 添加 SD 系列模型
|
||||
|
||||
在 `sdModelRegistry.ts` 中添加:
|
||||
|
||||
```typescript
|
||||
// packages/model-runtime/src/providers/comfyui/config/sdModelRegistry.ts
|
||||
export const SD_MODEL_REGISTRY: Record<string, ModelConfig> = {
|
||||
// 现有模型...
|
||||
|
||||
// 添加新的SD3.5模型
|
||||
'your-custom-sd35.safetensors': {
|
||||
modelFamily: 'SD3',
|
||||
priority: 2,
|
||||
variant: 'sd35',
|
||||
recommendedDtype: 'default',
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
### 4. 更新模型 ID 映射(可选)
|
||||
|
||||
如果需要为前端提供友好的模型 ID,在 `modelRegistry.ts` 中添加映射:
|
||||
|
||||
```typescript
|
||||
// packages/model-runtime/src/providers/comfyui/config/modelRegistry.ts
|
||||
export const MODEL_ID_VARIANT_MAP: Record<string, string> = {
|
||||
// 现有映射...
|
||||
|
||||
// 添加新模型的友好ID
|
||||
'my-custom-flux': 'dev', // 映射到dev变体
|
||||
'my-custom-sd35': 'sd35', // 映射到sd35变体
|
||||
};
|
||||
```
|
||||
|
||||
## 创建新工作流
|
||||
|
||||
### 工作流创建原理
|
||||
|
||||
**重要:工作流节点结构来自 ComfyUI 原生导出**
|
||||
|
||||
1. 在 ComfyUI 界面中设计工作流
|
||||
2. 使用 "Export (API Format)" 导出 JSON
|
||||
3. 将 JSON 结构复制到 TypeScript 文件
|
||||
4. 使用`PromptBuilder`包装并参数化
|
||||
|
||||
### 1. 从 ComfyUI 导出工作流
|
||||
|
||||
在 ComfyUI 界面中:
|
||||
|
||||
1. 拖拽节点构建所需工作流
|
||||
2. 连接各节点的输入输出
|
||||
3. 右键点击空白处 → "Export (API Format)"
|
||||
4. 复制生成的 JSON 结构
|
||||
|
||||
### 2. 工作流文件模板
|
||||
|
||||
创建新文件 `workflows/your-workflow.ts`:
|
||||
|
||||
```typescript
|
||||
import { PromptBuilder } from '@saintno/comfyui-sdk';
|
||||
|
||||
import type { WorkflowContext } from '../services/workflowBuilder';
|
||||
import { generateUniqueSeeds } from '../utils/seedGenerator';
|
||||
import { getWorkflowFilenamePrefix } from '../utils/workflowUtils';
|
||||
|
||||
/**
|
||||
* 构建自定义工作流
|
||||
* @param modelFileName - 模型文件名
|
||||
* @param params - 生成参数
|
||||
* @param context - 工作流上下文
|
||||
*/
|
||||
export async function buildYourCustomWorkflow(
|
||||
modelFileName: string,
|
||||
params: Record<string, any>,
|
||||
context: WorkflowContext,
|
||||
): Promise<PromptBuilder<any, any, any>> {
|
||||
|
||||
// 从ComfyUI "Export (API Format)" 获得的JSON结构
|
||||
const workflow = {
|
||||
'1': {
|
||||
_meta: { title: 'Load Checkpoint' },
|
||||
class_type: 'CheckpointLoaderSimple',
|
||||
inputs: {
|
||||
ckpt_name: modelFileName,
|
||||
},
|
||||
},
|
||||
'2': {
|
||||
_meta: { title: 'CLIP Text Encode' },
|
||||
class_type: 'CLIPTextEncode',
|
||||
inputs: {
|
||||
clip: ['1', 1], // 连接到节点1的CLIP输出
|
||||
text: params.prompt,
|
||||
},
|
||||
},
|
||||
'3': {
|
||||
_meta: { title: 'Empty Latent' },
|
||||
class_type: 'EmptyLatentImage',
|
||||
inputs: {
|
||||
width: params.width,
|
||||
height: params.height,
|
||||
batch_size: 1,
|
||||
},
|
||||
},
|
||||
'4': {
|
||||
_meta: { title: 'KSampler' },
|
||||
class_type: 'KSampler',
|
||||
inputs: {
|
||||
model: ['1', 0], // 连接到节点1的MODEL输出
|
||||
positive: ['2', 0], // 连接到节点2的CONDITIONING输出
|
||||
negative: ['2', 0], // 可以配置负面提示词
|
||||
latent_image: ['3', 0],
|
||||
seed: params.seed ?? generateUniqueSeeds(1)[0],
|
||||
steps: params.steps,
|
||||
cfg: params.cfg,
|
||||
sampler_name: 'euler',
|
||||
scheduler: 'normal',
|
||||
denoise: 1.0,
|
||||
},
|
||||
},
|
||||
'5': {
|
||||
_meta: { title: 'VAE Decode' },
|
||||
class_type: 'VAEDecode',
|
||||
inputs: {
|
||||
samples: ['4', 0],
|
||||
vae: ['1', 2], // 连接到节点1的VAE输出
|
||||
},
|
||||
},
|
||||
'6': {
|
||||
_meta: { title: 'Save Image' },
|
||||
class_type: 'SaveImage',
|
||||
inputs: {
|
||||
filename_prefix: getWorkflowFilenamePrefix('buildYourCustomWorkflow', context.variant),
|
||||
images: ['5', 0],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
// 使用PromptBuilder包装静态JSON
|
||||
const builder = new PromptBuilder(
|
||||
workflow,
|
||||
['width', 'height', 'steps', 'cfg', 'seed'], // 输入参数
|
||||
['images'], // 输出参数
|
||||
);
|
||||
|
||||
// 设置输出节点
|
||||
builder.setOutputNode('images', '6');
|
||||
|
||||
// 设置输入节点路径
|
||||
builder.setInputNode('width', '3.inputs.width');
|
||||
builder.setInputNode('height', '3.inputs.height');
|
||||
builder.setInputNode('steps', '4.inputs.steps');
|
||||
builder.setInputNode('cfg', '4.inputs.cfg');
|
||||
builder.setInputNode('seed', '4.inputs.seed');
|
||||
|
||||
// 设置参数值
|
||||
builder
|
||||
.input('width', params.width)
|
||||
.input('height', params.height)
|
||||
.input('steps', params.steps)
|
||||
.input('cfg', params.cfg)
|
||||
.input('seed', params.seed ?? generateUniqueSeeds(1)[0]);
|
||||
|
||||
return builder;
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 注册新工作流
|
||||
|
||||
在 `workflowRegistry.ts` 中添加工作流映射:
|
||||
|
||||
```typescript
|
||||
// packages/model-runtime/src/providers/comfyui/config/workflowRegistry.ts
|
||||
import { buildYourCustomWorkflow } from '../workflows/your-workflow';
|
||||
|
||||
export const VARIANT_WORKFLOW_MAP: Record<string, WorkflowBuilder> = {
|
||||
// 现有映射...
|
||||
|
||||
// 添加新工作流
|
||||
'your-variant': buildYourCustomWorkflow,
|
||||
};
|
||||
```
|
||||
|
||||
### 4. 实际工作流示例
|
||||
|
||||
参考 `flux-dev.ts` 的真实实现:
|
||||
|
||||
```typescript
|
||||
// packages/model-runtime/src/providers/comfyui/workflows/flux-dev.ts (简化版)
|
||||
export async function buildFluxDevWorkflow(
|
||||
modelFileName: string,
|
||||
params: Record<string, any>,
|
||||
context: WorkflowContext,
|
||||
): Promise<PromptBuilder<any, any, any>> {
|
||||
// 获取所需组件
|
||||
const selectedT5Model = await context.modelResolverService.getOptimalComponent('t5', 'FLUX');
|
||||
const selectedVAE = await context.modelResolverService.getOptimalComponent('vae', 'FLUX');
|
||||
const selectedCLIP = await context.modelResolverService.getOptimalComponent('clip', 'FLUX');
|
||||
|
||||
// 处理双提示词分割
|
||||
const { t5xxlPrompt, clipLPrompt } = splitPromptForDualCLIP(params.prompt);
|
||||
|
||||
// 静态工作流定义(来自ComfyUI导出)
|
||||
const workflow = {
|
||||
'1': {
|
||||
class_type: 'DualCLIPLoader',
|
||||
inputs: {
|
||||
clip_name1: selectedT5Model,
|
||||
clip_name2: selectedCLIP,
|
||||
type: 'flux',
|
||||
},
|
||||
},
|
||||
// ... 更多节点
|
||||
};
|
||||
|
||||
// 参数注入(必须在workflow文件内完成)
|
||||
workflow['5'].inputs.clip_l = clipLPrompt;
|
||||
workflow['5'].inputs.t5xxl = t5xxlPrompt;
|
||||
workflow['4'].inputs.width = params.width;
|
||||
workflow['4'].inputs.height = params.height;
|
||||
|
||||
// 创建并配置PromptBuilder
|
||||
const builder = new PromptBuilder(workflow, inputs, outputs);
|
||||
// 配置输入输出映射...
|
||||
|
||||
return builder;
|
||||
}
|
||||
```
|
||||
|
||||
## 系统组件管理
|
||||
|
||||
### 组件配置结构
|
||||
|
||||
所有系统组件(VAE、CLIP、T5、LoRA、ControlNet)统一配置在 `systemComponents.ts`:
|
||||
|
||||
```typescript
|
||||
// packages/model-runtime/src/providers/comfyui/config/systemComponents.ts
|
||||
export interface ComponentConfig {
|
||||
modelFamily: string; // 模型家族
|
||||
priority: number; // 1=必需, 2=标准, 3=可选
|
||||
type: string; // 组件类型
|
||||
compatibleVariants?: string[]; // 兼容变体(LoRA/ControlNet)
|
||||
controlnetType?: string; // ControlNet类型
|
||||
}
|
||||
|
||||
export const SYSTEM_COMPONENTS: Record<string, ComponentConfig> = {
|
||||
// VAE组件
|
||||
'ae.safetensors': {
|
||||
modelFamily: 'FLUX',
|
||||
priority: 1,
|
||||
type: 'vae',
|
||||
},
|
||||
|
||||
// CLIP组件
|
||||
'clip_l.safetensors': {
|
||||
modelFamily: 'FLUX',
|
||||
priority: 1,
|
||||
type: 'clip',
|
||||
},
|
||||
|
||||
// T5编码器
|
||||
't5xxl_fp16.safetensors': {
|
||||
modelFamily: 'FLUX',
|
||||
priority: 1,
|
||||
type: 't5',
|
||||
},
|
||||
|
||||
// LoRA适配器
|
||||
'realism_lora.safetensors': {
|
||||
compatibleVariants: ['dev'],
|
||||
modelFamily: 'FLUX',
|
||||
priority: 1,
|
||||
type: 'lora',
|
||||
},
|
||||
|
||||
// ControlNet模型
|
||||
'flux-controlnet-canny-v3.safetensors': {
|
||||
compatibleVariants: ['dev'],
|
||||
controlnetType: 'canny',
|
||||
modelFamily: 'FLUX',
|
||||
priority: 1,
|
||||
type: 'controlnet',
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
### 添加新组件
|
||||
|
||||
```typescript
|
||||
// 添加新的LoRA
|
||||
'your-custom-lora.safetensors': {
|
||||
compatibleVariants: ['dev', 'schnell'],
|
||||
modelFamily: 'FLUX',
|
||||
priority: 2,
|
||||
type: 'lora',
|
||||
},
|
||||
|
||||
// 添加新的ControlNet
|
||||
'your-controlnet-pose.safetensors': {
|
||||
compatibleVariants: ['dev'],
|
||||
controlnetType: 'pose',
|
||||
modelFamily: 'FLUX',
|
||||
priority: 2,
|
||||
type: 'controlnet',
|
||||
},
|
||||
```
|
||||
|
||||
### 组件查询 API
|
||||
|
||||
```typescript
|
||||
import { getAllComponentsWithNames, getOptimalComponent } from '../config/systemComponents';
|
||||
|
||||
// 获取最优组件
|
||||
const bestVAE = getOptimalComponent('vae', 'FLUX');
|
||||
const bestT5 = getOptimalComponent('t5', 'FLUX');
|
||||
|
||||
// 查询特定类型的组件
|
||||
const availableLoras = getAllComponentsWithNames({
|
||||
type: 'lora',
|
||||
modelFamily: 'FLUX',
|
||||
compatibleVariant: 'dev'
|
||||
});
|
||||
|
||||
// 查询ControlNet
|
||||
const cannyControlNets = getAllComponentsWithNames({
|
||||
type: 'controlnet',
|
||||
controlnetType: 'canny',
|
||||
modelFamily: 'FLUX'
|
||||
});
|
||||
```
|
||||
|
||||
## 模型解析和查找
|
||||
|
||||
### ModelResolverService 工作原理
|
||||
|
||||
```typescript
|
||||
// packages/model-runtime/src/providers/comfyui/services/modelResolver.ts
|
||||
export class ModelResolverService {
|
||||
async resolveModelFileName(modelId: string): Promise<string | undefined> {
|
||||
// 1. 清理模型ID
|
||||
const cleanId = modelId.replace(/^comfyui\//, '');
|
||||
|
||||
// 2. 检查模型ID映射
|
||||
const mappedVariant = MODEL_ID_VARIANT_MAP[cleanId];
|
||||
if (mappedVariant) {
|
||||
const prioritizedModels = getModelsByVariant(mappedVariant);
|
||||
const serverModels = await this.getAvailableModelFiles();
|
||||
|
||||
// 按优先级查找第一个可用模型
|
||||
for (const filename of prioritizedModels) {
|
||||
if (serverModels.includes(filename)) {
|
||||
return filename;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 直接注册表查找
|
||||
if (MODEL_REGISTRY[cleanId]) {
|
||||
return cleanId;
|
||||
}
|
||||
|
||||
// 4. 检查服务器文件存在性
|
||||
if (isModelFile(cleanId)) {
|
||||
const serverModels = await this.getAvailableModelFiles();
|
||||
if (serverModels.includes(cleanId)) {
|
||||
return cleanId;
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 模型查找示例
|
||||
|
||||
```typescript
|
||||
// 实际使用示例
|
||||
const resolver = new ModelResolverService(clientService);
|
||||
|
||||
// 友好ID查找
|
||||
const fluxDevFile = await resolver.resolveModelFileName('flux-dev');
|
||||
// 返回: 'flux1-dev.safetensors' (如果存在)
|
||||
|
||||
// 直接文件名查找
|
||||
const directFile = await resolver.resolveModelFileName('my-custom-model.safetensors');
|
||||
// 返回: 'my-custom-model.safetensors' (如果存在)
|
||||
|
||||
// 变体查找
|
||||
const devModels = getModelsByVariant('dev');
|
||||
console.log(devModels.slice(0, 3));
|
||||
// 输出: ['flux1-dev.safetensors', 'flux1-dev-fp8.safetensors', ...]
|
||||
```
|
||||
|
||||
## 错误处理
|
||||
|
||||
### 错误类型层次
|
||||
|
||||
```plaintext
|
||||
// packages/model-runtime/src/providers/comfyui/errors/
|
||||
ComfyUIInternalError // 基础错误
|
||||
├── ModelResolverError // 模型解析错误
|
||||
├── WorkflowError // 工作流错误
|
||||
├── ServicesError // 服务错误
|
||||
└── UtilsError // 工具错误
|
||||
```
|
||||
|
||||
### 错误处理示例
|
||||
|
||||
```typescript
|
||||
import { ModelResolverError, WorkflowError } from '../errors';
|
||||
|
||||
try {
|
||||
const result = await comfyUI.createImage({
|
||||
model: 'nonexistent-model',
|
||||
params: { prompt: '测试' }
|
||||
});
|
||||
} catch (error) {
|
||||
if (error instanceof ModelResolverError) {
|
||||
console.log('模型解析失败:', error.message);
|
||||
console.log('错误原因:', error.reason);
|
||||
console.log('错误详情:', error.details);
|
||||
} else if (error instanceof WorkflowError) {
|
||||
console.log('工作流错误:', error.message);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 统一错误解析器
|
||||
|
||||
客户端和服务器端错误处理可使用共享的错误解析器:
|
||||
|
||||
```typescript
|
||||
// packages/model-runtime/src/utils/comfyuiErrorParser.ts
|
||||
import { parseComfyUIErrorMessage, cleanComfyUIErrorMessage } from '../utils/comfyuiErrorParser';
|
||||
|
||||
// 解析错误消息并确定错误类型
|
||||
const { error, errorType } = parseComfyUIErrorMessage(rawError);
|
||||
|
||||
// 清理 ComfyUI 格式的错误消息
|
||||
const cleanMessage = cleanComfyUIErrorMessage(errorMessage);
|
||||
```
|
||||
|
||||
错误解析器处理:
|
||||
|
||||
- HTTP 状态码映射到错误类型
|
||||
- 服务器端错误增强
|
||||
- 模型文件缺失检测
|
||||
- 网络错误识别
|
||||
- 工作流验证错误
|
||||
|
||||
## 测试架构与开发
|
||||
|
||||
### 测试架构概述
|
||||
|
||||
ComfyUI 集成使用了统一的测试架构,确保测试的可维护性和定制友好性。该架构包括:
|
||||
|
||||
- **统一 Mock 系统**:集中管理所有外部依赖的模拟
|
||||
- **参数化测试**:自动适应新模型,无需修改现有测试
|
||||
- **夹具系统**:从配置文件中获取测试数据,确保准确性
|
||||
- **覆盖率目标**:ComfyUI 模块维持 97%+ 覆盖率
|
||||
|
||||
### 测试文件结构
|
||||
|
||||
```plaintext
|
||||
packages/model-runtime/src/providers/comfyui/__tests__/
|
||||
├── setup/
|
||||
│ └── unifiedMocks.ts # 统一Mock配置
|
||||
├── fixtures/
|
||||
│ ├── parameters.fixture.ts # 参数测试夹具
|
||||
│ └── workflow.fixture.ts # 工作流测试夹具
|
||||
├── integration/
|
||||
│ ├── parameterMapping.test.ts # 参数映射集成测试
|
||||
│ └── workflowBuilder.test.ts # 工作流构建测试
|
||||
├── services/ # 各服务单元测试
|
||||
└── workflows/ # 工作流单元测试
|
||||
```
|
||||
|
||||
### 添加新模型测试
|
||||
|
||||
当添加新模型时,测试会自动识别并运行相应的参数映射测试。你只需要:
|
||||
|
||||
#### 1. 在模型配置中添加参数架构
|
||||
|
||||
```typescript
|
||||
// packages/model-bank/src/aiModels/comfyui.ts
|
||||
export const myNewModelParamsSchema = {
|
||||
prompt: { type: 'string', required: true },
|
||||
steps: { type: 'number', default: 20, min: 1, max: 150 },
|
||||
cfg: { type: 'number', default: 7.0, min: 1.0, max: 30.0 }
|
||||
};
|
||||
```
|
||||
|
||||
#### 2. 创建工作流构建器
|
||||
|
||||
```typescript
|
||||
// packages/model-runtime/src/providers/comfyui/workflows/myNewModel.ts
|
||||
export async function buildMyNewModelWorkflow(
|
||||
modelName: string,
|
||||
params: MyNewModelParams,
|
||||
context: ComfyUIContext
|
||||
) {
|
||||
const workflow = { /* 工作流定义 */ };
|
||||
|
||||
// 参数注入
|
||||
workflow['1'].inputs.prompt = params.prompt;
|
||||
workflow['2'].inputs.steps = params.steps;
|
||||
|
||||
return workflow;
|
||||
}
|
||||
```
|
||||
|
||||
#### 3. 在夹具中注册模型
|
||||
|
||||
```typescript
|
||||
// packages/model-runtime/src/providers/comfyui/__tests__/fixtures/parameters.fixture.ts
|
||||
import {
|
||||
myNewModelParamsSchema,
|
||||
// ... 其他架构
|
||||
} from '../../../../../model-bank/src/aiModels/comfyui';
|
||||
|
||||
export const parametersFixture = {
|
||||
models: {
|
||||
'my-new-model': {
|
||||
schema: myNewModelParamsSchema,
|
||||
defaults: {
|
||||
steps: myNewModelParamsSchema.steps.default,
|
||||
cfg: myNewModelParamsSchema.cfg.default,
|
||||
},
|
||||
boundaries: {
|
||||
min: { steps: myNewModelParamsSchema.steps.min },
|
||||
max: { steps: myNewModelParamsSchema.steps.max }
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
### 测试最佳实践
|
||||
|
||||
#### 使用统一 Mock 系统
|
||||
|
||||
```typescript
|
||||
import { setupAllMocks } from '../setup/unifiedMocks';
|
||||
|
||||
describe('MyTest', () => {
|
||||
const mocks = setupAllMocks();
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
#### 编写参数映射测试
|
||||
|
||||
参数映射测试会自动运行,验证前端参数正确注入到工作流中:
|
||||
|
||||
```typescript
|
||||
// 测试会自动包含新注册的模型
|
||||
describe.each(
|
||||
Object.entries(models).filter(([name]) => workflowBuilders[name])
|
||||
)(
|
||||
'%s parameter mapping',
|
||||
(modelName, modelConfig) => {
|
||||
it('should map schema parameters to workflow', async () => {
|
||||
const params = {
|
||||
prompt: 'test prompt',
|
||||
...modelConfig.defaults,
|
||||
};
|
||||
|
||||
const workflow = await builder(`${modelName}.safetensors`, params, mockContext);
|
||||
expect(workflow).toBeDefined();
|
||||
});
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
#### 定制友好的测试原则
|
||||
|
||||
- **不测试工作流结构**:工作流是 ComfyUI 官方格式,只测试参数映射
|
||||
- **使用配置驱动的数据**:测试数据来自模型配置文件,确保一致性
|
||||
- **避免脆性断言**:不检查具体的节点 ID 或内部结构
|
||||
- **支持扩展**:新增模型应该只影响覆盖率,不破坏现有测试
|
||||
|
||||
### 运行测试
|
||||
|
||||
```bash
|
||||
# 运行 ComfyUI 相关测试
|
||||
cd packages/model-runtime
|
||||
bunx vitest run --silent='passed-only' 'src/comfyui'
|
||||
|
||||
# 查看覆盖率
|
||||
bunx vitest run --coverage 'src/comfyui'
|
||||
|
||||
# 运行特定测试文件
|
||||
bunx vitest run 'src/comfyui/__tests__/integration/parameterMapping.test.ts'
|
||||
```
|
||||
|
||||
### 覆盖率目标
|
||||
|
||||
- **整体覆盖率**:ComfyUI 模块维持 97%+ 覆盖率
|
||||
- **核心功能**:100% 分支覆盖率
|
||||
- **新增功能**:保持或提升现有覆盖率水平
|
||||
|
||||
## 开发和测试
|
||||
|
||||
### 1. 本地开发设置
|
||||
|
||||
```bash
|
||||
# 启动ComfyUI调试模式
|
||||
DEBUG=lobe-image:* pnpm dev
|
||||
```
|
||||
|
||||
### 2. 测试新功能
|
||||
|
||||
```typescript
|
||||
// 创建测试文件
|
||||
import { buildYourCustomWorkflow } from './your-workflow';
|
||||
|
||||
describe('Custom Workflow', () => {
|
||||
test('should build workflow correctly', async () => {
|
||||
const mockContext = {
|
||||
clientService: mockClientService,
|
||||
modelResolverService: mockModelResolver,
|
||||
};
|
||||
|
||||
const workflow = await buildYourCustomWorkflow(
|
||||
'test-model.safetensors',
|
||||
{ prompt: '测试', width: 512, height: 512 },
|
||||
mockContext
|
||||
);
|
||||
|
||||
expect(workflow).toBeDefined();
|
||||
// 验证工作流结构...
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### 3. 模型配置测试
|
||||
|
||||
```typescript
|
||||
import { getModelConfig, getAllModelNames } from '../config/modelRegistry';
|
||||
|
||||
describe('Model Registry', () => {
|
||||
test('should find new model', () => {
|
||||
const config = getModelConfig('your-new-model.safetensors');
|
||||
expect(config).toBeDefined();
|
||||
expect(config?.variant).toBe('dev');
|
||||
expect(config?.modelFamily).toBe('FLUX');
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
## 完整使用示例
|
||||
|
||||
### 基础图像生成
|
||||
|
||||
```typescript
|
||||
import { LobeComfyUI } from '@/libs/model-runtime/comfyui';
|
||||
|
||||
const comfyUI = new LobeComfyUI({
|
||||
baseURL: 'http://localhost:8000',
|
||||
authType: 'none'
|
||||
});
|
||||
|
||||
// FLUX Dev模型生成
|
||||
const result = await comfyUI.createImage({
|
||||
model: 'flux-dev',
|
||||
params: {
|
||||
prompt: '美丽的风景画,高质量,详细',
|
||||
width: 1024,
|
||||
height: 1024,
|
||||
steps: 20,
|
||||
cfg: 3.5,
|
||||
seed: -1
|
||||
}
|
||||
});
|
||||
|
||||
console.log('生成图像URL:', result.imageUrl);
|
||||
```
|
||||
|
||||
### SD3.5 模型使用
|
||||
|
||||
```typescript
|
||||
// SD3.5会自动检测可用编码器
|
||||
const sd35Result = await comfyUI.createImage({
|
||||
model: 'stable-diffusion-35',
|
||||
params: {
|
||||
prompt: '未来主义城市景观',
|
||||
width: 1344,
|
||||
height: 768,
|
||||
steps: 28,
|
||||
cfg: 4.5
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### 企业优化模型
|
||||
|
||||
```typescript
|
||||
// 系统会自动选择最佳可用变体(如FP8量化版本)
|
||||
const optimizedResult = await comfyUI.createImage({
|
||||
model: 'flux-dev',
|
||||
params: {
|
||||
prompt: '专业商务肖像',
|
||||
width: 768,
|
||||
height: 1024,
|
||||
steps: 15 // FP8模型可以用更少步数
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## 注意事项
|
||||
|
||||
- 确保 ComfyUI 服务正常运行并可访问
|
||||
- 检查所有必需的模型文件是否已正确安装
|
||||
- 注意模型文件的命名规范和路径配置
|
||||
- 定期检查和更新工作流配置以支持新功能
|
||||
- 注意不同模型系列的参数差异和兼容性
|
||||
- 添加新模型时,请遵循测试架构指南确保测试完整性
|
||||
- 在提交代码前务必运行相关测试确保覆盖率达标
|
||||
|
||||
通过遵循这些指南,开发者可以有效地在 LobeChat 中使用和扩展 ComfyUI 功能,为用户提供强大的图像生成和处理能力。
|
||||
@@ -11,13 +11,13 @@ But here is the easier approach that can reduce your pain.
|
||||
|
||||
### Environment Configuration
|
||||
|
||||
First, copy the example environment file to create your development configuration:
|
||||
First, copy the example environment file to create your Docker Compose configuration:
|
||||
|
||||
```bash
|
||||
cp .env.example.development .env.development
|
||||
cp docker-compose/local/.env.example docker-compose/local/.env
|
||||
```
|
||||
|
||||
This file contains all necessary environment variables for server-side database mode and configures:
|
||||
Edit `docker-compose/local/.env` as needed for your development setup. This file contains all necessary environment variables for the Docker services and configures:
|
||||
|
||||
- **Service Mode**: `NEXT_PUBLIC_SERVICE_MODE=server`
|
||||
- **Database**: PostgreSQL with connection string
|
||||
@@ -72,7 +72,7 @@ When working with image generation features (text-to-image, image-to-image), the
|
||||
|
||||
### Image Generation Configuration
|
||||
|
||||
The existing Docker Compose configuration already includes MinIO storage service and all necessary environment variables in `.env.example.development`. No additional setup is required.
|
||||
The existing Docker Compose configuration already includes MinIO storage service and all necessary environment variables in `docker-compose/local/.env.example`. No additional setup is required.
|
||||
|
||||
### Image Generation Architecture
|
||||
|
||||
@@ -84,7 +84,7 @@ The image generation feature requires:
|
||||
|
||||
### Storage Configuration
|
||||
|
||||
The `.env.example.development` file includes all necessary S3 environment variables:
|
||||
The `docker-compose/local/.env.example` file includes all necessary S3 environment variables:
|
||||
|
||||
```bash
|
||||
# S3 Storage Configuration (MinIO for local development)
|
||||
|
||||
@@ -11,13 +11,13 @@ LobeChat 提供了内置的客户端数据库体验。
|
||||
|
||||
### 环境配置
|
||||
|
||||
首先,复制示例环境文件来创建你的开发配置:
|
||||
首先,复制示例环境文件来创建你的 Docker Compose 配置:
|
||||
|
||||
```bash
|
||||
cp .env.example.development .env.development
|
||||
cp docker-compose/local/.env.example docker-compose/local/.env
|
||||
```
|
||||
|
||||
此文件包含服务端数据库模式所需的所有环境变量,配置了:
|
||||
根据需要编辑 `docker-compose/local/.env` 文件以适应你的开发设置。此文件包含 Docker 服务所需的所有环境变量,配置了:
|
||||
|
||||
- **服务模式**: `NEXT_PUBLIC_SERVICE_MODE=server`
|
||||
- **数据库**: 带连接字符串的 PostgreSQL
|
||||
@@ -72,7 +72,7 @@ docker-compose -f docker-compose.development.yml ps
|
||||
|
||||
### 图像生成配置
|
||||
|
||||
现有的 Docker Compose 配置已经包含了 MinIO 存储服务以及 `.env.example.development` 中的所有必要环境变量。无需额外配置。
|
||||
现有的 Docker Compose 配置已经包含了 MinIO 存储服务以及 `docker-compose/local/.env.example` 中的所有必要环境变量。无需额外配置。
|
||||
|
||||
### 图像生成架构
|
||||
|
||||
@@ -84,7 +84,7 @@ docker-compose -f docker-compose.development.yml ps
|
||||
|
||||
### 存储配置
|
||||
|
||||
`.env.example.development` 文件包含所有必要的 S3 环境变量:
|
||||
`docker-compose/local/.env.example` 文件包含所有必要的 S3 环境变量:
|
||||
|
||||
```bash
|
||||
# S3 存储配置(本地开发使用 MinIO)
|
||||
|
||||
@@ -0,0 +1,399 @@
|
||||
# 集成测试指南
|
||||
|
||||
## 概述
|
||||
|
||||
集成测试验证多个模块协同工作的正确性,确保完整的调用链路(Router → Service → Model → Database)正常运行。
|
||||
|
||||
## 为什么需要集成测试?
|
||||
|
||||
即使单元测试覆盖率很高(80%+),仍可能出现集成问题:
|
||||
|
||||
### 常见问题示例
|
||||
|
||||
```typescript
|
||||
// ❌ 问题:参数在调用链中丢失
|
||||
// Router 层
|
||||
const messageId = await messageModel.create({
|
||||
content: 'test',
|
||||
sessionId: 'xxx',
|
||||
topicId: 'yyy', // ← 传入了 topicId
|
||||
});
|
||||
|
||||
// Model 层(假设实现有问题)
|
||||
async create(data) {
|
||||
return this.db.insert(messages).values({
|
||||
content: data.content,
|
||||
sessionId: data.sessionId,
|
||||
// ❌ 忘记传递 topicId
|
||||
});
|
||||
}
|
||||
|
||||
// 结果:单元测试通过(因为 mock 了 Model),但实际运行时 topicId 丢失
|
||||
```
|
||||
|
||||
### 集成测试能发现的问题
|
||||
|
||||
1. **参数传递遗漏**: containerId、threadId、topicId 等在调用链中丢失
|
||||
2. **数据库约束**: 外键关系、级联删除等在 mock 中无法验证
|
||||
3. **事务完整性**: 跨表操作的原子性
|
||||
4. **权限验证**: 跨用户访问控制
|
||||
5. **真实场景**: 模拟用户的完整操作流程
|
||||
|
||||
## 运行集成测试
|
||||
|
||||
```bash
|
||||
# 运行所有集成测试
|
||||
pnpm test:integration
|
||||
|
||||
# 运行特定文件
|
||||
pnpm vitest tests/integration/routers/message.integration.test.ts
|
||||
|
||||
# 监听模式
|
||||
pnpm vitest tests/integration --watch
|
||||
|
||||
# 生成覆盖率报告
|
||||
pnpm test:integration --coverage
|
||||
```
|
||||
|
||||
## 目录结构
|
||||
|
||||
```
|
||||
tests/integration/
|
||||
├── README.md # 集成测试说明
|
||||
├── setup.ts # 通用设置和工具函数
|
||||
└── routers/ # Router 层集成测试
|
||||
├── message.integration.test.ts # Message Router 测试
|
||||
├── session.integration.test.ts # Session Router 测试
|
||||
├── topic.integration.test.ts # Topic Router 测试
|
||||
└── chat-flow.integration.test.ts # 完整聊天流程测试
|
||||
```
|
||||
|
||||
## 编写集成测试
|
||||
|
||||
### 基本模板
|
||||
|
||||
```typescript
|
||||
// @vitest-environment node
|
||||
import { eq } from 'drizzle-orm';
|
||||
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
||||
|
||||
import { getTestDB } from '@/database/models/__tests__/_util';
|
||||
import { messages, sessions, users } from '@/database/schemas';
|
||||
import { LobeChatDatabase } from '@/database/type';
|
||||
import { messageRouter } from '@/server/routers/lambda/message';
|
||||
|
||||
import { cleanupTestUser, createTestContext, createTestUser } from '../setup';
|
||||
|
||||
describe('Your Feature Integration Tests', () => {
|
||||
let serverDB: LobeChatDatabase;
|
||||
let userId: string;
|
||||
|
||||
beforeEach(async () => {
|
||||
// 1. 获取测试数据库
|
||||
serverDB = await getTestDB();
|
||||
|
||||
// 2. 创建测试用户
|
||||
userId = await createTestUser(serverDB);
|
||||
|
||||
// 3. 准备其他测试数据
|
||||
// ...
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
// 清理测试数据
|
||||
await cleanupTestUser(serverDB, userId);
|
||||
});
|
||||
|
||||
it('should do something', async () => {
|
||||
// 1. 创建 tRPC caller
|
||||
const caller = messageRouter.createCaller(createTestContext(userId));
|
||||
|
||||
// 2. 执行操作
|
||||
const result = await caller.someMethod({
|
||||
/* params */
|
||||
});
|
||||
|
||||
// 3. 验证结果
|
||||
expect(result).toBeDefined();
|
||||
|
||||
// 4. 🔥 关键:从数据库验证
|
||||
const [dbRecord] = await serverDB.select().from(messages).where(eq(messages.id, result));
|
||||
|
||||
expect(dbRecord).toMatchObject({
|
||||
// 验证所有关键字段
|
||||
});
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### 最佳实践
|
||||
|
||||
#### 1. 测试完整的调用链路
|
||||
|
||||
```typescript
|
||||
it('should create message with correct associations', async () => {
|
||||
const caller = messageRouter.createCaller(createTestContext(userId));
|
||||
|
||||
// 执行操作
|
||||
const messageId = await caller.createMessage({
|
||||
content: 'Test',
|
||||
sessionId: testSessionId,
|
||||
topicId: testTopicId,
|
||||
});
|
||||
|
||||
// ✅ 从数据库验证,而不是只验证返回值
|
||||
const [message] = await serverDB.select().from(messages).where(eq(messages.id, messageId));
|
||||
|
||||
expect(message.sessionId).toBe(testSessionId);
|
||||
expect(message.topicId).toBe(testTopicId);
|
||||
expect(message.userId).toBe(userId);
|
||||
});
|
||||
```
|
||||
|
||||
#### 2. 测试级联操作
|
||||
|
||||
```typescript
|
||||
it('should cascade delete messages when session is deleted', async () => {
|
||||
const sessionCaller = sessionRouter.createCaller(createTestContext(userId));
|
||||
const messageCaller = messageRouter.createCaller(createTestContext(userId));
|
||||
|
||||
// 创建 session 和 messages
|
||||
const sessionId = await sessionCaller.createSession({
|
||||
/* ... */
|
||||
});
|
||||
await messageCaller.createMessage({ sessionId /* ... */ });
|
||||
|
||||
// 删除 session
|
||||
await sessionCaller.removeSession({ id: sessionId });
|
||||
|
||||
// ✅ 验证相关消息也被删除
|
||||
const remainingMessages = await serverDB
|
||||
.select()
|
||||
.from(messages)
|
||||
.where(eq(messages.sessionId, sessionId));
|
||||
|
||||
expect(remainingMessages).toHaveLength(0);
|
||||
});
|
||||
```
|
||||
|
||||
#### 3. 测试跨 Router 协作
|
||||
|
||||
```typescript
|
||||
it('should handle complete chat flow', async () => {
|
||||
const sessionCaller = sessionRouter.createCaller(createTestContext(userId));
|
||||
const topicCaller = topicRouter.createCaller(createTestContext(userId));
|
||||
const messageCaller = messageRouter.createCaller(createTestContext(userId));
|
||||
|
||||
// 1. 创建 session
|
||||
const sessionId = await sessionCaller.createSession({
|
||||
/* ... */
|
||||
});
|
||||
|
||||
// 2. 创建 topic
|
||||
const topicId = await topicCaller.createTopic({ sessionId /* ... */ });
|
||||
|
||||
// 3. 创建 message
|
||||
const messageId = await messageCaller.createMessage({
|
||||
sessionId,
|
||||
topicId,
|
||||
/* ... */
|
||||
});
|
||||
|
||||
// ✅ 验证完整的关联关系
|
||||
const [message] = await serverDB.select().from(messages).where(eq(messages.id, messageId));
|
||||
|
||||
expect(message.sessionId).toBe(sessionId);
|
||||
expect(message.topicId).toBe(topicId);
|
||||
});
|
||||
```
|
||||
|
||||
#### 4. 测试错误场景
|
||||
|
||||
```typescript
|
||||
it('should prevent cross-user access', async () => {
|
||||
// 用户 A 创建 session
|
||||
const sessionId = await sessionRouter.createCaller(createTestContext(userA)).createSession({
|
||||
/* ... */
|
||||
});
|
||||
|
||||
// 用户 B 尝试访问
|
||||
const callerB = messageRouter.createCaller(createTestContext(userB));
|
||||
|
||||
// ✅ 应该抛出错误
|
||||
await expect(
|
||||
callerB.createMessage({
|
||||
sessionId,
|
||||
content: 'Unauthorized',
|
||||
}),
|
||||
).rejects.toThrow();
|
||||
});
|
||||
```
|
||||
|
||||
#### 5. 测试并发场景
|
||||
|
||||
```typescript
|
||||
it('should handle concurrent operations', async () => {
|
||||
const caller = messageRouter.createCaller(createTestContext(userId));
|
||||
|
||||
// 并发创建多个消息
|
||||
const promises = Array.from({ length: 10 }, (_, i) =>
|
||||
caller.createMessage({
|
||||
content: `Message ${i}`,
|
||||
sessionId: testSessionId,
|
||||
}),
|
||||
);
|
||||
|
||||
const messageIds = await Promise.all(promises);
|
||||
|
||||
// ✅ 验证所有消息都创建成功且唯一
|
||||
expect(messageIds).toHaveLength(10);
|
||||
expect(new Set(messageIds).size).toBe(10);
|
||||
});
|
||||
```
|
||||
|
||||
### 数据隔离
|
||||
|
||||
每个测试用例应该独立,不依赖其他测试:
|
||||
|
||||
```typescript
|
||||
beforeEach(async () => {
|
||||
// 为每个测试创建新的数据
|
||||
userId = await createTestUser(serverDB);
|
||||
testSessionId = await createTestSession(serverDB, userId);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
// 清理测试数据
|
||||
await cleanupTestUser(serverDB, userId);
|
||||
});
|
||||
```
|
||||
|
||||
### 测试命名
|
||||
|
||||
使用清晰的命名描述测试意图:
|
||||
|
||||
```typescript
|
||||
// ✅ 好的命名
|
||||
it('should create message with correct sessionId and topicId');
|
||||
it('should cascade delete messages when session is deleted');
|
||||
it('should prevent cross-user access to messages');
|
||||
|
||||
// ❌ 不好的命名
|
||||
it('test message creation');
|
||||
it('test delete');
|
||||
```
|
||||
|
||||
## 与单元测试的区别
|
||||
|
||||
| 维度 | 单元测试 | 集成测试 |
|
||||
| ------- | --------- | ------- |
|
||||
| **范围** | 单个函数 / 类 | 多个模块协作 |
|
||||
| **依赖** | Mock 外部依赖 | 使用真实依赖 |
|
||||
| **数据库** | Mock | 真实测试数据库 |
|
||||
| **速度** | 快(毫秒级) | 慢(秒级) |
|
||||
| **数量** | 多(60%) | 少(30%) |
|
||||
| **目的** | 验证逻辑正确性 | 验证集成正确性 |
|
||||
|
||||
## 测试金字塔
|
||||
|
||||
```
|
||||
/\
|
||||
/E2E\ ← 10% (关键业务流程)
|
||||
/------\
|
||||
/ 集成 \ ← 30% (API 集成测试) ⭐ 本指南重点
|
||||
/----------\
|
||||
/ 单元测试 \ ← 60% (已有 80%+)
|
||||
/--------------\
|
||||
```
|
||||
|
||||
## 覆盖目标
|
||||
|
||||
### 优先级 P0(必须覆盖)
|
||||
|
||||
- ✅ 跨层级的 ID 传递(sessionId、topicId、containerId、threadId)
|
||||
- ✅ 权限验证(用户只能访问自己的资源)
|
||||
- ✅ 级联删除(删除 session 时相关数据也删除)
|
||||
- ✅ 外键约束(不能创建不存在的关联)
|
||||
|
||||
### 优先级 P1(应该覆盖)
|
||||
|
||||
- 并发场景(多个请求同时操作)
|
||||
- 分页查询(正确的数据分页)
|
||||
- 搜索功能(关键词搜索)
|
||||
- 批量操作(批量创建 / 删除)
|
||||
|
||||
### 优先级 P2(可以覆盖)
|
||||
|
||||
- 统计功能(计数、排名)
|
||||
- 复杂查询(多条件筛选)
|
||||
- 性能测试(大量数据场景)
|
||||
|
||||
## 调试技巧
|
||||
|
||||
### 1. 查看测试数据库状态
|
||||
|
||||
```typescript
|
||||
it('debug test', async () => {
|
||||
// 执行操作
|
||||
await caller.createMessage({
|
||||
/* ... */
|
||||
});
|
||||
|
||||
// 打印数据库状态
|
||||
const allMessages = await serverDB.select().from(messages);
|
||||
console.log('All messages:', allMessages);
|
||||
});
|
||||
```
|
||||
|
||||
### 2. 使用 Drizzle Studio
|
||||
|
||||
```bash
|
||||
# 启动 Drizzle Studio 查看测试数据库
|
||||
pnpm db:studio
|
||||
```
|
||||
|
||||
### 3. 保留测试数据
|
||||
|
||||
```typescript
|
||||
afterEach(async () => {
|
||||
// 临时注释掉清理代码,保留数据用于调试
|
||||
// await cleanupTestUser(serverDB, userId);
|
||||
});
|
||||
```
|
||||
|
||||
## 常见问题
|
||||
|
||||
### Q: 集成测试很慢怎么办?
|
||||
|
||||
A:
|
||||
|
||||
1. 只测试关键路径,不要过度测试
|
||||
2. 使用 `test.concurrent` 并行执行独立的测试
|
||||
3. 优化测试数据准备,避免重复创建
|
||||
|
||||
### Q: 测试之间相互影响怎么办?
|
||||
|
||||
A:
|
||||
|
||||
1. 确保每个测试使用独立的 userId
|
||||
2. 在 `afterEach` 中彻底清理数据
|
||||
3. 使用事务隔离(如果数据库支持)
|
||||
|
||||
### Q: 如何测试需要认证的 API?
|
||||
|
||||
A: 使用 `createTestContext(userId)` 创建带认证信息的上下文:
|
||||
|
||||
```typescript
|
||||
const caller = messageRouter.createCaller(createTestContext(userId));
|
||||
```
|
||||
|
||||
## 参考资料
|
||||
|
||||
- [Vitest 文档](https://vitest.dev/)
|
||||
- [Drizzle ORM 文档](https://orm.drizzle.team/)
|
||||
- [tRPC 测试指南](https://trpc.io/docs/server/testing)
|
||||
- [测试金字塔](https://martinfowler.com/articles/practical-test-pyramid.html)
|
||||
|
||||
## 贡献
|
||||
|
||||
欢迎补充更多集成测试用例!请参考现有测试文件的风格。
|
||||
@@ -3,6 +3,7 @@ title: LobeChat Authentication Service Environment Variables
|
||||
description: >-
|
||||
Explore the essential environment variables for configuring authentication services in LobeChat, including OAuth SSO, NextAuth settings, and provider-specific details.
|
||||
|
||||
|
||||
tags:
|
||||
- Authentication Service
|
||||
- OAuth SSO
|
||||
@@ -279,6 +280,22 @@ LobeChat provides a complete authentication service capability when deployed. Th
|
||||
- Default: `-`
|
||||
- Example: `https://your-instance.okta.com`
|
||||
|
||||
### Feishu
|
||||
|
||||
#### `AUTH_FEISHU_APP_ID`
|
||||
|
||||
- Type: Required
|
||||
- Description: App ID of the Feishu application.
|
||||
- Default: `-`
|
||||
- Example: `cli_9f7b1e1e1e1e1e1e`
|
||||
|
||||
#### `AUTH_FEISHU_APP_SECRET`
|
||||
|
||||
- Type: Required
|
||||
- Description: App Secret of the Feishu application.
|
||||
- Default: `-`
|
||||
- Example: `AlHxxX1e1e1e1e1e1e1e1e1e1e1e1e1e`
|
||||
|
||||
### Generic OIDC
|
||||
|
||||
#### `AUTH_GENERIC_OIDC_ID`
|
||||
|
||||
@@ -651,6 +651,58 @@ If you need to use Azure OpenAI to provide model services, you can refer to the
|
||||
|
||||
The above example disables all models first, then enables `fal-ai/flux/schnell` and `fal-ai/flux-pro/kontext` (displayed as `FLUX.1 Kontext [pro]`).
|
||||
|
||||
## ComfyUI
|
||||
|
||||
### `COMFYUI_BASE_URL`
|
||||
|
||||
- Type: Optional
|
||||
- Description: The base URL address of the ComfyUI service
|
||||
- Default: `http://localhost:8188`
|
||||
- Example: `http://192.168.1.100:8188` or `https://my-comfyui-server.com`
|
||||
|
||||
### `COMFYUI_AUTH_TYPE`
|
||||
|
||||
- Type: Optional
|
||||
- Description: The authentication type for ComfyUI, supporting 4 authentication methods
|
||||
- `none`: No authentication (default)
|
||||
- `basic`: Basic authentication (username + password)
|
||||
- `bearer`: Bearer Token authentication (API key)
|
||||
- `custom`: Custom request header authentication
|
||||
- Default: `none`
|
||||
- Example: `basic`
|
||||
|
||||
### `COMFYUI_API_KEY`
|
||||
|
||||
- Type: Optional
|
||||
- Description: The API key used when the authentication type is `bearer`
|
||||
- Default: -
|
||||
- Example: `sk-xxxxxx...xxxxxx`
|
||||
|
||||
### `COMFYUI_USERNAME`
|
||||
|
||||
- Type: Optional
|
||||
- Description: The username used when the authentication type is `basic`
|
||||
- Default: -
|
||||
- Example: `admin`
|
||||
|
||||
### `COMFYUI_PASSWORD`
|
||||
|
||||
- Type: Optional
|
||||
- Description: The password used when the authentication type is `basic`
|
||||
- Default: -
|
||||
- Example: `password123`
|
||||
|
||||
### `COMFYUI_CUSTOM_HEADERS`
|
||||
|
||||
- Type: Optional
|
||||
- Description: Custom request headers used when the authentication type is `custom`, requires JSON format string
|
||||
- Default: -
|
||||
- Example: `{"X-Auth-Token": "your-token", "X-Custom-Header": "value"}`
|
||||
|
||||
<Callout type={'info'}>
|
||||
ComfyUI supports multiple authentication methods. Please choose the appropriate authentication type and corresponding authentication parameters according to your ComfyUI service configuration. If your ComfyUI service has no authentication set up, you can skip configuring authentication-related environment variables.
|
||||
</Callout>
|
||||
|
||||
## BFL
|
||||
|
||||
### `ENABLED_BFL`
|
||||
|
||||
@@ -165,6 +165,58 @@ LobeChat 在部署时提供了丰富的模型服务商相关的环境变量,
|
||||
- 默认值:`us-east-1`
|
||||
- 示例:`us-east-1`
|
||||
|
||||
## ComfyUI
|
||||
|
||||
### `COMFYUI_BASE_URL`
|
||||
|
||||
- 类型:可选
|
||||
- 描述:ComfyUI 服务的基础 URL 地址
|
||||
- 默认值:`http://localhost:8000`
|
||||
- 示例:`http://192.168.1.100:8000` 或 `https://my-comfyui-server.com`
|
||||
|
||||
### `COMFYUI_AUTH_TYPE`
|
||||
|
||||
- 类型:可选
|
||||
- 描述:ComfyUI 的认证类型,支持 4 种认证方式
|
||||
- `none`: 无认证(默认)
|
||||
- `basic`: 基础认证(用户名 + 密码)
|
||||
- `bearer`: Bearer Token 认证(API 密钥)
|
||||
- `custom`: 自定义请求头认证
|
||||
- 默认值:`none`
|
||||
- 示例:`basic`
|
||||
|
||||
### `COMFYUI_API_KEY`
|
||||
|
||||
- 类型:可选
|
||||
- 描述:当认证类型为 `bearer` 时使用的 API 密钥
|
||||
- 默认值:-
|
||||
- 示例:`sk-xxxxxx...xxxxxx`
|
||||
|
||||
### `COMFYUI_USERNAME`
|
||||
|
||||
- 类型:可选
|
||||
- 描述:当认证类型为 `basic` 时使用的用户名
|
||||
- 默认值:-
|
||||
- 示例:`admin`
|
||||
|
||||
### `COMFYUI_PASSWORD`
|
||||
|
||||
- 类型:可选
|
||||
- 描述:当认证类型为 `basic` 时使用的密码
|
||||
- 默认值:-
|
||||
- 示例:`password123`
|
||||
|
||||
### `COMFYUI_CUSTOM_HEADERS`
|
||||
|
||||
- 类型:可选
|
||||
- 描述:当认证类型为 `custom` 时使用的自定义请求头,需要使用 JSON 格式字符串
|
||||
- 默认值:-
|
||||
- 示例:`{"X-Auth-Token": "your-token", "X-Custom-Header": "value"}`
|
||||
|
||||
<Callout type={'info'}>
|
||||
ComfyUI 支持多种认证方式,请根据您的 ComfyUI 服务配置选择合适的认证类型和相应的认证参数。如果您的 ComfyUI 服务没有设置认证,可以不配置认证相关的环境变量。
|
||||
</Callout>
|
||||
|
||||
## DeepSeek AI
|
||||
|
||||
### `DEEPSEEK_PROXY_URL`
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
---
|
||||
title: Agent Team
|
||||
description: Turn any conversation into a team effort. Multiple AI agents collaborate naturally to give you richer, more insightful responses.
|
||||
tags:
|
||||
- Agent Team
|
||||
- Multi-Agent
|
||||
- AI Orchestration
|
||||
- Agent Coordination
|
||||
---
|
||||
|
||||
# Agent Team
|
||||
|
||||
<Image alt={'Agent Team'} cover src={'https://github.com/user-attachments/assets/6e5599f6-1e39-4b14-a218-4f5ffa2c306a'} />
|
||||
|
||||
Sometimes one perspective isn't enough. Agent Team brings together multiple AI agents, each with their own expertise, to collaborate on your conversations. Richer discussions, diverse viewpoints, and solutions you wouldn't get from any single agent.
|
||||
|
||||
## Highlights
|
||||
|
||||
- Multiple assistants with specialized knowledge work together, each contributing their strengths
|
||||
- A built-in host ensures the agent team conversation runs smoothly and organized
|
||||
- Private messaging allows seamless coordination between assistants
|
||||
- You get comprehensive answers from multiple perspectives
|
||||
- Ready to use with your own assistants or rich agent team templates
|
||||
|
||||
## Use Cases
|
||||
|
||||
**Learning and Research**: Different assistants gather different materials through different tools, then come together for spontaneous discussion.
|
||||
|
||||
**Entertainment**: Multiplayer language games like Werewolf, Model United Nations, and Turtle Soup.
|
||||
|
||||
**Brainstorming**: Diverse perspectives spark better ideas.
|
||||
|
||||
**Problem Solving**: Benefit from insights across different professional fields, with different tools and MCPs, agent team allows you to have the perfect AI team.
|
||||
|
||||
## Quick Start
|
||||
|
||||
Click the "Create Agent Team" button, you can choose to create directly from preset agent team templates, or select your own assistants to form an agent team.
|
||||
|
||||
You can use @ to mention a team member in the agent team, or click their avatar to send them a private message. Everything works just like in a real chat room.
|
||||
|
||||
### Interrupt and Resume Agent Team
|
||||
|
||||
You can interrupt the host's thinking at any time, and the agent team will "pause" after interruption. You can start the moderator at any time, and the agent team will continue.
|
||||
|
||||
Of course, conversations may also stop naturally.
|
||||
|
||||
### Advanced Options
|
||||
|
||||
- Agent Team Speed: Customize the response speed of the agent team
|
||||
- Custom Moderator: Guide the moderator's behavior according to specific needs
|
||||
|
||||
Agent Team transforms how you interact with AI. Instead of getting one answer, you participate in a conversation—complete with different viewpoints, collaborative problem-solving, and profound insights that emerge when AI agents work together.
|
||||
@@ -0,0 +1,52 @@
|
||||
---
|
||||
title: Agent 团队
|
||||
description: 让对话变成团队协作。多个 AI 智能体自然配合,为你提供更丰富、更有洞察力的回答。
|
||||
tags:
|
||||
- 群组对话
|
||||
- 多智能体
|
||||
- AI 编排
|
||||
- 智能体协调
|
||||
---
|
||||
|
||||
# Agent 团队
|
||||
|
||||
<Image alt={'Agent 团队'} cover src={'https://github.com/user-attachments/assets/6e5599f6-1e39-4b14-a218-4f5ffa2c306a'} />
|
||||
|
||||
有时候,一个视角远远不够。Agent 团队功能让多个拥有不同知识和技能的 AI 智能体聚在一起,协作参与你的对话。更丰富的讨论、多元的观点,以及任何单一智能体都无法提供的解决方案。
|
||||
|
||||
## 亮点
|
||||
|
||||
- 多个具有专业知识的助手协同工作,各取所长
|
||||
- 团队内置的主持人将确保整个团队聊天有条不紊的进行
|
||||
- 私信功能让助手间无缝协调配合
|
||||
- 你将从多个视角获得全面的答案
|
||||
- 开箱即用,由你自己的助手组成,或者使用丰富的团队模版
|
||||
|
||||
## 适用场景
|
||||
|
||||
**学习研究**:不同的助手通过不同的工具收集不同的资料,汇聚一处并自发讨论。
|
||||
|
||||
**娱乐**:狼人杀、模拟联合国、海龟汤等多人语聊游戏。
|
||||
|
||||
**头脑风暴**:多元观点激发更好的想法。
|
||||
|
||||
**问题解决**:受益于不同专业领域的见解,以及不同的工具和 MCP,Agent 团队允许你拥有完美的 AI 团队。
|
||||
|
||||
## 快速开始
|
||||
|
||||
点击「创建 Agent 团队」按钮,你可以选择直接从预设的团队模版创建,或选择你自己的助手组成团队。
|
||||
|
||||
你可以在团队聊天中输入 @ 来提及某个成员,或者点击他们的头像对其私聊。一切就像是在真实的聊天室中一样。
|
||||
|
||||
### 中断与继续团队聊天
|
||||
|
||||
你可以随时打断主持人的思考,打断后团队聊天将会「暂停」。你可以随时开启主持人,团队聊天便会继续。
|
||||
|
||||
当然,对话也有可能自然地停止。
|
||||
|
||||
### 高级选项
|
||||
|
||||
- 团队速度:自定义团队的回答速度
|
||||
- 自定义主持人:根据特定需要指导主持人的行为
|
||||
|
||||
Agent 团队改变了你与 AI 的互动方式。不再是获得一个答案,而是参与一场对话 —— 包含不同观点、协作解决问题,以及 AI 智能体协同工作时产生的深刻洞察。
|
||||
@@ -0,0 +1,816 @@
|
||||
---
|
||||
title: Using ComfyUI for Image Generation in LobeChat
|
||||
description: Learn how to configure and use ComfyUI service in LobeChat, supporting FLUX series models for high-quality image generation and editing features
|
||||
tags:
|
||||
- ComfyUI
|
||||
- FLUX
|
||||
- Text-to-Image
|
||||
- Image Editing
|
||||
- AI Image Generation
|
||||
---
|
||||
|
||||
# Using ComfyUI in LobeChat
|
||||
|
||||
<Image alt={'Using ComfyUI in LobeChat'} cover src={'https://github.com/lobehub/lobe-chat/assets/17870709/c9e5eafc-ca22-496b-a88d-cc0ae53bf720'} />
|
||||
|
||||
This documentation will guide you on how to use [ComfyUI](https://github.com/comfyanonymous/ComfyUI) in LobeChat for high-quality AI image generation and editing.
|
||||
|
||||
## ComfyUI Overview
|
||||
|
||||
ComfyUI is a powerful stable diffusion and flow diffusion GUI that provides a node-based workflow interface. LobeChat integrates with ComfyUI, supporting complete FLUX series models, including text-to-image generation and image editing capabilities.
|
||||
|
||||
### Key Features
|
||||
|
||||
- **Extensive Model Support**: Supports 223 models, including FLUX series (130) and SD series (93)
|
||||
- **Configuration-Driven Architecture**: Registry system provides intelligent model selection
|
||||
- **Multi-Format Support**: Supports .safetensors and .gguf formats with various quantization levels
|
||||
- **Dynamic Precision Selection**: Supports default, fp8\_e4m3fn, fp8\_e5m2, fp8\_e4m3fn\_fast precision
|
||||
- **Multiple Authentication Methods**: Supports no authentication, basic authentication, Bearer Token, and custom authentication
|
||||
- **Intelligent Component Selection**: Automatically selects optimal T5, CLIP, VAE encoder combinations
|
||||
- **Enterprise-Grade Optimization**: Includes NF4, SVDQuant, TorchAO, MFLUX optimization variants
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Step 1: Configure ComfyUI in LobeChat
|
||||
|
||||
#### 1. Open Settings Interface
|
||||
|
||||
- Access LobeChat's `Settings` interface
|
||||
- Find the `ComfyUI` setting item under `AI Providers`
|
||||
|
||||
<Image alt={'ComfyUI Settings Interface'} inStep src={'https://github.com/lobehub/lobe-chat/assets/17870709/3f31bc33-509f-4ad2-ba81-280c2a6ec5fa'} />
|
||||
|
||||
#### 2. Configure Connection Parameters
|
||||
|
||||
**Basic Configuration**:
|
||||
|
||||
- **Server Address**: Enter ComfyUI server address, e.g., `http://localhost:8188`
|
||||
- **Authentication Type**: Select appropriate authentication method (default: no authentication)
|
||||
|
||||
### Step 2: Select Model and Start Generating Images
|
||||
|
||||
#### 1. Select FLUX Model
|
||||
|
||||
In the conversation interface:
|
||||
|
||||
- Click the model selection button
|
||||
- Select the desired FLUX model from the ComfyUI category
|
||||
|
||||
<Image alt={'Select FLUX Model'} inStep src={'https://github.com/lobehub/lobe-chat/assets/17870709/ff7ebacf-27f0-42d7-810b-00314499a084'} />
|
||||
|
||||
#### 2. Text-to-Image Generation
|
||||
|
||||
**Using FLUX Schnell (Fast Generation)**:
|
||||
|
||||
```plaintext
|
||||
Generate an image: A cute orange cat sitting on a sunny windowsill, warm lighting, detailed fur texture
|
||||
```
|
||||
|
||||
**Using FLUX Dev (High Quality Generation)**:
|
||||
|
||||
```plaintext
|
||||
Generate high quality image: City skyline at sunset, cyberpunk style, neon lights, 4K high resolution, detailed architecture
|
||||
```
|
||||
|
||||
#### 3. Image Editing
|
||||
|
||||
**Using FLUX Kontext-dev for Image Editing**:
|
||||
|
||||
```plaintext
|
||||
Edit this image: Change the background to a starry night sky, keep the main subject, cosmic atmosphere
|
||||
```
|
||||
|
||||
Then upload the original image you want to edit.
|
||||
|
||||
<Callout type={'info'}>
|
||||
Image editing functionality requires uploading the original image first, then describing the modifications you want to make.
|
||||
</Callout>
|
||||
|
||||
## Authentication Configuration Guide
|
||||
|
||||
ComfyUI supports four authentication methods. Choose the appropriate method based on your server configuration and security requirements:
|
||||
|
||||
### No Authentication (none)
|
||||
|
||||
**Use Cases**:
|
||||
|
||||
- Local development environment (localhost)
|
||||
- Internal network with trusted users
|
||||
- Personal single-machine deployment
|
||||
|
||||
**Configuration**:
|
||||
|
||||
```yaml
|
||||
Authentication Type: None
|
||||
Server Address: http://localhost:8188
|
||||
```
|
||||
|
||||
### Basic Authentication (basic)
|
||||
|
||||
**Use Cases**:
|
||||
|
||||
- Deployments using Nginx reverse proxy
|
||||
- Team internal use requiring basic access control
|
||||
|
||||
**Configuration**:
|
||||
|
||||
1. **Create User Password**:
|
||||
|
||||
```bash
|
||||
# Install apache2-utils
|
||||
sudo apt-get install apache2-utils
|
||||
|
||||
# Create user 'admin'
|
||||
sudo htpasswd -c /etc/nginx/.htpasswd admin
|
||||
```
|
||||
|
||||
2. **LobeChat Configuration**:
|
||||
|
||||
```yaml
|
||||
Authentication Type: Basic Authentication
|
||||
Server Address: http://your-domain.com
|
||||
Username: admin
|
||||
Password: your_secure_password
|
||||
```
|
||||
|
||||
### Bearer Token (bearer)
|
||||
|
||||
**Use Cases**:
|
||||
|
||||
- API-driven application integration
|
||||
- Enterprise environments requiring Token authentication
|
||||
|
||||
**Generate Token**:
|
||||
|
||||
```python
|
||||
import jwt
|
||||
import datetime
|
||||
|
||||
payload = {
|
||||
'user': 'admin',
|
||||
'exp': datetime.datetime.utcnow() + datetime.timedelta(days=30)
|
||||
}
|
||||
|
||||
secret_key = "your-secret-key"
|
||||
token = jwt.encode(payload, secret_key, algorithm='HS256')
|
||||
print(f"Bearer Token: {token}")
|
||||
```
|
||||
|
||||
**LobeChat Configuration**:
|
||||
|
||||
```yaml
|
||||
Authentication Type: Bearer Token
|
||||
Server Address: http://your-server:8188
|
||||
API Key: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
||||
```
|
||||
|
||||
### Custom Authentication (custom)
|
||||
|
||||
**Use Cases**:
|
||||
|
||||
- Integration with existing enterprise authentication systems
|
||||
- Systems requiring multiple authentication headers
|
||||
|
||||
**LobeChat Configuration**:
|
||||
|
||||
```yaml
|
||||
Authentication Type: Custom
|
||||
Server Address: http://your-server:8188
|
||||
Custom Headers:
|
||||
{
|
||||
"X-API-Key": "your_api_key",
|
||||
"X-Client-ID": "lobechat"
|
||||
}
|
||||
```
|
||||
|
||||
## Common Issues Resolution
|
||||
|
||||
### 1. How to Install Comfy-Manager
|
||||
|
||||
Comfy-Manager is ComfyUI's extension manager that allows you to easily install and manage various nodes, models, and extensions.
|
||||
|
||||
<details>
|
||||
<summary><b>📦 Install Comfy-Manager Steps</b></summary>
|
||||
|
||||
#### Method 1: Manual Installation (Recommended)
|
||||
|
||||
```bash
|
||||
# Navigate to ComfyUI's custom_nodes directory
|
||||
cd ComfyUI/custom_nodes
|
||||
|
||||
# Clone Comfy-Manager repository
|
||||
git clone https://github.com/ltdrdata/ComfyUI-Manager.git
|
||||
|
||||
# Restart ComfyUI server
|
||||
# After restart, you'll see the Manager button in the UI
|
||||
```
|
||||
|
||||
#### Method 2: One-Click Installation Script
|
||||
|
||||
```bash
|
||||
# Execute in ComfyUI root directory
|
||||
curl -fsSL https://raw.githubusercontent.com/ltdrdata/ComfyUI-Manager/main/install.sh | bash
|
||||
```
|
||||
|
||||
#### Verify Installation
|
||||
|
||||
1. Restart ComfyUI server
|
||||
2. Visit `http://localhost:8188`
|
||||
3. You should see the "Manager" button in the bottom-right corner
|
||||
|
||||
#### Using Comfy-Manager
|
||||
|
||||
**Install Models**:
|
||||
|
||||
1. Click "Manager" button
|
||||
2. Select "Install Models"
|
||||
3. Search for needed models (e.g., FLUX, SD3.5)
|
||||
4. Click "Install" to automatically download to correct directory
|
||||
|
||||
**Install Node Extensions**:
|
||||
|
||||
1. Click "Manager" button
|
||||
2. Select "Install Custom Nodes"
|
||||
3. Search for needed nodes (e.g., ControlNet, AnimateDiff)
|
||||
4. Click "Install" and restart server
|
||||
|
||||
**Manage Installed Content**:
|
||||
|
||||
1. Click "Manager" button
|
||||
2. Select "Installed" to view installed extensions
|
||||
3. Update, disable, or uninstall extensions
|
||||
</details>
|
||||
|
||||
### 2. How to Handle "Model not found" Errors
|
||||
|
||||
When you see errors like `Model not found: flux1-dev.safetensors, flux1-krea-dev.safetensors, flux1-schnell.safetensors`, it means the required model files are missing from the server.
|
||||
|
||||
<details>
|
||||
<summary><b>🔧 Resolve Model not found Errors</b></summary>
|
||||
|
||||
#### Error Example
|
||||
|
||||
```plaintext
|
||||
Model not found: flux1-dev.safetensors, flux1-krea-dev.safetensors, flux1-schnell.safetensors
|
||||
```
|
||||
|
||||
This error indicates the system expects to find these model files but couldn't locate them on the server.
|
||||
|
||||
#### Resolution Methods
|
||||
|
||||
**Method 1: Download using Comfy-Manager (Recommended)**
|
||||
|
||||
1. Open ComfyUI interface
|
||||
2. Click "Manager" → "Install Models"
|
||||
3. Search for the model name from the error (e.g., "flux1-dev")
|
||||
4. Click "Install" to automatically download
|
||||
|
||||
**Method 2: Manual Model Download**
|
||||
|
||||
1. **Download Model Files**:
|
||||
- Visit [Hugging Face](https://huggingface.co/black-forest-labs/FLUX.1-dev) or other model sources
|
||||
- Download the files mentioned in the error (e.g., `flux1-dev.safetensors`)
|
||||
|
||||
2. **Place in Correct Directory**:
|
||||
```bash
|
||||
# FLUX and SD3.5 main models go to
|
||||
ComfyUI/models/diffusion_models/flux1-dev.safetensors
|
||||
|
||||
# SD1.5 and SDXL models go to
|
||||
ComfyUI/models/checkpoints/
|
||||
```
|
||||
|
||||
3. **Verify Files**:
|
||||
```bash
|
||||
# Check if file exists
|
||||
ls -la ComfyUI/models/diffusion_models/flux1-dev.safetensors
|
||||
|
||||
# Check file integrity (optional)
|
||||
sha256sum flux1-dev.safetensors
|
||||
```
|
||||
|
||||
4. **Restart ComfyUI Server**
|
||||
|
||||
**Method 3: Direct Download with wget/curl**
|
||||
|
||||
```bash
|
||||
# Navigate to models directory
|
||||
cd ComfyUI/models/diffusion_models/
|
||||
|
||||
# Download using wget (replace with actual download link)
|
||||
wget https://huggingface.co/black-forest-labs/FLUX.1-dev/resolve/main/flux1-dev.safetensors
|
||||
|
||||
# Or use curl
|
||||
curl -L -o flux1-dev.safetensors https://huggingface.co/black-forest-labs/FLUX.1-dev/resolve/main/flux1-dev.safetensors
|
||||
```
|
||||
|
||||
#### Common Model Download Sources
|
||||
|
||||
- **Hugging Face**: [https://huggingface.co/models](https://huggingface.co/models)
|
||||
- **Civitai**: [https://civitai.com/models](https://civitai.com/models)
|
||||
- **Official Sources**:
|
||||
- FLUX: [https://huggingface.co/black-forest-labs](https://huggingface.co/black-forest-labs)
|
||||
- SD3.5: [https://huggingface.co/stabilityai](https://huggingface.co/stabilityai)
|
||||
|
||||
#### Prevention Measures
|
||||
|
||||
1. **Basic Model Package**: Download at least one base model
|
||||
- FLUX: `flux1-schnell.safetensors` (fast) or `flux1-dev.safetensors` (high quality)
|
||||
- SD3.5: `sd3.5_large.safetensors`
|
||||
|
||||
2. **Check Disk Space**:
|
||||
```bash
|
||||
# Check available space
|
||||
df -h ComfyUI/models/
|
||||
```
|
||||
|
||||
3. **Set Model Path** (optional):
|
||||
If your models are stored elsewhere, create symbolic links:
|
||||
```bash
|
||||
ln -s /path/to/your/models ComfyUI/models/diffusion_models/
|
||||
```
|
||||
</details>
|
||||
|
||||
### 3. How to Handle Missing System Component Errors
|
||||
|
||||
When you see errors like `Missing VAE encoder: ae.safetensors` or other component files missing, you need to download the corresponding system components.
|
||||
|
||||
<details>
|
||||
<summary><b>🛠️ Resolve Missing System Component Errors</b></summary>
|
||||
|
||||
#### Common Component Errors
|
||||
|
||||
```plaintext
|
||||
Missing VAE encoder: ae.safetensors. Please download and place it in the models/vae folder.
|
||||
Missing CLIP encoder: clip_l.safetensors. Please download and place it in the models/clip folder.
|
||||
Missing T5 encoder: t5xxl_fp16.safetensors. Please download and place it in the models/clip folder.
|
||||
```
|
||||
|
||||
#### Component Types Description
|
||||
|
||||
| Component Type | Example Filename | Purpose | Storage Directory |
|
||||
| -------------- | ------------------------------ | ----------------------- | ------------------ |
|
||||
| **VAE** | ae.safetensors | Image encoding/decoding | models/vae/ |
|
||||
| **CLIP** | clip\_l.safetensors | Text encoding (CLIP) | models/clip/ |
|
||||
| **T5** | t5xxl\_fp16.safetensors | Text encoding (T5) | models/clip/ |
|
||||
| **ControlNet** | flux-controlnet-\*.safetensors | Control networks | models/controlnet/ |
|
||||
|
||||
#### Resolution Methods
|
||||
|
||||
**Method 1: Use Comfy-Manager (Recommended)**
|
||||
|
||||
1. Click "Manager" → "Install Models"
|
||||
2. Select component type in "Filter" (VAE/CLIP/T5)
|
||||
3. Download corresponding component files
|
||||
|
||||
**Method 2: Manual Component Download**
|
||||
|
||||
##### FLUX Required Components
|
||||
|
||||
```bash
|
||||
# 1. VAE Encoder
|
||||
cd ComfyUI/models/vae/
|
||||
wget https://huggingface.co/black-forest-labs/FLUX.1-dev/resolve/main/ae.safetensors
|
||||
|
||||
# 2. CLIP-L Encoder
|
||||
cd ComfyUI/models/clip/
|
||||
wget https://huggingface.co/comfyanonymous/flux_text_encoders/resolve/main/clip_l.safetensors
|
||||
|
||||
# 3. T5-XXL Encoder (choose different precisions)
|
||||
# FP16 version (recommended, balanced performance)
|
||||
wget https://huggingface.co/comfyanonymous/flux_text_encoders/resolve/main/t5xxl_fp16.safetensors
|
||||
|
||||
# Or FP8 version (saves VRAM)
|
||||
wget https://huggingface.co/comfyanonymous/flux_text_encoders/resolve/main/t5xxl_fp8_e4m3fn.safetensors
|
||||
```
|
||||
|
||||
##### SD3.5 Required Components
|
||||
|
||||
```bash
|
||||
# SD3.5 uses different encoders
|
||||
cd ComfyUI/models/clip/
|
||||
|
||||
# CLIP-G Encoder
|
||||
wget https://huggingface.co/stabilityai/stable-diffusion-3.5-large/resolve/main/text_encoders/clip_g.safetensors
|
||||
|
||||
# CLIP-L Encoder
|
||||
wget https://huggingface.co/stabilityai/stable-diffusion-3.5-large/resolve/main/text_encoders/clip_l.safetensors
|
||||
|
||||
# T5-XXL Encoder
|
||||
wget https://huggingface.co/stabilityai/stable-diffusion-3.5-large/resolve/main/text_encoders/t5xxl_fp16.safetensors
|
||||
```
|
||||
|
||||
##### SDXL Required Components
|
||||
|
||||
```bash
|
||||
# SDXL VAE
|
||||
cd ComfyUI/models/vae/
|
||||
wget https://huggingface.co/stabilityai/sdxl-vae/resolve/main/sdxl_vae.safetensors
|
||||
|
||||
# SDXL uses built-in CLIP encoders, usually no separate download needed
|
||||
```
|
||||
|
||||
#### Component Compatibility Matrix
|
||||
|
||||
| Model Series | Required VAE | Required CLIP | Required T5 | Optional Components |
|
||||
| ------------ | -------------- | ------------------- | ----------------------- | ------------------- |
|
||||
| **FLUX** | ae.safetensors | clip\_l.safetensors | t5xxl\_fp16.safetensors | ControlNet |
|
||||
| **SD3.5** | Built-in | clip\_g + clip\_l | t5xxl\_fp16 | - |
|
||||
| **SDXL** | sdxl\_vae | Built-in | - | Refiner |
|
||||
| **SD1.5** | vae-ft-mse | Built-in | - | ControlNet |
|
||||
|
||||
#### Precision Selection Recommendations
|
||||
|
||||
**T5 Encoder Precision Selection**:
|
||||
|
||||
| VRAM Capacity | Recommended Version | Filename |
|
||||
| ------------- | ------------------- | ------------------------------ |
|
||||
| \< 12GB | FP8 Quantized | t5xxl\_fp8\_e4m3fn.safetensors |
|
||||
| 12-16GB | FP16 | t5xxl\_fp16.safetensors |
|
||||
| > 16GB | FP32 | t5xxl.safetensors |
|
||||
|
||||
#### Verify Component Installation
|
||||
|
||||
```bash
|
||||
# Check all required components
|
||||
echo "=== VAE Components ==="
|
||||
ls -la ComfyUI/models/vae/
|
||||
|
||||
echo "=== CLIP/T5 Components ==="
|
||||
ls -la ComfyUI/models/clip/
|
||||
|
||||
echo "=== ControlNet Components ==="
|
||||
ls -la ComfyUI/models/controlnet/
|
||||
```
|
||||
|
||||
#### Troubleshooting
|
||||
|
||||
**Issue: Still getting errors after download**
|
||||
|
||||
1. **Check File Permissions**:
|
||||
```bash
|
||||
chmod 644 ComfyUI/models/vae/*.safetensors
|
||||
chmod 644 ComfyUI/models/clip/*.safetensors
|
||||
```
|
||||
|
||||
2. **Clear Cache**:
|
||||
```bash
|
||||
# Clear ComfyUI cache
|
||||
rm -rf ComfyUI/temp/*
|
||||
rm -rf ComfyUI/__pycache__/*
|
||||
```
|
||||
|
||||
3. **Restart Server**:
|
||||
```bash
|
||||
# Fully restart ComfyUI
|
||||
pkill -f "python main.py"
|
||||
python main.py --listen 0.0.0.0 --port 8188
|
||||
```
|
||||
|
||||
**Issue: Insufficient VRAM**
|
||||
|
||||
Use quantized component versions:
|
||||
|
||||
- T5: Use `t5xxl_fp8_e4m3fn.safetensors` instead of FP16/FP32
|
||||
- VAE: Some models support FP16 VAE versions
|
||||
|
||||
**Issue: Slow Downloads**
|
||||
|
||||
1. Use mirror sources (if applicable)
|
||||
2. Use download tools (like aria2c) with resume support:
|
||||
```bash
|
||||
aria2c -x 16 -s 16 -k 1M [download_link]
|
||||
```
|
||||
</details>
|
||||
|
||||
## ComfyUI Server Installation
|
||||
|
||||
<details>
|
||||
<summary><b>🚀 Install and Configure ComfyUI Server</b></summary>
|
||||
|
||||
### 1. Install ComfyUI
|
||||
|
||||
```bash
|
||||
# Clone ComfyUI repository
|
||||
git clone https://github.com/comfyanonymous/ComfyUI.git
|
||||
cd ComfyUI
|
||||
|
||||
# Install dependencies
|
||||
pip install -r requirements.txt
|
||||
|
||||
# Optional: Install JWT support (for Token authentication)
|
||||
pip install PyJWT
|
||||
|
||||
# Start ComfyUI server
|
||||
python main.py --listen 0.0.0.0 --port 8188
|
||||
```
|
||||
|
||||
### 2. Download Model Files
|
||||
|
||||
**Recommended Basic Configuration** (Minimal installation):
|
||||
|
||||
**Main Models** (place in `models/diffusion_models/` directory):
|
||||
|
||||
- `flux1-schnell.safetensors` - Fast generation (4 steps)
|
||||
- `flux1-dev.safetensors` - High-quality creation (20 steps)
|
||||
|
||||
**Required Components** (place in respective directories):
|
||||
|
||||
- `models/vae/ae.safetensors` - VAE encoder
|
||||
- `models/clip/clip_l.safetensors` - CLIP text encoder
|
||||
- `models/clip/t5xxl_fp16.safetensors` - T5 text encoder
|
||||
|
||||
### 3. Verify Server Running
|
||||
|
||||
Visit `http://localhost:8188` to confirm ComfyUI interface loads properly.
|
||||
|
||||
<Callout type={'info'}>
|
||||
**Smart Model Selection**: LobeChat will automatically select the best model based on available model files on the server. You don't need to download all models; the system will automatically choose from available models by priority (Official > Enterprise > Community).
|
||||
</Callout>
|
||||
</details>
|
||||
|
||||
## Supported Models
|
||||
|
||||
LobeChat's ComfyUI integration uses a configuration-driven architecture, supporting **223 models**, providing complete coverage from official models to community-optimized versions.
|
||||
|
||||
### FLUX Series Recommended Parameters
|
||||
|
||||
| Model Type | Recommended Steps | CFG Scale | Resolution Range |
|
||||
| ----------- | ----------------- | --------- | -------------------- |
|
||||
| **Schnell** | 4 steps | - | 512×512 to 1536×1536 |
|
||||
| **Dev** | 20 steps | 3.5 | 512×512 to 2048×2048 |
|
||||
| **Kontext** | 20 steps | 3.5 | 512×512 to 2048×2048 |
|
||||
| **Krea** | 20 steps | 4.5 | 512×512 to 2048×2048 |
|
||||
|
||||
### SD3.5 Series Parameters
|
||||
|
||||
| Model Type | Recommended Steps | CFG Scale | Resolution Range |
|
||||
| --------------- | ----------------- | --------- | -------------------- |
|
||||
| **Large** | 25 steps | 7.0 | 512×512 to 2048×2048 |
|
||||
| **Large Turbo** | 8 steps | 3.5 | 512×512 to 1536×1536 |
|
||||
| **Medium** | 20 steps | 6.0 | 512×512 to 1536×1536 |
|
||||
|
||||
<details>
|
||||
<summary><b>📋 Complete Supported Model List</b></summary>
|
||||
|
||||
### Model Classification System
|
||||
|
||||
#### Priority 1: Official Core Models
|
||||
|
||||
**FLUX.1 Official Series**:
|
||||
|
||||
- `flux1-dev.safetensors` - High-quality creation model
|
||||
- `flux1-schnell.safetensors` - Fast generation model
|
||||
- `flux1-kontext-dev.safetensors` - Image editing model
|
||||
- `flux1-krea-dev.safetensors` - Safety-enhanced model
|
||||
|
||||
**SD3.5 Official Series**:
|
||||
|
||||
- `sd3.5_large.safetensors` - SD3.5 large base model
|
||||
- `sd3.5_large_turbo.safetensors` - Fast generation version
|
||||
- `sd3.5_medium.safetensors` - Medium-scale model
|
||||
|
||||
#### Priority 2: Enterprise Optimized Models (106 FLUX)
|
||||
|
||||
**Quantization Optimization Series**:
|
||||
|
||||
- **GGUF Quantization**: Each variant supports 11 quantization levels (F16, Q8\_0, Q6\_K, Q5\_K\_M, Q5\_K\_S, Q4\_K\_M, Q4\_K\_S, Q4\_0, Q3\_K\_M, Q3\_K\_S, Q2\_K)
|
||||
- **FP8 Precision**: fp8\_e4m3fn, fp8\_e5m2 optimized versions
|
||||
- **Enterprise Lightweight**: FLUX.1-lite-8B series
|
||||
- **Technical Experiments**: NF4, SVDQuant, TorchAO, optimum-quanto, MFLUX optimized versions
|
||||
|
||||
#### Priority 3: Community Fine-tuned Models (48 FLUX)
|
||||
|
||||
**Community Optimization Series**:
|
||||
|
||||
- **Jib Mix Flux** Series: High-quality mixed models
|
||||
- **Real Dream FLUX** Series: Realism style
|
||||
- **Vision Realistic** Series: Visual realism
|
||||
- **PixelWave FLUX** Series: Pixel art optimization
|
||||
- **Fluxmania** Series: Diverse style support
|
||||
|
||||
### SD Series Model Support (93 models)
|
||||
|
||||
**SD3.5 Series**: 5 models
|
||||
**SD1.5 Series**: 37 models (including official, quantized, and community versions)
|
||||
**SDXL Series**: 50 models (including base, Refiner, and Playground models)
|
||||
|
||||
### Workflow Support
|
||||
|
||||
System supports **6 workflows**:
|
||||
|
||||
- **flux-dev**: High-quality creation workflow
|
||||
- **flux-schnell**: Fast generation workflow
|
||||
- **flux-kontext**: Image editing workflow
|
||||
- **sd35**: SD3.5 dedicated workflow
|
||||
- **simple-sd**: Simple SD workflow
|
||||
- **index**: Workflow entry point
|
||||
</details>
|
||||
|
||||
## Performance Optimization Recommendations
|
||||
|
||||
### Hardware Requirements
|
||||
|
||||
**Minimum Configuration** (GGUF quantized models):
|
||||
|
||||
- GPU: 6GB VRAM (using Q4 quantization)
|
||||
- RAM: 12GB
|
||||
- Storage: 30GB available space
|
||||
|
||||
**Recommended Configuration** (standard models):
|
||||
|
||||
- GPU: 12GB+ VRAM (RTX 4070 Ti or higher)
|
||||
- RAM: 24GB+
|
||||
- Storage: SSD 100GB+ available space
|
||||
|
||||
### VRAM Optimization Strategy
|
||||
|
||||
| VRAM Capacity | Recommended Quantization | Model Example | Performance Characteristics |
|
||||
| ------------- | ------------------------ | ---------------------------------- | --------------------------- |
|
||||
| **6-8GB** | Q4\_0, Q4\_K\_S | `flux1-dev-Q4_0.gguf` | Minimal VRAM usage |
|
||||
| **10-12GB** | Q6\_K, Q8\_0 | `flux1-dev-Q6_K.gguf` | Balance performance/quality |
|
||||
| **16GB+** | FP8, FP16 | `flux1-dev-fp8-e4m3fn.safetensors` | Near-original quality |
|
||||
| **24GB+** | Full model | `flux1-dev.safetensors` | Best quality |
|
||||
|
||||
## Custom Model Usage
|
||||
|
||||
<details>
|
||||
<summary><b>🎨 Configure Custom SD Models</b></summary>
|
||||
|
||||
LobeChat supports using custom Stable Diffusion models. The system uses fixed filenames to identify custom models.
|
||||
|
||||
### 1. Model File Preparation
|
||||
|
||||
**Required Files**:
|
||||
|
||||
- **Main Model File**: `custom_sd_lobe.safetensors`
|
||||
- **VAE File (Optional)**: `custom_sd_vae_lobe.safetensors`
|
||||
|
||||
### 2. Add Custom Model
|
||||
|
||||
**Method 1: Rename Existing Model**
|
||||
|
||||
```bash
|
||||
# Rename your model to fixed filename
|
||||
mv your_custom_model.safetensors custom_sd_lobe.safetensors
|
||||
|
||||
# Move to correct directory
|
||||
mv custom_sd_lobe.safetensors ComfyUI/models/diffusion_models/
|
||||
```
|
||||
|
||||
**Method 2: Create Symbolic Link (Recommended)**
|
||||
|
||||
```bash
|
||||
# Create soft link for easy model switching
|
||||
ln -s /path/to/your_model.safetensors ComfyUI/models/diffusion_models/custom_sd_lobe.safetensors
|
||||
```
|
||||
|
||||
### 3. Use Custom Model
|
||||
|
||||
In LobeChat, custom models will appear as:
|
||||
|
||||
- **stable-diffusion-custom**: Standard custom model
|
||||
- **stable-diffusion-custom-refiner**: Refiner custom model
|
||||
|
||||
### Custom Model Parameter Recommendations
|
||||
|
||||
| Parameter | SD 1.5 Models | SDXL Models |
|
||||
| ---------- | ------------- | ----------- |
|
||||
| **steps** | 20-30 | 25-40 |
|
||||
| **cfg** | 7.0 | 6.0-8.0 |
|
||||
| **width** | 512 | 1024 |
|
||||
| **height** | 512 | 1024 |
|
||||
</details>
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Smart Error Diagnosis System
|
||||
|
||||
LobeChat integrates a smart error handling system that can automatically diagnose and provide targeted solutions.
|
||||
|
||||
#### Error Types and Solutions
|
||||
|
||||
| Error Type | User Prompt | Automatic Diagnosis |
|
||||
| ------------------ | ---------------------------------- | --------------------------------------------------- |
|
||||
| **Connection** | "Cannot connect to ComfyUI server" | Auto-detect server status and connectivity |
|
||||
| **Authentication** | "API key invalid or expired" | Auto-verify authentication credentials |
|
||||
| **Permissions** | "Access permissions insufficient" | Auto-check user permissions and file access |
|
||||
| **Model Issues** | "Cannot find specified model file" | Auto-scan available models and suggest alternatives |
|
||||
| **Configuration** | "Configuration file error" | Auto-verify config completeness and syntax |
|
||||
|
||||
<details>
|
||||
<summary><b>🔍 Traditional Troubleshooting Methods</b></summary>
|
||||
|
||||
#### 1. Connection Failure
|
||||
|
||||
**Issue**: Cannot connect to ComfyUI server
|
||||
|
||||
**Solution**:
|
||||
|
||||
```bash
|
||||
# Confirm server running
|
||||
curl http://localhost:8188/system_stats
|
||||
|
||||
# Check port
|
||||
netstat -tulpn | grep 8188
|
||||
```
|
||||
|
||||
#### 2. Out of Memory
|
||||
|
||||
**Issue**: Memory errors during generation
|
||||
|
||||
**Solution**:
|
||||
|
||||
- Lower image resolution
|
||||
- Reduce generation steps
|
||||
- Use quantized models
|
||||
|
||||
#### 3. Authentication Failure
|
||||
|
||||
**Issue**: 401 or 403 errors
|
||||
|
||||
**Solution**:
|
||||
|
||||
- Verify authentication configuration
|
||||
- Check if Token is expired
|
||||
- Confirm user permissions
|
||||
</details>
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Prompt Writing
|
||||
|
||||
1. **Detailed Description**: Provide clear, detailed image descriptions
|
||||
2. **Style Specification**: Clearly specify artistic style, color style, etc.
|
||||
3. **Quality Keywords**: Add "4K", "high quality", "detailed" keywords
|
||||
4. **Avoid Contradictions**: Ensure description content is logically consistent
|
||||
|
||||
**Example**:
|
||||
|
||||
```plaintext
|
||||
A young woman with flowing long hair, wearing an elegant blue dress, standing in a cherry blossom park,
|
||||
sunlight filtering through leaves, warm atmosphere, cinematic lighting, 4K high resolution, detailed, photorealistic
|
||||
```
|
||||
|
||||
### Parameter Optimization
|
||||
|
||||
1. **FLUX Schnell**: Suitable for quick previews, use 4-step generation
|
||||
2. **FLUX Dev**: Balance quality and speed, CFG 3.5, 20 steps
|
||||
3. **FLUX Krea-dev**: Safe creation, CFG 4.5, note content filtering
|
||||
4. **FLUX Kontext-dev**: Image editing, strength 0.6-0.9
|
||||
|
||||
<Callout type={'warning'}>
|
||||
Please note during use:
|
||||
|
||||
- FLUX Dev, Krea-dev, Kontext-dev models are for non-commercial use only
|
||||
- Generated content must comply with relevant laws and platform policies
|
||||
- Large model generation may take considerable time, please be patient
|
||||
</Callout>
|
||||
|
||||
## API Reference
|
||||
|
||||
<details>
|
||||
<summary><b>📚 API Documentation</b></summary>
|
||||
|
||||
### Request Format
|
||||
|
||||
```typescript
|
||||
interface ComfyUIRequest {
|
||||
model: string; // Model ID, e.g., 'flux-schnell'
|
||||
prompt: string; // Text prompt
|
||||
width: number; // Image width
|
||||
height: number; // Image height
|
||||
steps: number; // Generation steps
|
||||
seed: number; // Random seed
|
||||
cfg?: number; // CFG Scale (Dev/Krea/Kontext specific)
|
||||
strength?: number; // Edit strength (Kontext specific)
|
||||
imageUrl?: string; // Input image (Kontext specific)
|
||||
}
|
||||
```
|
||||
|
||||
### Response Format
|
||||
|
||||
```typescript
|
||||
interface ComfyUIResponse {
|
||||
images: Array<{
|
||||
url: string; // Generated image URL
|
||||
filename: string; // Filename
|
||||
subfolder: string; // Subdirectory
|
||||
type: string; // File type
|
||||
}>;
|
||||
prompt_id: string; // Prompt ID
|
||||
}
|
||||
```
|
||||
|
||||
### Error Codes
|
||||
|
||||
| Error Code | Description | Resolution Suggestions |
|
||||
| ---------- | ------------------------ | -------------------------------- |
|
||||
| `400` | Invalid parameters | Check parameter format and range |
|
||||
| `401` | Authentication failed | Verify API key and auth config |
|
||||
| `403` | Insufficient permissions | Check user permissions |
|
||||
| `404` | Model not found | Confirm model file exists |
|
||||
| `500` | Server error | Check ComfyUI logs |
|
||||
</details>
|
||||
|
||||
You can now use ComfyUI in LobeChat for high-quality AI image generation and editing. If you encounter issues, please refer to the troubleshooting section or consult the [ComfyUI official documentation](https://github.com/comfyanonymous/ComfyUI).
|
||||
@@ -0,0 +1,816 @@
|
||||
---
|
||||
title: 在 LobeChat 中使用 ComfyUI 生成图像
|
||||
description: 学习如何在 LobeChat 中配置和使用 ComfyUI 服务,支持 FLUX 系列模型的高质量图像生成和编辑功能
|
||||
tags:
|
||||
- ComfyUI
|
||||
- FLUX
|
||||
- 文生图
|
||||
- 图像编辑
|
||||
- AI 图像生成
|
||||
---
|
||||
|
||||
# 在 LobeChat 中使用 ComfyUI
|
||||
|
||||
<Image alt={'在 LobeChat 中使用 ComfyUI'} cover src={'https://github.com/lobehub/lobe-chat/assets/17870709/c9e5eafc-ca22-496b-a88d-cc0ae53bf720'} />
|
||||
|
||||
本文档将指导你如何在 LobeChat 中使用 [ComfyUI](https://github.com/comfyanonymous/ComfyUI) 进行高质量的 AI 图像生成和编辑。
|
||||
|
||||
## ComfyUI 简介
|
||||
|
||||
ComfyUI 是一个功能强大的稳定扩散和流扩散 GUI,提供基于节点的工作流界面。LobeChat 集成了 ComfyUI,支持完整的 FLUX 系列模型,包括文本生成图像和图像编辑功能。
|
||||
|
||||
### 主要特性
|
||||
|
||||
- **广泛模型支持**:支持 223 个模型,包含 FLUX 系列(130 个)和 SD 系列(93 个)
|
||||
- **配置驱动架构**:注册表系统提供智能模型选择
|
||||
- **多格式支持**:支持 .safetensors 和 .gguf 格式,包含多种量化级别
|
||||
- **动态精度选择**:支持 default、fp8\_e4m3fn、fp8\_e5m2、fp8\_e4m3fn\_fast 精度
|
||||
- **多种认证方式**:支持无认证、基本认证、Bearer Token 和自定义认证
|
||||
- **智能组件选择**:自动选择最优的 T5、CLIP、VAE 编码器组合
|
||||
- **企业级优化**:包含 NF4、SVDQuant、TorchAO、MFLUX 等优化变体
|
||||
|
||||
## 快速开始
|
||||
|
||||
### 步骤一:在 LobeChat 中配置 ComfyUI
|
||||
|
||||
#### 1. 打开设置界面
|
||||
|
||||
- 访问 LobeChat 的 `设置` 界面
|
||||
- 在 `AI 服务商` 下找到 `ComfyUI` 的设置项
|
||||
|
||||
<Image alt={'ComfyUI 设置界面'} inStep src={'https://github.com/lobehub/lobe-chat/assets/17870709/3f31bc33-509f-4ad2-ba81-280c2a6ec5fa'} />
|
||||
|
||||
#### 2. 配置连接参数
|
||||
|
||||
**基本配置**:
|
||||
|
||||
- **服务器地址**:输入 ComfyUI 服务器地址,如 `http://localhost:8000`
|
||||
- **认证类型**:选择合适的认证方式(默认无认证)
|
||||
|
||||
### 步骤二:选择模型并开始生成图像
|
||||
|
||||
#### 1. 选择 FLUX 模型
|
||||
|
||||
在对话界面中:
|
||||
|
||||
- 点击模型选择按钮
|
||||
- 从 ComfyUI 分类中选择所需的 FLUX 模型
|
||||
|
||||
<Image alt={'选择 FLUX 模型'} inStep src={'https://github.com/lobehub/lobe-chat/assets/17870709/ff7ebacf-27f0-42d7-810b-00314499a084'} />
|
||||
|
||||
#### 2. 文本生成图像
|
||||
|
||||
**使用 FLUX Schnell(快速生成)**:
|
||||
|
||||
```plaintext
|
||||
Generate an image: A cute orange cat sitting on a sunny windowsill, warm lighting, detailed fur texture
|
||||
```
|
||||
|
||||
**使用 FLUX Dev(高质量生成)**:
|
||||
|
||||
```plaintext
|
||||
Generate high quality image: City skyline at sunset, cyberpunk style, neon lights, 4K high resolution, detailed architecture
|
||||
```
|
||||
|
||||
#### 3. 图像编辑
|
||||
|
||||
**使用 FLUX Kontext-dev 编辑图像**:
|
||||
|
||||
```plaintext
|
||||
Edit this image: Change the background to a starry night sky, keep the main subject, cosmic atmosphere
|
||||
```
|
||||
|
||||
然后上传需要编辑的原始图像。
|
||||
|
||||
<Callout type={'info'}>
|
||||
图像编辑功能需要先上传原始图像,然后描述你希望进行的修改。
|
||||
</Callout>
|
||||
|
||||
## 认证配置指南
|
||||
|
||||
ComfyUI 支持四种认证方式,请根据你的服务器配置和安全需求选择合适的认证方式:
|
||||
|
||||
### 无认证 (none)
|
||||
|
||||
**适用场景**:
|
||||
|
||||
- 本地开发环境(localhost)
|
||||
- 内网环境且信任所有用户
|
||||
- 个人使用的单机部署
|
||||
|
||||
**配置方法**:
|
||||
|
||||
```yaml
|
||||
认证类型:无认证
|
||||
服务器地址:http://localhost:8000
|
||||
```
|
||||
|
||||
### 基本认证 (basic)
|
||||
|
||||
**适用场景**:
|
||||
|
||||
- 使用 Nginx 反向代理的部署
|
||||
- 团队内部使用且需要基础访问控制
|
||||
|
||||
**配置方法**:
|
||||
|
||||
1. **创建用户密码**:
|
||||
|
||||
```bash
|
||||
# 安装 apache2-utils
|
||||
sudo apt-get install apache2-utils
|
||||
|
||||
# 创建用户 'admin'
|
||||
sudo htpasswd -c /etc/nginx/.htpasswd admin
|
||||
```
|
||||
|
||||
2. **LobeChat 配置**:
|
||||
|
||||
```yaml
|
||||
认证类型:基本认证
|
||||
服务器地址:https://your-domain.com
|
||||
用户名:admin
|
||||
密码:your_secure_password
|
||||
```
|
||||
|
||||
### Bearer Token (bearer)
|
||||
|
||||
**适用场景**:
|
||||
|
||||
- API 驱动的应用集成
|
||||
- 需要 Token 认证的企业环境
|
||||
|
||||
**生成 Token**:
|
||||
|
||||
```python
|
||||
import jwt
|
||||
import datetime
|
||||
|
||||
payload = {
|
||||
'user': 'admin',
|
||||
'exp': datetime.datetime.utcnow() + datetime.timedelta(days=30)
|
||||
}
|
||||
|
||||
secret_key = "your-secret-key"
|
||||
token = jwt.encode(payload, secret_key, algorithm='HS256')
|
||||
print(f"Bearer Token: {token}")
|
||||
```
|
||||
|
||||
**LobeChat 配置**:
|
||||
|
||||
```yaml
|
||||
认证类型:Bearer Token
|
||||
服务器地址:https://your-domain.com
|
||||
API 密钥:example-eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
||||
```
|
||||
|
||||
### 自定义认证 (custom)
|
||||
|
||||
**适用场景**:
|
||||
|
||||
- 集成现有企业认证系统
|
||||
- 需要多重认证头的系统
|
||||
|
||||
**LobeChat 配置**:
|
||||
|
||||
```yaml
|
||||
认证类型:自定义
|
||||
服务器地址:https://your-domain.com
|
||||
自定义请求头:
|
||||
{
|
||||
"X-API-Key": "your_api_key",
|
||||
"X-Client-ID": "lobechat"
|
||||
}
|
||||
```
|
||||
|
||||
## 常见问题处理
|
||||
|
||||
### 1. 如何安装 Comfy-Manager
|
||||
|
||||
Comfy-Manager 是 ComfyUI 的扩展管理器,让你能够轻松安装和管理各种节点、模型和扩展。
|
||||
|
||||
<details>
|
||||
<summary><b>📦 安装 Comfy-Manager 步骤</b></summary>
|
||||
|
||||
#### 方法一:手动安装(推荐)
|
||||
|
||||
```bash
|
||||
# 进入 ComfyUI 的 custom_nodes 目录
|
||||
cd ComfyUI/custom_nodes
|
||||
|
||||
# 克隆 Comfy-Manager 仓库
|
||||
git clone https://github.com/ltdrdata/ComfyUI-Manager.git
|
||||
|
||||
# 重启 ComfyUI 服务器
|
||||
# 重新启动后,你会在 UI 中看到 Manager 按钮
|
||||
```
|
||||
|
||||
#### 方法二:使用一键安装脚本
|
||||
|
||||
```bash
|
||||
# 在 ComfyUI 根目录下执行
|
||||
curl -fsSL https://raw.githubusercontent.com/ltdrdata/ComfyUI-Manager/main/install.sh | bash
|
||||
```
|
||||
|
||||
#### 验证安装
|
||||
|
||||
1. 重启 ComfyUI 服务器
|
||||
2. 访问 `http://localhost:8000`
|
||||
3. 你应该能在界面右下角看到 "Manager" 按钮
|
||||
|
||||
#### 使用 Comfy-Manager
|
||||
|
||||
**安装模型**:
|
||||
|
||||
1. 点击 "Manager" 按钮
|
||||
2. 选择 "Install Models"
|
||||
3. 搜索需要的模型(如 FLUX、SD3.5)
|
||||
4. 点击 "Install" 自动下载到正确目录
|
||||
|
||||
**安装节点扩展**:
|
||||
|
||||
1. 点击 "Manager" 按钮
|
||||
2. 选择 "Install Custom Nodes"
|
||||
3. 搜索需要的节点(如 ControlNet、AnimateDiff)
|
||||
4. 点击 "Install" 并重启服务器
|
||||
|
||||
**管理已安装内容**:
|
||||
|
||||
1. 点击 "Manager" 按钮
|
||||
2. 选择 "Installed" 查看已安装的扩展
|
||||
3. 可以更新、禁用或卸载扩展
|
||||
</details>
|
||||
|
||||
### 2. 如何处理 "Model not found" 错误
|
||||
|
||||
当你看到类似 `Model not found: flux1-dev.safetensors, please install one first.` 的错误时,说明服务器上缺少所需的模型文件。
|
||||
|
||||
<details>
|
||||
<summary><b>🔧 解决 Model not found 错误</b></summary>
|
||||
|
||||
#### 错误示例
|
||||
|
||||
```plaintext
|
||||
Model not found: flux1-dev.safetensors, please install one first.
|
||||
```
|
||||
|
||||
这个错误表示系统期望找到 `flux1-dev.safetensors` 模型文件,但在服务器上没有找到。
|
||||
|
||||
#### 解决方法
|
||||
|
||||
**方法一:使用 Comfy-Manager 下载(推荐)**
|
||||
|
||||
1. 打开 ComfyUI 界面
|
||||
2. 点击 "Manager" → "Install Models"
|
||||
3. 搜索错误提示中的模型名(如 "flux1-dev")
|
||||
4. 点击 "Install" 自动下载
|
||||
|
||||
**方法二:手动下载模型**
|
||||
|
||||
1. **下载模型文件**:
|
||||
- 访问 [Hugging Face](https://huggingface.co/black-forest-labs/FLUX.1-dev) 或其他模型源
|
||||
- 下载错误提示中的文件(如 `flux1-dev.safetensors`)
|
||||
|
||||
2. **放置到正确目录**:
|
||||
```bash
|
||||
# FLUX 和 SD3.5 主模型放入
|
||||
ComfyUI/models/diffusion_models/flux1-dev.safetensors
|
||||
|
||||
# SD1.5 和 SDXL 模型放入
|
||||
ComfyUI/models/checkpoints/
|
||||
```
|
||||
|
||||
3. **验证文件**:
|
||||
```bash
|
||||
# 检查文件是否存在
|
||||
ls -la ComfyUI/models/diffusion_models/flux1-dev.safetensors
|
||||
|
||||
# 检查文件完整性(可选)
|
||||
sha256sum flux1-dev.safetensors
|
||||
```
|
||||
|
||||
4. **重启 ComfyUI 服务器**
|
||||
|
||||
**方法三:使用 wget/curl 直接下载**
|
||||
|
||||
```bash
|
||||
# 进入模型目录
|
||||
cd ComfyUI/models/diffusion_models/
|
||||
|
||||
# 使用 wget 下载(替换为实际下载链接)
|
||||
wget https://huggingface.co/black-forest-labs/FLUX.1-dev/resolve/main/flux1-dev.safetensors
|
||||
|
||||
# 或使用 curl
|
||||
curl -L -o flux1-dev.safetensors https://huggingface.co/black-forest-labs/FLUX.1-dev/resolve/main/flux1-dev.safetensors
|
||||
```
|
||||
|
||||
#### 常见模型下载源
|
||||
|
||||
- **Hugging Face**:[https://huggingface.co/models](https://huggingface.co/models)
|
||||
- **Civitai**:[https://civitai.com/models](https://civitai.com/models)
|
||||
- **官方源**:
|
||||
- FLUX: [https://huggingface.co/black-forest-labs](https://huggingface.co/black-forest-labs)
|
||||
- SD3.5: [https://huggingface.co/stabilityai](https://huggingface.co/stabilityai)
|
||||
|
||||
#### 预防措施
|
||||
|
||||
1. **基础模型包**:至少下载一个基础模型
|
||||
- FLUX: `flux1-schnell.safetensors`(快速)或 `flux1-dev.safetensors`(高质量)
|
||||
- SD3.5: `sd3.5_large.safetensors`
|
||||
|
||||
2. **检查磁盘空间**:
|
||||
```bash
|
||||
# 检查可用空间
|
||||
df -h ComfyUI/models/
|
||||
```
|
||||
|
||||
3. **设置模型路径**(可选):
|
||||
如果你的模型存储在其他位置,可以创建符号链接:
|
||||
```bash
|
||||
ln -s /path/to/your/models ComfyUI/models/diffusion_models/
|
||||
```
|
||||
</details>
|
||||
|
||||
### 3. 如何处理缺少 System Component 错误
|
||||
|
||||
当你看到类似 `Missing VAE encoder: ae.safetensors` 或其他组件文件缺失的错误时,需要下载相应的系统组件。
|
||||
|
||||
<details>
|
||||
<summary><b>🛠️ 解决缺少 System Component 错误</b></summary>
|
||||
|
||||
#### 常见组件错误
|
||||
|
||||
```plaintext
|
||||
Missing VAE encoder: ae.safetensors. Please download and place it in the models/vae folder.
|
||||
Missing CLIP encoder: clip_l.safetensors. Please download and place it in the models/clip folder.
|
||||
Missing T5 encoder: t5xxl_fp16.safetensors. Please download and place it in the models/clip folder.
|
||||
```
|
||||
|
||||
#### 组件类型说明
|
||||
|
||||
| 组件类型 | 文件名示例 | 用途 | 存放目录 |
|
||||
| -------------- | ------------------------------ | ---------- | ------------------ |
|
||||
| **VAE** | ae.safetensors | 图像编码 / 解码 | models/vae/ |
|
||||
| **CLIP** | clip\_l.safetensors | 文本编码(CLIP) | models/clip/ |
|
||||
| **T5** | t5xxl\_fp16.safetensors | 文本编码(T5) | models/clip/ |
|
||||
| **ControlNet** | flux-controlnet-\*.safetensors | 控制网络 | models/controlnet/ |
|
||||
|
||||
#### 解决方法
|
||||
|
||||
**方法一:使用 Comfy-Manager(推荐)**
|
||||
|
||||
1. 点击 "Manager" → "Install Models"
|
||||
2. 在 "Filter" 中选择组件类型(VAE/CLIP/T5)
|
||||
3. 下载对应的组件文件
|
||||
|
||||
**方法二:手动下载必需组件**
|
||||
|
||||
##### FLUX 必需组件
|
||||
|
||||
```bash
|
||||
# 1. VAE 编码器
|
||||
cd ComfyUI/models/vae/
|
||||
wget https://huggingface.co/black-forest-labs/FLUX.1-dev/resolve/main/ae.safetensors
|
||||
|
||||
# 2. CLIP-L 编码器
|
||||
cd ComfyUI/models/clip/
|
||||
wget https://huggingface.co/comfyanonymous/flux_text_encoders/resolve/main/clip_l.safetensors
|
||||
|
||||
# 3. T5-XXL 编码器(可选择不同精度)
|
||||
# FP16 版本(推荐,平衡性能)
|
||||
wget https://huggingface.co/comfyanonymous/flux_text_encoders/resolve/main/t5xxl_fp16.safetensors
|
||||
|
||||
# 或 FP8 版本(节省显存)
|
||||
wget https://huggingface.co/comfyanonymous/flux_text_encoders/resolve/main/t5xxl_fp8_e4m3fn.safetensors
|
||||
```
|
||||
|
||||
##### SD3.5 必需组件
|
||||
|
||||
```bash
|
||||
# SD3.5 使用不同的编码器
|
||||
cd ComfyUI/models/clip/
|
||||
|
||||
# CLIP-G 编码器
|
||||
wget https://huggingface.co/stabilityai/stable-diffusion-3.5-large/resolve/main/text_encoders/clip_g.safetensors
|
||||
|
||||
# CLIP-L 编码器
|
||||
wget https://huggingface.co/stabilityai/stable-diffusion-3.5-large/resolve/main/text_encoders/clip_l.safetensors
|
||||
|
||||
# T5-XXL 编码器
|
||||
wget https://huggingface.co/stabilityai/stable-diffusion-3.5-large/resolve/main/text_encoders/t5xxl_fp16.safetensors
|
||||
```
|
||||
|
||||
##### SDXL 必需组件
|
||||
|
||||
```bash
|
||||
# SDXL VAE
|
||||
cd ComfyUI/models/vae/
|
||||
wget https://huggingface.co/stabilityai/sdxl-vae/resolve/main/sdxl_vae.safetensors
|
||||
|
||||
# SDXL 使用内置的 CLIP 编码器,通常不需要单独下载
|
||||
```
|
||||
|
||||
#### 组件兼容性矩阵
|
||||
|
||||
| 模型系列 | 必需 VAE | 必需 CLIP | 必需 T5 | 可选组件 |
|
||||
| --------- | -------------- | ------------------- | ----------------------- | ---------- |
|
||||
| **FLUX** | ae.safetensors | clip\_l.safetensors | t5xxl\_fp16.safetensors | ControlNet |
|
||||
| **SD3.5** | 内置 | clip\_g + clip\_l | t5xxl\_fp16 | - |
|
||||
| **SDXL** | sdxl\_vae | 内置 | - | Refiner |
|
||||
| **SD1.5** | vae-ft-mse | 内置 | - | ControlNet |
|
||||
|
||||
#### 精度选择建议
|
||||
|
||||
**T5 编码器精度选择**:
|
||||
|
||||
| 显存容量 | 推荐版本 | 文件名 |
|
||||
| ------- | ------ | ------------------------------ |
|
||||
| \< 12GB | FP8 量化 | t5xxl\_fp8\_e4m3fn.safetensors |
|
||||
| 12-16GB | FP16 | t5xxl\_fp16.safetensors |
|
||||
| > 16GB | FP32 | t5xxl.safetensors |
|
||||
|
||||
#### 验证组件安装
|
||||
|
||||
```bash
|
||||
# 检查所有必需组件
|
||||
echo "=== VAE Components ==="
|
||||
ls -la ComfyUI/models/vae/
|
||||
|
||||
echo "=== CLIP/T5 Components ==="
|
||||
ls -la ComfyUI/models/clip/
|
||||
|
||||
echo "=== ControlNet Components ==="
|
||||
ls -la ComfyUI/models/controlnet/
|
||||
```
|
||||
|
||||
#### 故障排除
|
||||
|
||||
**问题:下载后仍然报错**
|
||||
|
||||
1. **检查文件权限**:
|
||||
```bash
|
||||
chmod 644 ComfyUI/models/vae/*.safetensors
|
||||
chmod 644 ComfyUI/models/clip/*.safetensors
|
||||
```
|
||||
|
||||
2. **清除缓存**:
|
||||
```bash
|
||||
# 清除 ComfyUI 缓存
|
||||
rm -rf ComfyUI/temp/*
|
||||
rm -rf ComfyUI/__pycache__/*
|
||||
```
|
||||
|
||||
3. **重启服务器**:
|
||||
```bash
|
||||
# 完全重启 ComfyUI
|
||||
pkill -f "python main.py"
|
||||
python main.py --listen 0.0.0.0 --port 8000
|
||||
```
|
||||
|
||||
**问题:显存不足**
|
||||
|
||||
使用量化版本的组件:
|
||||
|
||||
- T5: 使用 `t5xxl_fp8_e4m3fn.safetensors` 而不是 FP16/FP32
|
||||
- VAE: 某些模型支持 FP16 VAE 版本
|
||||
|
||||
**问题:下载速度慢**
|
||||
|
||||
1. 使用镜像源(如适用)
|
||||
2. 使用下载工具(如 aria2c)支持断点续传:
|
||||
```bash
|
||||
aria2c -x 16 -s 16 -k 1M [下载链接]
|
||||
```
|
||||
</details>
|
||||
|
||||
## ComfyUI 服务器安装
|
||||
|
||||
<details>
|
||||
<summary><b>🚀 安装和配置 ComfyUI 服务器</b></summary>
|
||||
|
||||
### 1. 安装 ComfyUI
|
||||
|
||||
```bash
|
||||
# 克隆 ComfyUI 仓库
|
||||
git clone https://github.com/comfyanonymous/ComfyUI.git
|
||||
cd ComfyUI
|
||||
|
||||
# 安装依赖
|
||||
pip install -r requirements.txt
|
||||
|
||||
# 可选:安装JWT支持(用于Token认证)
|
||||
pip install PyJWT
|
||||
|
||||
# 启动 ComfyUI 服务器
|
||||
python main.py --listen 0.0.0.0 --port 8000
|
||||
```
|
||||
|
||||
### 2. 下载模型文件
|
||||
|
||||
**推荐基础配置** (最小化安装):
|
||||
|
||||
**主模型** (放入 `models/diffusion_models/` 目录):
|
||||
|
||||
- `flux1-schnell.safetensors` - 快速生成(4 步)
|
||||
- `flux1-dev.safetensors` - 高质量创作(20 步)
|
||||
|
||||
**必需组件** (放入相应目录):
|
||||
|
||||
- `models/vae/ae.safetensors` - VAE 编码器
|
||||
- `models/clip/clip_l.safetensors` - CLIP 文本编码器
|
||||
- `models/clip/t5xxl_fp16.safetensors` - T5 文本编码器
|
||||
|
||||
### 3. 验证服务器运行
|
||||
|
||||
访问 `http://localhost:8000` 确认 ComfyUI 界面正常加载。
|
||||
|
||||
<Callout type={'info'}>
|
||||
**智能模型选择**:LobeChat 会根据服务器上可用的模型文件自动选择最佳模型。您无需下载所有模型,系统会在可用模型中按优先级(官方 > 企业 > 社区)自动选择。
|
||||
</Callout>
|
||||
</details>
|
||||
|
||||
## 支持的模型
|
||||
|
||||
LobeChat ComfyUI 集成采用配置驱动的架构,支持 **223 个模型**,提供从官方模型到社区优化版本的全覆盖。
|
||||
|
||||
### FLUX 系列推荐参数
|
||||
|
||||
| 模型类型 | 推荐步数 | CFG Scale | 分辨率范围 |
|
||||
| ----------- | ---- | --------- | ------------------- |
|
||||
| **Schnell** | 4 步 | - | 512×512 至 1536×1536 |
|
||||
| **Dev** | 20 步 | 3.5 | 512×512 至 2048×2048 |
|
||||
| **Kontext** | 20 步 | 3.5 | 512×512 至 2048×2048 |
|
||||
| **Krea** | 20 步 | 4.5 | 512×512 至 2048×2048 |
|
||||
|
||||
### SD3.5 系列参数
|
||||
|
||||
| 模型类型 | 推荐步数 | CFG Scale | 分辨率范围 |
|
||||
| --------------- | ---- | --------- | ------------------- |
|
||||
| **Large** | 25 步 | 7.0 | 512×512 至 2048×2048 |
|
||||
| **Large Turbo** | 8 步 | 3.5 | 512×512 至 1536×1536 |
|
||||
| **Medium** | 20 步 | 6.0 | 512×512 至 1536×1536 |
|
||||
|
||||
<details>
|
||||
<summary><b>📋 当前完整支持的模型列表</b></summary>
|
||||
|
||||
### 模型分类体系
|
||||
|
||||
#### 优先级 1:官方核心模型
|
||||
|
||||
**FLUX.1 Official 系列**:
|
||||
|
||||
- `flux1-dev.safetensors` - 高质量创作模型
|
||||
- `flux1-schnell.safetensors` - 快速生成模型
|
||||
- `flux1-kontext-dev.safetensors` - 图像编辑模型
|
||||
- `flux1-krea-dev.safetensors` - 安全增强模型
|
||||
|
||||
**SD3.5 Official 系列**:
|
||||
|
||||
- `sd3.5_large.safetensors` - SD3.5 大型基础模型
|
||||
- `sd3.5_large_turbo.safetensors` - 快速生成版本
|
||||
- `sd3.5_medium.safetensors` - 中等规模模型
|
||||
|
||||
#### 优先级 2:企业优化模型(106 个 FLUX)
|
||||
|
||||
**量化优化系列**:
|
||||
|
||||
- **GGUF 量化**:每个变体支持 11 种量化级别(F16, Q8\_0, Q6\_K, Q5\_K\_M, Q5\_K\_S, Q4\_K\_M, Q4\_K\_S, Q4\_0, Q3\_K\_M, Q3\_K\_S, Q2\_K)
|
||||
- **FP8 精度**:fp8\_e4m3fn、fp8\_e5m2 优化版本
|
||||
- **企业轻量级**:FLUX.1-lite-8B 系列
|
||||
- **技术实验**:NF4、SVDQuant、TorchAO、optimum-quanto、MFLUX 优化版本
|
||||
|
||||
#### 优先级 3:社区精调模型(48 个 FLUX)
|
||||
|
||||
**社区优化系列**:
|
||||
|
||||
- **Jib Mix Flux** 系列:高质量混合模型
|
||||
- **Real Dream FLUX** 系列:现实主义风格
|
||||
- **Vision Realistic** 系列:视觉现实化
|
||||
- **PixelWave FLUX** 系列:像素艺术优化
|
||||
- **Fluxmania** 系列:多样化风格支持
|
||||
|
||||
### SD 系列模型支持(93 个)
|
||||
|
||||
**SD3.5 系列**:5 个模型
|
||||
**SD1.5 系列**:37 个模型(包括官方、量化和社区版本)
|
||||
**SDXL 系列**:50 个模型(包括基础、Refiner 和 Playground 模型)
|
||||
|
||||
### 工作流支持
|
||||
|
||||
系统支持 **6 种工作流**:
|
||||
|
||||
- **flux-dev**:高质量创作工作流
|
||||
- **flux-schnell**:快速生成工作流
|
||||
- **flux-kontext**:图像编辑工作流
|
||||
- **sd35**:SD3.5 专用工作流
|
||||
- **simple-sd**:简单 SD 工作流
|
||||
- **index**:工作流入口
|
||||
</details>
|
||||
|
||||
## 性能优化建议
|
||||
|
||||
### 硬件要求
|
||||
|
||||
**最低配置** (GGUF 量化模型):
|
||||
|
||||
- GPU:6GB VRAM (使用 Q4 量化)
|
||||
- RAM:12GB
|
||||
- 存储:30GB 可用空间
|
||||
|
||||
**推荐配置** (标准模型):
|
||||
|
||||
- GPU:12GB+ VRAM (RTX 4070 Ti 或更高)
|
||||
- RAM:24GB+
|
||||
- 存储:SSD 100GB+ 可用空间
|
||||
|
||||
### 显存优化策略
|
||||
|
||||
| 显存容量 | 推荐量化 | 模型示例 | 性能特点 |
|
||||
| ----------- | --------------- | ---------------------------------- | ------- |
|
||||
| **6-8GB** | Q4\_0, Q4\_K\_S | `flux1-dev-Q4_0.gguf` | 最小显存占用 |
|
||||
| **10-12GB** | Q6\_K, Q8\_0 | `flux1-dev-Q6_K.gguf` | 平衡性能与质量 |
|
||||
| **16GB+** | FP8, FP16 | `flux1-dev-fp8-e4m3fn.safetensors` | 接近原始质量 |
|
||||
| **24GB+** | 完整模型 | `flux1-dev.safetensors` | 最佳质量 |
|
||||
|
||||
## 自定义模型使用
|
||||
|
||||
<details>
|
||||
<summary><b>🎨 配置自定义 SD 模型</b></summary>
|
||||
|
||||
LobeChat 支持使用自定义的 Stable Diffusion 模型。系统使用固定的文件名来识别自定义模型。
|
||||
|
||||
### 1. 模型文件准备
|
||||
|
||||
**必需文件**:
|
||||
|
||||
- **主模型文件**:`custom_sd_lobe.safetensors`
|
||||
- **VAE 文件(可选)**:`custom_sd_vae_lobe.safetensors`
|
||||
|
||||
### 2. 添加自定义模型
|
||||
|
||||
**方法一:重命名现有模型**
|
||||
|
||||
```bash
|
||||
# 将您的模型重命名为固定文件名
|
||||
mv your_custom_model.safetensors custom_sd_lobe.safetensors
|
||||
|
||||
# 移动到正确目录
|
||||
mv custom_sd_lobe.safetensors ComfyUI/models/diffusion_models/
|
||||
```
|
||||
|
||||
**方法二:创建符号链接(推荐)**
|
||||
|
||||
```bash
|
||||
# 创建软链接,方便切换不同模型
|
||||
ln -s /path/to/your_model.safetensors ComfyUI/models/diffusion_models/custom_sd_lobe.safetensors
|
||||
```
|
||||
|
||||
### 3. 使用自定义模型
|
||||
|
||||
在 LobeChat 中,自定义模型会显示为:
|
||||
|
||||
- **stable-diffusion-custom**:标准自定义模型
|
||||
- **stable-diffusion-custom-refiner**:Refiner 自定义模型
|
||||
|
||||
### 自定义模型参数建议
|
||||
|
||||
| 参数 | SD 1.5 模型 | SDXL 模型 |
|
||||
| ---------- | --------- | ------- |
|
||||
| **steps** | 20-30 | 25-40 |
|
||||
| **cfg** | 7.0 | 6.0-8.0 |
|
||||
| **width** | 512 | 1024 |
|
||||
| **height** | 512 | 1024 |
|
||||
</details>
|
||||
|
||||
## 故障排除
|
||||
|
||||
### 智能错误诊断系统
|
||||
|
||||
LobeChat 集成了智能错误处理系统,能够自动诊断并提供针对性的解决方案。
|
||||
|
||||
#### 错误类型与解决方案
|
||||
|
||||
| 错误类型 | 用户提示 | 自动诊断 |
|
||||
| -------- | ------------------- | --------------- |
|
||||
| **连接问题** | "无法连接到 ComfyUI 服务器" | 自动检测服务器状态和网络连通性 |
|
||||
| **认证问题** | "API 密钥无效或已过期" | 自动验证认证凭据有效性 |
|
||||
| **权限问题** | "访问权限不足" | 自动检查用户权限和文件访问权限 |
|
||||
| **模型问题** | "找不到指定的模型文件" | 自动扫描可用模型并建议替代方案 |
|
||||
| **配置问题** | "配置文件存在错误" | 自动验证配置完整性和语法正确性 |
|
||||
|
||||
<details>
|
||||
<summary><b>🔍 传统故障排除方法</b></summary>
|
||||
|
||||
#### 1. 连接失败
|
||||
|
||||
**问题**:无法连接到 ComfyUI 服务器
|
||||
|
||||
**解决方案**:
|
||||
|
||||
```bash
|
||||
# 确认服务器运行
|
||||
curl http://localhost:8000/system_stats
|
||||
|
||||
# 检查端口
|
||||
netstat -tulpn | grep 8000
|
||||
```
|
||||
|
||||
#### 2. 内存不足
|
||||
|
||||
**问题**:生成过程中出现内存错误
|
||||
|
||||
**解决方案**:
|
||||
|
||||
- 降低图像分辨率
|
||||
- 减少生成步数
|
||||
- 使用量化模型
|
||||
|
||||
#### 3. 认证失败
|
||||
|
||||
**问题**:401 或 403 错误
|
||||
|
||||
**解决方案**:
|
||||
|
||||
- 验证认证配置
|
||||
- 检查 Token 是否过期
|
||||
- 确认用户权限
|
||||
</details>
|
||||
|
||||
## 最佳实践
|
||||
|
||||
### 提示词编写
|
||||
|
||||
1. **详细描述**:提供清晰、详细的图像描述
|
||||
2. **风格指定**:明确指定艺术风格、色彩风格等
|
||||
3. **质量关键词**:添加 "4K", "high quality", "detailed" 等关键词
|
||||
4. **避免矛盾**:确保描述内容逻辑一致
|
||||
|
||||
**示例**:
|
||||
|
||||
```plaintext
|
||||
A young woman with flowing long hair, wearing an elegant blue dress, standing in a cherry blossom park,
|
||||
sunlight filtering through leaves, warm atmosphere, cinematic lighting, 4K high resolution, detailed, photorealistic
|
||||
```
|
||||
|
||||
### 参数调优
|
||||
|
||||
1. **FLUX Schnell**:适合快速预览,使用 4 步生成
|
||||
2. **FLUX Dev**:平衡质量和速度,CFG 3.5,步数 20
|
||||
3. **FLUX Krea-dev**:安全创作,CFG 4.5,注意内容过滤
|
||||
4. **FLUX Kontext-dev**:图像编辑,strength 0.6-0.9
|
||||
|
||||
<Callout type={'warning'}>
|
||||
在使用过程中请注意:
|
||||
|
||||
- FLUX Dev、Krea-dev、Kontext-dev 模型仅限非商业使用
|
||||
- 生成内容请遵守相关法律法规和平台政策
|
||||
- 大型模型生成可能需要较长时间,请耐心等待
|
||||
</Callout>
|
||||
|
||||
## API 参考
|
||||
|
||||
<details>
|
||||
<summary><b>📚 API 文档</b></summary>
|
||||
|
||||
### 请求格式
|
||||
|
||||
```typescript
|
||||
interface ComfyUIRequest {
|
||||
model: string; // 模型 ID,如 'flux-schnell'
|
||||
prompt: string; // 文本提示词
|
||||
width: number; // 图像宽度
|
||||
height: number; // 图像高度
|
||||
steps: number; // 生成步数
|
||||
seed: number; // 随机种子
|
||||
cfg?: number; // CFG Scale (Dev/Krea/Kontext 专用)
|
||||
strength?: number; // 编辑强度 (Kontext 专用)
|
||||
imageUrl?: string; // 输入图像 (Kontext 专用)
|
||||
}
|
||||
```
|
||||
|
||||
### 响应格式
|
||||
|
||||
```typescript
|
||||
interface ComfyUIResponse {
|
||||
images: Array<{
|
||||
url: string; // 生成的图像 URL
|
||||
filename: string; // 文件名
|
||||
subfolder: string; // 子目录
|
||||
type: string; // 文件类型
|
||||
}>;
|
||||
prompt_id: string; // 提示 ID
|
||||
}
|
||||
```
|
||||
|
||||
### 错误代码
|
||||
|
||||
| 错误代码 | 描述 | 解决建议 |
|
||||
| ----- | ------ | -------------- |
|
||||
| `400` | 请求参数无效 | 检查参数格式和范围 |
|
||||
| `401` | 认证失败 | 验证 API 密钥和认证配置 |
|
||||
| `403` | 权限不足 | 检查用户权限 |
|
||||
| `404` | 模型未找到 | 确认模型文件存在 |
|
||||
| `500` | 服务器错误 | 检查 ComfyUI 日志 |
|
||||
</details>
|
||||
|
||||
至此你已经可以在 LobeChat 中使用 ComfyUI 进行高质量的 AI 图像生成和编辑了。如果遇到问题,请参考故障排除部分或查阅 [ComfyUI 官方文档](https://github.com/comfyanonymous/ComfyUI)。
|
||||
+143
@@ -0,0 +1,143 @@
|
||||
# E2E Tests for LobeChat
|
||||
|
||||
This directory contains end-to-end (E2E) tests for LobeChat using Cucumber (BDD) and Playwright.
|
||||
|
||||
## Directory Structure
|
||||
|
||||
````
|
||||
e2e/
|
||||
├── src/ # Source files
|
||||
│ ├── features/ # Gherkin feature files
|
||||
│ │ └── discover/ # Discover page tests
|
||||
│ ├── steps/ # Step definitions
|
||||
│ │ ├── common/ # Reusable step definitions
|
||||
│ │ └── discover/ # Discover-specific steps
|
||||
│ └── support/ # Test support files
|
||||
│ └── world.ts # Custom World context
|
||||
├── reports/ # Test reports (generated)
|
||||
├── cucumber.config.js # Cucumber configuration
|
||||
├── tsconfig.json # TypeScript configuration
|
||||
└── package.json # Dependencies and scripts
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Node.js 20, 22, or >=24
|
||||
- Dev server running on `http://localhost:3010` (or set `BASE_URL` env var)
|
||||
|
||||
## Installation
|
||||
|
||||
Install dependencies:
|
||||
|
||||
```bash
|
||||
cd e2e
|
||||
pnpm install
|
||||
````
|
||||
|
||||
Install Playwright browsers:
|
||||
|
||||
```bash
|
||||
npx playwright install chromium
|
||||
```
|
||||
|
||||
## Running Tests
|
||||
|
||||
Run all tests:
|
||||
|
||||
```bash
|
||||
npm test
|
||||
```
|
||||
|
||||
Run tests in headed mode (see browser):
|
||||
|
||||
```bash
|
||||
npm run test:headed
|
||||
```
|
||||
|
||||
Run only smoke tests:
|
||||
|
||||
```bash
|
||||
npm run test:smoke
|
||||
```
|
||||
|
||||
Run discover tests:
|
||||
|
||||
```bash
|
||||
npm run test:discover
|
||||
```
|
||||
|
||||
## Environment Variables
|
||||
|
||||
- `BASE_URL`: Base URL for the application (default: `http://localhost:3010`)
|
||||
- `PORT`: Port number (default: `3010`)
|
||||
- `HEADLESS`: Run browser in headless mode (default: `true`, set to `false` to see browser)
|
||||
|
||||
Example:
|
||||
|
||||
```bash
|
||||
HEADLESS=false BASE_URL=http://localhost:3000 npm run test:smoke
|
||||
```
|
||||
|
||||
## Writing Tests
|
||||
|
||||
### Feature Files
|
||||
|
||||
Feature files are written in Gherkin syntax and placed in the `src/features/` directory:
|
||||
|
||||
```gherkin
|
||||
@discover @smoke
|
||||
Feature: Discover Smoke Tests
|
||||
Critical path tests to ensure the discover module is functional
|
||||
|
||||
@DISCOVER-SMOKE-001 @P0
|
||||
Scenario: Load discover assistant list page
|
||||
Given I navigate to "/discover/assistant"
|
||||
Then the page should load without errors
|
||||
And I should see the page body
|
||||
And I should see the search bar
|
||||
And I should see assistant cards
|
||||
```
|
||||
|
||||
### Step Definitions
|
||||
|
||||
Step definitions are TypeScript files in the `src/steps/` directory that implement the steps from feature files:
|
||||
|
||||
```typescript
|
||||
import { Given, Then } from '@cucumber/cucumber';
|
||||
import { expect } from '@playwright/test';
|
||||
|
||||
import { CustomWorld } from '../../support/world';
|
||||
|
||||
Given('I navigate to {string}', async function (this: CustomWorld, path: string) {
|
||||
await this.page.goto(path);
|
||||
await this.page.waitForLoadState('domcontentloaded');
|
||||
});
|
||||
```
|
||||
|
||||
## Test Reports
|
||||
|
||||
After running tests, HTML and JSON reports are generated in the `reports/` directory:
|
||||
|
||||
- `reports/cucumber-report.html` - Human-readable HTML report
|
||||
- `reports/cucumber-report.json` - Machine-readable JSON report
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Browser not found
|
||||
|
||||
If you see errors about missing browser executables:
|
||||
|
||||
```bash
|
||||
npx playwright install chromium
|
||||
```
|
||||
|
||||
### Port already in use
|
||||
|
||||
Make sure the dev server is running on the expected port (3010 by default), or set `PORT` or `BASE_URL` environment variable.
|
||||
|
||||
### Test timeout
|
||||
|
||||
Increase timeout in `cucumber.config.js` or `src/steps/hooks.ts`:
|
||||
|
||||
```typescript
|
||||
setDefaultTimeout(120000); // 2 minutes
|
||||
```
|
||||
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* @type {import('@cucumber/cucumber').IConfiguration}
|
||||
*/
|
||||
export default {
|
||||
format: [
|
||||
'progress-bar',
|
||||
'html:reports/cucumber-report.html',
|
||||
'json:reports/cucumber-report.json',
|
||||
],
|
||||
formatOptions: {
|
||||
snippetInterface: 'async-await',
|
||||
},
|
||||
parallel: process.env.CI ? 1 : 4,
|
||||
paths: ['src/features/**/*.feature'],
|
||||
publishQuiet: true,
|
||||
require: ['src/steps/**/*.ts', 'src/support/**/*.ts'],
|
||||
requireModule: ['tsx/cjs'],
|
||||
retry: 0,
|
||||
timeout: 120_000,
|
||||
};
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "@lobechat/e2e-tests",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"description": "E2E tests for LobeChat using Cucumber and Playwright",
|
||||
"scripts": {
|
||||
"test": "cucumber-js --config cucumber.config.js",
|
||||
"test:discover": "cucumber-js --config cucumber.config.js src/features/discover/",
|
||||
"test:headed": "HEADLESS=false cucumber-js --config cucumber.config.js",
|
||||
"test:routes": "cucumber-js --config cucumber.config.js --tags '@routes'",
|
||||
"test:routes:ci": "cucumber-js --config cucumber.config.js --tags '@routes and not @ci-skip'",
|
||||
"test:smoke": "cucumber-js --config cucumber.config.js --tags '@smoke'"
|
||||
},
|
||||
"dependencies": {
|
||||
"@cucumber/cucumber": "^12.2.0",
|
||||
"@playwright/test": "^1.56.1",
|
||||
"playwright": "^1.56.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^22.10.5",
|
||||
"tsx": "^4.20.6",
|
||||
"typescript": "^5.7.3"
|
||||
}
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
import { expect, test } from '@playwright/test';
|
||||
|
||||
// 覆盖核心可访问路径(含重定向来源)
|
||||
const baseRoutes: string[] = [
|
||||
'/',
|
||||
'/chat',
|
||||
'/discover',
|
||||
'/image',
|
||||
'/files',
|
||||
'/repos', // next.config.ts -> /files
|
||||
'/changelog',
|
||||
];
|
||||
|
||||
// settings 路由改为通过 query 参数控制 active tab
|
||||
// 参考 SettingsTabs: about, agent, common, hotkey, llm, provider, proxy, storage, system-agent, tts
|
||||
const settingsTabs = [
|
||||
'common',
|
||||
'llm',
|
||||
'provider',
|
||||
'about',
|
||||
'hotkey',
|
||||
'proxy',
|
||||
'storage',
|
||||
'tts',
|
||||
'system-agent',
|
||||
'agent',
|
||||
];
|
||||
|
||||
const routes: string[] = [...baseRoutes, ...settingsTabs.map((key) => `/settings?active=${key}`)];
|
||||
|
||||
// CI 环境下跳过容易不稳定或受特性开关影响的路由
|
||||
const ciSkipPaths = new Set<string>([
|
||||
'/image',
|
||||
'/changelog',
|
||||
'/settings?active=common',
|
||||
'/settings?active=llm',
|
||||
]);
|
||||
|
||||
// @ts-ignore
|
||||
async function assertNoPageErrors(page: Parameters<typeof test>[0]['page']) {
|
||||
const pageErrors: Error[] = [];
|
||||
const consoleErrors: string[] = [];
|
||||
|
||||
page.on('pageerror', (err: Error) => pageErrors.push(err));
|
||||
page.on('console', (msg: any) => {
|
||||
if (msg.type() === 'error') consoleErrors.push(msg.text());
|
||||
});
|
||||
|
||||
// 仅校验页面级错误,忽略控制台 error 以提升稳定性
|
||||
expect
|
||||
.soft(pageErrors, `page errors: ${pageErrors.map((e) => e.message).join('\n')}`)
|
||||
.toHaveLength(0);
|
||||
}
|
||||
|
||||
test.describe('Smoke: core routes', () => {
|
||||
for (const path of routes) {
|
||||
test(`should open ${path} without error`, async ({ page }) => {
|
||||
if (process.env.CI && ciSkipPaths.has(path)) test.skip(true, 'skip flaky route on CI');
|
||||
const response = await page.goto(path, { waitUntil: 'commit' });
|
||||
// 2xx 或 3xx 视为可接受(允许中间件/重定向)
|
||||
const status = response?.status() ?? 0;
|
||||
expect(status, `unexpected status for ${path}: ${status}`).toBeLessThan(400);
|
||||
|
||||
// 一般错误标题防御
|
||||
await expect(page).not.toHaveTitle(/not found|error/i);
|
||||
|
||||
// body 可见
|
||||
await expect(page.locator('body')).toBeVisible();
|
||||
|
||||
await assertNoPageErrors(page);
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,11 @@
|
||||
@discover @smoke
|
||||
Feature: Discover Smoke Tests
|
||||
Critical path tests to ensure the discover module is functional
|
||||
|
||||
@DISCOVER-SMOKE-001 @P0
|
||||
Scenario: Load discover assistant list page
|
||||
Given I navigate to "/discover/assistant"
|
||||
Then the page should load without errors
|
||||
And I should see the page body
|
||||
And I should see the search bar
|
||||
And I should see assistant cards
|
||||
@@ -0,0 +1,43 @@
|
||||
@routes @smoke
|
||||
Feature: Core Routes Accessibility
|
||||
As a user
|
||||
I want all core application routes to be accessible
|
||||
So that I can navigate the application without errors
|
||||
|
||||
Background:
|
||||
Given the application is running
|
||||
|
||||
@ROUTES-001 @P0
|
||||
Scenario Outline: Access core routes without errors
|
||||
When I navigate to "<route>"
|
||||
Then the response status should be less than 400
|
||||
And the page should load without errors
|
||||
And I should see the page body
|
||||
And the page title should not contain "error" or "not found"
|
||||
|
||||
Examples:
|
||||
| route |
|
||||
| / |
|
||||
| /chat |
|
||||
| /discover |
|
||||
| /files |
|
||||
| /repos |
|
||||
|
||||
@ROUTES-002 @P0
|
||||
Scenario Outline: Access settings routes without errors
|
||||
When I navigate to "/settings?active=<tab>"
|
||||
Then the response status should be less than 400
|
||||
And the page should load without errors
|
||||
And I should see the page body
|
||||
And the page title should not contain "error" or "not found"
|
||||
|
||||
Examples:
|
||||
| tab |
|
||||
| about |
|
||||
| agent |
|
||||
| hotkey |
|
||||
| provider |
|
||||
| proxy |
|
||||
| storage |
|
||||
| system-agent |
|
||||
| tts |
|
||||
@@ -0,0 +1,36 @@
|
||||
import { Given, Then } from '@cucumber/cucumber';
|
||||
import { expect } from '@playwright/test';
|
||||
|
||||
import { CustomWorld } from '../../support/world';
|
||||
|
||||
// ============================================
|
||||
// Given Steps (Preconditions)
|
||||
// ============================================
|
||||
|
||||
Given('I navigate to {string}', async function (this: CustomWorld, path: string) {
|
||||
const response = await this.page.goto(path, { waitUntil: 'commit' });
|
||||
this.testContext.lastResponse = response;
|
||||
await this.page.waitForLoadState('domcontentloaded');
|
||||
});
|
||||
|
||||
// ============================================
|
||||
// Then Steps (Assertions)
|
||||
// ============================================
|
||||
|
||||
Then('the page should load without errors', async function (this: CustomWorld) {
|
||||
// Check for no JavaScript errors
|
||||
expect(this.testContext.jsErrors).toHaveLength(0);
|
||||
|
||||
// Check page didn't navigate to error page
|
||||
const url = this.page.url();
|
||||
expect(url).not.toMatch(/\/404|\/error|not-found/i);
|
||||
|
||||
// Check no error title
|
||||
const title = await this.page.title();
|
||||
expect(title).not.toMatch(/not found|error/i);
|
||||
});
|
||||
|
||||
Then('I should see the page body', async function (this: CustomWorld) {
|
||||
const body = this.page.locator('body');
|
||||
await expect(body).toBeVisible();
|
||||
});
|
||||
@@ -0,0 +1,34 @@
|
||||
import { Then } from '@cucumber/cucumber';
|
||||
import { expect } from '@playwright/test';
|
||||
|
||||
import { CustomWorld } from '../../support/world';
|
||||
|
||||
// ============================================
|
||||
// Then Steps (Assertions)
|
||||
// ============================================
|
||||
|
||||
Then('I should see the search bar', async function (this: CustomWorld) {
|
||||
// Wait for network to be idle to ensure Suspense components are loaded
|
||||
await this.page.waitForLoadState('networkidle', { timeout: 120_000 });
|
||||
|
||||
// The SearchBar component from @lobehub/ui may not pass through data-testid
|
||||
// Try to find the input element within the search component
|
||||
const searchBar = this.page.locator('input[type="text"]').first();
|
||||
await expect(searchBar).toBeVisible({ timeout: 120_000 });
|
||||
});
|
||||
|
||||
Then('I should see assistant cards', async function (this: CustomWorld) {
|
||||
// Wait for content to load
|
||||
await this.page.waitForLoadState('networkidle', { timeout: 120_000 });
|
||||
|
||||
// After migrating to SPA (react-router), links use relative paths like /assistant/:id
|
||||
// Look for assistant items by data-testid instead of href
|
||||
const assistantItems = this.page.locator('[data-testid="assistant-item"]');
|
||||
|
||||
// Wait for at least one item to be visible
|
||||
await expect(assistantItems.first()).toBeVisible({ timeout: 120_000 });
|
||||
|
||||
// Check we have multiple items
|
||||
const count = await assistantItems.count();
|
||||
expect(count).toBeGreaterThan(0);
|
||||
});
|
||||
@@ -0,0 +1,69 @@
|
||||
import { After, AfterAll, Before, BeforeAll, Status, setDefaultTimeout } from '@cucumber/cucumber';
|
||||
|
||||
import { startWebServer, stopWebServer } from '../support/webServer';
|
||||
import { CustomWorld } from '../support/world';
|
||||
|
||||
// Set default timeout for all steps to 120 seconds
|
||||
setDefaultTimeout(120_000);
|
||||
|
||||
BeforeAll({ timeout: 120_000 }, async function () {
|
||||
console.log('🚀 Starting E2E test suite...');
|
||||
|
||||
const PORT = process.env.PORT ? Number(process.env.PORT) : 3010;
|
||||
const BASE_URL = process.env.BASE_URL || `http://localhost:${PORT}`;
|
||||
|
||||
console.log(`Base URL: ${BASE_URL}`);
|
||||
|
||||
// Start web server if not using external BASE_URL
|
||||
if (!process.env.BASE_URL) {
|
||||
await startWebServer({
|
||||
command: 'npm run dev',
|
||||
port: PORT,
|
||||
reuseExistingServer: !process.env.CI,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
Before(async function (this: CustomWorld, { pickle }) {
|
||||
await this.init();
|
||||
|
||||
const testId = pickle.tags.find((tag) => tag.name.startsWith('@DISCOVER-'));
|
||||
console.log(`\n📝 Running: ${pickle.name}${testId ? ` (${testId.name.replace('@', '')})` : ''}`);
|
||||
});
|
||||
|
||||
After(async function (this: CustomWorld, { pickle, result }) {
|
||||
const testId = pickle.tags
|
||||
.find((tag) => tag.name.startsWith('@DISCOVER-'))
|
||||
?.name.replace('@', '');
|
||||
|
||||
if (result?.status === Status.FAILED) {
|
||||
const screenshot = await this.takeScreenshot(`${testId || 'failure'}-${Date.now()}`);
|
||||
this.attach(screenshot, 'image/png');
|
||||
|
||||
const html = await this.page.content();
|
||||
this.attach(html, 'text/html');
|
||||
|
||||
if (this.testContext.jsErrors.length > 0) {
|
||||
const errors = this.testContext.jsErrors.map((e) => e.message).join('\n');
|
||||
this.attach(`JavaScript Errors:\n${errors}`, 'text/plain');
|
||||
}
|
||||
|
||||
console.log(`❌ Failed: ${pickle.name}`);
|
||||
if (result.message) {
|
||||
console.log(` Error: ${result.message}`);
|
||||
}
|
||||
} else if (result?.status === Status.PASSED) {
|
||||
console.log(`✅ Passed: ${pickle.name}`);
|
||||
}
|
||||
|
||||
await this.cleanup();
|
||||
});
|
||||
|
||||
AfterAll(async function () {
|
||||
console.log('\n🏁 Test suite completed');
|
||||
|
||||
// Stop web server if we started it
|
||||
if (!process.env.BASE_URL && process.env.CI) {
|
||||
await stopWebServer();
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,41 @@
|
||||
import { Given, Then } from '@cucumber/cucumber';
|
||||
import { expect } from '@playwright/test';
|
||||
|
||||
import { CustomWorld } from '../../support/world';
|
||||
|
||||
// ============================================
|
||||
// Given Steps (Preconditions)
|
||||
// ============================================
|
||||
|
||||
Given('the application is running', async function (this: CustomWorld) {
|
||||
// This is a placeholder step to indicate that the app should be running
|
||||
// The actual server startup is handled outside the test (in CI or locally)
|
||||
// We just verify we can reach the base URL
|
||||
const response = await this.page.goto('/');
|
||||
expect(response).toBeTruthy();
|
||||
// Store the response for later assertions
|
||||
this.testContext.lastResponse = response;
|
||||
});
|
||||
|
||||
// ============================================
|
||||
// Then Steps (Assertions)
|
||||
// ============================================
|
||||
|
||||
Then(
|
||||
'the response status should be less than {int}',
|
||||
async function (this: CustomWorld, maxStatus: number) {
|
||||
const status = this.testContext.lastResponse?.status() ?? 0;
|
||||
expect(status, `Expected status < ${maxStatus}, but got ${status}`).toBeLessThan(maxStatus);
|
||||
},
|
||||
);
|
||||
|
||||
Then(
|
||||
'the page title should not contain {string} or {string}',
|
||||
async function (this: CustomWorld, text1: string, text2: string) {
|
||||
const title = await this.page.title();
|
||||
const regex = new RegExp(`${text1}|${text2}`, 'i');
|
||||
expect(title, `Page title "${title}" should not contain "${text1}" or "${text2}"`).not.toMatch(
|
||||
regex,
|
||||
);
|
||||
},
|
||||
);
|
||||
@@ -0,0 +1,96 @@
|
||||
import { type ChildProcess, exec } from 'node:child_process';
|
||||
import { resolve } from 'node:path';
|
||||
|
||||
let serverProcess: ChildProcess | null = null;
|
||||
let serverStartPromise: Promise<void> | null = null;
|
||||
|
||||
interface WebServerOptions {
|
||||
command: string;
|
||||
env?: Record<string, string>;
|
||||
port: number;
|
||||
reuseExistingServer?: boolean;
|
||||
timeout?: number;
|
||||
}
|
||||
|
||||
async function isServerRunning(port: number): Promise<boolean> {
|
||||
try {
|
||||
const response = await fetch(`http://localhost:${port}/chat`, {
|
||||
method: 'HEAD',
|
||||
});
|
||||
return response.ok;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export async function startWebServer(options: WebServerOptions): Promise<void> {
|
||||
const { command, port, timeout = 120_000, env = {}, reuseExistingServer = true } = options;
|
||||
|
||||
// If server is already being started by another worker, wait for it
|
||||
if (serverStartPromise) {
|
||||
console.log(`⏳ Waiting for server to start (started by another worker)...`);
|
||||
return serverStartPromise;
|
||||
}
|
||||
|
||||
// Check if server is already running
|
||||
if (reuseExistingServer && (await isServerRunning(port))) {
|
||||
console.log(`✅ Reusing existing server on port ${port}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a promise for the server startup and store it
|
||||
serverStartPromise = (async () => {
|
||||
console.log(`🚀 Starting web server: ${command}`);
|
||||
|
||||
// Get the project root directory (parent of e2e folder)
|
||||
const projectRoot = resolve(__dirname, '../../..');
|
||||
|
||||
// Start the server process
|
||||
serverProcess = exec(command, {
|
||||
cwd: projectRoot,
|
||||
env: {
|
||||
...process.env,
|
||||
ENABLE_AUTH_PROTECTION: '0',
|
||||
ENABLE_OIDC: '0',
|
||||
NEXT_PUBLIC_ENABLE_CLERK_AUTH: '0',
|
||||
NEXT_PUBLIC_ENABLE_NEXT_AUTH: '0',
|
||||
NODE_OPTIONS: '--max-old-space-size=6144',
|
||||
PORT: String(port),
|
||||
...env,
|
||||
},
|
||||
});
|
||||
|
||||
// Forward server output to console for debugging
|
||||
serverProcess.stdout?.on('data', (data) => {
|
||||
console.log(`[server] ${data}`);
|
||||
});
|
||||
|
||||
serverProcess.stderr?.on('data', (data) => {
|
||||
console.error(`[server] ${data}`);
|
||||
});
|
||||
|
||||
// Wait for server to be ready
|
||||
const startTime = Date.now();
|
||||
while (!(await isServerRunning(port))) {
|
||||
if (Date.now() - startTime > timeout) {
|
||||
throw new Error(`Server failed to start within ${timeout}ms`);
|
||||
}
|
||||
await new Promise((resolve) => {
|
||||
setTimeout(resolve, 1000);
|
||||
});
|
||||
}
|
||||
|
||||
console.log(`✅ Web server is ready on port ${port}`);
|
||||
})();
|
||||
|
||||
return serverStartPromise;
|
||||
}
|
||||
|
||||
export async function stopWebServer(): Promise<void> {
|
||||
if (serverProcess) {
|
||||
console.log('🛑 Stopping web server...');
|
||||
serverProcess.kill();
|
||||
serverProcess = null;
|
||||
serverStartPromise = null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
import { IWorldOptions, World, setWorldConstructor } from '@cucumber/cucumber';
|
||||
import { Browser, BrowserContext, Page, Response, chromium } from '@playwright/test';
|
||||
|
||||
export interface TestContext {
|
||||
[key: string]: any;
|
||||
consoleErrors: string[];
|
||||
jsErrors: Error[];
|
||||
lastResponse?: Response | null;
|
||||
previousUrl?: string;
|
||||
}
|
||||
|
||||
export class CustomWorld extends World {
|
||||
browser!: Browser;
|
||||
browserContext!: BrowserContext;
|
||||
page!: Page;
|
||||
testContext: TestContext;
|
||||
|
||||
constructor(options: IWorldOptions) {
|
||||
super(options);
|
||||
this.testContext = {
|
||||
consoleErrors: [],
|
||||
jsErrors: [],
|
||||
};
|
||||
}
|
||||
|
||||
// Getter for easier access
|
||||
get context(): TestContext {
|
||||
return this.testContext;
|
||||
}
|
||||
|
||||
async init() {
|
||||
const PORT = process.env.PORT ? Number(process.env.PORT) : 3010;
|
||||
const BASE_URL = process.env.BASE_URL || `http://localhost:${PORT}`;
|
||||
|
||||
this.browser = await chromium.launch({
|
||||
headless: process.env.HEADLESS !== 'false',
|
||||
});
|
||||
|
||||
this.browserContext = await this.browser.newContext({
|
||||
baseURL: BASE_URL,
|
||||
viewport: { height: 720, width: 1280 },
|
||||
});
|
||||
|
||||
// Set expect timeout for assertions (e.g., toBeVisible, toHaveText)
|
||||
this.browserContext.setDefaultTimeout(120_000);
|
||||
|
||||
this.page = await this.browserContext.newPage();
|
||||
|
||||
// Set up error listeners
|
||||
this.page.on('pageerror', (error) => {
|
||||
this.testContext.jsErrors.push(error);
|
||||
console.error('Page error:', error.message);
|
||||
});
|
||||
|
||||
this.page.on('console', (msg) => {
|
||||
if (msg.type() === 'error') {
|
||||
this.testContext.consoleErrors.push(msg.text());
|
||||
}
|
||||
});
|
||||
|
||||
this.page.setDefaultTimeout(120_000);
|
||||
}
|
||||
|
||||
async cleanup() {
|
||||
await this.page?.close();
|
||||
await this.browserContext?.close();
|
||||
await this.browser?.close();
|
||||
}
|
||||
|
||||
async takeScreenshot(name: string): Promise<Buffer> {
|
||||
console.log(name);
|
||||
return await this.page.screenshot({ fullPage: true });
|
||||
}
|
||||
}
|
||||
|
||||
setWorldConstructor(CustomWorld);
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"target": "ES2020",
|
||||
"lib": ["ES2020"],
|
||||
"types": ["node", "@cucumber/cucumber", "@playwright/test"],
|
||||
"esModuleInterop": true,
|
||||
"resolveJsonModule": true,
|
||||
"skipLibCheck": true,
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["../*"]
|
||||
}
|
||||
},
|
||||
"exclude": ["node_modules", "reports"],
|
||||
"extends": "../tsconfig.json",
|
||||
"include": ["src/**/*", "*.js"]
|
||||
}
|
||||
+111
-1
@@ -2,6 +2,7 @@
|
||||
"ModelSwitch": {
|
||||
"title": "النموذج"
|
||||
},
|
||||
"active": "نشط",
|
||||
"agentDefaultMessage": "مرحبًا، أنا **{{name}}**، يمكنك بدء المحادثة معي على الفور، أو يمكنك الذهاب إلى [إعدادات المساعد]({{url}}) لإكمال معلوماتي.",
|
||||
"agentDefaultMessageWithSystemRole": "مرحبًا، أنا **{{name}}**، كيف يمكنني مساعدتك؟",
|
||||
"agentDefaultMessageWithoutEdit": "مرحبًا، أنا **{{name}}**، كيف يمكنني مساعدتك؟",
|
||||
@@ -13,17 +14,28 @@
|
||||
"thought": "عملية التفكير",
|
||||
"unknownTitle": "عمل غير مسمى"
|
||||
},
|
||||
"availableAgents": "المساعدون المتاحون",
|
||||
"backToBottom": "العودة إلى الأسفل",
|
||||
"chatList": {
|
||||
"longMessageDetail": "عرض التفاصيل"
|
||||
},
|
||||
"clearCurrentMessages": "مسح رسائل الجلسة الحالية",
|
||||
"confirmClearCurrentMessages": "سيتم مسح رسائل الجلسة الحالية قريبًا، وبمجرد المسح لن يمكن استعادتها، يرجى تأكيد الإجراء الخاص بك",
|
||||
"confirmRemoveChatGroupItemAlert": "سيتم حذف فريق الوكيل هذا، ولن يتأثر الأعضاء الآخرون. يرجى تأكيد الإجراء.",
|
||||
"confirmRemoveGroupItemAlert": "سيتم حذف هذه المجموعة قريبًا. بعد الحذف، سيُنتقل المساعدون في هذه المجموعة إلى القائمة الافتراضية. يرجى تأكيد إجراء الحذف.",
|
||||
"confirmRemoveGroupSuccess": "تم حذف فريق الوكلاء بنجاح",
|
||||
"confirmRemoveSessionItemAlert": "سيتم حذف هذا المساعد قريبًا، وبمجرد الحذف لن يمكن استعادته، يرجى تأكيد الإجراء الخاص بك",
|
||||
"confirmRemoveSessionSuccess": "تم حذف المساعد بنجاح",
|
||||
"defaultAgent": "المساعد الافتراضي",
|
||||
"defaultGroupChat": "فريق الوكلاء",
|
||||
"defaultList": "القائمة الافتراضية",
|
||||
"defaultSession": "المساعد الافتراضي",
|
||||
"dm": {
|
||||
"placeholder": "ستظهر رسائلك الخاصة مع {{agentTitle}} هنا.",
|
||||
"tooltip": "أرسل رسالة خاصة",
|
||||
"visibleTo": "مرئي فقط لـ {{target}}",
|
||||
"you": "أنت"
|
||||
},
|
||||
"duplicateSession": {
|
||||
"loading": "جاري النسخ...",
|
||||
"success": "تم النسخ بنجاح",
|
||||
@@ -58,11 +70,56 @@
|
||||
"title": "استخراج محتوى رابط الويب"
|
||||
}
|
||||
},
|
||||
"group": {
|
||||
"desc": "التعاون مع عدة مساعدين للذكاء الاصطناعي في مساحة محادثة مشتركة.",
|
||||
"memberTooltip": "هناك {{count}} عضوًا في المجموعة",
|
||||
"orchestratorThinking": "المُنسق يفكر...",
|
||||
"removeMember": "إزالة عضو",
|
||||
"title": "مجموعة"
|
||||
},
|
||||
"groupDescription": "وصف الفريق",
|
||||
"groupSidebar": {
|
||||
"members": {
|
||||
"addMember": "إضافة عضو",
|
||||
"memberSettings": "إعدادات العضو",
|
||||
"orchestrator": "المُنسق",
|
||||
"orchestratorThinking": "المُنسق يفكر...",
|
||||
"removeMember": "إزالة عضو",
|
||||
"stopOrchestrator": "إيقاف التفكير",
|
||||
"triggerOrchestrator": "بدء المحادثة الجماعية"
|
||||
},
|
||||
"tabs": {
|
||||
"host": "المضيف",
|
||||
"members": "الأعضاء",
|
||||
"role": "الإعداد"
|
||||
}
|
||||
},
|
||||
"groupWizard": {
|
||||
"chooseMembers": "اختر المساعدين الحاليين...",
|
||||
"createGroup": "إنشاء فريق",
|
||||
"existingMembers": "الوكلاء الحاليون",
|
||||
"groupMembers": "سيتم أيضًا إضافة هؤلاء المساعدين إلى قائمتك",
|
||||
"host": {
|
||||
"description": "تمكين الفريق من العمل بشكل مستقل",
|
||||
"title": "تفعيل المضيف",
|
||||
"tooltip": "إذا قمت بتعطيل المضيف، فستحتاج إلى الإشارة إلى الأعضاء يدويًا باستخدام @ لكي يتمكنوا من الرد"
|
||||
},
|
||||
"memberCount": "{{count}} عضو",
|
||||
"noMatchingTemplates": "لا توجد قوالب مطابقة",
|
||||
"noSelectedTemplates": "لم يتم اختيار أي قالب",
|
||||
"noTemplateMembers": "لا يوجد أعضاء في القالب",
|
||||
"noTemplates": "لا توجد قوالب متاحة",
|
||||
"searchTemplates": "ابحث في القوالب...",
|
||||
"title": "إنشاء فريق وكلاء",
|
||||
"useTemplate": "استخدام القالب"
|
||||
},
|
||||
"hideForYou": "تم إخفاء محتوى الرسائل الخاصة، يرجى تفعيل خيار 【عرض محتوى الرسائل الخاصة】 في الإعدادات للعرض",
|
||||
"history": {
|
||||
"title": "سيتذكر المساعد آخر {{count}} رسالة فقط"
|
||||
},
|
||||
"historyRange": "نطاق التاريخ",
|
||||
"historySummary": "ملخص الرسائل التاريخية",
|
||||
"inactive": "غير نشط",
|
||||
"inbox": {
|
||||
"desc": "قم بتشغيل مجموعة الدماغ وأشعل شرارة التفكير. مساعدك الذكي، هنا حيث يمكنك التواصل بكل شيء",
|
||||
"title": "دردشة عشوائية"
|
||||
@@ -83,6 +140,7 @@
|
||||
"intentUnderstanding": {
|
||||
"title": "جارٍ فهم وتحليل نواياك..."
|
||||
},
|
||||
"inviteMembers": "دعوة الأعضاء",
|
||||
"knowledgeBase": {
|
||||
"all": "جميع المحتويات",
|
||||
"allFiles": "جميع الملفات",
|
||||
@@ -101,12 +159,29 @@
|
||||
"uploadGuide": "يمكنك عرض الملفات التي تم تحميلها في «قاعدة المعرفة»",
|
||||
"viewMore": "عرض المزيد"
|
||||
},
|
||||
"memberSelection": {
|
||||
"addMember": "إضافة عضو",
|
||||
"allMembers": "جميع الأعضاء",
|
||||
"createGroup": "إنشاء فريق وكيل",
|
||||
"noAvailableAgents": "لا يوجد مساعدين متاحين للدعوة",
|
||||
"noSelectedAgents": "لم يتم اختيار مساعدين بعد",
|
||||
"searchAgents": "البحث عن مساعدين...",
|
||||
"setInitialMembers": "اختيار أعضاء الفريق"
|
||||
},
|
||||
"members": "الأعضاء",
|
||||
"mention": {
|
||||
"title": "الإشارة إلى الأعضاء"
|
||||
},
|
||||
"messageAction": {
|
||||
"delAndRegenerate": "حذف وإعادة الإنشاء",
|
||||
"deleteDisabledByThreads": "يوجد موضوعات فرعية، لا يمكن الحذف",
|
||||
"regenerate": "إعادة الإنشاء"
|
||||
},
|
||||
"messages": {
|
||||
"dm": {
|
||||
"sentTo": "مرئي فقط لـ {{name}}",
|
||||
"title": "الرسائل الخاصة"
|
||||
},
|
||||
"modelCard": {
|
||||
"credit": "نقاط",
|
||||
"creditPricing": "التسعير",
|
||||
@@ -153,9 +228,18 @@
|
||||
"minimap": {
|
||||
"jumpToMessage": "الانتقال إلى الرسالة رقم {{index}}",
|
||||
"nextMessage": "الرسالة التالية",
|
||||
"previousMessage": "الرسالة السابقة"
|
||||
"previousMessage": "الرسالة السابقة",
|
||||
"senderAssistant": "المساعد",
|
||||
"senderUser": "أنت"
|
||||
},
|
||||
"newAgent": "مساعد جديد",
|
||||
"newGroupChat": "إنشاء فريق وكلاء جديد",
|
||||
"noAgentsYet": "لا يوجد أعضاء في هذا الفريق بعد. انقر على زر + لدعوة مساعد.",
|
||||
"noAvailableAgents": "لا يوجد أعضاء متاحون للدعوة",
|
||||
"noMatchingAgents": "لا يوجد أعضاء مطابقون",
|
||||
"noMembersYet": "لا يوجد أعضاء في هذه المجموعة بعد. انقر على زر + لدعوة المساعدين.",
|
||||
"noSelectedAgents": "لم يتم اختيار أي أعضاء بعد",
|
||||
"owner": "مالك المجموعة",
|
||||
"pin": "تثبيت",
|
||||
"pinOff": "إلغاء التثبيت",
|
||||
"rag": {
|
||||
@@ -196,12 +280,16 @@
|
||||
"title": "بحث عبر الإنترنت"
|
||||
},
|
||||
"searchAgentPlaceholder": "مساعد البحث...",
|
||||
"searchAgents": "مساعد البحث...",
|
||||
"selectedAgents": "المساعدون المختارون",
|
||||
"sendPlaceholder": "أدخل محتوى الدردشة...",
|
||||
"sessionGroup": {
|
||||
"config": "إدارة المجموعات",
|
||||
"confirmRemoveGroupAlert": "سيتم حذف هذه المجموعة قريبًا، وبعد الحذف، سيتم نقل مساعدي هذه المجموعة إلى القائمة الافتراضية، يرجى تأكيد إجراءك",
|
||||
"createAgentSuccess": "تم إنشاء المساعد بنجاح",
|
||||
"createGroup": "إضافة مجموعة جديدة",
|
||||
"createGroupFailed": "فشل إنشاء المحادثة الجماعية",
|
||||
"createGroupSuccess": "تم إنشاء المحادثة الجماعية بنجاح",
|
||||
"createSuccess": "تم الإنشاء بنجاح",
|
||||
"creatingAgent": "جاري إنشاء المساعد...",
|
||||
"inputPlaceholder": "الرجاء إدخال اسم المجموعة...",
|
||||
@@ -216,11 +304,24 @@
|
||||
"shareModal": {
|
||||
"copy": "نسخ",
|
||||
"download": "تحميل اللقطة",
|
||||
"downloadError": "فشل التنزيل",
|
||||
"downloadFile": "تحميل الملف",
|
||||
"downloadPdf": "تنزيل PDF",
|
||||
"downloadSuccess": "تم التنزيل بنجاح",
|
||||
"exportPdf": "تصدير إلى PDF",
|
||||
"exportTitle": "العنوان الافتراضي",
|
||||
"generatePdf": "إنشاء ملف PDF",
|
||||
"generatingPdf": "جارٍ إنشاء PDF...",
|
||||
"imageType": "نوع الصورة",
|
||||
"includeTool": "تضمين رسالة الأداة",
|
||||
"includeUser": "تضمين رسالة المستخدم",
|
||||
"loadingPdf": "جارٍ تحميل ملف PDF...",
|
||||
"noPdfData": "لا توجد بيانات PDF",
|
||||
"pdf": "PDF",
|
||||
"pdfErrorDescription": "حدث خطأ أثناء إنشاء PDF، يرجى المحاولة مرة أخرى",
|
||||
"pdfGenerationError": "فشل إنشاء PDF",
|
||||
"pdfReady": "تم تجهيز PDF",
|
||||
"regeneratePdf": "إعادة إنشاء ملف PDF",
|
||||
"screenshot": "لقطة شاشة",
|
||||
"settings": "إعدادات التصدير",
|
||||
"text": "نص",
|
||||
@@ -235,6 +336,12 @@
|
||||
"loading": "جارٍ التعرف...",
|
||||
"prettifying": "جارٍ التجميل..."
|
||||
},
|
||||
"supervisor": {
|
||||
"todoList": {
|
||||
"allComplete": "تم إنجاز جميع المهام",
|
||||
"title": "المهام المنجزة"
|
||||
}
|
||||
},
|
||||
"thread": {
|
||||
"divider": "موضوع فرعي",
|
||||
"threadMessageCount": "{{messageCount}} رسالة",
|
||||
@@ -248,6 +355,7 @@
|
||||
"chats": "رسائل المحادثة",
|
||||
"historySummary": "ملخص التاريخ",
|
||||
"rest": "المتبقي",
|
||||
"supervisor": "مُنسق المجموعة",
|
||||
"systemRole": "تعيين الدور",
|
||||
"title": "تفاصيل الرمز",
|
||||
"tools": "تعيين الإضافات",
|
||||
@@ -273,6 +381,7 @@
|
||||
"action": "قراءة صوتية",
|
||||
"clear": "مسح الصوت"
|
||||
},
|
||||
"untitledAgent": "مساعد بدون اسم",
|
||||
"updateAgent": "تحديث معلومات المساعد",
|
||||
"upload": {
|
||||
"action": {
|
||||
@@ -300,5 +409,6 @@
|
||||
"videoSizeExceeded": "لا يمكن أن يتجاوز حجم ملف الفيديو 20 ميغابايت، حجم الملف الحالي هو {{actualSize}}"
|
||||
}
|
||||
},
|
||||
"you": "أنت",
|
||||
"zenMode": "وضع التركيز"
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
"batchDelete": "حذف دفعة",
|
||||
"blog": "مدونة المنتجات",
|
||||
"branching": "إنشاء موضوع فرعي",
|
||||
"branchingDisable": "ميزة \"الموضوع الفرعي\" متاحة فقط في إصدار الخادم. إذا كنت بحاجة إلى هذه الميزة، يرجى التبديل إلى وضع نشر الخادم أو استخدام LobeChat Cloud",
|
||||
"branchingDisable": "ميزة \"الموضوعات الفرعية\" غير متاحة في الوضع الحالي. لاستخدام هذه الميزة، يُرجى التبديل إلى وضع قاعدة البيانات Postgres/Pglite أو استخدام LobeHub Cloud",
|
||||
"branchingRequiresSavedTopic": "الموضوع الحالي غير محفوظ، يجب الحفظ قبل استخدام ميزة الموضوع الفرعي",
|
||||
"cancel": "إلغاء",
|
||||
"changelog": "سجل التغييرات",
|
||||
@@ -338,6 +338,7 @@
|
||||
"chat": "الدردشة",
|
||||
"discover": "اكتشاف",
|
||||
"files": "ملفات",
|
||||
"knowledgeBase": "قاعدة المعرفة",
|
||||
"me": "أنا",
|
||||
"setting": "الإعدادات"
|
||||
},
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"ArgsInput": {
|
||||
"addArgument": "إضافة معامل",
|
||||
"argumentPlaceholder": "المعامل {{index}}",
|
||||
"enterFirstArgument": "أدخل المعامل الأول..."
|
||||
"addArgument": "إضافة وسيط",
|
||||
"argumentPlaceholder": "الوسيط {{index}}",
|
||||
"enterFirstArgument": "أدخل الوسيط الأول..."
|
||||
},
|
||||
"DragUpload": {
|
||||
"dragDesc": "اسحب الملفات هنا، يدعم تحميل عدة صور.",
|
||||
@@ -50,6 +50,10 @@
|
||||
"total": {
|
||||
"fileCount": "إجمالي {{count}} عنصر",
|
||||
"selectedCount": "تم تحديد {{count}} عنصر"
|
||||
},
|
||||
"view": {
|
||||
"list": "عرض القائمة",
|
||||
"masonry": "عرض الشبكة"
|
||||
}
|
||||
},
|
||||
"FileParsingStatus": {
|
||||
@@ -145,10 +149,10 @@
|
||||
"uploadingWithCount": "تم تحميل {{completed}} من أصل {{total}}"
|
||||
},
|
||||
"validation": {
|
||||
"fileSizeExceeded": "تجاوز حجم الملف الحد المسموح به",
|
||||
"fileSizeExceededDetail": "{{fileName}} ({{actualSize}}) يتجاوز الحد الأقصى للحجم وهو {{maxSize}}",
|
||||
"fileSizeExceededMultiple": "{{count}} من الملفات تتجاوز الحد الأقصى للحجم {{maxSize}}: {{fileList}}",
|
||||
"imageCountExceeded": "تجاوز عدد الصور الحد المسموح به"
|
||||
"fileSizeExceeded": "تجاوز حجم الملف الحد المسموح",
|
||||
"fileSizeExceededDetail": "{{fileName}} ({{actualSize}}) يتجاوز الحد الأقصى للحجم {{maxSize}}",
|
||||
"fileSizeExceededMultiple": "{{count}} ملفات تتجاوز الحد الأقصى للحجم {{maxSize}}: {{fileList}}",
|
||||
"imageCountExceeded": "تجاوز عدد الصور الحد المسموح"
|
||||
}
|
||||
},
|
||||
"OllamaSetupGuide": {
|
||||
|
||||
@@ -92,14 +92,15 @@
|
||||
"installLater": "تحديث عند بدء التشغيل التالي",
|
||||
"isLatestVersion": "الإصدار الحالي هو الأحدث",
|
||||
"isLatestVersionDesc": "رائع، الإصدار {{version}} الذي تستخدمه هو أحدث إصدار متاح.",
|
||||
"later": "تحديث لاحقًا",
|
||||
"later": "لاحقًا",
|
||||
"newVersionAvailable": "يتوفر إصدار جديد",
|
||||
"newVersionAvailableDesc": "تم العثور على إصدار جديد {{version}}، هل ترغب في التنزيل الآن؟",
|
||||
"restartAndInstall": "تثبيت التحديث وإعادة التشغيل",
|
||||
"updateError": "خطأ في التحديث",
|
||||
"updateReady": "التحديث جاهز",
|
||||
"updateReady": "يتوفر إصدار جديد",
|
||||
"updateReadyDesc": "تم تنزيل الإصدار الجديد {{version}}، يمكنك إكمال التثبيت بعد إعادة تشغيل التطبيق.",
|
||||
"upgradeNow": "تحديث الآن"
|
||||
"upgradeNow": "تحديث الآن",
|
||||
"willInstallLater": "سيتم تثبيت التحديث عند بدء التشغيل التالي"
|
||||
},
|
||||
"waitingOAuth": {
|
||||
"cancel": "إلغاء",
|
||||
|
||||
@@ -81,6 +81,12 @@
|
||||
"522": "نعتذر، انتهت مهلة الاتصال بالخادم، ولم يتمكن من الاستجابة لطلبك في الوقت المناسب. قد يكون ذلك بسبب عدم استقرار الشبكة أو أن الخادم غير متاح مؤقتًا. يرجى المحاولة لاحقًا، نحن نبذل جهدًا لاستعادة الخدمة.",
|
||||
"524": "نعتذر، انتهت مهلة الخادم أثناء انتظار الرد، قد يكون ذلك بسبب بطء الاستجابة، يرجى المحاولة لاحقًا.",
|
||||
"AgentRuntimeError": "حدث خطأ في تشغيل نموذج Lobe اللغوي، يرجى التحقق من المعلومات التالية أو إعادة المحاولة",
|
||||
"ComfyUIBizError": "حدث خطأ أثناء طلب خدمة ComfyUI، يرجى التحقق من المعلومات التالية أو المحاولة مرة أخرى",
|
||||
"ComfyUIEmptyResult": "لم يتم إنشاء أي صورة من قبل ComfyUI، يرجى التحقق من إعدادات النموذج أو المحاولة مرة أخرى",
|
||||
"ComfyUIModelError": "فشل تحميل نموذج ComfyUI، يرجى التحقق من وجود ملف النموذج",
|
||||
"ComfyUIServiceUnavailable": "فشل الاتصال بخدمة ComfyUI، يرجى التأكد من أن ComfyUI يعمل بشكل صحيح أو التحقق من صحة عنوان الخدمة",
|
||||
"ComfyUIUploadFailed": "فشل تحميل الصورة إلى ComfyUI، يرجى التحقق من الاتصال بالخادم أو المحاولة مرة أخرى",
|
||||
"ComfyUIWorkflowError": "فشل تنفيذ سير العمل في ComfyUI، يرجى التحقق من إعدادات سير العمل",
|
||||
"ConnectionCheckFailed": "الاستجابة فارغة، يرجى التحقق من أن عنوان وكيل الـ API لا ينتهي بـ `/v1`",
|
||||
"CreateMessageError": "عذرًا، لم يتم إرسال الرسالة بشكل صحيح، يرجى نسخ المحتوى وإعادة إرساله، بعد تحديث الصفحة لن يتم الاحتفاظ بهذه الرسالة",
|
||||
"ExceededContextWindow": "المحتوى المطلوب الحالي يتجاوز الطول الذي يمكن للنموذج معالجته، يرجى تقليل كمية المحتوى ثم إعادة المحاولة",
|
||||
@@ -100,6 +106,7 @@
|
||||
"InvalidAccessCode": "كلمة المرور غير صحيحة أو فارغة، يرجى إدخال كلمة مرور الوصول الصحيحة أو إضافة مفتاح API مخصص",
|
||||
"InvalidBedrockCredentials": "فشلت مصادقة Bedrock، يرجى التحقق من AccessKeyId/SecretAccessKey وإعادة المحاولة",
|
||||
"InvalidClerkUser": "عذرًا، لم تقم بتسجيل الدخول بعد، يرجى تسجيل الدخول أو التسجيل للمتابعة",
|
||||
"InvalidComfyUIArgs": "تكوين ComfyUI غير صحيح، يرجى التحقق من إعدادات ComfyUI ثم المحاولة مرة أخرى",
|
||||
"InvalidGithubToken": "رمز وصول شخصية GitHub غير صحيح أو فارغ، يرجى التحقق من رمز وصول GitHub الشخصي والمحاولة مرة أخرى",
|
||||
"InvalidOllamaArgs": "تكوين Ollama غير صحيح، يرجى التحقق من تكوين Ollama وإعادة المحاولة",
|
||||
"InvalidProviderAPIKey": "{{provider}} مفتاح API غير صحيح أو فارغ، يرجى التحقق من مفتاح API {{provider}} الخاص بك وحاول مرة أخرى",
|
||||
@@ -134,6 +141,9 @@
|
||||
"stt": {
|
||||
"responseError": "فشل طلب الخدمة، يرجى التحقق من الإعدادات أو إعادة المحاولة"
|
||||
},
|
||||
"supervisor": {
|
||||
"decisionFailed": "تعذر على مشرف المجموعة العمل. يرجى التحقق من إعدادات المشرف الخاصة بك، والتأكد من تكوين النموذج الصحيح، ومفتاح API، وعنوان API."
|
||||
},
|
||||
"testConnectionFailed": "فشل اختبار الاتصال: {{error}}",
|
||||
"tts": {
|
||||
"responseError": "فشل طلب الخدمة، يرجى التحقق من الإعدادات أو إعادة المحاولة"
|
||||
@@ -146,6 +156,11 @@
|
||||
"title": "استخدام مفتاح API {{name}} المخصص"
|
||||
},
|
||||
"closeMessage": "إغلاق الرسالة",
|
||||
"comfyui": {
|
||||
"description": "يرجى إدخال معلومات المصادقة الصحيحة لـ {{name}} للبدء في إنشاء الصور",
|
||||
"modifyBaseUrl": "تعديل عنوان خدمة Comfy UI",
|
||||
"title": "تأكيد معلومات المصادقة الخاصة بـ {{name}}"
|
||||
},
|
||||
"confirm": "تأكيد وإعادة المحاولة",
|
||||
"oauth": {
|
||||
"description": "فتح المسؤول توثيق تسجيل الدخول الموحد، انقر فوق الزر أدناه لتسجيل الدخول وفتح التطبيق",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"desc": "إدارة ملفاتك ومكتبتك المعرفية",
|
||||
"desc": "إدارة معرفتك",
|
||||
"detail": {
|
||||
"basic": {
|
||||
"createdAt": "تاريخ الإنشاء",
|
||||
@@ -70,7 +70,7 @@
|
||||
"videos": "الفيديوهات",
|
||||
"websites": "المواقع"
|
||||
},
|
||||
"title": "الملفات",
|
||||
"title": "قاعدة المعرفة",
|
||||
"toggleLeftPanel": {
|
||||
"title": "عرض/إخفاء اللوحة الجانبية اليسرى"
|
||||
},
|
||||
|
||||
@@ -82,6 +82,58 @@
|
||||
"title": "رقم حساب Cloudflare / عنوان URL API"
|
||||
}
|
||||
},
|
||||
"comfyui": {
|
||||
"apiKey": {
|
||||
"desc": "مفتاح API المطلوب لمصادقة Bearer Token",
|
||||
"placeholder": "يرجى إدخال مفتاح API",
|
||||
"required": "يرجى إدخال مفتاح API",
|
||||
"title": "مفتاح API"
|
||||
},
|
||||
"authType": {
|
||||
"desc": "اختر طريقة المصادقة مع خادم ComfyUI",
|
||||
"options": {
|
||||
"basic": "اسم المستخدم/كلمة المرور",
|
||||
"bearer": "Bearer (مفتاح API)",
|
||||
"custom": "رؤوس مخصصة",
|
||||
"none": "لا حاجة للمصادقة"
|
||||
},
|
||||
"placeholder": "يرجى اختيار نوع المصادقة",
|
||||
"title": "نوع المصادقة"
|
||||
},
|
||||
"baseURL": {
|
||||
"desc": "عنوان الوصول إلى واجهة ComfyUI على الويب",
|
||||
"placeholder": "http://127.0.0.1:8000",
|
||||
"required": "يرجى إدخال عنوان خدمة ComfyUI",
|
||||
"title": "عنوان خدمة ComfyUI"
|
||||
},
|
||||
"checker": {
|
||||
"desc": "اختبار ما إذا كان الاتصال مهيأ بشكل صحيح",
|
||||
"title": "فحص الاتصال"
|
||||
},
|
||||
"customHeaders": {
|
||||
"addButton": "إضافة رأس طلب",
|
||||
"deleteTooltip": "حذف رأس الطلب هذا",
|
||||
"desc": "رؤوس الطلب المطلوبة لطريقة المصادقة المخصصة، بتنسيق زوج مفتاح-قيمة",
|
||||
"duplicateKeyError": "لا يمكن تكرار أسماء رؤوس الطلب",
|
||||
"keyPlaceholder": "اسم المفتاح",
|
||||
"required": "يرجى إدخال رؤوس الطلب المخصصة",
|
||||
"title": "رؤوس الطلب المخصصة",
|
||||
"valuePlaceholder": "القيمة"
|
||||
},
|
||||
"password": {
|
||||
"desc": "كلمة المرور المطلوبة للمصادقة الأساسية",
|
||||
"placeholder": "يرجى إدخال كلمة المرور",
|
||||
"required": "يرجى إدخال كلمة المرور",
|
||||
"title": "كلمة المرور"
|
||||
},
|
||||
"title": "ComfyUI",
|
||||
"username": {
|
||||
"desc": "اسم المستخدم المطلوب للمصادقة الأساسية",
|
||||
"placeholder": "يرجى إدخال اسم المستخدم",
|
||||
"required": "يرجى إدخال اسم المستخدم",
|
||||
"title": "اسم المستخدم"
|
||||
}
|
||||
},
|
||||
"createNewAiProvider": {
|
||||
"apiKey": {
|
||||
"placeholder": "يرجى إدخال مفتاح API الخاص بك",
|
||||
@@ -399,6 +451,11 @@
|
||||
"desc": "أدخل مفاتيح Vertex AI الخاصة بك",
|
||||
"placeholder": "{ \"type\": \"service_account\", \"project_id\": \"xxx\", \"private_key_id\": ... }",
|
||||
"title": "مفاتيح Vertex AI"
|
||||
},
|
||||
"region": {
|
||||
"desc": "اختر منطقة خدمة Vertex AI. بعض النماذج مثل Gemini 2.5 متاحة فقط في مناطق محددة (مثل global)",
|
||||
"placeholder": "اختر المنطقة",
|
||||
"title": "منطقة Vertex AI"
|
||||
}
|
||||
},
|
||||
"zeroone": {
|
||||
|
||||
+80
-8
@@ -311,6 +311,12 @@
|
||||
"Qwen/QwQ-32B-Preview": {
|
||||
"description": "QwQ-32B-Preview هو أحدث نموذج بحث تجريبي من Qwen، يركز على تعزيز قدرات الاستدلال للذكاء الاصطناعي. من خلال استكشاف آليات معقدة مثل خلط اللغة والاستدلال التكراري، تشمل المزايا الرئيسية القدرة القوية على التحليل الاستدلالي، والقدرات الرياضية والبرمجية. في الوقت نفسه، هناك أيضًا مشكلات في تبديل اللغة، ودورات الاستدلال، واعتبارات الأمان، واختلافات في القدرات الأخرى."
|
||||
},
|
||||
"Qwen/Qwen-Image": {
|
||||
"description": "Qwen-Image هو نموذج أساسي لتوليد الصور تم تطويره من قبل فريق Tongyi Qianwen التابع لشركة Alibaba، ويحتوي على 20 مليار معلمة. حقق هذا النموذج تقدمًا ملحوظًا في عرض النصوص المعقدة وتحرير الصور بدقة، ويتميز بقدرته العالية على توليد صور تحتوي على نصوص صينية وإنجليزية عالية الدقة. لا يقتصر عمل Qwen-Image على معالجة تخطيطات متعددة الأسطر والنصوص على مستوى الفقرات، بل يحافظ أيضًا على اتساق التنسيق وتناسق السياق أثناء توليد الصور. بالإضافة إلى قدراته الفائقة في عرض النصوص، يدعم النموذج مجموعة واسعة من الأساليب الفنية، من الصور الواقعية إلى الجماليات الأنمي، مما يجعله قادرًا على التكيف مع مختلف احتياجات الإبداع. كما يتمتع بقدرات قوية في تحرير الصور وفهمها، ويدعم عمليات متقدمة مثل نقل الأسلوب، إضافة أو إزالة العناصر، تعزيز التفاصيل، تحرير النصوص، وحتى التحكم في وضعيات الجسم البشري، ليكون نموذجًا أساسيًا شاملاً لمعالجة الصور الذكية يجمع بين اللغة والتنسيق والصورة."
|
||||
},
|
||||
"Qwen/Qwen-Image-Edit-2509": {
|
||||
"description": "Qwen-Image-Edit-2509 هو أحدث إصدار لتحرير الصور من نموذج Qwen-Image، تم تطويره من قبل فريق Tongyi Qianwen التابع لشركة Alibaba. يعتمد هذا النموذج على Qwen-Image الذي يحتوي على 20 مليار معلمة، وتم تدريبه بعمق لتوسيع قدراته الفريدة في عرض النصوص إلى مجال تحرير الصور، مما يتيح تحريرًا دقيقًا للنصوص داخل الصور. يستخدم Qwen-Image-Edit بنية مبتكرة تُدخل الصورة إلى كل من Qwen2.5-VL (للتحكم في المعنى البصري) وVAE Encoder (للتحكم في المظهر البصري)، مما يمنحه قدرة مزدوجة على التحرير من حيث المعنى والمظهر. وهذا يعني أنه لا يدعم فقط تحرير المظهر المحلي مثل الإضافة أو الحذف أو التعديل، بل يدعم أيضًا تحريرًا بصريًا دلاليًا متقدمًا يتطلب الحفاظ على الاتساق المعنوي، مثل إنشاء محتوى IP أو نقل الأسلوب. وقد أظهر النموذج أداءً رائدًا (SOTA) في العديد من اختبارات المعايير العامة، مما يجعله نموذجًا أساسيًا قويًا لتحرير الصور."
|
||||
},
|
||||
"Qwen/Qwen2-72B-Instruct": {
|
||||
"description": "Qwen2 هو نموذج لغوي عام متقدم، يدعم أنواع متعددة من التعليمات."
|
||||
},
|
||||
@@ -392,6 +398,12 @@
|
||||
"Qwen/Qwen3-Next-80B-A3B-Thinking": {
|
||||
"description": "Qwen3-Next-80B-A3B-Thinking هو نموذج أساسي من الجيل التالي أصدره فريق Tongyi Qianwen في علي بابا، مصمم خصيصًا لمهام الاستدلال المعقدة. يعتمد على بنية Qwen3-Next المبتكرة التي تدمج آلية انتباه هجينة (Gated DeltaNet و Gated Attention) وهيكل خبراء مختلط عالي التشتت (MoE)، بهدف تحقيق أقصى كفاءة في التدريب والاستدلال. كنموذج متناثر يحتوي على 80 مليار معلمة إجمالية، فإنه ينشط حوالي 3 مليارات معلمة فقط أثناء الاستدلال، مما يقلل بشكل كبير من تكلفة الحوسبة، وعند معالجة مهام سياق طويل تتجاوز 32 ألف رمز، فإن معدل الاستدلال يتفوق على نموذج Qwen3-32B بأكثر من 10 أضعاف. نسخة \"Thinking\" هذه مخصصة لتنفيذ مهام متعددة الخطوات عالية الصعوبة مثل الإثباتات الرياضية، توليف الشيفرة، التحليل المنطقي والتخطيط، وتخرج عملية الاستدلال بشكل افتراضي في شكل \"سلسلة تفكير\" منظمة. من حيث الأداء، يتفوق هذا النموذج ليس فقط على نماذج ذات تكلفة أعلى مثل Qwen3-32B-Thinking، بل يتفوق أيضًا في عدة اختبارات معيارية على Gemini-2.5-Flash-Thinking."
|
||||
},
|
||||
"Qwen/Qwen3-VL-8B-Instruct": {
|
||||
"description": "Qwen3-VL-8B-Instruct هو نموذج لغة بصرية من سلسلة Qwen3، تم تطويره استنادًا إلى Qwen3-8B-Instruct وتدريبه على كمية كبيرة من بيانات الصور والنصوص. يتميز بقدرته على فهم الرؤية العامة، وإجراء حوارات تتمحور حول المحتوى البصري، والتعرف على النصوص متعددة اللغات داخل الصور. وهو مناسب لتطبيقات مثل الأسئلة والأجوبة البصرية، ووصف الصور، واتباع التعليمات متعددة الوسائط، واستدعاء الأدوات."
|
||||
},
|
||||
"Qwen/Qwen3-VL-8B-Thinking": {
|
||||
"description": "Qwen3-VL-8B-Thinking هو إصدار التفكير البصري من سلسلة Qwen3، تم تحسينه خصيصًا لمهام الاستدلال المعقدة متعددة الخطوات. يقوم بشكل افتراضي بتوليد سلسلة من الأفكار (thinking chain) قبل الإجابة لتحسين دقة الاستدلال. وهو مناسب للسيناريوهات التي تتطلب استدلالًا عميقًا مثل الأسئلة والأجوبة البصرية، ومراجعة محتوى الصور وتقديم تحليلات مفصلة."
|
||||
},
|
||||
"Qwen2-72B-Instruct": {
|
||||
"description": "Qwen2 هو أحدث سلسلة من نموذج Qwen، ويدعم سياقًا يصل إلى 128 ألف، مقارنةً بأفضل النماذج مفتوحة المصدر الحالية، يتفوق Qwen2-72B بشكل ملحوظ في فهم اللغة الطبيعية والمعرفة والترميز والرياضيات والقدرات متعددة اللغات."
|
||||
},
|
||||
@@ -767,6 +779,9 @@
|
||||
"claude-3-sonnet-20240229": {
|
||||
"description": "Claude 3 Sonnet يوفر توازنًا مثاليًا بين الذكاء والسرعة لحمولات العمل المؤسسية. يقدم أقصى فائدة بسعر أقل، موثوق ومناسب للنشر على نطاق واسع."
|
||||
},
|
||||
"claude-haiku-4-5-20251001": {
|
||||
"description": "Claude Haiku 4.5 هو نموذج Haiku الأسرع والأذكى من Anthropic، يتميز بسرعة فائقة وقدرة متقدمة على التفكير المتسلسل."
|
||||
},
|
||||
"claude-opus-4-1-20250805": {
|
||||
"description": "Claude Opus 4.1 هو أحدث وأقوى نموذج من Anthropic لمعالجة المهام المعقدة للغاية. يتميز بأداء ذكي وسلس وفهم عميق."
|
||||
},
|
||||
@@ -851,6 +866,39 @@
|
||||
"cohere/embed-v4.0": {
|
||||
"description": "نموذج يسمح بتصنيف النصوص أو الصور أو المحتوى المختلط أو تحويلها إلى تمثيلات مضمنة."
|
||||
},
|
||||
"comfyui/flux-dev": {
|
||||
"description": "FLUX.1 Dev - نموذج تحويل النص إلى صورة عالي الجودة، يولّد الصور خلال 10 إلى 50 خطوة، مناسب للإبداع الفني وإنتاج الأعمال الفنية الراقية"
|
||||
},
|
||||
"comfyui/flux-kontext-dev": {
|
||||
"description": "FLUX.1 Kontext-dev - نموذج لتحرير الصور، يدعم تعديل الصور الحالية بناءً على التعليمات النصية، ويتيح التعديلات الموضعية ونقل الأسلوب"
|
||||
},
|
||||
"comfyui/flux-krea-dev": {
|
||||
"description": "FLUX.1 Krea-dev - نموذج تحويل النص إلى صورة معزز بالأمان، تم تطويره بالتعاون مع Krea، ويحتوي على مرشحات أمان مدمجة"
|
||||
},
|
||||
"comfyui/flux-schnell": {
|
||||
"description": "FLUX.1 Schnell - نموذج فائق السرعة لتحويل النص إلى صورة، يولّد صوراً عالية الجودة خلال 1 إلى 4 خطوات فقط، مثالي للتطبيقات الفورية والنماذج الأولية السريعة"
|
||||
},
|
||||
"comfyui/stable-diffusion-15": {
|
||||
"description": "Stable Diffusion 1.5 - نموذج تحويل النص إلى صورة الكلاسيكي بدقة 512x512، مناسب للنماذج الأولية السريعة والتجارب الإبداعية"
|
||||
},
|
||||
"comfyui/stable-diffusion-35": {
|
||||
"description": "Stable Diffusion 3.5 - الجيل الجديد من نماذج تحويل النص إلى صورة، يدعم نسختي Large وMedium، يتطلب ملف ترميز CLIP خارجي، ويوفر جودة صور ممتازة وتطابقاً دقيقاً مع الكلمات المفتاحية"
|
||||
},
|
||||
"comfyui/stable-diffusion-35-inclclip": {
|
||||
"description": "Stable Diffusion 3.5 - نسخة مدمجة مع مشفرات CLIP/T5، لا يتطلب ملفات ترميز خارجية، مناسب لنماذج مثل sd3.5_medium_incl_clips، ويستهلك موارد أقل"
|
||||
},
|
||||
"comfyui/stable-diffusion-custom": {
|
||||
"description": "نموذج مخصص لتحويل النص إلى صورة باستخدام Stable Diffusion، يجب تسمية ملف النموذج بـ custom_sd_lobe.safetensors، وإذا كان هناك VAE يجب تسميته بـ custom_sd_vae_lobe.safetensors، ويجب وضع الملفات في المجلدات المحددة حسب متطلبات Comfy"
|
||||
},
|
||||
"comfyui/stable-diffusion-custom-refiner": {
|
||||
"description": "نموذج مخصص لتحويل الصورة إلى صورة باستخدام SDXL، يجب تسمية ملف النموذج بـ custom_sd_lobe.safetensors، وإذا كان هناك VAE يجب تسميته بـ custom_sd_vae_lobe.safetensors، ويجب وضع الملفات في المجلدات المحددة حسب متطلبات Comfy"
|
||||
},
|
||||
"comfyui/stable-diffusion-refiner": {
|
||||
"description": "نموذج SDXL لتحويل الصورة إلى صورة، يتيح تحويل الصور بجودة عالية بناءً على صورة الإدخال، ويدعم نقل الأسلوب، ترميم الصور، والتحولات الإبداعية"
|
||||
},
|
||||
"comfyui/stable-diffusion-xl": {
|
||||
"description": "نموذج SDXL لتحويل النص إلى صورة، يدعم توليد صور عالية الدقة تصل إلى 1024x1024، ويوفر جودة صور أفضل وتفاصيل أدق"
|
||||
},
|
||||
"command": {
|
||||
"description": "نموذج حواري يتبع التعليمات، يظهر جودة عالية وموثوقية أكبر في المهام اللغوية، ويتميز بطول سياق أطول مقارنة بنموذجنا الأساسي للتوليد."
|
||||
},
|
||||
@@ -1148,6 +1196,9 @@
|
||||
"doubao-seed-1.6-flash": {
|
||||
"description": "نموذج Doubao-Seed-1.6-flash للتفكير العميق متعدد الوسائط مع سرعة استدلال فائقة، حيث يحتاج TPOT فقط إلى 10 مللي ثانية؛ يدعم فهم النصوص والرؤية، وتفوق قدرات فهم النصوص على الجيل السابق lite، وفهم الرؤية يضاهي نماذج pro المنافسة. يدعم نافذة سياق بحجم 256k وطول إخراج يصل إلى 16k رمز."
|
||||
},
|
||||
"doubao-seed-1.6-lite": {
|
||||
"description": "Doubao-Seed-1.6-lite هو نموذج تفكير متعدد الوسائط جديد كليًا، يدعم ضبط مستوى الجهد الاستدلالي (reasoning effort) بأربعة أوضاع: الحد الأدنى، منخفض، متوسط، وعالٍ. يتميز بكفاءة عالية وتكلفة مناسبة، وهو الخيار الأمثل للمهام الشائعة، مع نافذة سياق تصل إلى 256 ألف."
|
||||
},
|
||||
"doubao-seed-1.6-thinking": {
|
||||
"description": "نموذج Doubao-Seed-1.6-thinking يعزز قدرات التفكير بشكل كبير، مقارنة بـ Doubao-1.5-thinking-pro، مع تحسينات إضافية في القدرات الأساسية مثل البرمجة والرياضيات والاستدلال المنطقي، ويدعم الفهم البصري. يدعم نافذة سياق بحجم 256k وطول إخراج يصل إلى 16k رمز."
|
||||
},
|
||||
@@ -1541,9 +1592,6 @@
|
||||
"glm-zero-preview": {
|
||||
"description": "يمتلك GLM-Zero-Preview قدرة قوية على الاستدلال المعقد، ويظهر أداءً ممتازًا في مجالات الاستدلال المنطقي، والرياضيات، والبرمجة."
|
||||
},
|
||||
"glm4.6:355b": {
|
||||
"description": "نموذج GLM-4.6 (355B) الرائد الأحدث من Zhipu يتفوق بشكل شامل على الجيل السابق في الترميز المتقدم، ومعالجة النصوص الطويلة، والاستدلال، وقدرات الوكلاء الذكيين، لا سيما في مجال البرمجة حيث يتماشى مع Claude Sonnet 4، ليصبح من أفضل نماذج الترميز في الصين."
|
||||
},
|
||||
"google/gemini-2.0-flash": {
|
||||
"description": "Gemini 2.0 Flash يقدم ميزات الجيل التالي وتحسينات تشمل سرعة فائقة، استخدام أدوات مدمجة، توليد متعدد الوسائط، ونافذة سياق تصل إلى مليون رمز."
|
||||
},
|
||||
@@ -1934,12 +1982,18 @@
|
||||
"inception/mercury-coder-small": {
|
||||
"description": "Mercury Coder Small هو الخيار المثالي لمهام توليد الكود، وتصحيح الأخطاء، وإعادة الهيكلة، مع أدنى تأخير."
|
||||
},
|
||||
"inclusionAI/Ling-1T": {
|
||||
"description": "Ling-1T هو أول نموذج رائد من سلسلة \"Ling 2.0\" غير المعتمد على التفكير، يحتوي على تريليون معلمة إجمالية و50 مليار معلمة نشطة لكل رمز. تم بناؤه على بنية Ling 2.0، ويهدف إلى تجاوز حدود الاستدلال الفعال والإدراك القابل للتوسع. تم تدريب Ling-1T-base على أكثر من 200 تريليون رمز عالي الجودة وغني بالاستدلال."
|
||||
},
|
||||
"inclusionAI/Ling-flash-2.0": {
|
||||
"description": "Ling-flash-2.0 هو النموذج الثالث في سلسلة بنية Ling 2.0 التي أصدرها فريق Bailing في مجموعة Ant. هو نموذج خبراء مختلط (MoE) بحجم إجمالي 100 مليار معلمة، لكنه ينشط فقط 6.1 مليار معلمة لكل رمز (غير متضمنة تمثيلات الكلمات 4.8 مليار). كنموذج خفيف الوزن، أظهر Ling-flash-2.0 أداءً يضاهي أو يتفوق على نماذج كثيفة بحجم 40 مليار معلمة ونماذج MoE أكبر في عدة تقييمات موثوقة. يهدف النموذج إلى استكشاف مسارات عالية الكفاءة من خلال تصميم معماري واستراتيجيات تدريب متقدمة، في ظل القناعة بأن \"النموذج الكبير يعني معلمات كثيرة\"."
|
||||
},
|
||||
"inclusionAI/Ling-mini-2.0": {
|
||||
"description": "Ling-mini-2.0 هو نموذج لغة كبير صغير الحجم وعالي الأداء مبني على بنية MoE. يحتوي على 16 مليار معلمة إجمالية، لكنه ينشط فقط 1.4 مليار معلمة لكل رمز (غير متضمنة التضمين 789 مليون)، مما يحقق سرعة توليد عالية جدًا. بفضل تصميم MoE الفعال وبيانات تدريب ضخمة وعالية الجودة، رغم تنشيط معلمات قليلة، يظهر Ling-mini-2.0 أداءً متقدمًا في المهام اللاحقة يضاهي نماذج LLM كثيفة أقل من 10 مليارات معلمة ونماذج MoE أكبر."
|
||||
},
|
||||
"inclusionAI/Ring-1T": {
|
||||
"description": "Ring-1T هو نموذج تفكير مفتوح المصدر بحجم تريليون معلمة، أطلقه فريق Bailing. يعتمد على بنية Ling 2.0 ونموذج Ling-1T-base، ويحتوي على تريليون معلمة إجمالية و50 مليار معلمة نشطة، ويدعم نافذة سياق تصل إلى 128 ألف. تم تحسينه من خلال تعلم التعزيز القابل للتحقق على نطاق واسع."
|
||||
},
|
||||
"inclusionAI/Ring-flash-2.0": {
|
||||
"description": "Ring-flash-2.0 هو نموذج تفكير عالي الأداء محسّن بعمق بناءً على Ling-flash-2.0-base. يستخدم بنية خبراء مختلط (MoE) بحجم إجمالي 100 مليار معلمة، لكنه ينشط فقط 6.1 مليار معلمة في كل استدلال. يحل النموذج من خلال خوارزمية icepop المبتكرة مشكلة عدم استقرار نماذج MoE الكبيرة في تدريب التعلم المعزز (RL)، مما يسمح بتحسين مستمر لقدرات الاستدلال المعقدة خلال التدريب طويل الأمد. حقق Ring-flash-2.0 تقدمًا ملحوظًا في مسابقات الرياضيات، توليد الشيفرة، والاستدلال المنطقي، متفوقًا على أفضل النماذج الكثيفة التي تقل عن 40 مليار معلمة، وقريبًا من نماذج MoE مفتوحة المصدر الأكبر ونماذج التفكير عالية الأداء المغلقة المصدر. رغم تركيزه على الاستدلال المعقد، يظهر أداءً ممتازًا في مهام الكتابة الإبداعية. بالإضافة إلى ذلك، وبفضل تصميمه المعماري الفعال، يوفر Ring-flash-2.0 أداءً قويًا مع استدلال عالي السرعة، مما يقلل بشكل كبير من تكلفة نشر نماذج التفكير في بيئات ذات حمل عالٍ."
|
||||
},
|
||||
@@ -2036,9 +2090,6 @@
|
||||
"llama-3.3-instruct": {
|
||||
"description": "تم تحسين نموذج Llama 3.3 المعدل للتعليمات خصيصًا لسيناريوهات المحادثة، حيث تفوق على العديد من نماذج الدردشة مفتوحة المصدر الحالية في اختبارات المعايير الصناعية الشائعة."
|
||||
},
|
||||
"llama-4-maverick-17b-128e-instruct": {
|
||||
"description": "Llama 4 Maverick: نموذج عالي الأداء من سلسلة Llama، مناسب لمهام الاستدلال المتقدم، حل المشكلات المعقدة، وتنفيذ التعليمات."
|
||||
},
|
||||
"llama-4-scout-17b-16e-instruct": {
|
||||
"description": "Llama 4 Scout: نموذج عالي الأداء من سلسلة Llama، مثالي للسيناريوهات التي تتطلب إنتاجية عالية وزمن استجابة منخفض."
|
||||
},
|
||||
@@ -2906,6 +2957,9 @@
|
||||
"qwen3-8b": {
|
||||
"description": "Qwen3 هو نموذج جديد من الجيل التالي مع تحسينات كبيرة في القدرات، حيث يصل إلى مستويات رائدة في الصناعة في الاستدلال، والعموم، والوكلاء، واللغات المتعددة، ويدعم التبديل بين أنماط التفكير."
|
||||
},
|
||||
"qwen3-coder-30b-a3b-instruct": {
|
||||
"description": "النسخة مفتوحة المصدر من نموذج Qwen3 للبرمجة. النموذج الأحدث qwen3-coder-30b-a3b-instruct مبني على Qwen3، ويتميز بقدرات قوية كوكيل برمجي، بارع في استخدام الأدوات والتفاعل مع البيئات، ويجمع بين مهارات البرمجة الذاتية والقدرات العامة."
|
||||
},
|
||||
"qwen3-coder-480b-a35b-instruct": {
|
||||
"description": "نسخة مفتوحة المصدر من نموذج كود Tongyi Qianwen. أحدث نموذج qwen3-coder-480b-a35b-instruct مبني على Qwen3 لتوليد الكود، يتمتع بقدرات قوية كوكيل برمجي، بارع في استدعاء الأدوات والتفاعل مع البيئة، قادر على البرمجة الذاتية مع أداء برمجي ممتاز وقدرات عامة."
|
||||
},
|
||||
@@ -2927,11 +2981,29 @@
|
||||
"qwen3-next-80b-a3b-thinking": {
|
||||
"description": "نموذج مفتوح المصدر من الجيل الجديد لوضع التفكير مبني على Qwen3، يتميز بتحسين في الالتزام بالتعليمات مقارنة بالإصدار السابق (Tongyi Qianwen 3-235B-A22B-Thinking-2507)، مع ردود ملخصة وأكثر إيجازًا من النموذج."
|
||||
},
|
||||
"qwen3-omni-flash": {
|
||||
"description": "نموذج Qwen-Omni قادر على استقبال مدخلات متعددة الوسائط مثل النصوص، الصور، الصوت، والفيديو، ويولّد ردودًا على شكل نص أو صوت. يوفر أصواتًا بشرية متعددة، ويدعم إخراج الصوت بعدة لغات ولهجات، ويمكن استخدامه في مجالات مثل إنشاء النصوص، التعرف البصري، والمساعدات الصوتية."
|
||||
},
|
||||
"qwen3-vl-235b-a22b-instruct": {
|
||||
"description": "Qwen3 VL 235B A22B Instruct هو نموذج متعدد الوسائط أطلقته Tongyi Qianwen، يدعم الفهم البصري والاستدلال."
|
||||
"description": "Qwen3 VL 235B A22B في وضع غير التفكير (Instruct)، مصمم لسيناريوهات الأوامر غير المعتمدة على التفكير، مع الحفاظ على قدرات قوية في الفهم البصري."
|
||||
},
|
||||
"qwen3-vl-235b-a22b-thinking": {
|
||||
"description": "Qwen3 VL 235B A22B Thinking هو نموذج استدلال متعدد الوسائط أطلقته Tongyi Qianwen، يدعم الفهم البصري والاستدلال."
|
||||
"description": "Qwen3 VL 235B A22B في وضع التفكير (نسخة مفتوحة المصدر)، مخصص للمهام المعقدة التي تتطلب استدلالًا عاليًا وفهمًا لمقاطع الفيديو الطويلة، ويقدم قدرات رائدة في الاستدلال البصري والنصي."
|
||||
},
|
||||
"qwen3-vl-30b-a3b-instruct": {
|
||||
"description": "Qwen3 VL 30B في وضع غير التفكير (Instruct)، موجه لسيناريوهات متابعة الأوامر العامة، مع الحفاظ على مستوى عالٍ من الفهم والتوليد متعدد الوسائط."
|
||||
},
|
||||
"qwen3-vl-30b-a3b-thinking": {
|
||||
"description": "Qwen-VL (نسخة مفتوحة المصدر) يوفر قدرات في الفهم البصري وتوليد النصوص، ويدعم التفاعل الذكي، الترميز البصري، الإدراك المكاني، فهم الفيديوهات الطويلة والتفكير العميق، مع دعم قوي للتعرف على النصوص المتقدمة وتعدد اللغات في البيئات المعقدة."
|
||||
},
|
||||
"qwen3-vl-8b-instruct": {
|
||||
"description": "Qwen3 VL 8B في وضع غير التفكير (Instruct)، مناسب لمهام التوليد والتعرف متعدد الوسائط الروتينية."
|
||||
},
|
||||
"qwen3-vl-8b-thinking": {
|
||||
"description": "Qwen3 VL 8B في وضع التفكير، مخصص لسيناريوهات الاستدلال والتفاعل متعدد الوسائط الخفيفة، مع الحفاظ على قدرة فهم السياق الطويل."
|
||||
},
|
||||
"qwen3-vl-flash": {
|
||||
"description": "Qwen3 VL Flash: نسخة خفيفة وسريعة للاستدلال، مناسبة للسيناريوهات الحساسة للزمن أو التي تتطلب معالجة عدد كبير من الطلبات."
|
||||
},
|
||||
"qwen3-vl-plus": {
|
||||
"description": "Tongyi Qianwen VL هو نموذج توليد نصوص يمتلك قدرات فهم بصرية (صور)، لا يقتصر على التعرف الضوئي على الحروف (OCR)، بل يمكنه أيضًا التلخيص والاستدلال، مثل استخراج خصائص من صور المنتجات، وحل المسائل بناءً على صور التمارين."
|
||||
|
||||
@@ -461,7 +461,7 @@
|
||||
"tabs": {
|
||||
"installed": "مثبت",
|
||||
"mcp": "إضافات MCP",
|
||||
"old": "إضافات LobeChat"
|
||||
"old": "ملحقات LobeHub"
|
||||
},
|
||||
"title": "متجر الإضافات"
|
||||
},
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
"description": "Bedrock هي خدمة تقدمها أمازون AWS، تركز على توفير نماذج لغة ورؤية متقدمة للذكاء الاصطناعي للشركات. تشمل عائلة نماذجها سلسلة Claude من Anthropic وسلسلة Llama 3.1 من Meta، وتغطي مجموعة من الخيارات من النماذج الخفيفة إلى عالية الأداء، وتدعم مهام مثل توليد النصوص، والحوار، ومعالجة الصور، مما يجعلها مناسبة لتطبيقات الشركات بمختلف أحجامها واحتياجاتها."
|
||||
},
|
||||
"bfl": {
|
||||
"description": "مختبر أبحاث رائد في مقدمة الذكاء الاصطناعي، يبني البنية التحتية البصرية للمستقبل."
|
||||
"description": "مختبر بحثي رائد في مجال الذكاء الاصطناعي المتقدّم، يبني بنية تحتية بصرية للغد."
|
||||
},
|
||||
"cerebras": {
|
||||
"description": "Cerebras هو نظام استدلال ذكاء اصطناعي يعتمد على نظام CS-3 المخصص، ويهدف إلى تقديم أسرع خدمات النماذج اللغوية الكبيرة (LLM) في العالم مع استجابة فورية وقدرة معالجة عالية. تم تصميمه خصيصًا للقضاء على التأخير وتسريع سير العمل المعقد للذكاء الاصطناعي مثل توليد الشيفرات في الوقت الحقيقي والمهام التفاعلية."
|
||||
@@ -44,6 +44,9 @@
|
||||
"cometapi": {
|
||||
"description": "CometAPI هو منصة خدمات توفر واجهات متعددة لنماذج الذكاء الاصطناعي المتقدمة، تدعم OpenAI وAnthropic وGoogle والمزيد، مناسبة لمتطلبات التطوير والتطبيق المتنوعة. يمكن للمستخدمين اختيار النموذج والسعر الأمثل وفقًا لاحتياجاتهم، مما يعزز تجربة الذكاء الاصطناعي."
|
||||
},
|
||||
"comfyui": {
|
||||
"description": "محرك سير عمل قوي ومفتوح المصدر لتوليد الصور والفيديو والصوت، يدعم نماذج متقدمة مثل SD وFLUX وQwen وHunyuan وWAN، ويوفر إمكانيات تحرير سير العمل عبر العقد والنشر الخاص."
|
||||
},
|
||||
"deepseek": {
|
||||
"description": "DeepSeek هي شركة تركز على أبحاث وتطبيقات تقنيات الذكاء الاصطناعي، حيث يجمع نموذجها الأحدث DeepSeek-V2.5 بين قدرات الحوار العامة ومعالجة الشيفرات، وقد حقق تحسينات ملحوظة في محاذاة تفضيلات البشر، ومهام الكتابة، واتباع التعليمات."
|
||||
},
|
||||
|
||||
@@ -35,9 +35,16 @@
|
||||
"title": "إعادة تعيين جميع الإعدادات"
|
||||
}
|
||||
},
|
||||
"groupTab": {
|
||||
"chat": "الدردشة",
|
||||
"members": "الأعضاء",
|
||||
"meta": "المعلومات الأساسية"
|
||||
},
|
||||
"header": {
|
||||
"desc": "إعدادات التفضيلات والنماذج.",
|
||||
"global": "إعدادات عامة",
|
||||
"group": "إعدادات الفريق",
|
||||
"groupDesc": "إدارة فريق الوكلاء وتفضيلات المحادثة",
|
||||
"session": "إعدادات الجلسة",
|
||||
"sessionDesc": "إعداد الشخصية وتفضيلات الجلسة.",
|
||||
"sessionWithName": "إعدادات الجلسة · {{name}}",
|
||||
@@ -139,6 +146,9 @@
|
||||
},
|
||||
"waitingForMore": "يتم <1>التخطيط لتوفير</1> المزيد من النماذج، ترقبوا المزيد"
|
||||
},
|
||||
"message": {
|
||||
"success": "تم التحديث بنجاح"
|
||||
},
|
||||
"plugin": {
|
||||
"addMCPPlugin": "إضافة مكون MCP",
|
||||
"addTooltip": "إضافة البرنامج المساعد",
|
||||
@@ -294,6 +304,102 @@
|
||||
},
|
||||
"title": "الإعدادات العامة"
|
||||
},
|
||||
"settingGroup": {
|
||||
"description": {
|
||||
"placeholder": "يرجى إدخال وصف الفريق",
|
||||
"title": "وصف الفريق"
|
||||
},
|
||||
"name": {
|
||||
"placeholder": "يرجى إدخال اسم الفريق",
|
||||
"title": "اسم الفريق"
|
||||
},
|
||||
"scene": {
|
||||
"desc": "اختر سيناريو الفريق",
|
||||
"options": {
|
||||
"casual": "غير رسمي",
|
||||
"productive": "إنتاجي"
|
||||
},
|
||||
"title": "سيناريو الفريق"
|
||||
},
|
||||
"submit": "تحديث الفريق",
|
||||
"systemPrompt": {
|
||||
"placeholder": "يرجى إدخال كلمة تلميح نظام المضيف",
|
||||
"title": "كلمة تلميح نظام المضيف"
|
||||
},
|
||||
"title": "معلومات فريق الوكلاء"
|
||||
},
|
||||
"settingGroupChat": {
|
||||
"allowDM": {
|
||||
"desc": "عند الإيقاف، لا يزال بإمكانك إرسال رسائل خاصة إلى المساعد يدويًا",
|
||||
"title": "السماح للمساعد بإرسال رسائل خاصة"
|
||||
},
|
||||
"enableSupervisor": {
|
||||
"desc": "تفعيل وظيفة المشرف لفريق الوكلاء، حيث يدير المشرف سير المحادثة داخل الفريق",
|
||||
"title": "تفعيل المشرف"
|
||||
},
|
||||
"maxResponseInRow": {
|
||||
"desc": "اختر عدد الرسائل التي يمكن للأعضاء الرد عليها بشكل متتالي. تعيين القيمة إلى 0 لتعطيل هذا القيد.",
|
||||
"title": "عدد الردود المتتالية"
|
||||
},
|
||||
"model": {
|
||||
"desc": "لن يتأثر حديث أعضاء المجموعة. بعض النماذج لا يمكن استخدامها كنماذج مشرف.",
|
||||
"title": "نموذج المضيف"
|
||||
},
|
||||
"orchestratorTitle": "إعدادات المضيف",
|
||||
"responseOrder": {
|
||||
"desc": "سيقوم الوكلاء بالرد وفقًا للترتيب المحدد في المحادثة",
|
||||
"options": {
|
||||
"natural": "طبيعي",
|
||||
"sequential": "تتابعي"
|
||||
},
|
||||
"placeholder": "اختر ترتيب الردود",
|
||||
"title": "ترتيب الردود"
|
||||
},
|
||||
"responseSpeed": {
|
||||
"desc": "التحكم في سرعة سير المحادثة بشكل عام",
|
||||
"options": {
|
||||
"fast": "سريع",
|
||||
"medium": "متوسط",
|
||||
"slow": "بطيء"
|
||||
},
|
||||
"placeholder": "اختر سرعة الرد",
|
||||
"title": "سرعة الرد"
|
||||
},
|
||||
"revealDM": {
|
||||
"desc": "اجعل محتوى الرسائل الخاصة المرسلة إلى الأعضاء الآخرين مرئيًا لك.",
|
||||
"title": "عرض محتوى الرسائل الخاصة"
|
||||
},
|
||||
"submit": "تحديث الإعدادات",
|
||||
"systemPrompt": {
|
||||
"desc": "كلمة تلميح نظام مخصصة لمضيف محادثة الدردشة الجماعية. قد تؤثر على سلوك المضيف الافتراضي.",
|
||||
"placeholder": "يرجى إدخال كلمة تلميح نظام المضيف المخصصة...",
|
||||
"title": "كلمة تلميح نظام المضيف"
|
||||
},
|
||||
"title": "إعدادات الدردشة"
|
||||
},
|
||||
"settingGroupMembers": {
|
||||
"addToGroup": "انضم إلى المجموعة",
|
||||
"availableAgents": "المساعدون المتاحون",
|
||||
"createMember": "إنشاء عضو",
|
||||
"defaultAgent": "المساعد المخصص",
|
||||
"disableHost": "تعطيل مساعد المضيف",
|
||||
"edit": "تعديل الأعضاء",
|
||||
"empty": "لا يوجد أعضاء في هذا الفريق حاليًا. انقر على زر + لإضافة أعضاء.",
|
||||
"enableHost": "تمكين مساعد المضيف",
|
||||
"groupHost": "مضيف المجموعة",
|
||||
"groupMembers": "أعضاء المجموعة",
|
||||
"host": {
|
||||
"description": "عندما يكون المضيف في المجموعة، ستعمل الدردشة الجماعية بشكل تلقائي، مناسب للمهام الإبداعية.",
|
||||
"title": "المضيف"
|
||||
},
|
||||
"noAvailableAgents": "لا يوجد مساعدين متاحين",
|
||||
"noDescription": "لا يوجد وصف",
|
||||
"noMembersInGroup": "لا يوجد أعضاء في المجموعة",
|
||||
"owner": "أنت (المالك)",
|
||||
"remove": "إزالة العضو",
|
||||
"removeFromGroup": "إخراج من المجموعة",
|
||||
"you": "أنت"
|
||||
},
|
||||
"settingImage": {
|
||||
"defaultCount": {
|
||||
"desc": "اضبط عدد الصور الافتراضي عند إنشاء مهمة جديدة في لوحة توليد الصور.",
|
||||
|
||||
+334
-17
@@ -6,26 +6,343 @@
|
||||
},
|
||||
"defaultMessage": "أنا مساعدك الذكي الشخصي {{appName}}، كيف يمكنني مساعدتك الآن؟<br />إذا كنت بحاجة إلى مساعد أكثر احترافية أو تخصيصًا، يمكنك النقر على <plus /> لإنشاء مساعد مخصص",
|
||||
"defaultMessageWithoutCreate": "أنا مساعدك الذكي الشخصي {{appName}}، كيف يمكنني مساعدتك الآن؟",
|
||||
"qa": {
|
||||
"q01": "ما هو LobeHub؟",
|
||||
"q02": "ما هو {{appName}}؟",
|
||||
"q03": "هل يوجد دعم مجتمعي لـ {{appName}}؟",
|
||||
"q04": "ما هي الميزات التي يدعمها {{appName}}؟",
|
||||
"q05": "كيف يمكن نشر واستخدام {{appName}}؟",
|
||||
"q06": "كيف يتم تسعير {{appName}}؟",
|
||||
"q07": "هل {{appName}} مجاني؟",
|
||||
"q08": "هل هناك نسخة سحابية؟",
|
||||
"q09": "هل يدعم نماذج اللغة المحلية؟",
|
||||
"q10": "هل يدعم التعرف على الصور وتوليدها؟",
|
||||
"q11": "هل يدعم تحويل النص إلى كلام والتعرف على الصوت؟",
|
||||
"q12": "هل يدعم نظام الإضافات؟",
|
||||
"q13": "هل يوجد سوق خاص للحصول على GPTs؟",
|
||||
"q14": "هل يدعم مزودي خدمات الذكاء الاصطناعي المتعددين؟",
|
||||
"q15": "ماذا يجب أن أفعل إذا واجهت مشكلة أثناء الاستخدام؟"
|
||||
"groupActivities": {
|
||||
"analysis": {
|
||||
"codeReview": {
|
||||
"description": "مناقشة تقنية ومراجعة الأقران لتغييرات وتنفيذ الشيفرة البرمجية",
|
||||
"emoji": "💻",
|
||||
"prompt": "دعنا نراجع بعض الشيفرات معًا. هل يمكنك مساعدتنا في تحليل هذه الشيفرات وتحديد مجالات التحسين؟",
|
||||
"title": "مراجعة الشيفرة"
|
||||
},
|
||||
"investment": {
|
||||
"description": "تحليل السوق، مناقشة استراتيجيات الاستثمار ومشاركة الرؤى المالية",
|
||||
"emoji": "📈",
|
||||
"prompt": "دعنا نحلل السوق معًا. هل يمكنك مساعدتنا في مناقشة استراتيجيات الاستثمار ومشاركة الرؤى المالية؟",
|
||||
"title": "نادي الاستثمار"
|
||||
},
|
||||
"research": {
|
||||
"description": "استكشاف المفاهيم العلمية، إجراء التجارب ومشاركة الاكتشافات",
|
||||
"emoji": "🔬",
|
||||
"prompt": "دعنا نستكشف العلوم معًا! هل يمكنك مساعدتنا في إجراء التجارب ومشاركة اكتشافاتنا؟",
|
||||
"title": "معرض العلوم"
|
||||
},
|
||||
"study": {
|
||||
"description": "اجتماعات تعلم تعاونية، مناقشة المفاهيم وحل المشكلات معًا",
|
||||
"emoji": "📚",
|
||||
"prompt": "دعنا نشكل مجموعة دراسة. هل يمكنك مساعدتنا في فهم هذه المفاهيم وحل المشكلات معًا؟",
|
||||
"title": "مجموعة الدراسة"
|
||||
}
|
||||
},
|
||||
"brainstorm": {
|
||||
"artWorkshop": {
|
||||
"description": "إنشاء، نقد وتقدير أشكال مختلفة من الفن البصري والرقمي",
|
||||
"emoji": "🖼️",
|
||||
"prompt": "دعنا نقيم ورشة عمل فنية! هل يمكنك مساعدتنا في إنشاء، نقد وتقدير أشكال مختلفة من الفن؟",
|
||||
"title": "ورشة العمل الفنية"
|
||||
},
|
||||
"debate": {
|
||||
"description": "نقاشات ومناظرات منظمة حول مواضيع وقضايا مختلفة",
|
||||
"emoji": "⚖️",
|
||||
"prompt": "دعنا نجري مناظرة منظمة. هل يمكنك مساعدتنا في تنظيم نقاش منطقي حول هذا الموضوع؟",
|
||||
"title": "نادي المناظرة"
|
||||
},
|
||||
"designReview": {
|
||||
"description": "اجتماعات تعاونية لتقديم ملاحظات على مفاهيم التصميم، النماذج الأولية أو الأعمال الإبداعية",
|
||||
"emoji": "🎨",
|
||||
"prompt": "نحتاج إلى مراجعة بعض التصاميم. هل يمكنك مساعدتنا في تقديم ملاحظات بناءة على مفاهيم التصميم والنماذج الأولية؟",
|
||||
"title": "مراجعة التصميم"
|
||||
},
|
||||
"ideation": {
|
||||
"description": "توليد أفكار إبداعية وحل المشكلات بشكل تعاوني من وجهات نظر متعددة",
|
||||
"emoji": "🧠",
|
||||
"prompt": "دعنا نبدأ جلسة عصف ذهني للمشروع. هل يمكنك مساعدتنا في توليد أفكار وحلول إبداعية؟",
|
||||
"title": "جلسة العصف الذهني"
|
||||
}
|
||||
},
|
||||
"game": {
|
||||
"debateClub": {
|
||||
"description": "نقاشات ومناظرات منظمة حول مواضيع وقضايا مختلفة",
|
||||
"emoji": "⚖️",
|
||||
"prompt": "دعنا نجري مناظرة منظمة. هل يمكنك مساعدتنا في تنظيم نقاش منطقي حول هذا الموضوع؟",
|
||||
"title": "نادي المناظرة"
|
||||
},
|
||||
"gameNight": {
|
||||
"description": "ألعاب تفاعلية ممتعة وأنشطة لبناء الروابط بين الفريق والاستمتاع",
|
||||
"emoji": "🎲",
|
||||
"prompt": "ليلة الألعاب بدأت! هل يمكنك مساعدتنا في تنظيم بعض الألعاب التفاعلية الممتعة لبناء الروابط بين الفريق؟",
|
||||
"title": "ليلة الألعاب"
|
||||
},
|
||||
"modelUN": {
|
||||
"description": "محاكاة مناظرات الأمم المتحدة والمفاوضات الدبلوماسية حول القضايا العالمية",
|
||||
"emoji": "🌍",
|
||||
"prompt": "دعنا نحاكي مناظرة الأمم المتحدة. هل يمكنك مساعدتنا في إعداد مفاوضات دبلوماسية حول القضايا العالمية؟",
|
||||
"title": "محاكاة الأمم المتحدة"
|
||||
},
|
||||
"werewolf": {
|
||||
"description": "لعبة اجتماعية تعتمد على الاستراتيجية والنقاش لكشف دور الذئب بين اللاعبين",
|
||||
"emoji": "🐺",
|
||||
"prompt": "دعنا نلعب لعبة الذئب! هل يمكنك مساعدتنا في إعداد القواعد وإدارة هذه اللعبة الاجتماعية الاستنتاجية؟",
|
||||
"title": "لعبة الذئب"
|
||||
}
|
||||
},
|
||||
"general": {
|
||||
"brainstorm": {
|
||||
"description": "توليد أفكار إبداعية وحل المشكلات بشكل تعاوني من وجهات نظر متعددة",
|
||||
"emoji": "🧠",
|
||||
"prompt": "دعنا نبدأ جلسة عصف ذهني للمشروع. هل يمكنك مساعدتنا في توليد أفكار وحلول إبداعية؟",
|
||||
"title": "جلسة العصف الذهني"
|
||||
},
|
||||
"debate": {
|
||||
"description": "نقاشات ومناظرات منظمة حول مواضيع وقضايا مختلفة",
|
||||
"emoji": "⚖️",
|
||||
"prompt": "دعنا نجري مناظرة منظمة. هل يمكنك مساعدتنا في تنظيم نقاش منطقي حول هذا الموضوع؟",
|
||||
"title": "نادي المناظرة"
|
||||
},
|
||||
"languagePractice": {
|
||||
"description": "ممارسة المحادثة وتعلم لغات جديدة مع الناطقين بها",
|
||||
"emoji": "🗣️",
|
||||
"prompt": "دعنا نمارس لغة جديدة معًا. هل يمكنك مساعدتنا في تعلم وممارسة التحدث بهذه اللغة؟",
|
||||
"title": "ممارسة اللغة"
|
||||
},
|
||||
"studyGroup": {
|
||||
"description": "اجتماعات تعلم تعاونية، مناقشة المفاهيم وحل المشكلات معًا",
|
||||
"emoji": "📚",
|
||||
"prompt": "دعنا نشكل مجموعة دراسة. هل يمكنك مساعدتنا في فهم هذه المفاهيم وحل المشكلات معًا؟",
|
||||
"title": "مجموعة الدراسة"
|
||||
}
|
||||
},
|
||||
"planning": {
|
||||
"cookingClass": {
|
||||
"description": "تعلم ومشاركة مهارات الطهي، الوصفات والتقاليد الطهوية",
|
||||
"emoji": "👨🍳",
|
||||
"prompt": "دعنا نحضر درس طبخ! هل يمكنك مساعدتنا في تعلم وصفات جديدة ومهارات الطهي؟",
|
||||
"title": "صف الطبخ"
|
||||
},
|
||||
"fitnessChallenge": {
|
||||
"description": "تحديد أهداف لياقة جماعية، مشاركة تمارين وتحفيز بعضنا البعض",
|
||||
"emoji": "💪",
|
||||
"prompt": "دعنا نبدأ تحدي اللياقة! هل يمكنك مساعدتنا في تحديد الأهداف وتحفيز بعضنا البعض للحفاظ على الصحة؟",
|
||||
"title": "تحدي اللياقة"
|
||||
},
|
||||
"planningPoker": {
|
||||
"description": "تقنية تقدير مهام المشروع وحجم العمل باستخدام بطاقات التخطيط الرشيق",
|
||||
"emoji": "🃏",
|
||||
"prompt": "نحن نقوم بلعب البوكر التخطيطي للمشروع. هل يمكنك مساعدتنا في استخدام تقنيات الرشيق لتقدير حجم هذه المهام؟",
|
||||
"title": "بوكر التخطيط"
|
||||
},
|
||||
"travelPlanning": {
|
||||
"description": "تخطيط الرحلات، مشاركة تجارب السفر واكتشاف وجهات جديدة",
|
||||
"emoji": "✈️",
|
||||
"prompt": "دعنا نخطط رحلة معًا! هل يمكنك مساعدتنا في البحث عن الوجهات وتخطيط مسار الرحلة؟",
|
||||
"title": "تخطيط السفر"
|
||||
}
|
||||
},
|
||||
"product": {
|
||||
"codeReview": {
|
||||
"description": "مناقشة تقنية ومراجعة الأقران لتغييرات وتنفيذ الشيفرة البرمجية",
|
||||
"emoji": "💻",
|
||||
"prompt": "دعنا نراجع بعض الشيفرات معًا. هل يمكنك مساعدتنا في تحليل هذه الشيفرات وتحديد مجالات التحسين؟",
|
||||
"title": "مراجعة الشيفرة"
|
||||
},
|
||||
"designReview": {
|
||||
"description": "اجتماعات تعاونية لتقديم ملاحظات على مفاهيم التصميم، النماذج الأولية أو الأعمال الإبداعية",
|
||||
"emoji": "🎨",
|
||||
"prompt": "نحتاج إلى مراجعة بعض التصاميم. هل يمكنك مساعدتنا في تقديم ملاحظات بناءة على مفاهيم التصميم والنماذج الأولية؟",
|
||||
"title": "مراجعة التصميم"
|
||||
},
|
||||
"sprintPlanning": {
|
||||
"description": "تقنية تقدير مهام المشروع وحجم العمل باستخدام بطاقات التخطيط الرشيق",
|
||||
"emoji": "🃏",
|
||||
"prompt": "نحن نقوم بلعب البوكر التخطيطي للمشروع. هل يمكنك مساعدتنا في استخدام تقنيات الرشيق لتقدير حجم هذه المهام؟",
|
||||
"title": "بوكر التخطيط"
|
||||
},
|
||||
"techExchange": {
|
||||
"description": "مناقشة التقنيات الناشئة، الابتكار واتجاهات الصناعة",
|
||||
"emoji": "🚀",
|
||||
"prompt": "دعنا نجري تبادلًا تقنيًا! هل يمكنك مساعدتنا في مناقشة التقنيات الناشئة واتجاهات الصناعة؟",
|
||||
"title": "تبادل تقني"
|
||||
}
|
||||
},
|
||||
"title": "توصيات لاستخدام الدردشة الجماعية",
|
||||
"writing": {
|
||||
"bookClub": {
|
||||
"description": "مناقشات وتحليلات أدبية للكتب، القصص والأعمال الأدبية",
|
||||
"emoji": "📖",
|
||||
"prompt": "دعنا نبدأ مناقشة نادي الكتاب. هل يمكنك مساعدتنا في تحليل هذا الكتاب ومناقشة مواضيعه؟",
|
||||
"title": "نادي الكتاب"
|
||||
},
|
||||
"movieClub": {
|
||||
"description": "مشاهدة ومناقشة الأفلام، الوثائقيات والوسائط البصرية معًا",
|
||||
"emoji": "🎬",
|
||||
"prompt": "دعنا نبدأ مناقشة نادي الأفلام. هل يمكنك مساعدتنا في تحليل هذا الفيلم ومناقشة مواضيعه؟",
|
||||
"title": "نادي الأفلام"
|
||||
},
|
||||
"musicSession": {
|
||||
"description": "جلسات تعاون في تأليف الموسيقى، المشاركة والتقدير",
|
||||
"emoji": "🎵",
|
||||
"prompt": "دعنا نقم بجلسة ارتجال موسيقية! هل يمكنك مساعدتنا في إنشاء وتقدير الموسيقى معًا؟",
|
||||
"title": "جلسة الموسيقى الارتجالية"
|
||||
},
|
||||
"studyGroup": {
|
||||
"description": "اجتماعات تعلم تعاونية، مناقشة المفاهيم وحل المشكلات معًا",
|
||||
"emoji": "📚",
|
||||
"prompt": "دعنا نشكل مجموعة دراسة. هل يمكنك مساعدتنا في فهم هذه المفاهيم وحل المشكلات معًا؟",
|
||||
"title": "مجموعة الدراسة"
|
||||
}
|
||||
}
|
||||
},
|
||||
"groupMessage": "مرحبًا بك في الدردشة الجماعية! تعاون مع عدة مساعدين من الذكاء الاصطناعي في مساحة محادثة مشتركة.",
|
||||
"groupTemplates": {
|
||||
"analysis": {
|
||||
"description": "رؤى مدفوعة بالبيانات، بحث وتحليل معمق",
|
||||
"members": [
|
||||
{
|
||||
"avatar": "📊",
|
||||
"backgroundColor": "#E8F8F5",
|
||||
"plugins": ["steam"],
|
||||
"systemRole": "أنت بارع في معالجة البيانات وتفسيرها، وتكشف عن الأنماط والاتجاهات الكامنة وراء البيانات من خلال الرسوم البيانية والتحليلات الإحصائية.",
|
||||
"title": "محلل بيانات"
|
||||
},
|
||||
{
|
||||
"avatar": "🧑🔬",
|
||||
"backgroundColor": "#E8F5FF",
|
||||
"systemRole": "أنت خبير بحث، مسؤول عن جمع المعلومات والبحث المعمق، قادر على تحليل المشكلات من عدة أبعاد بشكل شامل.",
|
||||
"title": "خبير بحث"
|
||||
},
|
||||
{
|
||||
"avatar": "📈",
|
||||
"backgroundColor": "#FFF7E8",
|
||||
"systemRole": "أنت خبير إحصاء، متمكن من مختلف الطرق والنماذج الإحصائية، قادر على استخراج رؤى تجارية قيمة من البيانات.",
|
||||
"title": "خبير إحصاء"
|
||||
},
|
||||
{
|
||||
"avatar": "🧮",
|
||||
"backgroundColor": "#F0F8FF",
|
||||
"systemRole": "أنت محلل كمي، متخصص في النمذجة الكمية وتقييم المخاطر، تستخدم الطرق الرياضية لحل المشكلات المعقدة.",
|
||||
"title": "محلل كمي"
|
||||
}
|
||||
],
|
||||
"title": "فريق التحليل"
|
||||
},
|
||||
"brainstorm": {
|
||||
"description": "تفكير إبداعي متعدد الأبعاد، تحفيز إمكانيات لا محدودة",
|
||||
"members": [
|
||||
{
|
||||
"avatar": "🧠",
|
||||
"backgroundColor": "#E8F5FF",
|
||||
"systemRole": "أنت مدير إبداعي، ماهر في التحكم في اتجاه الإبداع من منظور شامل، قادر على تحويل المفاهيم المجردة إلى خطط إبداعية قابلة للتنفيذ.",
|
||||
"title": "مدير إبداعي"
|
||||
},
|
||||
{
|
||||
"avatar": "🧑🔬",
|
||||
"backgroundColor": "#FFF7E8",
|
||||
"systemRole": "أنت خبير ابتكار، مسؤول عن اكتشاف حلول جديدة وأفكار مبتكرة، تجيد التفكير خارج الأطر التقليدية.",
|
||||
"title": "خبير ابتكار"
|
||||
},
|
||||
{
|
||||
"avatar": "🎨",
|
||||
"backgroundColor": "#F6E8FF",
|
||||
"systemRole": "أنت خبير تفكير تصميمي، تفكر من منظور تجربة المستخدم والعرض البصري، تركز على التعبير الإبداعي المرئي.",
|
||||
"title": "خبير تفكير تصميمي"
|
||||
}
|
||||
],
|
||||
"title": "مجموعة العصف الذهني"
|
||||
},
|
||||
"game": {
|
||||
"description": "الاستمتاع بألعاب نصية متعددة اللاعبين مثل لعبة الذئب ومن هو العميل السري",
|
||||
"members": [
|
||||
null,
|
||||
{
|
||||
"avatar": "🧑🔬",
|
||||
"backgroundColor": "#FFF7E8",
|
||||
"systemRole": "أنت ماهر في المشاركة في مختلف ألعاب النص المتعددة اللاعبين، وقادر على اللعب وفقًا لقواعد اللعبة.",
|
||||
"title": "لاعب"
|
||||
},
|
||||
{
|
||||
"avatar": "🎨",
|
||||
"backgroundColor": "#F6E8FF",
|
||||
"systemRole": "أنت ماهر في المشاركة في مختلف ألعاب النص المتعددة اللاعبين، وقادر على اللعب وفقًا لقواعد اللعبة.",
|
||||
"title": "لاعب"
|
||||
},
|
||||
{
|
||||
"avatar": "🧑🎨",
|
||||
"backgroundColor": "#F6E8FF",
|
||||
"systemRole": "أنت ماهر في المشاركة في مختلف ألعاب النص المتعددة اللاعبين، وقادر على اللعب وفقًا لقواعد اللعبة.",
|
||||
"title": "لاعب"
|
||||
}
|
||||
],
|
||||
"title": "صالة الألعاب"
|
||||
},
|
||||
"planning": {
|
||||
"description": "التخطيط الاستراتيجي وإدارة المشاريع، تنسيق شامل",
|
||||
"members": [
|
||||
{
|
||||
"avatar": "📋",
|
||||
"backgroundColor": "#E8F5FF",
|
||||
"systemRole": "أنت مسؤول عن التخطيط العام للمشروع، مراقبة التقدم وتنسيق الموارد لضمان إتمام المشروع في الوقت المحدد وبجودة عالية.",
|
||||
"title": "طباخ"
|
||||
},
|
||||
{
|
||||
"avatar": "🎯",
|
||||
"backgroundColor": "#FFF7E8",
|
||||
"systemRole": "أنت مسؤول عن وضع الخطط الاستراتيجية طويلة الأمد، تحليل فرص السوق، تحديد الأهداف ومسارات التنفيذ.",
|
||||
"title": "خبير شراء المواد"
|
||||
},
|
||||
{
|
||||
"avatar": "🧑🎨",
|
||||
"backgroundColor": "#F0F8FF",
|
||||
"systemRole": "أنت مسؤول عن وضع خطط تنفيذية مفصلة، تنسيق موارد الأقسام المختلفة وضمان قابلية تنفيذ الخطة.",
|
||||
"title": "خبير تطوير الطعام"
|
||||
}
|
||||
],
|
||||
"title": "فريق تطوير الطعام"
|
||||
},
|
||||
"product": {
|
||||
"description": "تصميم وتطوير المنتجات، ابتكار منتجات عالية الجودة",
|
||||
"members": [
|
||||
{
|
||||
"avatar": "🎨",
|
||||
"backgroundColor": "#F6E8FF",
|
||||
"systemRole": "أنت مصمم، ماهر في تصميم مختلف أنواع المنتجات، قادر على التصميم وفق متطلبات المنتج.",
|
||||
"title": "مصمم"
|
||||
},
|
||||
{
|
||||
"avatar": "🧑",
|
||||
"backgroundColor": "#E8F5FF",
|
||||
"systemRole": "أنت مدير منتج، مسؤول عن تخطيط وتصميم وتطوير وصيانة المنتج، لضمان جودة المنتج وتجربة المستخدم.",
|
||||
"title": "مدير منتج"
|
||||
},
|
||||
{
|
||||
"avatar": "🧑💻",
|
||||
"backgroundColor": "#E8F8F5",
|
||||
"systemRole": "أنت مهندس شامل ذو خبرة، ماهر في تطوير مختلف أنواع المنتجات، قادر على التطوير وفق متطلبات المنتج.",
|
||||
"title": "مهندس شامل"
|
||||
}
|
||||
],
|
||||
"title": "فريق تطوير المنتج"
|
||||
},
|
||||
"writing": {
|
||||
"description": "إنشاء المحتوى والتحرير، ابتكار نصوص عالية الجودة",
|
||||
"members": [
|
||||
{
|
||||
"avatar": "✍️",
|
||||
"backgroundColor": "#F6E8FF",
|
||||
"systemRole": "أنت ماهر في إنشاء محتوى بأنماط أدبية مختلفة، وقادر على تعديل أسلوب الكتابة حسب المشاهد والجمهور.",
|
||||
"title": "كاتب محتوى"
|
||||
},
|
||||
{
|
||||
"avatar": "🧑🎨",
|
||||
"backgroundColor": "#E8F8F5",
|
||||
"systemRole": "أنت محرر، مسؤول عن تدقيق النصوص، تنقيحها وتحسينها، لضمان دقة المحتوى وسلاسته واحترافيته.",
|
||||
"title": "محرر"
|
||||
}
|
||||
],
|
||||
"title": "دائرة الكتابة"
|
||||
}
|
||||
},
|
||||
"questions": {
|
||||
"moreBtn": "معرفة المزيد",
|
||||
"title": "الأسئلة الشائعة:"
|
||||
"title": "جرّب أن تسأل:"
|
||||
},
|
||||
"welcome": {
|
||||
"afternoon": "مساء الخير",
|
||||
|
||||
+111
-1
@@ -2,6 +2,7 @@
|
||||
"ModelSwitch": {
|
||||
"title": "Модел"
|
||||
},
|
||||
"active": "Активен",
|
||||
"agentDefaultMessage": "Здравейте, аз съм **{{name}}**, можете да започнете разговор с мен веднага или да отидете на [Настройки на асистента]({{url}}), за да попълните информацията ми.",
|
||||
"agentDefaultMessageWithSystemRole": "Здравейте, аз съм **{{name}}**. Как мога да ви помогна?",
|
||||
"agentDefaultMessageWithoutEdit": "Здравейте, аз съм **{{name}}**. Как мога да ви помогна?",
|
||||
@@ -13,17 +14,28 @@
|
||||
"thought": "Процес на мислене",
|
||||
"unknownTitle": "Неназован артефакт"
|
||||
},
|
||||
"availableAgents": "Налични асистенти",
|
||||
"backToBottom": "Върни се в началото",
|
||||
"chatList": {
|
||||
"longMessageDetail": "Вижте детайлите"
|
||||
},
|
||||
"clearCurrentMessages": "Изчисти съобщенията от текущата сесия",
|
||||
"confirmClearCurrentMessages": "На път си да изчистиш съобщенията от текущата сесия. След като бъдат изчистени, те не могат да бъдат възстановени. Моля, потвърди действието си.",
|
||||
"confirmRemoveChatGroupItemAlert": "Този екип на Agent ще бъде изтрит. Членовете на екипа няма да бъдат засегнати. Моля, потвърдете действието си.",
|
||||
"confirmRemoveGroupItemAlert": "Ще изтриете тази група. След изтриването помощниците ѝ ще бъдат преместени в списъка по подразбиране. Моля, потвърдете действието си.",
|
||||
"confirmRemoveGroupSuccess": "Екипът на агентите беше успешно изтрит",
|
||||
"confirmRemoveSessionItemAlert": "На път си да изтриеш този агент. След като бъде изтрит, той не може да бъде възстановен. Моля, потвърди действието си.",
|
||||
"confirmRemoveSessionSuccess": "Сесията е успешно изтрита",
|
||||
"defaultAgent": "Агент по подразбиране",
|
||||
"defaultGroupChat": "Екип на агентите",
|
||||
"defaultList": "Списък по подразбиране",
|
||||
"defaultSession": "Агент по подразбиране",
|
||||
"dm": {
|
||||
"placeholder": "Вашите лични съобщения с {{agentTitle}} ще се показват тук.",
|
||||
"tooltip": "Изпрати лично съобщение",
|
||||
"visibleTo": "Видимо само за {{target}}",
|
||||
"you": "ти"
|
||||
},
|
||||
"duplicateSession": {
|
||||
"loading": "Копиране...",
|
||||
"success": "Копирането е успешно",
|
||||
@@ -58,11 +70,56 @@
|
||||
"title": "Извличане на съдържание от уеб връзки"
|
||||
}
|
||||
},
|
||||
"group": {
|
||||
"desc": "Сътрудничете с няколко асистента с изкуствен интелект в споделено пространство за разговор.",
|
||||
"memberTooltip": "В групата има {{count}} членове",
|
||||
"orchestratorThinking": "Водещият мисли...",
|
||||
"removeMember": "Премахване на член",
|
||||
"title": "Група"
|
||||
},
|
||||
"groupDescription": "Описание на екипа",
|
||||
"groupSidebar": {
|
||||
"members": {
|
||||
"addMember": "Добавяне на член",
|
||||
"memberSettings": "Настройки на член",
|
||||
"orchestrator": "Водещ",
|
||||
"orchestratorThinking": "Водещият мисли...",
|
||||
"removeMember": "Премахване на член",
|
||||
"stopOrchestrator": "Спиране на мисленето",
|
||||
"triggerOrchestrator": "Започване на групов чат"
|
||||
},
|
||||
"tabs": {
|
||||
"host": "Водещ",
|
||||
"members": "Членове",
|
||||
"role": "Настройка"
|
||||
}
|
||||
},
|
||||
"groupWizard": {
|
||||
"chooseMembers": "Изберете съществуващи асистенти...",
|
||||
"createGroup": "Създаване на екип",
|
||||
"existingMembers": "Съществуващи агенти",
|
||||
"groupMembers": "Тези асистенти също ще бъдат добавени към вашия списък",
|
||||
"host": {
|
||||
"description": "Позволява на екипа да работи самостоятелно",
|
||||
"title": "Активиране на модератор",
|
||||
"tooltip": "Ако деактивирате модератора на екипа, ще трябва ръчно да използвате @ за споменаване на членове, за да могат да отговорят"
|
||||
},
|
||||
"memberCount": "{{count}} членове",
|
||||
"noMatchingTemplates": "Няма съвпадащи шаблони",
|
||||
"noSelectedTemplates": "Не са избрани шаблони",
|
||||
"noTemplateMembers": "В шаблона няма членове",
|
||||
"noTemplates": "Няма налични шаблони",
|
||||
"searchTemplates": "Търсене на шаблони...",
|
||||
"title": "Създаване на екип на агентите",
|
||||
"useTemplate": "Използвай шаблон"
|
||||
},
|
||||
"hideForYou": "Съдържанието на личните съобщения е скрито. Моля, активирайте „Показване на съдържанието на личните съобщения“ в настройките, за да го видите.",
|
||||
"history": {
|
||||
"title": "Асистентът ще запомни само последните {{count}} съобщения"
|
||||
},
|
||||
"historyRange": "Диапазон на историята",
|
||||
"historySummary": "Исторически обобщение на съобщения",
|
||||
"inactive": "Неактивен",
|
||||
"inbox": {
|
||||
"desc": "Активирай мозъчния клъстер и събуди креативното мислене. Твоят виртуален агент е тук, за да общува с теб за всичко.",
|
||||
"title": "Просто чати"
|
||||
@@ -83,6 +140,7 @@
|
||||
"intentUnderstanding": {
|
||||
"title": "Разбирам и анализирам вашето намерение..."
|
||||
},
|
||||
"inviteMembers": "Поканете членове",
|
||||
"knowledgeBase": {
|
||||
"all": "Всички съдържания",
|
||||
"allFiles": "Всички файлове",
|
||||
@@ -101,12 +159,29 @@
|
||||
"uploadGuide": "Качените файлове могат да бъдат прегледани в „База знания“",
|
||||
"viewMore": "Вижте още"
|
||||
},
|
||||
"memberSelection": {
|
||||
"addMember": "Добавяне на член",
|
||||
"allMembers": "Всички членове",
|
||||
"createGroup": "Създаване на екип на Agent",
|
||||
"noAvailableAgents": "Няма налични асистенти за покана",
|
||||
"noSelectedAgents": "Все още не са избрани асистенти",
|
||||
"searchAgents": "Търсене на асистенти...",
|
||||
"setInitialMembers": "Избор на членове на екипа"
|
||||
},
|
||||
"members": "Членове",
|
||||
"mention": {
|
||||
"title": "Споменаване на членове"
|
||||
},
|
||||
"messageAction": {
|
||||
"delAndRegenerate": "Изтрий и прегенерирай",
|
||||
"deleteDisabledByThreads": "Съществуват подтеми, не можете да изтриете.",
|
||||
"regenerate": "Прегенерирай"
|
||||
},
|
||||
"messages": {
|
||||
"dm": {
|
||||
"sentTo": "Видимо само за {{name}}",
|
||||
"title": "Лично съобщение"
|
||||
},
|
||||
"modelCard": {
|
||||
"credit": "Кредити",
|
||||
"creditPricing": "Ценообразуване",
|
||||
@@ -153,9 +228,18 @@
|
||||
"minimap": {
|
||||
"jumpToMessage": "Отиди до съобщение № {{index}}",
|
||||
"nextMessage": "Следващо съобщение",
|
||||
"previousMessage": "Предишно съобщение"
|
||||
"previousMessage": "Предишно съобщение",
|
||||
"senderAssistant": "Асистент",
|
||||
"senderUser": "Ти"
|
||||
},
|
||||
"newAgent": "Нов агент",
|
||||
"newGroupChat": "Нов екип на агентите",
|
||||
"noAgentsYet": "Този екип на агентите все още няма членове. Натиснете бутона +, за да поканите асистент.",
|
||||
"noAvailableAgents": "Няма налични членове за покана",
|
||||
"noMatchingAgents": "Няма съвпадащи членове",
|
||||
"noMembersYet": "В тази група все още няма членове. Щракнете върху бутона +, за да поканите асистенти.",
|
||||
"noSelectedAgents": "Все още не са избрани членове",
|
||||
"owner": "Собственик на групата",
|
||||
"pin": "Закачи",
|
||||
"pinOff": "Откачи",
|
||||
"rag": {
|
||||
@@ -196,12 +280,16 @@
|
||||
"title": "Търсене в интернет"
|
||||
},
|
||||
"searchAgentPlaceholder": "Търсач на помощ...",
|
||||
"searchAgents": "Асистент за търсене...",
|
||||
"selectedAgents": "Избрани помощници",
|
||||
"sendPlaceholder": "Напиши съобщението си тук...",
|
||||
"sessionGroup": {
|
||||
"config": "Управление на групи",
|
||||
"confirmRemoveGroupAlert": "Тази група е на път да бъде изтрита. След изтриването, агентите в тази група ще бъдат преместени в списъка по подразбиране. Моля, потвърди действието си.",
|
||||
"createAgentSuccess": "Асистентът е създаден успешно",
|
||||
"createGroup": "Добави нова група",
|
||||
"createGroupFailed": "Създаването на груповия чат не бе успешно",
|
||||
"createGroupSuccess": "Груповият чат бе създаден успешно",
|
||||
"createSuccess": "Създадена успешно",
|
||||
"creatingAgent": "Създаване на асистент...",
|
||||
"inputPlaceholder": "Моля, въведете име на групата...",
|
||||
@@ -216,11 +304,24 @@
|
||||
"shareModal": {
|
||||
"copy": "Копирай",
|
||||
"download": "Изтегли екранна снимка",
|
||||
"downloadError": "Грешка при изтегляне",
|
||||
"downloadFile": "Изтегли файла",
|
||||
"downloadPdf": "Изтегляне на PDF",
|
||||
"downloadSuccess": "Изтеглянето е успешно",
|
||||
"exportPdf": "Експортиране като PDF",
|
||||
"exportTitle": "По подразбиране заглавие",
|
||||
"generatePdf": "Генериране на PDF",
|
||||
"generatingPdf": "Генериране на PDF...",
|
||||
"imageType": "Формат на изображението",
|
||||
"includeTool": "Включи съобщения от инструмента",
|
||||
"includeUser": "Включи съобщения от потребителя",
|
||||
"loadingPdf": "Зареждане на PDF...",
|
||||
"noPdfData": "Няма налични PDF данни",
|
||||
"pdf": "PDF",
|
||||
"pdfErrorDescription": "Възникна грешка при генерирането на PDF, моля опитайте отново",
|
||||
"pdfGenerationError": "Грешка при генериране на PDF",
|
||||
"pdfReady": "PDF е готов",
|
||||
"regeneratePdf": "Генериране на PDF отново",
|
||||
"screenshot": "Екранна снимка",
|
||||
"settings": "Настройки за експортиране",
|
||||
"text": "Текст",
|
||||
@@ -235,6 +336,12 @@
|
||||
"loading": "Разпознаване...",
|
||||
"prettifying": "Изглаждане..."
|
||||
},
|
||||
"supervisor": {
|
||||
"todoList": {
|
||||
"allComplete": "Всички задачи са изпълнени",
|
||||
"title": "Задачите са изпълнени"
|
||||
}
|
||||
},
|
||||
"thread": {
|
||||
"divider": "Подтема",
|
||||
"threadMessageCount": "{{messageCount}} съобщения",
|
||||
@@ -248,6 +355,7 @@
|
||||
"chats": "Чат съобщения",
|
||||
"historySummary": "Историческо резюме",
|
||||
"rest": "Оставащи",
|
||||
"supervisor": "Водещ на групата",
|
||||
"systemRole": "Настройки на ролята",
|
||||
"title": "Детайли на токена",
|
||||
"tools": "Настройки на плъгина",
|
||||
@@ -273,6 +381,7 @@
|
||||
"action": "Текст към говор",
|
||||
"clear": "Изчисти речта"
|
||||
},
|
||||
"untitledAgent": "Безименен асистент",
|
||||
"updateAgent": "Актуализирай информацията за агента",
|
||||
"upload": {
|
||||
"action": {
|
||||
@@ -300,5 +409,6 @@
|
||||
"videoSizeExceeded": "Размерът на видео файла не може да надвишава 20MB, текущият размер е {{actualSize}}"
|
||||
}
|
||||
},
|
||||
"you": "ти",
|
||||
"zenMode": "Режим на фокус"
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
"batchDelete": "Пакетно изтриване",
|
||||
"blog": "Продуктов блог",
|
||||
"branching": "Създаване на подтема",
|
||||
"branchingDisable": "Функцията „подтема“ е налична само в сървърната версия. Ако искате да използвате тази функция, моля, превключете на режим на сървърно разполагане или използвайте LobeChat Cloud.",
|
||||
"branchingDisable": "Функцията „Подтеми“ не е налична в текущия режим. За да я използвате, превключете към режим Postgres/Pglite DB или използвайте LobeHub Cloud.",
|
||||
"branchingRequiresSavedTopic": "Текущата тема не е запазена, моля запазете я, за да използвате функцията за под-теми",
|
||||
"cancel": "Отказ",
|
||||
"changelog": "Дневник на промените",
|
||||
@@ -338,6 +338,7 @@
|
||||
"chat": "Чат",
|
||||
"discover": "Открий",
|
||||
"files": "Файлове",
|
||||
"knowledgeBase": "База знания",
|
||||
"me": "аз",
|
||||
"setting": "Настройки"
|
||||
},
|
||||
|
||||
@@ -50,6 +50,10 @@
|
||||
"total": {
|
||||
"fileCount": "Общо {{count}} елемента",
|
||||
"selectedCount": "Избрани {{count}} елемента"
|
||||
},
|
||||
"view": {
|
||||
"list": "Изглед като списък",
|
||||
"masonry": "Изглед като мрежа"
|
||||
}
|
||||
},
|
||||
"FileParsingStatus": {
|
||||
|
||||
@@ -92,14 +92,15 @@
|
||||
"installLater": "Актуализиране при следващо стартиране",
|
||||
"isLatestVersion": "Вече имате най-новата версия",
|
||||
"isLatestVersionDesc": "Страхотно, версията {{version}} е най-новата налична версия.",
|
||||
"later": "Актуализирай по-късно",
|
||||
"later": "По-късно",
|
||||
"newVersionAvailable": "Налична е нова версия",
|
||||
"newVersionAvailableDesc": "Открита е нова версия {{version}}, искате ли да я изтеглите сега?",
|
||||
"restartAndInstall": "Инсталиране на актуализацията и рестартиране",
|
||||
"updateError": "Грешка при актуализацията",
|
||||
"updateReady": "Актуализацията е готова",
|
||||
"updateReady": "Налична е нова версия",
|
||||
"updateReadyDesc": "Нова версия {{version}} е изтеглена, инсталацията ще завърши след рестартиране на приложението.",
|
||||
"upgradeNow": "Актуализирай сега"
|
||||
"upgradeNow": "Актуализирай сега",
|
||||
"willInstallLater": "Актуализацията ще бъде инсталирана при следващото стартиране"
|
||||
},
|
||||
"waitingOAuth": {
|
||||
"cancel": "Отмени",
|
||||
|
||||
@@ -81,6 +81,12 @@
|
||||
"522": "Съжаляваме, времето за свързване на сървъра изтече, без да успее да отговори на вашето искане навреме. Може да е поради нестабилна мрежа или сървърът временно не е достъпен. Моля, опитайте отново по-късно, ние работим за възстановяване на услугата.",
|
||||
"524": "Съжаляваме, сървърът изтече времето за изчакване, докато чакаше отговор, вероятно поради бавен отговор. Моля, опитайте отново по-късно.",
|
||||
"AgentRuntimeError": "Грешка при изпълнение на времето за изпълнение на езиковия модел Lobe. Моля, отстранете неизправностите или опитайте отново въз основа на следната информация.",
|
||||
"ComfyUIBizError": "Възникна грешка при заявката към услугата ComfyUI. Моля, проверете информацията по-долу или опитайте отново.",
|
||||
"ComfyUIEmptyResult": "ComfyUI не генерира изображение. Моля, проверете конфигурацията на модела или опитайте отново.",
|
||||
"ComfyUIModelError": "Неуспешно зареждане на модела в ComfyUI. Моля, проверете дали файлът на модела съществува.",
|
||||
"ComfyUIServiceUnavailable": "Неуспешна връзка с услугата ComfyUI. Моля, уверете се, че ComfyUI работи правилно и че адресът на услугата е коректно конфигуриран.",
|
||||
"ComfyUIUploadFailed": "Неуспешно качване на изображение в ComfyUI. Моля, проверете връзката със сървъра или опитайте отново.",
|
||||
"ComfyUIWorkflowError": "Грешка при изпълнение на работния процес в ComfyUI. Моля, проверете конфигурацията на работния процес.",
|
||||
"ConnectionCheckFailed": "Заявката върна празен отговор. Моля, проверете дали адресът на API проксито не завършва с `/v1`.",
|
||||
"CreateMessageError": "Съжалявам, съобщението не можа да бъде изпратено успешно. Моля, копирайте съдържанието и го изпратете отново. След опресняване на страницата, това съобщение няма да бъде запазено.",
|
||||
"ExceededContextWindow": "Текущото съдържание на заявката надвишава дължината, която моделът може да обработи. Моля, намалете обема на съдържанието и опитайте отново.",
|
||||
@@ -100,6 +106,7 @@
|
||||
"InvalidAccessCode": "Невалиден или празен код за достъп. Моля, въведете правилния код за достъп или добавете персонализиран API ключ.",
|
||||
"InvalidBedrockCredentials": "Удостоверяването на Bedrock е неуспешно. Моля, проверете AccessKeyId/SecretAccessKey и опитайте отново.",
|
||||
"InvalidClerkUser": "很抱歉,你当前尚未登录,请先登录或注册账号后继续操作",
|
||||
"InvalidComfyUIArgs": "Неправилна конфигурация на ComfyUI. Моля, проверете настройките и опитайте отново.",
|
||||
"InvalidGithubToken": "GitHub Личният Достъпен Токен е неправилен или е празен. Моля, проверете Личния Достъпен Токен на GitHub и опитайте отново.",
|
||||
"InvalidOllamaArgs": "Невалидна конфигурация на Ollama, моля, проверете конфигурацията на Ollama и опитайте отново",
|
||||
"InvalidProviderAPIKey": "{{provider}} API ключ е невалиден или липсва, моля проверете {{provider}} API ключа и опитайте отново",
|
||||
@@ -134,6 +141,9 @@
|
||||
"stt": {
|
||||
"responseError": "Заявката за услуга е неуспешна, моля, проверете конфигурацията или опитайте отново"
|
||||
},
|
||||
"supervisor": {
|
||||
"decisionFailed": "Ръководителят на групата не може да работи. Моля, проверете конфигурацията на ръководителя си, за да се уверите, че е зададен правилният модел, API ключ и API адрес."
|
||||
},
|
||||
"testConnectionFailed": "Неуспешно свързване: {{error}}",
|
||||
"tts": {
|
||||
"responseError": "Заявката за услуга е неуспешна, моля, проверете конфигурацията или опитайте отново"
|
||||
@@ -146,6 +156,11 @@
|
||||
"title": "Използване на персонализиран {{name}} API ключ"
|
||||
},
|
||||
"closeMessage": "Затвори съобщението",
|
||||
"comfyui": {
|
||||
"description": "Моля, въведете валидна удостоверителна информация за {{name}}, за да започнете с генерирането на изображения.",
|
||||
"modifyBaseUrl": "Промяна на адреса на услугата Comfy UI",
|
||||
"title": "Потвърдете удостоверителната си информация за {{name}}"
|
||||
},
|
||||
"confirm": "Потвърди и опитай отново",
|
||||
"oauth": {
|
||||
"description": "Администраторът е активирал унифицирано удостоверяване за вход. Щракнете върху бутона по-долу, за да влезете и отключите приложението.",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"desc": "Управлявайте вашите файлове и база знания",
|
||||
"desc": "Управлявайте своите знания",
|
||||
"detail": {
|
||||
"basic": {
|
||||
"createdAt": "Дата на създаване",
|
||||
@@ -70,7 +70,7 @@
|
||||
"videos": "Видеа",
|
||||
"websites": "Уебсайтове"
|
||||
},
|
||||
"title": "Файлове",
|
||||
"title": "База знания",
|
||||
"toggleLeftPanel": {
|
||||
"title": "Покажи/Скрий лявото панел"
|
||||
},
|
||||
|
||||
@@ -82,6 +82,58 @@
|
||||
"title": "ID на Cloudflare / API адрес"
|
||||
}
|
||||
},
|
||||
"comfyui": {
|
||||
"apiKey": {
|
||||
"desc": "API ключ, необходим за удостоверяване с Bearer Token",
|
||||
"placeholder": "Моля, въведете API ключ",
|
||||
"required": "Моля, въведете API ключ",
|
||||
"title": "API ключ"
|
||||
},
|
||||
"authType": {
|
||||
"desc": "Изберете метод за удостоверяване със сървъра ComfyUI",
|
||||
"options": {
|
||||
"basic": "Потребителско име/Парола",
|
||||
"bearer": "Bearer (API ключ)",
|
||||
"custom": "Потребителски HTTP хедъри",
|
||||
"none": "Без удостоверяване"
|
||||
},
|
||||
"placeholder": "Моля, изберете тип удостоверяване",
|
||||
"title": "Тип удостоверяване"
|
||||
},
|
||||
"baseURL": {
|
||||
"desc": "Уеб адрес за достъп до ComfyUI",
|
||||
"placeholder": "http://127.0.0.1:8000",
|
||||
"required": "Моля, въведете адреса на услугата ComfyUI",
|
||||
"title": "Адрес на услугата ComfyUI"
|
||||
},
|
||||
"checker": {
|
||||
"desc": "Проверете дали връзката е конфигурирана правилно",
|
||||
"title": "Проверка на свързаността"
|
||||
},
|
||||
"customHeaders": {
|
||||
"addButton": "Добавяне на хедър",
|
||||
"deleteTooltip": "Изтриване на този хедър",
|
||||
"desc": "HTTP хедъри, необходими за потребителски метод на удостоверяване, във формат ключ-стойност",
|
||||
"duplicateKeyError": "Ключовете на хедърите не трябва да се повтарят",
|
||||
"keyPlaceholder": "Ключ",
|
||||
"required": "Моля, въведете потребителски HTTP хедър",
|
||||
"title": "Потребителски HTTP хедъри",
|
||||
"valuePlaceholder": "Стойност"
|
||||
},
|
||||
"password": {
|
||||
"desc": "Парола, необходима за базово удостоверяване",
|
||||
"placeholder": "Моля, въведете парола",
|
||||
"required": "Моля, въведете парола",
|
||||
"title": "Парола"
|
||||
},
|
||||
"title": "ComfyUI",
|
||||
"username": {
|
||||
"desc": "Потребителско име, необходимо за базово удостоверяване",
|
||||
"placeholder": "Моля, въведете потребителско име",
|
||||
"required": "Моля, въведете потребителско име",
|
||||
"title": "Потребителско име"
|
||||
}
|
||||
},
|
||||
"createNewAiProvider": {
|
||||
"apiKey": {
|
||||
"placeholder": "Моля, въведете вашия API ключ",
|
||||
@@ -399,6 +451,11 @@
|
||||
"desc": "Въведете вашите ключове за Vertex AI",
|
||||
"placeholder": "{ \"type\": \"service_account\", \"project_id\": \"xxx\", \"private_key_id\": ... }",
|
||||
"title": "Ключове за Vertex AI"
|
||||
},
|
||||
"region": {
|
||||
"desc": "Изберете регион за услугата Vertex AI. Някои модели, като Gemini 2.5, са налични само в определени региони (например global)",
|
||||
"placeholder": "Изберете регион",
|
||||
"title": "Регион на Vertex AI"
|
||||
}
|
||||
},
|
||||
"zeroone": {
|
||||
|
||||
@@ -311,6 +311,12 @@
|
||||
"Qwen/QwQ-32B-Preview": {
|
||||
"description": "QwQ-32B-Preview е най-новият експериментален изследователски модел на Qwen, който се фокусира върху подобряване на AI разсъдъчните способности. Чрез изследване на сложни механизми като езикови смеси и рекурсивно разсъждение, основните предимства включват мощни аналитични способности, математически и програмистки умения. В същото време съществуват проблеми с езиковото превключване, цикли на разсъждение, съображения за безопасност и разлики в други способности."
|
||||
},
|
||||
"Qwen/Qwen-Image": {
|
||||
"description": "Qwen-Image е базов модел за генериране на изображения, разработен от екипа на Tongyi Qianwen в Alibaba, с 20 милиарда параметъра. Моделът постига значителен напредък в сложния текстов рендеринг и прецизното редактиране на изображения, като е особено добър в създаването на изображения с висококачествен текст както на китайски, така и на английски език. Qwen-Image може да обработва многострочно оформление и текст на ниво абзац, като същевременно поддържа последователност в типографията и хармония в контекста при генериране на изображения. Освен изключителните си способности за текстов рендеринг, моделът поддържа широка гама от художествени стилове — от реалистична фотография до аниме естетика — и може гъвкаво да се адаптира към различни творчески нужди. Също така притежава мощни възможности за редактиране и разбиране на изображения, включително трансфер на стил, добавяне и премахване на обекти, подобряване на детайли, редактиране на текст и дори управление на човешки пози. Целта му е да бъде цялостен интелигентен базов модел за визуално творчество и обработка, който обединява език, оформление и изображение."
|
||||
},
|
||||
"Qwen/Qwen-Image-Edit-2509": {
|
||||
"description": "Qwen-Image-Edit-2509 е най-новата версия за редактиране на изображения от Qwen-Image, разработена от екипа на Tongyi Qianwen в Alibaba. Моделът е допълнително обучен на базата на Qwen-Image с 20 милиарда параметъра и успешно разширява уникалните си способности за текстов рендеринг в областта на редактирането на изображения, позволявайки прецизна редакция на текст в изображения. Qwen-Image-Edit използва иновативна архитектура, при която входното изображение се подава едновременно към Qwen2.5-VL (за семантичен визуален контрол) и VAE Encoder (за контрол на визуалния външен вид), осигурявайки двойна способност за редактиране както на семантиката, така и на външния вид. Това означава, че моделът поддържа не само локални редакции като добавяне, премахване или промяна на елементи, но и по-сложни семантични редакции, изискващи запазване на смисъла, като създаване на IP съдържание и трансфер на стил. Моделът показва водеща (SOTA) производителност в множество публични бенчмаркове, което го прави мощен базов модел за редактиране на изображения."
|
||||
},
|
||||
"Qwen/Qwen2-72B-Instruct": {
|
||||
"description": "Qwen2 е напреднал универсален езиков модел, поддържащ множество типове инструкции."
|
||||
},
|
||||
@@ -392,6 +398,12 @@
|
||||
"Qwen/Qwen3-Next-80B-A3B-Thinking": {
|
||||
"description": "Qwen3-Next-80B-A3B-Thinking е следващото поколение основен модел, публикуван от екипа на Alibaba Tongyi Qianwen, специално проектиран за сложни задачи за разсъждение. Той е базиран на иновативната архитектура Qwen3-Next, която комбинира хибриден механизъм за внимание (Gated DeltaNet и Gated Attention) и структура с висока степен на разреждане на смесени експерти (MoE), с цел постигане на изключителна ефективност при обучение и извод. Като разреден модел с общо 80 милиарда параметри, при извод активира само около 3 милиарда параметри, което значително намалява изчислителните разходи. При обработка на задачи с дълъг контекст над 32K токена, пропускателната способност при извод е над 10 пъти по-висока в сравнение с модела Qwen3-32B. Тази „Thinking“ версия е оптимизирана за изпълнение на сложни многостъпкови задачи като математически доказателства, синтез на код, логически анализ и планиране, като по подразбиране изходът на разсъжденията е във формата на структурирана „мисловна верига“. По отношение на производителността, тя не само превъзхожда модели с по-високи разходи като Qwen3-32B-Thinking, но и превъзхожда Gemini-2.5-Flash-Thinking в множество бенчмаркове."
|
||||
},
|
||||
"Qwen/Qwen3-VL-8B-Instruct": {
|
||||
"description": "Qwen3-VL-8B-Instruct е визуално-езиков модел от серията Qwen3, базиран на Qwen3-8B-Instruct и обучен върху голям обем от данни с изображения и текст. Той е особено добър в общо визуално разбиране, визуално-центрирани диалози и разпознаване на многоезичен текст в изображения. Подходящ е за визуални въпроси и отговори, описание на изображения, мултимодални инструкции и използване на инструменти."
|
||||
},
|
||||
"Qwen/Qwen3-VL-8B-Thinking": {
|
||||
"description": "Qwen3-VL-8B-Thinking е версия от серията Qwen3, фокусирана върху визуално мислене, оптимизирана за сложни задачи с многостъпково разсъждение. По подразбиране генерира верига от мисли (thinking chain) преди отговора, за да подобри точността на разсъжденията. Подходящ е за визуални въпроси и отговори, които изискват дълбоко разсъждение, преглед на съдържанието на изображения и предоставяне на подробен анализ."
|
||||
},
|
||||
"Qwen2-72B-Instruct": {
|
||||
"description": "Qwen2 е най-новата серия на модела Qwen, поддържаща 128k контекст. В сравнение с текущите най-добри отворени модели, Qwen2-72B значително надминава водещите модели в области като разбиране на естествен език, знания, код, математика и многоезичност."
|
||||
},
|
||||
@@ -767,6 +779,9 @@
|
||||
"claude-3-sonnet-20240229": {
|
||||
"description": "Claude 3 Sonnet предлага идеален баланс между интелигентност и скорост за корпоративни работни натоварвания. Той предлага максимална полезност на по-ниска цена, надежден и подходящ за мащабно внедряване."
|
||||
},
|
||||
"claude-haiku-4-5-20251001": {
|
||||
"description": "Claude Haiku 4.5 е най-бързият и интелигентен Haiku модел на Anthropic, отличаващ се със светкавична скорост и разширени способности за мислене."
|
||||
},
|
||||
"claude-opus-4-1-20250805": {
|
||||
"description": "Claude Opus 4.1 е най-новият и най-мощен модел на Anthropic за справяне с изключително сложни задачи. Той се отличава с изключителна производителност, интелигентност, плавност и разбиране."
|
||||
},
|
||||
@@ -851,6 +866,39 @@
|
||||
"cohere/embed-v4.0": {
|
||||
"description": "Модел, който позволява класифициране на текст, изображения или смесено съдържание или преобразуването им във вграждания."
|
||||
},
|
||||
"comfyui/flux-dev": {
|
||||
"description": "FLUX.1 Dev - Висококачествен текст-към-изображение модел, генерира изображения за 10-50 стъпки, подходящ за художествено творчество и създаване на изкуство"
|
||||
},
|
||||
"comfyui/flux-kontext-dev": {
|
||||
"description": "FLUX.1 Kontext-dev - Модел за редактиране на изображения, поддържа модификации на съществуващи изображения чрез текстови инструкции, включително локални промени и трансфер на стил"
|
||||
},
|
||||
"comfyui/flux-krea-dev": {
|
||||
"description": "FLUX.1 Krea-dev - Подобрен и сигурен текст-към-изображение модел, разработен в сътрудничество с Krea, с вградена система за безопасно филтриране"
|
||||
},
|
||||
"comfyui/flux-schnell": {
|
||||
"description": "FLUX.1 Schnell - Ултрабърз текст-към-изображение модел, генерира висококачествени изображения само за 1-4 стъпки, идеален за приложения в реално време и бързо прототипиране"
|
||||
},
|
||||
"comfyui/stable-diffusion-15": {
|
||||
"description": "Stable Diffusion 1.5 текст-към-изображение модел, класическа генерация с резолюция 512x512, подходящ за бързо прототипиране и творчески експерименти"
|
||||
},
|
||||
"comfyui/stable-diffusion-35": {
|
||||
"description": "Stable Diffusion 3.5 - ново поколение текст-към-изображение модел, предлага се във версии Large и Medium, изисква външен CLIP енкодер файл, осигурява изключително качество на изображенията и висока точност на съвпадение с подадените подсказки"
|
||||
},
|
||||
"comfyui/stable-diffusion-35-inclclip": {
|
||||
"description": "Stable Diffusion 3.5 с вграден CLIP/T5 енкодер, не изисква външни енкодер файлове, подходящ за модели като sd3.5_medium_incl_clips, с по-ниска консумация на ресурси"
|
||||
},
|
||||
"comfyui/stable-diffusion-custom": {
|
||||
"description": "Персонализиран SD текст-към-изображение модел. Името на модела трябва да бъде custom_sd_lobe.safetensors, ако има VAE, използвайте custom_sd_vae_lobe.safetensors. Файловете на модела трябва да бъдат поставени в съответната папка според изискванията на Comfy"
|
||||
},
|
||||
"comfyui/stable-diffusion-custom-refiner": {
|
||||
"description": "Персонализиран SDXL изображение-към-изображение модел. Името на модела трябва да бъде custom_sd_lobe.safetensors, ако има VAE, използвайте custom_sd_vae_lobe.safetensors. Файловете на модела трябва да бъдат поставени в съответната папка според изискванията на Comfy"
|
||||
},
|
||||
"comfyui/stable-diffusion-refiner": {
|
||||
"description": "SDXL изображение-към-изображение модел, извършва висококачествено преобразуване на изображения въз основа на входно изображение, поддържа трансфер на стил, възстановяване на изображения и креативни трансформации"
|
||||
},
|
||||
"comfyui/stable-diffusion-xl": {
|
||||
"description": "SDXL текст-към-изображение модел, поддържа генериране на изображения с висока резолюция 1024x1024, осигурява по-добро качество и детайлност"
|
||||
},
|
||||
"command": {
|
||||
"description": "Диалогов модел, следващ инструкции, който показва високо качество и надеждност в езиковите задачи, с по-дълга контекстна дължина в сравнение с нашия основен генеративен модел."
|
||||
},
|
||||
@@ -1148,6 +1196,9 @@
|
||||
"doubao-seed-1.6-flash": {
|
||||
"description": "Doubao-Seed-1.6-flash е изключително бърз много модален модел за дълбоко мислене с TPOT само 10ms; поддържа както текстово, така и визуално разбиране, като текстовите му възможности надминават предишното поколение lite, а визуалното разбиране е на нивото на професионалните модели на конкурентите. Поддържа контекстен прозорец от 256k и максимална дължина на изхода до 16k токена."
|
||||
},
|
||||
"doubao-seed-1.6-lite": {
|
||||
"description": "Doubao-Seed-1.6-lite е нов мултимодален модел за дълбоко мислене, поддържащ регулируеми нива на разсъждение (reasoning effort): Minimal, Low, Medium и High. Със своята висока ефективност и достъпност, той е отличен избор за често срещани задачи и поддържа контекстуален прозорец до 256k."
|
||||
},
|
||||
"doubao-seed-1.6-thinking": {
|
||||
"description": "Doubao-Seed-1.6-thinking моделът значително подобрява способностите за мислене в сравнение с Doubao-1.5-thinking-pro, с допълнителни подобрения в кодиране, математика и логическо разсъждение, като поддържа и визуално разбиране. Поддържа контекстен прозорец от 256k и максимална дължина на изхода до 16k токена."
|
||||
},
|
||||
@@ -1541,9 +1592,6 @@
|
||||
"glm-zero-preview": {
|
||||
"description": "GLM-Zero-Preview притежава мощни способности за сложни разсъждения, показвайки отлични резултати в логическото разсъждение, математиката и програмирането."
|
||||
},
|
||||
"glm4.6:355b": {
|
||||
"description": "Най-новият флагмански модел на Zhipu — GLM-4.6 (355B) — значително надминава предшествениците си в напреднало програмиране, обработка на дълги текстове, логическо разсъждение и способности на интелигентни агенти. Особено в програмирането се изравнява с Claude Sonnet 4, превръщайки се в водещ модел за кодиране в Китай."
|
||||
},
|
||||
"google/gemini-2.0-flash": {
|
||||
"description": "Gemini 2.0 Flash предлага следващо поколение функции и подобрения, включително изключителна скорост, вградена употреба на инструменти, мултимодално генериране и контекстен прозорец от 1 милион токена."
|
||||
},
|
||||
@@ -1934,12 +1982,18 @@
|
||||
"inception/mercury-coder-small": {
|
||||
"description": "Mercury Coder Small е идеален за задачи по генериране, отстраняване на грешки и рефакториране на код с минимална латентност."
|
||||
},
|
||||
"inclusionAI/Ling-1T": {
|
||||
"description": "Ling-1T е първият флагмански non-thinking модел от серията „Ling 2.0“, с общо 1 трилион параметри и около 50 милиарда активни параметри на токен. Изграден върху архитектурата Ling 2.0, Ling-1T цели да преодолее границите на ефективното разсъждение и мащабируемото познание. Ling-1T-base е обучен върху над 20 трилиона висококачествени, интензивно логически токени."
|
||||
},
|
||||
"inclusionAI/Ling-flash-2.0": {
|
||||
"description": "Ling-flash-2.0 е третият модел от серията Ling 2.0 архитектури, публикуван от екипа на Ant Group Bailing. Това е модел с хибридни експерти (MoE) с общо 100 милиарда параметри, но при всеки токен активира само 6.1 милиарда параметри (без вграждания – 4.8 милиарда). Като леко конфигуриран модел, Ling-flash-2.0 показва в множество авторитетни оценки производителност, сравнима или дори превъзхождаща плътни (Dense) модели с 40 милиарда параметри и по-големи MoE модели. Моделът е предназначен да изследва пътища за висока ефективност чрез изключителен дизайн на архитектурата и стратегии за обучение, в контекста на общоприетото схващане, че „големият модел е равен на големи параметри“."
|
||||
},
|
||||
"inclusionAI/Ling-mini-2.0": {
|
||||
"description": "Ling-mini-2.0 е малък, но високопроизводителен голям езиков модел, базиран на MoE архитектура. Той има общо 16 милиарда параметри, но при всеки токен активира само 1.4 милиарда (без вграждания – 789 милиона), което осигурява изключително бърза генерация. Благодарение на ефективния MoE дизайн и големия обем висококачествени тренировъчни данни, въпреки че активираните параметри са само 1.4 милиарда, Ling-mini-2.0 демонстрира върхова производителност в downstream задачи, сравнима с плътни LLM под 10 милиарда параметри и по-големи MoE модели."
|
||||
},
|
||||
"inclusionAI/Ring-1T": {
|
||||
"description": "Ring-1T е отворен модел за мислене с трилион параметри, разработен от екипа на Bailing. Базиран е на архитектурата Ling 2.0 и основния модел Ling-1T-base, с общо 1 трилион параметри и 50 милиарда активни параметри, поддържащ контекстуален прозорец до 128K. Моделът е оптимизиран чрез мащабно обучение с проверими награди и подсилено обучение."
|
||||
},
|
||||
"inclusionAI/Ring-flash-2.0": {
|
||||
"description": "Ring-flash-2.0 е високопроизводителен мисловен модел, дълбоко оптимизиран на базата на Ling-flash-2.0-base. Той използва MoE архитектура с общо 100 милиарда параметри, но при всяко извод активира само 6.1 милиарда параметри. Моделът решава нестабилността на големите MoE модели при обучение с подсилено учене (RL) чрез уникалния алгоритъм icepop, което позволява непрекъснато подобряване на сложните разсъждения при дългосрочно обучение. Ring-flash-2.0 постига значителни пробиви в множество трудни бенчмаркове като математически състезания, генериране на код и логически разсъждения. Неговата производителност не само превъзхожда топ плътни модели с по-малко от 40 милиарда параметри, но и се сравнява с по-големи отворени MoE модели и затворени високопроизводителни мисловни модели. Въпреки че е фокусиран върху сложни разсъждения, моделът се представя отлично и в творческо писане. Благодарение на ефективния си архитектурен дизайн, Ring-flash-2.0 осигурява висока производителност и бърз извод, значително намалявайки разходите за внедряване на мисловни модели при висока паралелност."
|
||||
},
|
||||
@@ -2036,9 +2090,6 @@
|
||||
"llama-3.3-instruct": {
|
||||
"description": "Моделата Llama 3.3 с фина настройка за инструкции е оптимизирана за диалогови сценарии и надминава много съществуващи модели с отворен код в общи отраслови бенчмарк тестове."
|
||||
},
|
||||
"llama-4-maverick-17b-128e-instruct": {
|
||||
"description": "Llama 4 Maverick: високопроизводителен модел от серията Llama, подходящ за напреднало разсъждение, решаване на сложни задачи и следване на инструкции."
|
||||
},
|
||||
"llama-4-scout-17b-16e-instruct": {
|
||||
"description": "Llama 4 Scout: високопроизводителен модел от серията Llama, оптимизиран за сценарии с висока пропускателна способност и ниска латентност."
|
||||
},
|
||||
@@ -2906,6 +2957,9 @@
|
||||
"qwen3-8b": {
|
||||
"description": "Qwen3 е ново поколение модел с значително подобрени способности, който достига водещо ниво в индустрията в области като разсъждение, общо използване, агенти и многоезичност, и поддържа превключване на режимите на разсъждение."
|
||||
},
|
||||
"qwen3-coder-30b-a3b-instruct": {
|
||||
"description": "Откритият кодов модел на Tongyi Qianwen. Най-новият qwen3-coder-30b-a3b-instruct е модел за генериране на код, базиран на Qwen3, с мощни способности като Coding Agent, умело използва инструменти и взаимодейства с околната среда, способен на автономно програмиране и отлични кодови умения, съчетани с общи способности."
|
||||
},
|
||||
"qwen3-coder-480b-a35b-instruct": {
|
||||
"description": "Отворена версия на кодовия модел Tongyi Qianwen. Най-новият qwen3-coder-480b-a35b-instruct е кодов модел, базиран на Qwen3, с мощни Coding Agent способности, умения за използване на инструменти и взаимодействие с околната среда, способен на автономно програмиране с отлични кодови и общи умения."
|
||||
},
|
||||
@@ -2927,11 +2981,29 @@
|
||||
"qwen3-next-80b-a3b-thinking": {
|
||||
"description": "Базирано на Qwen3, ново поколение отворен модел с мисловен режим, който подобрява спазването на инструкции и предоставя по-кратки и точни обобщения в сравнение с предишната версия (Tongyi Qianwen 3-235B-A22B-Thinking-2507)."
|
||||
},
|
||||
"qwen3-omni-flash": {
|
||||
"description": "Моделът Qwen-Omni приема комбинирани входове от текст, изображения, аудио и видео, и генерира отговори под формата на текст или реч. Предлага разнообразни хуманизирани гласове, поддържа много езици и диалекти, и е приложим в сценарии като текстово творчество, визуално разпознаване и гласови асистенти."
|
||||
},
|
||||
"qwen3-vl-235b-a22b-instruct": {
|
||||
"description": "Qwen3 VL 235B A22B Instruct е мултимодален модел, разработен от Tongyi Qianwen, който поддържа визуално разбиране и извеждане на заключения."
|
||||
"description": "Qwen3 VL 235B A22B в non-thinking режим (Instruct), подходящ за инструкции без необходимост от дълбоко разсъждение, като същевременно запазва силни визуални разбирания."
|
||||
},
|
||||
"qwen3-vl-235b-a22b-thinking": {
|
||||
"description": "Qwen3 VL 235B A22B Thinking е мултимодален модел за извеждане на заключения, разработен от Tongyi Qianwen, с поддръжка на визуално разбиране и логическо мислене."
|
||||
"description": "Qwen3 VL 235B A22B в мисловен режим (отворен код), предназначен за сложни задачи с интензивно разсъждение и разбиране на дълги видеа, предоставяйки водещи способности за визуално и текстово разсъждение."
|
||||
},
|
||||
"qwen3-vl-30b-a3b-instruct": {
|
||||
"description": "Qwen3 VL 30B в non-thinking режим (Instruct), насочен към обичайни сценарии за следване на инструкции, като същевременно поддържа високо ниво на мултимодално разбиране и генериране."
|
||||
},
|
||||
"qwen3-vl-30b-a3b-thinking": {
|
||||
"description": "Qwen-VL (отворен код) предлага способности за визуално разбиране и генериране на текст, поддържа взаимодействие с интелигентни агенти, визуално кодиране, пространствено възприятие, разбиране на дълги видеа и дълбоко мислене, с подобрено разпознаване на текст и многоезична поддръжка в сложни сценарии."
|
||||
},
|
||||
"qwen3-vl-8b-instruct": {
|
||||
"description": "Qwen3 VL 8B в non-thinking режим (Instruct), подходящ за стандартни задачи по мултимодално генериране и разпознаване."
|
||||
},
|
||||
"qwen3-vl-8b-thinking": {
|
||||
"description": "Qwen3 VL 8B в мисловен режим, предназначен за леки мултимодални задачи по разсъждение и взаимодействие, като същевременно запазва способността за разбиране на дълъг контекст."
|
||||
},
|
||||
"qwen3-vl-flash": {
|
||||
"description": "Qwen3 VL Flash: олекотена версия за високоскоростно разсъждение, подходяща за сценарии, чувствителни към закъснение или с голям обем заявки."
|
||||
},
|
||||
"qwen3-vl-plus": {
|
||||
"description": "Tongyi Qianwen VL е текстов генеративен модел с визуални (изображения) разбирания, който не само може да извършва OCR (разпознаване на текст в изображения), но и да обобщава и прави изводи, например извличане на атрибути от снимки на продукти или решаване на задачи по математика от изображения."
|
||||
|
||||
@@ -461,7 +461,7 @@
|
||||
"tabs": {
|
||||
"installed": "Инсталирани",
|
||||
"mcp": "MCP плъгини",
|
||||
"old": "LobeChat плъгини"
|
||||
"old": "Разширения на LobeHub"
|
||||
},
|
||||
"title": "Магазин за плъгини"
|
||||
},
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
"description": "Bedrock е услуга, предоставяна от Amazon AWS, фокусирана върху предоставянето на напреднали AI езикови и визуални модели за предприятия. Семейството на моделите включва серията Claude на Anthropic, серията Llama 3.1 на Meta и други, обхващащи разнообразие от опции от леки до високо производителни, поддържащи текстово генериране, диалог, обработка на изображения и много други задачи, подходящи за различни мащаби и нужди на бизнес приложения."
|
||||
},
|
||||
"bfl": {
|
||||
"description": "Водеща изследователска лаборатория за авангарден изкуствен интелект, която изгражда визуалната инфраструктура на утрешния ден."
|
||||
"description": "Водеща лаборатория за авангардни изследвания в областта на изкуствения интелект, изграждаща визуалната инфраструктура на утрешния ден."
|
||||
},
|
||||
"cerebras": {
|
||||
"description": "Cerebras е AI платформа за извеждане, базирана на специализираната си система CS-3, създадена да предоставя най-бързите в света услуги за големи езикови модели (LLM) с незабавен отговор и висок капацитет на обработка. Тя е проектирана да елиминира закъсненията и да ускори сложни AI работни процеси, като генериране на код в реално време и изпълнение на агентски задачи."
|
||||
@@ -44,6 +44,9 @@
|
||||
"cometapi": {
|
||||
"description": "CometAPI е платформа за услуги, която предоставя множество интерфейси за водещи големи модели, поддържайки OpenAI, Anthropic, Google и други, подходяща за разнообразни нужди на разработка и приложение. Потребителите могат гъвкаво да избират най-добрия модел и цена според своите изисквания, подпомагайки подобряването на AI изживяването."
|
||||
},
|
||||
"comfyui": {
|
||||
"description": "Мощен open-source енджин за създаване на изображения, видео и аудио чрез работни потоци, поддържащ напреднали модели като SD FLUX, Qwen, Hunyuan, WAN и други, с възможности за редактиране на работни потоци чрез възли и за частно внедряване."
|
||||
},
|
||||
"deepseek": {
|
||||
"description": "DeepSeek е компания, специализирана в изследвания и приложения на технологии за изкуствен интелект, чийто най-нов модел DeepSeek-V2.5 комбинира способности за общи диалози и обработка на код, постигайки значителни подобрения в съответствието с човешките предпочитания, писателските задачи и следването на инструкции."
|
||||
},
|
||||
|
||||
@@ -35,9 +35,16 @@
|
||||
"title": "Нулиране на всички настройки"
|
||||
}
|
||||
},
|
||||
"groupTab": {
|
||||
"chat": "Чат",
|
||||
"members": "Членове",
|
||||
"meta": "Основна информация"
|
||||
},
|
||||
"header": {
|
||||
"desc": "Предпочитания и настройки на модела.",
|
||||
"global": "Глобални настройки",
|
||||
"group": "Настройки на екипа",
|
||||
"groupDesc": "Управление на екипа от агенти и предпочитания за чат",
|
||||
"session": "Настройки на сесията",
|
||||
"sessionDesc": "Задаване на роля и предпочитания за сесия.",
|
||||
"sessionWithName": "Настройки на сесията · {{name}}",
|
||||
@@ -139,6 +146,9 @@
|
||||
},
|
||||
"waitingForMore": "Още модели са <1>планирани да бъдат добавени</1>, очаквайте"
|
||||
},
|
||||
"message": {
|
||||
"success": "Актуализацията беше успешна"
|
||||
},
|
||||
"plugin": {
|
||||
"addMCPPlugin": "Добавяне на MCP плъгин",
|
||||
"addTooltip": "Персонализиран плъгин",
|
||||
@@ -294,6 +304,102 @@
|
||||
},
|
||||
"title": "Общи настройки"
|
||||
},
|
||||
"settingGroup": {
|
||||
"description": {
|
||||
"placeholder": "Моля, въведете описание на екипа",
|
||||
"title": "Описание на екипа"
|
||||
},
|
||||
"name": {
|
||||
"placeholder": "Моля, въведете име на екипа",
|
||||
"title": "Име на екипа"
|
||||
},
|
||||
"scene": {
|
||||
"desc": "Изберете сценарий за екипа",
|
||||
"options": {
|
||||
"casual": "Свободно",
|
||||
"productive": "Продуктивно"
|
||||
},
|
||||
"title": "Сценарий на екипа"
|
||||
},
|
||||
"submit": "Актуализирай екипа",
|
||||
"systemPrompt": {
|
||||
"placeholder": "Моля, въведете системно подсещане за водещия",
|
||||
"title": "Системно подсещане за водещия"
|
||||
},
|
||||
"title": "Информация за екипа от агенти"
|
||||
},
|
||||
"settingGroupChat": {
|
||||
"allowDM": {
|
||||
"desc": "След изключване все още можете да изпращате лични съобщения до асистента",
|
||||
"title": "Разреши лични съобщения от асистента"
|
||||
},
|
||||
"enableSupervisor": {
|
||||
"desc": "Активиране на функцията за модератор на екипа от агенти. Модераторът ще управлява хода на разговорите в екипа.",
|
||||
"title": "Активирай модератор"
|
||||
},
|
||||
"maxResponseInRow": {
|
||||
"desc": "Изберете колко поредни съобщения може да отговори един член. Задайте 0 за деактивиране на ограничението.",
|
||||
"title": "Брой поредни отговори"
|
||||
},
|
||||
"model": {
|
||||
"desc": "Изказванията на членовете на групата няма да бъдат засегнати. Някои модели не могат да се използват като модераторски модели.",
|
||||
"title": "Модел на водещия"
|
||||
},
|
||||
"orchestratorTitle": "Настройки на водещия",
|
||||
"responseOrder": {
|
||||
"desc": "Агентите ще отговарят в реда, зададен в чата",
|
||||
"options": {
|
||||
"natural": "Естествен",
|
||||
"sequential": "Последователен"
|
||||
},
|
||||
"placeholder": "Изберете ред на отговор",
|
||||
"title": "Ред на отговор"
|
||||
},
|
||||
"responseSpeed": {
|
||||
"desc": "Контролиране на общата скорост на провеждане на чата",
|
||||
"options": {
|
||||
"fast": "Бързо",
|
||||
"medium": "Средно",
|
||||
"slow": "Бавно"
|
||||
},
|
||||
"placeholder": "Изберете скорост на отговор",
|
||||
"title": "Скорост на отговор"
|
||||
},
|
||||
"revealDM": {
|
||||
"desc": "Позволява ви да виждате личните съобщения, изпратени до други членове.",
|
||||
"title": "Показване на лични съобщения"
|
||||
},
|
||||
"submit": "Актуализиране на настройките",
|
||||
"systemPrompt": {
|
||||
"desc": "Персонализирано системно подсещане за водещия на груповия чат. Това може да повлияе на поведението на водещия по подразбиране.",
|
||||
"placeholder": "Моля, въведете персонализирано системно подсещане за водещия...",
|
||||
"title": "Системно подсещане за водещия"
|
||||
},
|
||||
"title": "Настройки на чата"
|
||||
},
|
||||
"settingGroupMembers": {
|
||||
"addToGroup": "Добавяне към групата",
|
||||
"availableAgents": "Налични асистенти",
|
||||
"createMember": "Създаване на член",
|
||||
"defaultAgent": "Персонализиран асистент",
|
||||
"disableHost": "Изключване на асистента на водещия",
|
||||
"edit": "Редактиране на членове",
|
||||
"empty": "Няма членове в този екип. Натиснете бутона +, за да добавите членове.",
|
||||
"enableHost": "Включване на асистента на водещия",
|
||||
"groupHost": "Водещ на групата",
|
||||
"groupMembers": "Членове на групата",
|
||||
"host": {
|
||||
"description": "Когато водещият е в групата, груповият чат се управлява автоматично, подходящ за творчески задачи.",
|
||||
"title": "Водещ"
|
||||
},
|
||||
"noAvailableAgents": "Няма налични асистенти",
|
||||
"noDescription": "Няма описание",
|
||||
"noMembersInGroup": "Групата няма членове",
|
||||
"owner": "Вие (собственик)",
|
||||
"remove": "Премахване на член",
|
||||
"removeFromGroup": "Премахване от групата",
|
||||
"you": "Вие"
|
||||
},
|
||||
"settingImage": {
|
||||
"defaultCount": {
|
||||
"desc": "Задайте броя на изображенията по подразбиране, които да се генерират при създаване на нова задача в панела за генериране на изображения.",
|
||||
|
||||
+334
-17
@@ -6,26 +6,343 @@
|
||||
},
|
||||
"defaultMessage": "Аз съм вашият личен интелигентен асистент {{appName}}. Как мога да ви помогна сега?<br />Ако имате нужда от по-професионален или персонализиран асистент, можете да кликнете на <plus />, за да създадете персонализиран асистент.",
|
||||
"defaultMessageWithoutCreate": "Аз съм вашият личен интелигентен асистент {{appName}}. Как мога да ви помогна сега?",
|
||||
"qa": {
|
||||
"q01": "Какво е LobeHub?",
|
||||
"q02": "Какво е {{appName}}?",
|
||||
"q03": "Има ли общностна поддръжка за {{appName}}?",
|
||||
"q04": "Какви функции поддържа {{appName}}?",
|
||||
"q05": "Как да инсталирам и използвам {{appName}}?",
|
||||
"q06": "Каква е ценовата политика на {{appName}}?",
|
||||
"q07": "Дали {{appName}} е безплатен?",
|
||||
"q08": "Има ли облачна версия на услугата?",
|
||||
"q09": "Поддържа ли локални езикови модели?",
|
||||
"q10": "Поддържа ли разпознаване и генериране на изображения?",
|
||||
"q11": "Поддържа ли синтез на реч и разпознаване на реч?",
|
||||
"q12": "Поддържа ли система за плъгини?",
|
||||
"q13": "Има ли собствен пазар за получаване на GPTs?",
|
||||
"q14": "Поддържа ли различни доставчици на AI услуги?",
|
||||
"q15": "Какво да направя, ако срещна проблеми при използването?"
|
||||
"groupActivities": {
|
||||
"analysis": {
|
||||
"codeReview": {
|
||||
"description": "Техническо обсъждане и преглед на промените в кода и реализацията от колеги",
|
||||
"emoji": "💻",
|
||||
"prompt": "Нека прегледаме някакъв код заедно. Можеш ли да ни помогнеш да анализираме този код и да идентифицираме възможности за подобрение?",
|
||||
"title": "Преглед на код"
|
||||
},
|
||||
"investment": {
|
||||
"description": "Анализ на пазара, обсъждане на инвестиционни стратегии и споделяне на финансови прозрения",
|
||||
"emoji": "📈",
|
||||
"prompt": "Нека анализираме пазара заедно. Можеш ли да ни помогнеш да обсъдим инвестиционни стратегии и да споделим финансови прозрения?",
|
||||
"title": "Инвестиционен клуб"
|
||||
},
|
||||
"research": {
|
||||
"description": "Изследване на научни концепции, провеждане на експерименти и споделяне на открития",
|
||||
"emoji": "🔬",
|
||||
"prompt": "Нека изследваме науката заедно! Можеш ли да ни помогнеш да проведем експерименти и да споделим нашите открития?",
|
||||
"title": "Научна изложба"
|
||||
},
|
||||
"study": {
|
||||
"description": "Съвместни учебни сесии, обсъждане на концепции и решаване на проблеми заедно",
|
||||
"emoji": "📚",
|
||||
"prompt": "Нека сформираме учебна група. Можеш ли да ни помогнеш да разберем тези концепции и да решим проблемите заедно?",
|
||||
"title": "Учебна група"
|
||||
}
|
||||
},
|
||||
"brainstorm": {
|
||||
"artWorkshop": {
|
||||
"description": "Създаване, коментиране и оценяване на различни форми на визуално и дигитално изкуство",
|
||||
"emoji": "🖼️",
|
||||
"prompt": "Нека организираме арт работилница! Можеш ли да ни помогнеш да създаваме, коментираме и оценяваме различни форми на изкуство?",
|
||||
"title": "Арт работилница"
|
||||
},
|
||||
"debate": {
|
||||
"description": "Структурирани дискусии и дебати по различни теми и актуални въпроси",
|
||||
"emoji": "⚖️",
|
||||
"prompt": "Нека проведем структурирана дискусия. Можеш ли да ни помогнеш да организираме аргументиран дебат по тази тема?",
|
||||
"title": "Дебатен клуб"
|
||||
},
|
||||
"designReview": {
|
||||
"description": "Съвместни сесии за обратна връзка относно дизайнерски концепции, прототипи или творчески проекти",
|
||||
"emoji": "🎨",
|
||||
"prompt": "Трябва да прегледаме някои дизайнерски проекти. Можеш ли да ни помогнеш да дадем конструктивна обратна връзка за концепциите и прототипите?",
|
||||
"title": "Преглед на дизайн"
|
||||
},
|
||||
"ideation": {
|
||||
"description": "Многоаспектно сътрудничество за генериране на идеи и креативно решаване на проблеми",
|
||||
"emoji": "🧠",
|
||||
"prompt": "Нека започнем мозъчна атака за проекта. Можеш ли да ни помогнеш да генерираме идеи и решения?",
|
||||
"title": "Мозъчна атака"
|
||||
}
|
||||
},
|
||||
"game": {
|
||||
"debateClub": {
|
||||
"description": "Структурирани дискусии и дебати по различни теми и актуални въпроси",
|
||||
"emoji": "⚖️",
|
||||
"prompt": "Нека проведем структурирана дискусия. Можеш ли да ни помогнеш да организираме аргументиран дебат по тази тема?",
|
||||
"title": "Дебатен клуб"
|
||||
},
|
||||
"gameNight": {
|
||||
"description": "Забавни интерактивни игри и дейности за изграждане на екипен дух и забавление",
|
||||
"emoji": "🎲",
|
||||
"prompt": "Време е за игрова вечер! Можеш ли да ни помогнеш да организираме забавни интерактивни игри за изграждане на екипен дух?",
|
||||
"title": "Игрова вечер"
|
||||
},
|
||||
"modelUN": {
|
||||
"description": "Симулация на ООН с дебати и дипломатически преговори по глобални въпроси",
|
||||
"emoji": "🌍",
|
||||
"prompt": "Нека симулираме дебат в ООН. Можеш ли да ни помогнеш да организираме дипломатически преговори по глобални въпроси?",
|
||||
"title": "Симулация на ООН"
|
||||
},
|
||||
"werewolf": {
|
||||
"description": "Социална игра за разгадаване на вълци чрез стратегия и дискусии",
|
||||
"emoji": "🐺",
|
||||
"prompt": "Нека играем Вълк! Можеш ли да ни помогнеш да установим правилата и да водиш тази социална игра за разгадаване?",
|
||||
"title": "Игра Вълк"
|
||||
}
|
||||
},
|
||||
"general": {
|
||||
"brainstorm": {
|
||||
"description": "Многоаспектно сътрудничество за генериране на идеи и креативно решаване на проблеми",
|
||||
"emoji": "🧠",
|
||||
"prompt": "Нека започнем мозъчна атака за проекта. Можеш ли да ни помогнеш да генерираме идеи и решения?",
|
||||
"title": "Мозъчна атака"
|
||||
},
|
||||
"debate": {
|
||||
"description": "Структурирани дискусии и дебати по различни теми и актуални въпроси",
|
||||
"emoji": "⚖️",
|
||||
"prompt": "Нека проведем структурирана дискусия. Можеш ли да ни помогнеш да организираме аргументиран дебат по тази тема?",
|
||||
"title": "Дебатен клуб"
|
||||
},
|
||||
"languagePractice": {
|
||||
"description": "Практика на говорене и учене на нов език с носители на езика",
|
||||
"emoji": "🗣️",
|
||||
"prompt": "Нека практикуваме нов език заедно. Можеш ли да ни помогнеш да учим и практикуваме говорене на този език?",
|
||||
"title": "Езикова практика"
|
||||
},
|
||||
"studyGroup": {
|
||||
"description": "Съвместни учебни сесии, обсъждане на концепции и решаване на проблеми заедно",
|
||||
"emoji": "📚",
|
||||
"prompt": "Нека сформираме учебна група. Можеш ли да ни помогнеш да разберем тези концепции и да решим проблемите заедно?",
|
||||
"title": "Учебна група"
|
||||
}
|
||||
},
|
||||
"planning": {
|
||||
"cookingClass": {
|
||||
"description": "Учене и споделяне на кулинарни умения, рецепти и традиции",
|
||||
"emoji": "👨🍳",
|
||||
"prompt": "Нека посетим кулинарен клас! Можеш ли да ни помогнеш да научим нови рецепти и кулинарни техники?",
|
||||
"title": "Кулинарен клас"
|
||||
},
|
||||
"fitnessChallenge": {
|
||||
"description": "Поставяне на групови фитнес цели, споделяне на упражнения и взаимна мотивация",
|
||||
"emoji": "💪",
|
||||
"prompt": "Нека започнем фитнес предизвикателство! Можеш ли да ни помогнеш да поставим цели и да се мотивираме взаимно да останем здрави?",
|
||||
"title": "Фитнес предизвикателство"
|
||||
},
|
||||
"planningPoker": {
|
||||
"description": "Аджайл техника за оценка на задачи и обем на работа чрез карти",
|
||||
"emoji": "🃏",
|
||||
"prompt": "Провеждаме планиращ покер за проекта. Можеш ли да ни помогнеш да използваме аджайл техники за оценка на обема на задачите?",
|
||||
"title": "Планиращ покер"
|
||||
},
|
||||
"travelPlanning": {
|
||||
"description": "Планиране на пътувания, споделяне на преживявания и откриване на нови дестинации",
|
||||
"emoji": "✈️",
|
||||
"prompt": "Нека планираме пътуване заедно! Можеш ли да ни помогнеш да проучим дестинации и да организираме маршрута?",
|
||||
"title": "Планиране на пътуване"
|
||||
}
|
||||
},
|
||||
"product": {
|
||||
"codeReview": {
|
||||
"description": "Техническо обсъждане и преглед на промените в кода и реализацията от колеги",
|
||||
"emoji": "💻",
|
||||
"prompt": "Нека прегледаме някакъв код заедно. Можеш ли да ни помогнеш да анализираме този код и да идентифицираме възможности за подобрение?",
|
||||
"title": "Преглед на код"
|
||||
},
|
||||
"designReview": {
|
||||
"description": "Съвместни сесии за обратна връзка относно дизайнерски концепции, прототипи или творчески проекти",
|
||||
"emoji": "🎨",
|
||||
"prompt": "Трябва да прегледаме някои дизайнерски проекти. Можеш ли да ни помогнеш да дадем конструктивна обратна връзка за концепциите и прототипите?",
|
||||
"title": "Преглед на дизайн"
|
||||
},
|
||||
"sprintPlanning": {
|
||||
"description": "Аджайл техника за оценка на задачи и обем на работа чрез карти",
|
||||
"emoji": "🃏",
|
||||
"prompt": "Провеждаме планиращ покер за проекта. Можеш ли да ни помогнеш да използваме аджайл техники за оценка на обема на задачите?",
|
||||
"title": "Планиращ покер"
|
||||
},
|
||||
"techExchange": {
|
||||
"description": "Обсъждане на нови технологии, иновации и тенденции в индустрията",
|
||||
"emoji": "🚀",
|
||||
"prompt": "Нека проведем технически обмен! Можеш ли да ни помогнеш да обсъдим нови технологии и тенденции в индустрията?",
|
||||
"title": "Технически обмен"
|
||||
}
|
||||
},
|
||||
"title": "Препоръки за използване на групов чат",
|
||||
"writing": {
|
||||
"bookClub": {
|
||||
"description": "Литературни дискусии и анализи на книги, истории и литературни произведения",
|
||||
"emoji": "📖",
|
||||
"prompt": "Нека започнем дискусия в книжен клуб. Можеш ли да ни помогнеш да анализираме тази книга и да обсъдим темите ѝ заедно?",
|
||||
"title": "Книжен клуб"
|
||||
},
|
||||
"movieClub": {
|
||||
"description": "Гледане и обсъждане на филми, документални и визуални медии заедно",
|
||||
"emoji": "🎬",
|
||||
"prompt": "Нека започнем дискусия в кино клуб. Можеш ли да ни помогнеш да анализираме този филм и да обсъдим темите му заедно?",
|
||||
"title": "Кино клуб"
|
||||
},
|
||||
"musicSession": {
|
||||
"description": "Съвместно създаване, споделяне и оценяване на музика",
|
||||
"emoji": "🎵",
|
||||
"prompt": "Нека направим музикална импровизация! Можеш ли да ни помогнеш да създаваме и оценяваме музика заедно?",
|
||||
"title": "Музикална импровизация"
|
||||
},
|
||||
"studyGroup": {
|
||||
"description": "Съвместни учебни сесии, обсъждане на концепции и решаване на проблеми заедно",
|
||||
"emoji": "📚",
|
||||
"prompt": "Нека сформираме учебна група. Можеш ли да ни помогнеш да разберем тези концепции и да решим проблемите заедно?",
|
||||
"title": "Учебна група"
|
||||
}
|
||||
}
|
||||
},
|
||||
"groupMessage": "Добре дошли в груповия чат! Сътрудничете с няколко AI помощника в споделено разговорно пространство.",
|
||||
"groupTemplates": {
|
||||
"analysis": {
|
||||
"description": "Данни, водещи до прозрения, задълбочен анализ и изследване",
|
||||
"members": [
|
||||
{
|
||||
"avatar": "📊",
|
||||
"backgroundColor": "#E8F8F5",
|
||||
"plugins": ["steam"],
|
||||
"systemRole": "Вие сте експерт в обработката и тълкуването на данни, разкривайки закономерности и тенденции чрез диаграми и статистически анализи.",
|
||||
"title": "Анализатор на данни"
|
||||
},
|
||||
{
|
||||
"avatar": "🧑🔬",
|
||||
"backgroundColor": "#E8F5FF",
|
||||
"systemRole": "Ти си изследовател, специализиран в събирането на информация и задълбочени проучвания, способен да анализира проблемите от множество гледни точки.",
|
||||
"title": "Изследовател"
|
||||
},
|
||||
{
|
||||
"avatar": "📈",
|
||||
"backgroundColor": "#FFF7E8",
|
||||
"systemRole": "Ти си статистик, експерт в различни статистически методи и модели, който извлича ценни бизнес прозрения от данните.",
|
||||
"title": "Статистик"
|
||||
},
|
||||
{
|
||||
"avatar": "🧮",
|
||||
"backgroundColor": "#F0F8FF",
|
||||
"systemRole": "Ти си количествен анализатор, специализиран в количествено моделиране и оценка на риска, използващ математически методи за решаване на сложни проблеми.",
|
||||
"title": "Количествен анализатор"
|
||||
}
|
||||
],
|
||||
"title": "Екип за анализ"
|
||||
},
|
||||
"brainstorm": {
|
||||
"description": "Многостранно креативно мислене, стимулиране на безкрайни възможности",
|
||||
"members": [
|
||||
{
|
||||
"avatar": "🧠",
|
||||
"backgroundColor": "#E8F5FF",
|
||||
"systemRole": "Ти си креативен директор, умел в управлението на творческата посока от макро ниво, способен да превръща абстрактни концепции в конкретни изпълними творчески решения.",
|
||||
"title": "Креативен директор"
|
||||
},
|
||||
{
|
||||
"avatar": "🧑🔬",
|
||||
"backgroundColor": "#FFF7E8",
|
||||
"systemRole": "Ти си експерт по иновации, специализиран в откриването на новаторски решения и пробивни идеи, умеещ да мисли извън установените рамки.",
|
||||
"title": "Експерт по иновации"
|
||||
},
|
||||
{
|
||||
"avatar": "🎨",
|
||||
"backgroundColor": "#F6E8FF",
|
||||
"systemRole": "Ти си специалист по дизайн мислене, който разглежда проблемите от гледна точка на потребителското изживяване и визуалната презентация, с акцент върху визуалното изразяване на креативността.",
|
||||
"title": "Дизайнер на мислене"
|
||||
}
|
||||
],
|
||||
"title": "Мозъчна атака група"
|
||||
},
|
||||
"game": {
|
||||
"description": "Забавлявай се с различни многопотребителски текстови игри, като Мафия и Кой е предателят",
|
||||
"members": [
|
||||
null,
|
||||
{
|
||||
"avatar": "🧑🔬",
|
||||
"backgroundColor": "#FFF7E8",
|
||||
"systemRole": "Ти си експерт в различни многопотребителски текстови игри и можеш да играеш според правилата на играта.",
|
||||
"title": "Играч"
|
||||
},
|
||||
{
|
||||
"avatar": "🎨",
|
||||
"backgroundColor": "#F6E8FF",
|
||||
"systemRole": "Ти си експерт в различни многопотребителски текстови игри и можеш да играеш според правилата на играта.",
|
||||
"title": "Играч"
|
||||
},
|
||||
{
|
||||
"avatar": "🧑🎨",
|
||||
"backgroundColor": "#F6E8FF",
|
||||
"systemRole": "Ти си експерт в различни многопотребителски текстови игри и можеш да играеш според правилата на играта.",
|
||||
"title": "Играч"
|
||||
}
|
||||
],
|
||||
"title": "Игрална зала"
|
||||
},
|
||||
"planning": {
|
||||
"description": "Стратегическо планиране и управление на проекти, координиране на цялостната картина",
|
||||
"members": [
|
||||
{
|
||||
"avatar": "📋",
|
||||
"backgroundColor": "#E8F5FF",
|
||||
"systemRole": "Отговаряш за цялостното планиране на проекта, контрол на напредъка и координация на ресурсите, за да осигуриш навременно и качествено изпълнение.",
|
||||
"title": "Главен готвач"
|
||||
},
|
||||
{
|
||||
"avatar": "🎯",
|
||||
"backgroundColor": "#FFF7E8",
|
||||
"systemRole": "Отговаряш за разработване на дългосрочни стратегически планове, анализ на пазарните възможности, поставяне на цели и определяне на пътища за постигането им.",
|
||||
"title": "Експерт по снабдяване с продукти"
|
||||
},
|
||||
{
|
||||
"avatar": "🧑🎨",
|
||||
"backgroundColor": "#F0F8FF",
|
||||
"systemRole": "Отговаряш за изготвяне на детайлни оперативни планове, координация на ресурсите между отделите и осигуряване на изпълнимостта на плана.",
|
||||
"title": "Експерт по кулинарни разработки"
|
||||
}
|
||||
],
|
||||
"title": "Екип за кулинарни разработки"
|
||||
},
|
||||
"product": {
|
||||
"description": "Проектиране и разработка на продукти, създаване на качествени продукти",
|
||||
"members": [
|
||||
{
|
||||
"avatar": "🎨",
|
||||
"backgroundColor": "#F6E8FF",
|
||||
"systemRole": "Ти си дизайнер, умел в проектирането на различни видове продукти, способен да проектира според изискванията на продукта.",
|
||||
"title": "Дизайнер"
|
||||
},
|
||||
{
|
||||
"avatar": "🧑",
|
||||
"backgroundColor": "#E8F5FF",
|
||||
"systemRole": "Ти си продуктов мениджър, отговорен за планирането, проектирането, разработката и поддръжката на продукта, осигурявайки качеството и потребителското изживяване.",
|
||||
"title": "Продуктов мениджър"
|
||||
},
|
||||
{
|
||||
"avatar": "🧑💻",
|
||||
"backgroundColor": "#E8F8F5",
|
||||
"systemRole": "Ти си опитен full-stack инженер, умел в разработката на различни видове продукти, способен да разработва според изискванията на продукта.",
|
||||
"title": "Full-stack инженер"
|
||||
}
|
||||
],
|
||||
"title": "Екип за разработка на продукти"
|
||||
},
|
||||
"writing": {
|
||||
"description": "Създаване и редактиране на съдържание, създаване на качествени текстове",
|
||||
"members": [
|
||||
{
|
||||
"avatar": "✍️",
|
||||
"backgroundColor": "#F6E8FF",
|
||||
"systemRole": "Експерт си в създаването на съдържание в различни жанрове и можеш да адаптираш стила на писане според различни ситуации и аудитории.",
|
||||
"title": "Писател на съдържание"
|
||||
},
|
||||
{
|
||||
"avatar": "🧑🎨",
|
||||
"backgroundColor": "#E8F8F5",
|
||||
"systemRole": "Ти си редактор, отговорен за корекция, полиране и оптимизиране на текстове, осигурявайки точност, плавност и професионализъм на съдържанието.",
|
||||
"title": "Редактор"
|
||||
}
|
||||
],
|
||||
"title": "Кръг на писателите"
|
||||
}
|
||||
},
|
||||
"questions": {
|
||||
"moreBtn": "Научи повече",
|
||||
"title": "Често задавани въпроси:"
|
||||
"title": "Опитайте да попитате:"
|
||||
},
|
||||
"welcome": {
|
||||
"afternoon": "Добър ден",
|
||||
|
||||
+111
-1
@@ -2,6 +2,7 @@
|
||||
"ModelSwitch": {
|
||||
"title": "Modell"
|
||||
},
|
||||
"active": "Aktiv",
|
||||
"agentDefaultMessage": "Hallo, ich bin **{{name}}**. Du kannst sofort mit mir sprechen oder zu den [Assistenteneinstellungen]({{url}}) gehen, um meine Informationen zu vervollständigen.",
|
||||
"agentDefaultMessageWithSystemRole": "Hallo, ich bin **{{name}}**. Wie kann ich Ihnen behilflich sein?",
|
||||
"agentDefaultMessageWithoutEdit": "Hallo, ich bin **{{name}}**. Wie kann ich Ihnen behilflich sein?",
|
||||
@@ -13,17 +14,28 @@
|
||||
"thought": "Denkenprozess",
|
||||
"unknownTitle": "Unbenanntes Werk"
|
||||
},
|
||||
"availableAgents": "Verfügbare Assistenten",
|
||||
"backToBottom": "Zurück zum Ende",
|
||||
"chatList": {
|
||||
"longMessageDetail": "Details anzeigen"
|
||||
},
|
||||
"clearCurrentMessages": "Aktuelle Nachrichten löschen",
|
||||
"confirmClearCurrentMessages": "Möchtest du wirklich die aktuellen Nachrichten löschen? Diese Aktion kann nicht rückgängig gemacht werden.",
|
||||
"confirmRemoveChatGroupItemAlert": "Dieses Agenten-Team wird gelöscht. Die Teammitglieder bleiben davon unberührt. Bitte bestätigen Sie Ihre Aktion.",
|
||||
"confirmRemoveGroupItemAlert": "Sie sind dabei, diese Gruppe zu löschen. Nach der Löschung werden die Assistenten dieser Gruppe in die Standardliste verschoben. Bitte bestätigen Sie Ihre Aktion.",
|
||||
"confirmRemoveGroupSuccess": "Agent-Team erfolgreich gelöscht",
|
||||
"confirmRemoveSessionItemAlert": "Möchtest du diesen Assistenten wirklich löschen? Diese Aktion kann nicht rückgängig gemacht werden.",
|
||||
"confirmRemoveSessionSuccess": "Hilfe wurde erfolgreich entfernt",
|
||||
"defaultAgent": "Standardassistent",
|
||||
"defaultGroupChat": "Agent-Team",
|
||||
"defaultList": "Standardliste",
|
||||
"defaultSession": "Standardassistent",
|
||||
"dm": {
|
||||
"placeholder": "Ihre Direktnachrichten mit {{agentTitle}} werden hier angezeigt.",
|
||||
"tooltip": "Direktnachricht senden",
|
||||
"visibleTo": "Nur für {{target}} sichtbar",
|
||||
"you": "Du"
|
||||
},
|
||||
"duplicateSession": {
|
||||
"loading": "Kopieren läuft...",
|
||||
"success": "Kopieren erfolgreich",
|
||||
@@ -58,11 +70,56 @@
|
||||
"title": "Webseiten-Link-Inhalt extrahieren"
|
||||
}
|
||||
},
|
||||
"group": {
|
||||
"desc": "Mit mehreren KI‑Assistenten in einem gemeinsamen Gesprächsraum zusammenarbeiten.",
|
||||
"memberTooltip": "In der Gruppe sind {{count}} Mitglieder",
|
||||
"orchestratorThinking": "Der Moderator denkt nach...",
|
||||
"removeMember": "Mitglied entfernen",
|
||||
"title": "Gruppe"
|
||||
},
|
||||
"groupDescription": "Team-Beschreibung",
|
||||
"groupSidebar": {
|
||||
"members": {
|
||||
"addMember": "Mitglied hinzufügen",
|
||||
"memberSettings": "Mitgliedereinstellungen",
|
||||
"orchestrator": "Moderator",
|
||||
"orchestratorThinking": "Der Moderator denkt nach...",
|
||||
"removeMember": "Mitglied entfernen",
|
||||
"stopOrchestrator": "Nachdenken beenden",
|
||||
"triggerOrchestrator": "Gruppenchat starten"
|
||||
},
|
||||
"tabs": {
|
||||
"host": "Moderator",
|
||||
"members": "Mitglieder",
|
||||
"role": "Einstellungen"
|
||||
}
|
||||
},
|
||||
"groupWizard": {
|
||||
"chooseMembers": "Bestehende Assistenten auswählen...",
|
||||
"createGroup": "Team erstellen",
|
||||
"existingMembers": "Vorhandene Agenten",
|
||||
"groupMembers": "Diese Assistenten werden ebenfalls zu Ihrer Liste hinzugefügt",
|
||||
"host": {
|
||||
"description": "Ermöglicht dem Team, eigenständig zu arbeiten",
|
||||
"title": "Moderator aktivieren",
|
||||
"tooltip": "Wenn der Team-Moderator deaktiviert ist, müssen Sie Mitglieder manuell mit @ erwähnen, damit sie antworten können"
|
||||
},
|
||||
"memberCount": "{{count}} Mitglieder",
|
||||
"noMatchingTemplates": "Keine passenden Vorlagen",
|
||||
"noSelectedTemplates": "Keine Vorlagen ausgewählt",
|
||||
"noTemplateMembers": "Keine Mitglieder in der Vorlage",
|
||||
"noTemplates": "Keine Vorlagen verfügbar",
|
||||
"searchTemplates": "Vorlagen durchsuchen...",
|
||||
"title": "Agent-Team erstellen",
|
||||
"useTemplate": "Vorlage verwenden"
|
||||
},
|
||||
"hideForYou": "Private Nachrichten sind ausgeblendet. Bitte aktivieren Sie in den Einstellungen „Private Nachrichten anzeigen“, um sie zu sehen.",
|
||||
"history": {
|
||||
"title": "Der Assistent wird nur die letzten {{count}} Nachrichten speichern"
|
||||
},
|
||||
"historyRange": "Verlaufsbereich",
|
||||
"historySummary": "Zusammenfassung historischer Nachrichten",
|
||||
"inactive": "Inaktiv",
|
||||
"inbox": {
|
||||
"desc": "Aktiviere das Gehirncluster und entfache den Funken des Denkens. Dein intelligenter Assistent, der mit dir über alles kommuniziert.",
|
||||
"title": "Lass uns plaudern"
|
||||
@@ -83,6 +140,7 @@
|
||||
"intentUnderstanding": {
|
||||
"title": "Verstehe und analysiere gerade Ihre Absicht..."
|
||||
},
|
||||
"inviteMembers": "Mitglieder einladen",
|
||||
"knowledgeBase": {
|
||||
"all": "Alle Inhalte",
|
||||
"allFiles": "Alle Dateien",
|
||||
@@ -101,12 +159,29 @@
|
||||
"uploadGuide": "Hochgeladene Dateien können in der „Wissensdatenbank“ eingesehen werden.",
|
||||
"viewMore": "Mehr anzeigen"
|
||||
},
|
||||
"memberSelection": {
|
||||
"addMember": "Mitglied hinzufügen",
|
||||
"allMembers": "Alle Mitglieder",
|
||||
"createGroup": "Agenten-Team erstellen",
|
||||
"noAvailableAgents": "Keine verfügbaren Assistenten zum Einladen",
|
||||
"noSelectedAgents": "Noch keine Assistenten ausgewählt",
|
||||
"searchAgents": "Assistenten suchen...",
|
||||
"setInitialMembers": "Teammitglieder auswählen"
|
||||
},
|
||||
"members": "Mitglieder",
|
||||
"mention": {
|
||||
"title": "Mitglieder erwähnen"
|
||||
},
|
||||
"messageAction": {
|
||||
"delAndRegenerate": "Löschen und neu generieren",
|
||||
"deleteDisabledByThreads": "Es gibt Unterthemen, die Löschung ist nicht möglich.",
|
||||
"regenerate": "Neu generieren"
|
||||
},
|
||||
"messages": {
|
||||
"dm": {
|
||||
"sentTo": "Nur für {{name}} sichtbar",
|
||||
"title": "Direktnachricht"
|
||||
},
|
||||
"modelCard": {
|
||||
"credit": "Punkte",
|
||||
"creditPricing": "Preisgestaltung",
|
||||
@@ -153,9 +228,18 @@
|
||||
"minimap": {
|
||||
"jumpToMessage": "Zur Nachricht Nr. {{index}} springen",
|
||||
"nextMessage": "Nächste Nachricht",
|
||||
"previousMessage": "Vorherige Nachricht"
|
||||
"previousMessage": "Vorherige Nachricht",
|
||||
"senderAssistant": "Assistent",
|
||||
"senderUser": "Du"
|
||||
},
|
||||
"newAgent": "Neuer Assistent",
|
||||
"newGroupChat": "Neues Agent-Team",
|
||||
"noAgentsYet": "Dieses Agent-Team hat noch keine Mitglieder. Klicken Sie auf die + Schaltfläche, um Assistenten einzuladen.",
|
||||
"noAvailableAgents": "Keine Mitglieder verfügbar zum Einladen",
|
||||
"noMatchingAgents": "Keine passenden Mitglieder gefunden",
|
||||
"noMembersYet": "Diese Gruppe hat noch keine Mitglieder. Klicken Sie auf die +-Schaltfläche, um Assistenten einzuladen.",
|
||||
"noSelectedAgents": "Noch keine Mitglieder ausgewählt",
|
||||
"owner": "Gruppeninhaber",
|
||||
"pin": "Anheften",
|
||||
"pinOff": "Anheften aufheben",
|
||||
"rag": {
|
||||
@@ -196,12 +280,16 @@
|
||||
"title": "Netzwerksuche"
|
||||
},
|
||||
"searchAgentPlaceholder": "Suchassistent...",
|
||||
"searchAgents": "Suchassistent...",
|
||||
"selectedAgents": "Ausgewählte Assistenten",
|
||||
"sendPlaceholder": "Chat-Nachricht eingeben...",
|
||||
"sessionGroup": {
|
||||
"config": "Gruppenkonfiguration",
|
||||
"confirmRemoveGroupAlert": "Die Gruppe wird bald gelöscht. Nach dem Löschen werden die Assistenten in die Standardliste verschoben. Bitte bestätigen Sie Ihre Aktion.",
|
||||
"createAgentSuccess": "Assistent erfolgreich erstellt",
|
||||
"createGroup": "Neue Gruppe erstellen",
|
||||
"createGroupFailed": "Gruppenerstellung fehlgeschlagen",
|
||||
"createGroupSuccess": "Gruppe erfolgreich erstellt",
|
||||
"createSuccess": "Erstellung erfolgreich",
|
||||
"creatingAgent": "Assistent wird erstellt...",
|
||||
"inputPlaceholder": "Geben Sie den Gruppennamen ein...",
|
||||
@@ -216,11 +304,24 @@
|
||||
"shareModal": {
|
||||
"copy": "Kopieren",
|
||||
"download": "Screenshot herunterladen",
|
||||
"downloadError": "Download fehlgeschlagen",
|
||||
"downloadFile": "Datei herunterladen",
|
||||
"downloadPdf": "PDF herunterladen",
|
||||
"downloadSuccess": "Download erfolgreich",
|
||||
"exportPdf": "Als PDF exportieren",
|
||||
"exportTitle": "Standardtitel",
|
||||
"generatePdf": "PDF erstellen",
|
||||
"generatingPdf": "PDF wird erstellt...",
|
||||
"imageType": "Bildformat",
|
||||
"includeTool": "Plugin-Nachricht einfügen",
|
||||
"includeUser": "Benutzernachricht einfügen",
|
||||
"loadingPdf": "PDF wird geladen...",
|
||||
"noPdfData": "Keine PDF-Daten vorhanden",
|
||||
"pdf": "PDF",
|
||||
"pdfErrorDescription": "Beim Erstellen des PDFs ist ein Fehler aufgetreten, bitte versuchen Sie es erneut",
|
||||
"pdfGenerationError": "PDF-Erstellung fehlgeschlagen",
|
||||
"pdfReady": "PDF ist bereit",
|
||||
"regeneratePdf": "PDF neu erstellen",
|
||||
"screenshot": "Screenshot",
|
||||
"settings": "Exporteinstellungen",
|
||||
"text": "Text",
|
||||
@@ -235,6 +336,12 @@
|
||||
"loading": "Erkenne...",
|
||||
"prettifying": "Verschönern..."
|
||||
},
|
||||
"supervisor": {
|
||||
"todoList": {
|
||||
"allComplete": "Alle Aufgaben erledigt",
|
||||
"title": "Aufgaben abgeschlossen"
|
||||
}
|
||||
},
|
||||
"thread": {
|
||||
"divider": "Unterthema",
|
||||
"threadMessageCount": "{{messageCount}} Nachrichten",
|
||||
@@ -248,6 +355,7 @@
|
||||
"chats": "Chats",
|
||||
"historySummary": "Historische Zusammenfassung",
|
||||
"rest": "Verbleibend",
|
||||
"supervisor": "Gruppenmoderator",
|
||||
"systemRole": "Systemrolle",
|
||||
"title": "Kontextdetails",
|
||||
"tools": "Werkzeuge",
|
||||
@@ -273,6 +381,7 @@
|
||||
"action": "Sprachausgabe",
|
||||
"clear": "Sprachausgabe löschen"
|
||||
},
|
||||
"untitledAgent": "Unbenannter Assistent",
|
||||
"updateAgent": "Assistenteninformationen aktualisieren",
|
||||
"upload": {
|
||||
"action": {
|
||||
@@ -300,5 +409,6 @@
|
||||
"videoSizeExceeded": "Die Videodatei darf nicht größer als 20 MB sein, die aktuelle Dateigröße beträgt {{actualSize}}"
|
||||
}
|
||||
},
|
||||
"you": "du",
|
||||
"zenMode": "Fokusmodus"
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
"batchDelete": "Massenlöschung",
|
||||
"blog": "Produkt-Blog",
|
||||
"branching": "Unterthema erstellen",
|
||||
"branchingDisable": "Die Funktion „Unterthema“ ist nur in der Serverversion verfügbar. Wenn Sie diese Funktion benötigen, wechseln Sie bitte in den Serverbereitstellungsmodus oder verwenden Sie LobeChat Cloud.",
|
||||
"branchingDisable": "Die Funktion „Unterthemen“ ist im aktuellen Modus nicht verfügbar. Bitte wechsle in den Postgres-/Pglite-DB-Modus oder nutze LobeHub Cloud, um diese Funktion zu verwenden.",
|
||||
"branchingRequiresSavedTopic": "Das aktuelle Thema wurde nicht gespeichert. Speichern Sie es, um die Unterthemenfunktion nutzen zu können.",
|
||||
"cancel": "Abbrechen",
|
||||
"changelog": "Änderungsprotokoll",
|
||||
@@ -338,6 +338,7 @@
|
||||
"chat": "Chat",
|
||||
"discover": "Entdecken",
|
||||
"files": "Dateien",
|
||||
"knowledgeBase": "Wissensdatenbank",
|
||||
"me": "Ich",
|
||||
"setting": "Einstellung"
|
||||
},
|
||||
|
||||
@@ -50,6 +50,10 @@
|
||||
"total": {
|
||||
"fileCount": "Insgesamt {{count}} Elemente",
|
||||
"selectedCount": "Ausgewählt {{count}} Elemente"
|
||||
},
|
||||
"view": {
|
||||
"list": "Listenansicht",
|
||||
"masonry": "Kachelansicht"
|
||||
}
|
||||
},
|
||||
"FileParsingStatus": {
|
||||
|
||||
@@ -92,14 +92,15 @@
|
||||
"installLater": "Beim nächsten Start aktualisieren",
|
||||
"isLatestVersion": "Sie verwenden bereits die neueste Version",
|
||||
"isLatestVersionDesc": "Fantastisch, die verwendete Version {{version}} ist die aktuellste Version.",
|
||||
"later": "Später aktualisieren",
|
||||
"later": "Später",
|
||||
"newVersionAvailable": "Neue Version verfügbar",
|
||||
"newVersionAvailableDesc": "Eine neue Version {{version}} wurde gefunden, möchten Sie jetzt herunterladen?",
|
||||
"restartAndInstall": "Update installieren und neu starten",
|
||||
"updateError": "Update-Fehler",
|
||||
"updateReady": "Update ist bereit",
|
||||
"updateReady": "Eine neue Version ist verfügbar",
|
||||
"updateReadyDesc": "Die neue Version {{version}} wurde heruntergeladen, die Installation wird nach dem Neustart der Anwendung abgeschlossen.",
|
||||
"upgradeNow": "Jetzt aktualisieren"
|
||||
"upgradeNow": "Jetzt aktualisieren",
|
||||
"willInstallLater": "Das Update wird beim nächsten Start installiert"
|
||||
},
|
||||
"waitingOAuth": {
|
||||
"cancel": "Abbrechen",
|
||||
|
||||
@@ -81,6 +81,12 @@
|
||||
"522": "Es tut uns leid, die Serververbindung hat aufgrund einer Zeitüberschreitung nicht rechtzeitig auf Ihre Anfrage reagiert. Möglicherweise ist das Netzwerk instabil oder der Server vorübergehend nicht erreichbar. Bitte versuchen Sie es später erneut, wir arbeiten daran, den Dienst wiederherzustellen.",
|
||||
"524": "Es tut uns leid, der Server hat beim Warten auf eine Antwort eine Zeitüberschreitung erreicht, möglicherweise aufgrund einer langsamen Antwort. Bitte versuchen Sie es später erneut.",
|
||||
"AgentRuntimeError": "Es ist ein Fehler bei der Ausführung des Lobe-Sprachmodells aufgetreten. Bitte überprüfen Sie die folgenden Informationen oder versuchen Sie es erneut.",
|
||||
"ComfyUIBizError": "Fehler bei der Anfrage an den ComfyUI-Dienst. Bitte überprüfe die folgenden Informationen oder versuche es erneut.",
|
||||
"ComfyUIEmptyResult": "ComfyUI hat kein Bild generiert. Bitte überprüfe die Modellkonfiguration oder versuche es erneut.",
|
||||
"ComfyUIModelError": "Laden des ComfyUI-Modells fehlgeschlagen. Bitte überprüfe, ob die Modellsdatei vorhanden ist.",
|
||||
"ComfyUIServiceUnavailable": "Verbindung zum ComfyUI-Dienst fehlgeschlagen. Bitte stelle sicher, dass ComfyUI ordnungsgemäß läuft und die Dienstadresse korrekt konfiguriert ist.",
|
||||
"ComfyUIUploadFailed": "Hochladen des Bildes zu ComfyUI fehlgeschlagen. Bitte überprüfe die Serververbindung oder versuche es erneut.",
|
||||
"ComfyUIWorkflowError": "Ausführung des ComfyUI-Workflows fehlgeschlagen. Bitte überprüfe die Workflow-Konfiguration.",
|
||||
"ConnectionCheckFailed": "Die Anfrage brachte eine leere Antwort zurück. Bitte überprüfen Sie, ob die API-Proxy-Adresse am Ende nicht mit `/v1` endet.",
|
||||
"CreateMessageError": "Es tut uns leid, die Nachricht konnte nicht erfolgreich gesendet werden. Bitte kopieren Sie den Inhalt und senden Sie ihn erneut. Nach dem Aktualisieren der Seite wird diese Nachricht nicht gespeichert.",
|
||||
"ExceededContextWindow": "Der aktuelle Anfrageinhalt überschreitet die von dem Modell verarbeitbare Länge. Bitte reduzieren Sie die Menge des Inhalts und versuchen Sie es erneut.",
|
||||
@@ -100,6 +106,7 @@
|
||||
"InvalidAccessCode": "Das Passwort ist ungültig oder leer. Bitte geben Sie das richtige Zugangspasswort ein oder fügen Sie einen benutzerdefinierten API-Schlüssel hinzu.",
|
||||
"InvalidBedrockCredentials": "Die Bedrock-Authentifizierung ist fehlgeschlagen. Bitte überprüfen Sie AccessKeyId/SecretAccessKey und versuchen Sie es erneut.",
|
||||
"InvalidClerkUser": "Entschuldigung, du bist derzeit nicht angemeldet. Bitte melde dich an oder registriere ein Konto, um fortzufahren.",
|
||||
"InvalidComfyUIArgs": "ComfyUI-Konfiguration ist ungültig. Bitte überprüfe die Einstellungen und versuche es erneut.",
|
||||
"InvalidGithubToken": "Der persönliche Zugriffstoken für Github ist ungültig oder leer. Bitte überprüfen Sie den persönlichen Zugriffstoken für Github und versuchen Sie es erneut.",
|
||||
"InvalidOllamaArgs": "Ollama-Konfiguration ist ungültig. Bitte überprüfen Sie die Ollama-Konfiguration und versuchen Sie es erneut.",
|
||||
"InvalidProviderAPIKey": "{{provider}} API-Schlüssel ist ungültig oder leer. Bitte überprüfen Sie den {{provider}} API-Schlüssel und versuchen Sie es erneut.",
|
||||
@@ -134,6 +141,9 @@
|
||||
"stt": {
|
||||
"responseError": "Serviceanfrage fehlgeschlagen. Bitte überprüfen Sie die Konfiguration oder versuchen Sie es erneut"
|
||||
},
|
||||
"supervisor": {
|
||||
"decisionFailed": "Der Gruppenleiter kann nicht arbeiten. Bitte überprüfen Sie Ihre Leiterkonfiguration und stellen Sie sicher, dass das richtige Modell, der API-Schlüssel und die API-Adresse korrekt konfiguriert sind."
|
||||
},
|
||||
"testConnectionFailed": "Verbindungstest fehlgeschlagen: {{error}}",
|
||||
"tts": {
|
||||
"responseError": "Serviceanfrage fehlgeschlagen. Bitte überprüfen Sie die Konfiguration oder versuchen Sie es erneut"
|
||||
@@ -146,6 +156,11 @@
|
||||
"title": "Verwenden Sie Ihren benutzerdefinierten {{name}} API-Schlüssel"
|
||||
},
|
||||
"closeMessage": "Hinweis schließen",
|
||||
"comfyui": {
|
||||
"description": "Bitte gib die korrekten {{name}}-Authentifizierungsinformationen ein, um mit der Bildgenerierung zu beginnen.",
|
||||
"modifyBaseUrl": "ComfyUI-Dienstadresse ändern",
|
||||
"title": "Bestätige deine {{name}}-Authentifizierungsinformationen"
|
||||
},
|
||||
"confirm": "Bestätigen und erneut versuchen",
|
||||
"oauth": {
|
||||
"description": "Der Administrator hat die einheitliche Anmeldeauthentifizierung aktiviert. Klicken Sie unten auf die Schaltfläche, um sich anzumelden und die App zu entsperren.",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"desc": "Verwalten Sie Ihre Dateien und Wissensdatenbank",
|
||||
"desc": "Verwalte dein Wissen",
|
||||
"detail": {
|
||||
"basic": {
|
||||
"createdAt": "Erstellungszeit",
|
||||
@@ -70,7 +70,7 @@
|
||||
"videos": "Videos",
|
||||
"websites": "Webseiten"
|
||||
},
|
||||
"title": "Dateien",
|
||||
"title": "Wissensdatenbank",
|
||||
"toggleLeftPanel": {
|
||||
"title": "Linkes Panel einblenden/ausblenden"
|
||||
},
|
||||
|
||||
@@ -82,6 +82,58 @@
|
||||
"title": "Cloudflare-Kundenkennung / API-Adresse"
|
||||
}
|
||||
},
|
||||
"comfyui": {
|
||||
"apiKey": {
|
||||
"desc": "API-Schlüssel für die Authentifizierung mit Bearer-Token",
|
||||
"placeholder": "Bitte API-Schlüssel eingeben",
|
||||
"required": "Bitte API-Schlüssel eingeben",
|
||||
"title": "API-Schlüssel"
|
||||
},
|
||||
"authType": {
|
||||
"desc": "Wählen Sie die Authentifizierungsmethode für den ComfyUI-Server",
|
||||
"options": {
|
||||
"basic": "Benutzername/Passwort",
|
||||
"bearer": "Bearer (API-Schlüssel)",
|
||||
"custom": "Benutzerdefinierte Header",
|
||||
"none": "Keine Authentifizierung erforderlich"
|
||||
},
|
||||
"placeholder": "Bitte Authentifizierungstyp wählen",
|
||||
"title": "Authentifizierungstyp"
|
||||
},
|
||||
"baseURL": {
|
||||
"desc": "Webadresse für den Zugriff auf ComfyUI",
|
||||
"placeholder": "http://127.0.0.1:8000",
|
||||
"required": "Bitte ComfyUI-Serveradresse eingeben",
|
||||
"title": "ComfyUI-Serveradresse"
|
||||
},
|
||||
"checker": {
|
||||
"desc": "Verbindung testen, um die Konfiguration zu überprüfen",
|
||||
"title": "Verbindungsprüfung"
|
||||
},
|
||||
"customHeaders": {
|
||||
"addButton": "Header hinzufügen",
|
||||
"deleteTooltip": "Diesen Header löschen",
|
||||
"desc": "Erforderliche Header für benutzerdefinierte Authentifizierung im Schlüssel-Wert-Format",
|
||||
"duplicateKeyError": "Header-Schlüssel dürfen nicht doppelt sein",
|
||||
"keyPlaceholder": "Schlüssel",
|
||||
"required": "Bitte benutzerdefinierte Header eingeben",
|
||||
"title": "Benutzerdefinierte Header",
|
||||
"valuePlaceholder": "Wert"
|
||||
},
|
||||
"password": {
|
||||
"desc": "Passwort für die Basis-Authentifizierung",
|
||||
"placeholder": "Bitte Passwort eingeben",
|
||||
"required": "Bitte Passwort eingeben",
|
||||
"title": "Passwort"
|
||||
},
|
||||
"title": "ComfyUI",
|
||||
"username": {
|
||||
"desc": "Benutzername für die Basis-Authentifizierung",
|
||||
"placeholder": "Bitte Benutzernamen eingeben",
|
||||
"required": "Bitte Benutzernamen eingeben",
|
||||
"title": "Benutzername"
|
||||
}
|
||||
},
|
||||
"createNewAiProvider": {
|
||||
"apiKey": {
|
||||
"placeholder": "Bitte geben Sie Ihren API-Schlüssel ein",
|
||||
@@ -399,6 +451,11 @@
|
||||
"desc": "Geben Sie Ihre Vertex AI-Schlüssel ein",
|
||||
"placeholder": "{ \"type\": \"service_account\", \"project_id\": \"xxx\", \"private_key_id\": ... }",
|
||||
"title": "Vertex AI-Schlüssel"
|
||||
},
|
||||
"region": {
|
||||
"desc": "Wählen Sie die Region für den Vertex AI-Dienst aus. Einige Modelle wie Gemini 2.5 sind nur in bestimmten Regionen verfügbar (z. B. global).",
|
||||
"placeholder": "Region auswählen",
|
||||
"title": "Vertex AI-Region"
|
||||
}
|
||||
},
|
||||
"zeroone": {
|
||||
|
||||
@@ -311,6 +311,12 @@
|
||||
"Qwen/QwQ-32B-Preview": {
|
||||
"description": "QwQ-32B-Preview ist das neueste experimentelle Forschungsmodell von Qwen, das sich auf die Verbesserung der KI-Inferenzfähigkeiten konzentriert. Durch die Erforschung komplexer Mechanismen wie Sprachmischung und rekursive Inferenz bietet es Hauptvorteile wie starke Analysefähigkeiten, mathematische und Programmierfähigkeiten. Gleichzeitig gibt es Herausforderungen wie Sprachwechsel, Inferenzzyklen, Sicherheitsüberlegungen und Unterschiede in anderen Fähigkeiten."
|
||||
},
|
||||
"Qwen/Qwen-Image": {
|
||||
"description": "Qwen-Image ist ein von Alibabas Tongyi Qianwen-Team entwickeltes Basismodell zur Bildgenerierung mit 20 Milliarden Parametern. Das Modell erzielt bemerkenswerte Fortschritte bei der komplexen Textrendering und präzisen Bildbearbeitung und ist besonders gut darin, Bilder mit hochauflösenden chinesischen und englischen Texten zu erzeugen. Qwen-Image kann nicht nur mehrzeilige Layouts und absatzweise Texte verarbeiten, sondern bewahrt auch die Kohärenz des Layouts und die Kontextharmonie bei der Bildgenerierung. Neben seiner herausragenden Textrendering-Fähigkeit unterstützt das Modell eine breite Palette künstlerischer Stile – von realistischen Fotografien bis hin zu Anime-Ästhetik – und passt sich flexibel an verschiedene kreative Anforderungen an. Darüber hinaus verfügt es über leistungsstarke Bildbearbeitungs- und Bildverständnisfähigkeiten, einschließlich Stiltransfer, Objektentfernung und -hinzufügung, Detailverbesserung, Textbearbeitung und sogar Steuerung menschlicher Posen. Ziel ist es, ein umfassendes intelligentes Basismodell für visuelle Kreation und Verarbeitung zu sein, das Sprache, Layout und Bild vereint."
|
||||
},
|
||||
"Qwen/Qwen-Image-Edit-2509": {
|
||||
"description": "Qwen-Image-Edit-2509 ist die neueste Version des Bildbearbeitungsmodells Qwen-Image, entwickelt vom Tongyi Qianwen-Team bei Alibaba. Das Modell basiert auf dem 20B-Parameter-Modell Qwen-Image und wurde gezielt weitertrainiert, um dessen einzigartige Textrendering-Fähigkeiten erfolgreich auf den Bereich der Bildbearbeitung zu übertragen – insbesondere für die präzise Bearbeitung von Texten in Bildern. Qwen-Image-Edit verwendet eine innovative Architektur, bei der das Eingabebild gleichzeitig in Qwen2.5-VL (für semantische Steuerung) und den VAE-Encoder (für visuelle Erscheinungskontrolle) eingespeist wird. Dadurch ermöglicht es sowohl semantische als auch visuelle Bearbeitungen. Das bedeutet, dass es nicht nur lokale visuelle Änderungen wie das Hinzufügen, Entfernen oder Modifizieren von Elementen unterstützt, sondern auch komplexe semantische Bearbeitungen wie IP-Kreationen oder Stilübertragungen, bei denen die inhaltliche Konsistenz gewahrt bleibt. In mehreren öffentlichen Benchmark-Tests erzielte das Modell Spitzenleistungen (SOTA) und etabliert sich damit als leistungsstarkes Basismodell für die Bildbearbeitung."
|
||||
},
|
||||
"Qwen/Qwen2-72B-Instruct": {
|
||||
"description": "Qwen2 ist ein fortschrittliches allgemeines Sprachmodell, das eine Vielzahl von Anweisungsarten unterstützt."
|
||||
},
|
||||
@@ -392,6 +398,12 @@
|
||||
"Qwen/Qwen3-Next-80B-A3B-Thinking": {
|
||||
"description": "Qwen3-Next-80B-A3B-Thinking ist ein von Alibaba Tongyi Qianwen Team veröffentlichtes nächstes Generation Basis-Modell, das speziell für komplexe Inferenzaufgaben entwickelt wurde. Es basiert auf der innovativen Qwen3-Next-Architektur, die hybride Aufmerksamkeitsmechanismen (Gated DeltaNet und Gated Attention) mit einer hochgradig spärlichen Mixture-of-Experts (MoE)-Struktur kombiniert, um höchste Trainings- und Inferenz-Effizienz zu gewährleisten. Als spärliches Modell mit insgesamt 80 Milliarden Parametern werden bei der Inferenz nur etwa 3 Milliarden Parameter aktiviert, was die Rechenkosten stark reduziert. Bei der Verarbeitung von Langkontextaufgaben mit über 32K Tokens übertrifft der Durchsatz das Qwen3-32B-Modell um das Zehnfache. Diese „Thinking“-Version ist für anspruchsvolle mehrstufige Aufgaben wie mathematische Beweise, Code-Synthese, logische Analyse und Planung optimiert und gibt den Inferenzprozess standardmäßig in strukturierter „Denkketten“-Form aus. In der Leistung übertrifft es nicht nur kostenintensivere Modelle wie Qwen3-32B-Thinking, sondern auch in mehreren Benchmarks das Gemini-2.5-Flash-Thinking."
|
||||
},
|
||||
"Qwen/Qwen3-VL-8B-Instruct": {
|
||||
"description": "Qwen3-VL-8B-Instruct ist ein visuelles Sprachmodell der Qwen3-Serie, basierend auf Qwen3-8B-Instruct und auf umfangreichen Bild-Text-Daten trainiert. Es ist spezialisiert auf allgemeines visuelles Verständnis, visuell zentrierte Dialoge und mehrsprachige Texterkennung in Bildern. Es eignet sich für Szenarien wie visuelle Frage-Antwort-Systeme, Bildbeschreibungen, multimodale Befehlsausführung und Tool-Integration."
|
||||
},
|
||||
"Qwen/Qwen3-VL-8B-Thinking": {
|
||||
"description": "Qwen3-VL-8B-Thinking ist die Version der Qwen3-Serie mit Fokus auf visuelles Denken. Sie wurde für komplexe, mehrstufige Schlussfolgerungsaufgaben optimiert und generiert standardmäßig eine schrittweise Denkweise (Thinking Chain), um die Genauigkeit der Schlussfolgerungen zu verbessern. Ideal für Szenarien, die tiefgreifende visuelle Analysen erfordern, wie visuelle Frage-Antwort-Systeme oder die detaillierte Auswertung von Bildinhalten."
|
||||
},
|
||||
"Qwen2-72B-Instruct": {
|
||||
"description": "Qwen2 ist die neueste Reihe des Qwen-Modells, das 128k Kontext unterstützt. Im Vergleich zu den derzeit besten Open-Source-Modellen übertrifft Qwen2-72B in den Bereichen natürliche Sprachverständnis, Wissen, Code, Mathematik und Mehrsprachigkeit deutlich die führenden Modelle."
|
||||
},
|
||||
@@ -767,6 +779,9 @@
|
||||
"claude-3-sonnet-20240229": {
|
||||
"description": "Claude 3 Sonnet bietet eine ideale Balance zwischen Intelligenz und Geschwindigkeit für Unternehmensarbeitslasten. Es bietet maximalen Nutzen zu einem niedrigeren Preis, ist zuverlässig und für großflächige Bereitstellungen geeignet."
|
||||
},
|
||||
"claude-haiku-4-5-20251001": {
|
||||
"description": "Claude Haiku 4.5 ist das schnellste und intelligenteste Haiku-Modell von Anthropic, mit blitzschneller Geschwindigkeit und erweiterter Denkfähigkeit."
|
||||
},
|
||||
"claude-opus-4-1-20250805": {
|
||||
"description": "Claude Opus 4.1 ist das neueste und leistungsstärkste Modell von Anthropic zur Bewältigung hochkomplexer Aufgaben. Es überzeugt durch herausragende Leistung, Intelligenz, Flüssigkeit und Verständnis."
|
||||
},
|
||||
@@ -851,6 +866,39 @@
|
||||
"cohere/embed-v4.0": {
|
||||
"description": "Ein Modell, das es ermöglicht, Text, Bilder oder gemischte Inhalte zu klassifizieren oder in Einbettungen umzuwandeln."
|
||||
},
|
||||
"comfyui/flux-dev": {
|
||||
"description": "FLUX.1 Dev – Hochwertiges Text-zu-Bild-Modell, erzeugt Bilder in 10–50 Schritten, ideal für kreative Arbeiten und künstlerische Bildgenerierung"
|
||||
},
|
||||
"comfyui/flux-kontext-dev": {
|
||||
"description": "FLUX.1 Kontext-dev – Bildbearbeitungsmodell, unterstützt textbasierte Anweisungen zur Modifikation bestehender Bilder, inklusive lokaler Änderungen und Stilübertragungen"
|
||||
},
|
||||
"comfyui/flux-krea-dev": {
|
||||
"description": "FLUX.1 Krea-dev – Sicheres Text-zu-Bild-Modell, entwickelt in Zusammenarbeit mit Krea, mit integriertem Sicherheitsfilter"
|
||||
},
|
||||
"comfyui/flux-schnell": {
|
||||
"description": "FLUX.1 Schnell – Ultraflottes Text-zu-Bild-Modell, erzeugt hochwertige Bilder in nur 1–4 Schritten, ideal für Echtzeitanwendungen und schnelles Prototyping"
|
||||
},
|
||||
"comfyui/stable-diffusion-15": {
|
||||
"description": "Stable Diffusion 1.5 Text-zu-Bild-Modell, klassisches 512x512-Auflösungsmodell für schnelle Prototypen und kreative Experimente"
|
||||
},
|
||||
"comfyui/stable-diffusion-35": {
|
||||
"description": "Stable Diffusion 3.5 – Nächste Generation des Text-zu-Bild-Modells, verfügbar in Large- und Medium-Versionen, benötigt externe CLIP-Encoder-Dateien, bietet herausragende Bildqualität und präzise Prompt-Übereinstimmung"
|
||||
},
|
||||
"comfyui/stable-diffusion-35-inclclip": {
|
||||
"description": "Stable Diffusion 3.5 mit integriertem CLIP/T5-Encoder – keine externen Encoder-Dateien erforderlich, geeignet für Modelle wie sd3.5_medium_incl_clips, ressourcenschonender"
|
||||
},
|
||||
"comfyui/stable-diffusion-custom": {
|
||||
"description": "Benutzerdefiniertes SD Text-zu-Bild-Modell – Modell-Dateiname sollte custom_sd_lobe.safetensors lauten, bei VAE bitte custom_sd_vae_lobe.safetensors verwenden; Modell-Dateien müssen gemäß Comfy-Vorgaben im entsprechenden Ordner abgelegt werden"
|
||||
},
|
||||
"comfyui/stable-diffusion-custom-refiner": {
|
||||
"description": "Benutzerdefiniertes SDXL Bild-zu-Bild-Modell – Modell-Dateiname sollte custom_sd_lobe.safetensors lauten, bei VAE bitte custom_sd_vae_lobe.safetensors verwenden; Modell-Dateien müssen gemäß Comfy-Vorgaben im entsprechenden Ordner abgelegt werden"
|
||||
},
|
||||
"comfyui/stable-diffusion-refiner": {
|
||||
"description": "SDXL Bild-zu-Bild-Modell – Hochwertige Bildtransformation basierend auf Eingabebildern, unterstützt Stilübertragungen, Bildrestaurierung und kreative Modifikationen"
|
||||
},
|
||||
"comfyui/stable-diffusion-xl": {
|
||||
"description": "SDXL Text-zu-Bild-Modell – Unterstützt hochauflösende 1024x1024 Text-zu-Bild-Generierung, bietet verbesserte Bildqualität und Detailgenauigkeit"
|
||||
},
|
||||
"command": {
|
||||
"description": "Ein dialogbasiertes Modell, das Anweisungen folgt und in sprachlichen Aufgaben hohe Qualität und Zuverlässigkeit bietet. Im Vergleich zu unserem grundlegenden Generierungsmodell hat es eine längere Kontextlänge."
|
||||
},
|
||||
@@ -1148,6 +1196,9 @@
|
||||
"doubao-seed-1.6-flash": {
|
||||
"description": "Doubao-Seed-1.6-flash ist ein multimodales Modell für tiefgehendes Denken mit extrem schneller Inferenzgeschwindigkeit, TPOT benötigt nur 10 ms; unterstützt sowohl Text- als auch visuelles Verständnis, die Textverständnisfähigkeit übertrifft die vorherige Lite-Generation, das visuelle Verständnis ist vergleichbar mit den Pro-Modellen der Konkurrenz. Unterstützt ein Kontextfenster von 256k und eine maximale Ausgabelänge von 16k Tokens."
|
||||
},
|
||||
"doubao-seed-1.6-lite": {
|
||||
"description": "Doubao-Seed-1.6-lite ist ein neues multimodales Modell für tiefes Denken mit einstellbarem Denkaufwand (reasoning effort) in vier Stufen: Minimal, Low, Medium und High. Es bietet ein hervorragendes Preis-Leistungs-Verhältnis und ist die beste Wahl für gängige Aufgaben, mit einem Kontextfenster von bis zu 256k."
|
||||
},
|
||||
"doubao-seed-1.6-thinking": {
|
||||
"description": "Das Doubao-Seed-1.6-thinking Modell verfügt über stark verbesserte Denkfähigkeiten. Im Vergleich zu Doubao-1.5-thinking-pro wurden die Grundfähigkeiten in Coding, Mathematik und logischem Denken weiter verbessert und unterstützt visuelles Verständnis. Unterstützt ein Kontextfenster von 256k und eine maximale Ausgabelänge von 16k Tokens."
|
||||
},
|
||||
@@ -1541,9 +1592,6 @@
|
||||
"glm-zero-preview": {
|
||||
"description": "GLM-Zero-Preview verfügt über starke Fähigkeiten zur komplexen Schlussfolgerung und zeigt hervorragende Leistungen in den Bereichen logisches Denken, Mathematik und Programmierung."
|
||||
},
|
||||
"glm4.6:355b": {
|
||||
"description": "Das neueste Flaggschiffmodell GLM-4.6 (355B) von Zhipu übertrifft seinen Vorgänger in den Bereichen fortgeschrittenes Codieren, Verarbeitung langer Texte, logisches Schlussfolgern und Agentenfähigkeiten deutlich. Besonders im Bereich Programmierung erreicht es das Niveau von Claude Sonnet 4 und zählt damit zu den führenden Coding-Modellen in China."
|
||||
},
|
||||
"google/gemini-2.0-flash": {
|
||||
"description": "Gemini 2.0 Flash bietet Funktionen der nächsten Generation und Verbesserungen, darunter herausragende Geschwindigkeit, integrierte Werkzeugnutzung, multimodale Generierung und ein Kontextfenster von 1 Million Tokens."
|
||||
},
|
||||
@@ -1934,12 +1982,18 @@
|
||||
"inception/mercury-coder-small": {
|
||||
"description": "Mercury Coder Small ist ideal für Codegenerierung, Debugging und Refactoring-Aufgaben mit minimaler Latenz."
|
||||
},
|
||||
"inclusionAI/Ling-1T": {
|
||||
"description": "Ling-1T ist das erste Flaggschiffmodell der „Ling 2.0“-Reihe ohne Denkfunktion (non-thinking), mit insgesamt einer Billion Parametern und etwa 50 Milliarden aktiven Parametern pro Token. Es basiert auf der Ling 2.0-Architektur und zielt darauf ab, die Grenzen effizienter Schlussfolgerung und skalierbarer Kognition zu durchbrechen. Ling-1T-base wurde mit über 20 Billionen hochwertigen, reasoning-intensiven Tokens trainiert."
|
||||
},
|
||||
"inclusionAI/Ling-flash-2.0": {
|
||||
"description": "Ling-flash-2.0 ist das dritte Modell der Ling 2.0 Architekturserie, veröffentlicht vom Ant Group Bailing Team. Es handelt sich um ein Mixture-of-Experts (MoE)-Modell mit insgesamt 100 Milliarden Parametern, wobei pro Token nur 6,1 Milliarden Parameter aktiviert werden (ohne Wortvektoren 4,8 Milliarden). Als leichtgewichtige Konfiguration zeigt Ling-flash-2.0 in mehreren renommierten Benchmarks Leistungen, die mit 40-Milliarden-Dense-Modellen und größeren MoE-Modellen vergleichbar oder überlegen sind. Das Modell zielt darauf ab, durch exzellentes Architekturdesign und Trainingsstrategien effiziente Wege zu erforschen, um die gängige Annahme „großes Modell = viele Parameter“ zu hinterfragen."
|
||||
},
|
||||
"inclusionAI/Ling-mini-2.0": {
|
||||
"description": "Ling-mini-2.0 ist ein kleines, leistungsstarkes Sprachmodell basierend auf der MoE-Architektur. Es verfügt über 16 Milliarden Gesamtparameter, aktiviert jedoch pro Token nur 1,4 Milliarden (ohne Einbettungen 789 Millionen), was eine sehr hohe Generierungsgeschwindigkeit ermöglicht. Dank effizientem MoE-Design und großem, hochwertigem Trainingsdatensatz zeigt Ling-mini-2.0 trotz der geringen aktivierten Parameter eine Spitzenleistung, die mit dichten LLMs unter 10 Milliarden und größeren MoE-Modellen in nachgelagerten Aufgaben vergleichbar ist."
|
||||
},
|
||||
"inclusionAI/Ring-1T": {
|
||||
"description": "Ring-1T ist ein Open-Source-Modell für kognitives Denken im Billionen-Parameter-Maßstab, veröffentlicht vom Bailing-Team. Es basiert auf der Ling 2.0-Architektur und dem Ling-1T-base-Modell, mit insgesamt einer Billion Parametern und 50 Milliarden aktiven Parametern. Es unterstützt ein Kontextfenster von bis zu 128K und wurde durch groß angelegtes, verifizierbares, belohnungsbasiertes Reinforcement Learning optimiert."
|
||||
},
|
||||
"inclusionAI/Ring-flash-2.0": {
|
||||
"description": "Ring-flash-2.0 ist ein hochleistungsfähiges Denkmodell, das auf Ling-flash-2.0-base tief optimiert wurde. Es verwendet eine Mixture-of-Experts (MoE)-Architektur mit insgesamt 100 Milliarden Parametern, aktiviert jedoch bei jeder Inferenz nur 6,1 Milliarden Parameter. Durch den innovativen Icepop-Algorithmus löst es die Instabilitätsprobleme großer MoE-Modelle im Reinforcement Learning (RL) Training und verbessert kontinuierlich seine komplexen Inferenzfähigkeiten über lange Trainingszyklen. Ring-flash-2.0 erzielt bedeutende Durchbrüche in anspruchsvollen Benchmarks wie Mathematikwettbewerben, Codegenerierung und logischem Schließen. Seine Leistung übertrifft nicht nur dichte Spitzenmodelle unter 40 Milliarden Parametern, sondern ist auch vergleichbar mit größeren Open-Source-MoE-Modellen und proprietären Hochleistungs-Denkmodellen. Obwohl es auf komplexe Inferenz spezialisiert ist, zeigt es auch bei kreativen Schreibaufgaben hervorragende Ergebnisse. Dank seiner effizienten Architektur bietet Ring-flash-2.0 starke Leistung bei gleichzeitig hoher Inferenzgeschwindigkeit und senkt deutlich die Bereitstellungskosten in hochparallelen Szenarien."
|
||||
},
|
||||
@@ -2036,9 +2090,6 @@
|
||||
"llama-3.3-instruct": {
|
||||
"description": "Das Llama 3.3 Instruct-Modell ist für Dialogszenarien optimiert und übertrifft in gängigen Branchenbenchmarks viele bestehende Open-Source-Chatmodelle."
|
||||
},
|
||||
"llama-4-maverick-17b-128e-instruct": {
|
||||
"description": "Llama 4 Maverick: Ein leistungsstarkes Modell der Llama-Serie, ideal für fortgeschrittenes logisches Denken, komplexe Problemlösungen und Aufgaben mit Anweisungsbefolgung."
|
||||
},
|
||||
"llama-4-scout-17b-16e-instruct": {
|
||||
"description": "Llama 4 Scout: Ein leistungsstarkes Modell der Llama-Serie, optimiert für Szenarien mit hoher Verarbeitungsgeschwindigkeit und niedriger Latenz."
|
||||
},
|
||||
@@ -2906,6 +2957,9 @@
|
||||
"qwen3-8b": {
|
||||
"description": "Qwen3 ist ein neues, leistungsstarkes Modell der nächsten Generation, das in den Bereichen Inferenz, Allgemeinwissen, Agenten und Mehrsprachigkeit erhebliche Fortschritte erzielt hat und den Wechsel zwischen Denkmodi unterstützt."
|
||||
},
|
||||
"qwen3-coder-30b-a3b-instruct": {
|
||||
"description": "Open-Source-Version des Qwen-Codegenerierungsmodells. Das neueste qwen3-coder-30b-a3b-instruct basiert auf Qwen3 und bietet leistungsstarke Coding-Agent-Fähigkeiten. Es ist spezialisiert auf Tool-Nutzung und Interaktion mit Umgebungen, ermöglicht autonomes Programmieren und kombiniert herausragende Programmierfähigkeiten mit allgemeinen Fähigkeiten."
|
||||
},
|
||||
"qwen3-coder-480b-a35b-instruct": {
|
||||
"description": "Open-Source-Code-Modell von Tongyi Qianwen. Das neueste qwen3-coder-480b-a35b-instruct basiert auf Qwen3, verfügt über starke Coding-Agent-Fähigkeiten, ist versiert im Werkzeugaufruf und in der Umgebungskommunikation und ermöglicht selbstständiges Programmieren mit hervorragender Codequalität und allgemeinen Fähigkeiten."
|
||||
},
|
||||
@@ -2927,11 +2981,29 @@
|
||||
"qwen3-next-80b-a3b-thinking": {
|
||||
"description": "Ein neues Open-Source-Modell der nächsten Generation im Denkmodus basierend auf Qwen3. Im Vergleich zur vorherigen Version (Tongyi Qianwen 3-235B-A22B-Thinking-2507) wurde die Befehlsbefolgung verbessert und die Modellantworten sind prägnanter zusammengefasst."
|
||||
},
|
||||
"qwen3-omni-flash": {
|
||||
"description": "Das Qwen-Omni-Modell kann kombinierte Eingaben aus Text, Bildern, Audio und Video verarbeiten und Antworten in Text- oder Sprachform generieren. Es bietet verschiedene menschenähnliche Sprachstile, unterstützt mehrsprachige und dialektale Sprachausgabe und eignet sich für Anwendungen wie Textgenerierung, visuelle Erkennung und Sprachassistenten."
|
||||
},
|
||||
"qwen3-vl-235b-a22b-instruct": {
|
||||
"description": "Qwen3 VL 235B A22B Instruct ist ein multimodales Modell von Tongyi Qianwen mit Unterstützung für visuelles Verständnis und logisches Denken."
|
||||
"description": "Qwen3 VL 235B A22B im Non-Thinking-Modus (Instruct), geeignet für Anwendungsfälle mit einfachen Anweisungen, bei gleichzeitig starker visueller Verständnisfähigkeit."
|
||||
},
|
||||
"qwen3-vl-235b-a22b-thinking": {
|
||||
"description": "Qwen3 VL 235B A22B Thinking ist ein multimodales Inferenzmodell von Tongyi Qianwen mit Unterstützung für visuelles Verständnis und logisches Denken."
|
||||
"description": "Qwen3 VL 235B A22B im Thinking-Modus (Open-Source-Version), bietet erstklassige visuelle und textbasierte Schlussfolgerungsfähigkeiten für komplexe Aufgaben mit hoher kognitiver Anforderung und Langvideo-Verständnis."
|
||||
},
|
||||
"qwen3-vl-30b-a3b-instruct": {
|
||||
"description": "Qwen3 VL 30B im Non-Thinking-Modus (Instruct), konzipiert für allgemeine Anweisungsfolgeszenarien mit starker multimodaler Verständnis- und Generierungsfähigkeit."
|
||||
},
|
||||
"qwen3-vl-30b-a3b-thinking": {
|
||||
"description": "Qwen-VL (Open-Source-Version) bietet visuelles Verständnis und Textgenerierung, unterstützt Agenteninteraktion, visuelle Kodierung, räumliches Bewusstsein, Langvideo-Verständnis und tiefes Denken. Es verfügt über starke Texterkennungs- und Mehrsprachenfähigkeiten in komplexen Szenarien."
|
||||
},
|
||||
"qwen3-vl-8b-instruct": {
|
||||
"description": "Qwen3 VL 8B im Non-Thinking-Modus (Instruct), geeignet für Standardaufgaben der multimodalen Generierung und Erkennung."
|
||||
},
|
||||
"qwen3-vl-8b-thinking": {
|
||||
"description": "Qwen3 VL 8B im Thinking-Modus, konzipiert für leichte multimodale Schlussfolgerungs- und Interaktionsszenarien, mit erhaltener Fähigkeit zum Verständnis langer Kontexte."
|
||||
},
|
||||
"qwen3-vl-flash": {
|
||||
"description": "Qwen3 VL Flash: eine leichtgewichtige, hochperformante Version für schnelle Inferenz, ideal für latenzkritische oder großvolumige Anfragen."
|
||||
},
|
||||
"qwen3-vl-plus": {
|
||||
"description": "Tongyi Qianwen VL ist ein Textgenerierungsmodell mit visuellen (Bild-)Verständnisfähigkeiten. Es kann nicht nur OCR (Texterkennung in Bildern) durchführen, sondern auch weiterführende Zusammenfassungen und Schlussfolgerungen ziehen, z. B. Attribute aus Produktfotos extrahieren oder Aufgaben anhand von Übungsbildern lösen."
|
||||
|
||||
@@ -461,7 +461,7 @@
|
||||
"tabs": {
|
||||
"installed": "Installiert",
|
||||
"mcp": "MCP Plugins",
|
||||
"old": "LobeChat Plugins"
|
||||
"old": "LobeHub Erweiterung"
|
||||
},
|
||||
"title": "Plugin-Shop"
|
||||
},
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
"description": "Bedrock ist ein Service von Amazon AWS, der sich darauf konzentriert, Unternehmen fortschrittliche KI-Sprach- und visuelle Modelle bereitzustellen. Die Modellfamilie umfasst die Claude-Serie von Anthropic, die Llama 3.1-Serie von Meta und mehr, und bietet eine Vielzahl von Optionen von leichtgewichtig bis hochleistungsfähig, die Textgenerierung, Dialoge, Bildverarbeitung und andere Aufgaben unterstützen und für Unternehmensanwendungen unterschiedlicher Größen und Anforderungen geeignet sind."
|
||||
},
|
||||
"bfl": {
|
||||
"description": "Ein führendes, an vorderster Front tätiges KI-Forschungslabor, das die visuelle Infrastruktur von morgen gestaltet."
|
||||
"description": "Ein führendes, hochmodernes Forschungslabor für künstliche Intelligenz, das die visuelle Infrastruktur von morgen aufbaut."
|
||||
},
|
||||
"cerebras": {
|
||||
"description": "Cerebras ist eine KI-Inferenzplattform, die auf dem spezialisierten CS-3-System basiert. Sie wurde entwickelt, um weltweit die schnellsten, in Echtzeit reagierenden und hochdurchsatzfähigen LLM-Dienste bereitzustellen. Ziel ist es, Latenzen zu eliminieren und komplexe KI-Workflows wie die Echtzeit-Codegenerierung und Agentenaufgaben zu beschleunigen."
|
||||
@@ -44,6 +44,9 @@
|
||||
"cometapi": {
|
||||
"description": "CometAPI ist eine Serviceplattform, die verschiedene fortschrittliche Schnittstellen für große Modelle anbietet und OpenAI, Anthropic, Google und weitere unterstützt. Sie eignet sich für vielfältige Entwicklungs- und Anwendungsanforderungen. Nutzer können je nach Bedarf das optimale Modell und den besten Preis flexibel auswählen, um das KI-Erlebnis zu verbessern."
|
||||
},
|
||||
"comfyui": {
|
||||
"description": "Leistungsstarke Open-Source-Engine für die Erstellung von Bildern, Videos und Audiodateien. Unterstützt fortschrittliche Modelle wie SD, FLUX, Qwen, Hunyuan und WAN. Bietet eine node-basierte Workflow-Bearbeitung sowie Möglichkeiten zur privaten Bereitstellung."
|
||||
},
|
||||
"deepseek": {
|
||||
"description": "DeepSeek ist ein Unternehmen, das sich auf die Forschung und Anwendung von KI-Technologien spezialisiert hat. Ihr neuestes Modell, DeepSeek-V2.5, kombiniert allgemeine Dialog- und Codeverarbeitungsfähigkeiten und hat signifikante Fortschritte in den Bereichen menschliche Präferenzanpassung, Schreibaufgaben und Befehlsbefolgung erzielt."
|
||||
},
|
||||
|
||||
@@ -35,9 +35,16 @@
|
||||
"title": "Alle Einstellungen zurücksetzen"
|
||||
}
|
||||
},
|
||||
"groupTab": {
|
||||
"chat": "Chat",
|
||||
"members": "Mitglieder",
|
||||
"meta": "Grundinformationen"
|
||||
},
|
||||
"header": {
|
||||
"desc": "Präferenzen und Modellkonfigurationen.",
|
||||
"global": "Global Einstellungen",
|
||||
"group": "Team-Einstellungen",
|
||||
"groupDesc": "Verwalten Sie Agent-Teams und Chat-Einstellungen",
|
||||
"session": "Sitzungseinstellungen",
|
||||
"sessionDesc": "Rollenkonfiguration und Sitzungspräferenzen.",
|
||||
"sessionWithName": "Sitzungseinstellungen · {{name}}",
|
||||
@@ -139,6 +146,9 @@
|
||||
},
|
||||
"waitingForMore": "Weitere Modelle werden <1>geplant</1>, bitte freuen Sie sich auf weitere Updates"
|
||||
},
|
||||
"message": {
|
||||
"success": "Erfolgreich aktualisiert"
|
||||
},
|
||||
"plugin": {
|
||||
"addMCPPlugin": "MCP-Plugin hinzufügen",
|
||||
"addTooltip": "Benutzerdefiniertes Plugin",
|
||||
@@ -294,6 +304,102 @@
|
||||
},
|
||||
"title": "Allgemeine Einstellungen"
|
||||
},
|
||||
"settingGroup": {
|
||||
"description": {
|
||||
"placeholder": "Bitte geben Sie eine Team-Beschreibung ein",
|
||||
"title": "Team-Beschreibung"
|
||||
},
|
||||
"name": {
|
||||
"placeholder": "Bitte geben Sie einen Teamnamen ein",
|
||||
"title": "Teamname"
|
||||
},
|
||||
"scene": {
|
||||
"desc": "Wählen Sie ein Teamszenario",
|
||||
"options": {
|
||||
"casual": "Freizeit",
|
||||
"productive": "Produktivität"
|
||||
},
|
||||
"title": "Teamszenario"
|
||||
},
|
||||
"submit": "Team aktualisieren",
|
||||
"systemPrompt": {
|
||||
"placeholder": "Bitte geben Sie den Systemhinweis für den Moderator ein",
|
||||
"title": "Systemhinweis des Moderators"
|
||||
},
|
||||
"title": "Agent-Teaminformationen"
|
||||
},
|
||||
"settingGroupChat": {
|
||||
"allowDM": {
|
||||
"desc": "Wenn deaktiviert, kannst du dem Assistenten weiterhin direkt Nachrichten senden",
|
||||
"title": "Direktnachrichten vom Assistenten erlauben"
|
||||
},
|
||||
"enableSupervisor": {
|
||||
"desc": "Aktivieren Sie die Moderatorfunktion für das Agent-Team. Moderatoren verwalten den Gesprächsverlauf des Teams.",
|
||||
"title": "Moderator aktivieren"
|
||||
},
|
||||
"maxResponseInRow": {
|
||||
"desc": "Wählen Sie, wie viele Nachrichten ein Mitglied hintereinander antworten kann. Setzen Sie auf 0, um diese Begrenzung zu deaktivieren.",
|
||||
"title": "Anzahl der aufeinanderfolgenden Antworten"
|
||||
},
|
||||
"model": {
|
||||
"desc": "Beiträge von Gruppenmitgliedern bleiben unbeeinträchtigt. Einige Modelle können nicht als Moderatoren verwendet werden.",
|
||||
"title": "Moderator-Modell"
|
||||
},
|
||||
"orchestratorTitle": "Moderatoreinstellungen",
|
||||
"responseOrder": {
|
||||
"desc": "Agenten antworten in der im Chat festgelegten Reihenfolge",
|
||||
"options": {
|
||||
"natural": "Natürlich",
|
||||
"sequential": "Sequenziell"
|
||||
},
|
||||
"placeholder": "Antwortreihenfolge wählen",
|
||||
"title": "Antwortreihenfolge"
|
||||
},
|
||||
"responseSpeed": {
|
||||
"desc": "Steuern Sie die allgemeine Geschwindigkeit des Gesprächs",
|
||||
"options": {
|
||||
"fast": "Schnell",
|
||||
"medium": "Mittel",
|
||||
"slow": "Langsam"
|
||||
},
|
||||
"placeholder": "Antwortgeschwindigkeit wählen",
|
||||
"title": "Antwortgeschwindigkeit"
|
||||
},
|
||||
"revealDM": {
|
||||
"desc": "Macht private Nachrichten, die an andere Mitglieder gesendet wurden, für Sie sichtbar.",
|
||||
"title": "Private Nachrichten anzeigen"
|
||||
},
|
||||
"submit": "Einstellungen aktualisieren",
|
||||
"systemPrompt": {
|
||||
"desc": "Benutzerdefinierter Systemhinweis für den Moderator des Gruppenchats. Dies kann das Standardverhalten des Moderators beeinflussen.",
|
||||
"placeholder": "Bitte geben Sie einen benutzerdefinierten Systemhinweis für den Moderator ein...",
|
||||
"title": "Systemhinweis des Moderators"
|
||||
},
|
||||
"title": "Chat-Einstellungen"
|
||||
},
|
||||
"settingGroupMembers": {
|
||||
"addToGroup": "Zur Gruppe hinzufügen",
|
||||
"availableAgents": "Verfügbare Assistenten",
|
||||
"createMember": "Mitglied erstellen",
|
||||
"defaultAgent": "Benutzerdefinierter Assistent",
|
||||
"disableHost": "Moderator-Assistent deaktivieren",
|
||||
"edit": "Mitglieder bearbeiten",
|
||||
"empty": "Dieses Team hat derzeit keine Mitglieder. Klicken Sie auf die + Schaltfläche, um Mitglieder hinzuzufügen.",
|
||||
"enableHost": "Moderator-Assistent aktivieren",
|
||||
"groupHost": "Gruppenmoderator",
|
||||
"groupMembers": "Gruppenmitglieder",
|
||||
"host": {
|
||||
"description": "Wenn der Moderator in der Gruppe ist, läuft der Gruppenchat automatisiert, geeignet für kreative Aufgaben.",
|
||||
"title": "Moderator"
|
||||
},
|
||||
"noAvailableAgents": "Keine verfügbaren Assistenten",
|
||||
"noDescription": "Keine Beschreibung vorhanden",
|
||||
"noMembersInGroup": "Keine Mitglieder in der Gruppe",
|
||||
"owner": "Sie (Eigentümer)",
|
||||
"remove": "Mitglied entfernen",
|
||||
"removeFromGroup": "Aus der Gruppe entfernen",
|
||||
"you": "Sie"
|
||||
},
|
||||
"settingImage": {
|
||||
"defaultCount": {
|
||||
"desc": "Legen Sie die Standardanzahl der Bilder fest, die beim Erstellen einer neuen Aufgabe im Bildgenerierungs-Panel erzeugt werden.",
|
||||
|
||||
+334
-17
@@ -6,26 +6,343 @@
|
||||
},
|
||||
"defaultMessage": "Ich bin Ihr persönlicher intelligenter Assistent {{appName}}. Wie kann ich Ihnen jetzt helfen?<br />Wenn Sie einen professionelleren oder maßgeschneiderten Assistenten benötigen, klicken Sie auf <plus />, um einen benutzerdefinierten Assistenten zu erstellen.",
|
||||
"defaultMessageWithoutCreate": "Ich bin Ihr persönlicher intelligenter Assistent {{appName}}. Wie kann ich Ihnen jetzt helfen?",
|
||||
"qa": {
|
||||
"q01": "Was ist LobeHub?",
|
||||
"q02": "Was ist {{appName}}?",
|
||||
"q03": "Hat {{appName}} Community-Support?",
|
||||
"q04": "Welche Funktionen unterstützt {{appName}}?",
|
||||
"q05": "Wie wird {{appName}} bereitgestellt und verwendet?",
|
||||
"q06": "Wie ist die Preisgestaltung von {{appName}}?",
|
||||
"q07": "Ist {{appName}} kostenlos?",
|
||||
"q08": "Gibt es eine Cloud-Service-Version?",
|
||||
"q09": "Unterstützt es lokale Sprachmodelle?",
|
||||
"q10": "Unterstützt es Bildverarbeitung und -erzeugung?",
|
||||
"q11": "Unterstützt es Sprachsynthese und Spracherkennung?",
|
||||
"q12": "Unterstützt es ein Plug-in-System?",
|
||||
"q13": "Gibt es einen eigenen Marktplatz für GPTs?",
|
||||
"q14": "Unterstützt es mehrere AI-Dienstanbieter?",
|
||||
"q15": "Was soll ich tun, wenn ich Probleme bei der Nutzung habe?"
|
||||
"groupActivities": {
|
||||
"analysis": {
|
||||
"codeReview": {
|
||||
"description": "Technische Diskussion und Peer-Review von Codeänderungen und Implementierungen",
|
||||
"emoji": "💻",
|
||||
"prompt": "Lass uns gemeinsam etwas Code überprüfen. Kannst du uns helfen, diesen Code zu analysieren und Verbesserungsmöglichkeiten zu identifizieren?",
|
||||
"title": "Code-Review"
|
||||
},
|
||||
"investment": {
|
||||
"description": "Marktanalyse, Diskussion von Anlagestrategien und Teilen von Finanzinsights",
|
||||
"emoji": "📈",
|
||||
"prompt": "Lass uns gemeinsam den Markt analysieren. Kannst du uns helfen, Anlagestrategien zu diskutieren und Finanzinsights zu teilen?",
|
||||
"title": "Investment-Club"
|
||||
},
|
||||
"research": {
|
||||
"description": "Erforschung wissenschaftlicher Konzepte, Durchführung von Experimenten und Teilen von Erkenntnissen",
|
||||
"emoji": "🔬",
|
||||
"prompt": "Lass uns gemeinsam Wissenschaft entdecken! Kannst du uns helfen, Experimente durchzuführen und unsere Erkenntnisse zu teilen?",
|
||||
"title": "Wissenschaftsausstellung"
|
||||
},
|
||||
"study": {
|
||||
"description": "Kooperative Lernsitzungen, Diskussion von Konzepten und gemeinsames Lösen von Problemen",
|
||||
"emoji": "📚",
|
||||
"prompt": "Lass uns eine Lerngruppe bilden. Kannst du uns helfen, diese Konzepte zu verstehen und gemeinsam Probleme zu lösen?",
|
||||
"title": "Lerngruppe"
|
||||
}
|
||||
},
|
||||
"brainstorm": {
|
||||
"artWorkshop": {
|
||||
"description": "Kreation, Kritik und Wertschätzung verschiedener Formen visueller und digitaler Kunst",
|
||||
"emoji": "🖼️",
|
||||
"prompt": "Lass uns einen Kunstworkshop veranstalten! Kannst du uns helfen, verschiedene Kunstformen zu kreieren, zu kritisieren und zu schätzen?",
|
||||
"title": "Kunstworkshop"
|
||||
},
|
||||
"debate": {
|
||||
"description": "Strukturierte Diskussionen und Debatten zu verschiedenen Themen und aktuellen Ereignissen",
|
||||
"emoji": "⚖️",
|
||||
"prompt": "Lass uns eine strukturierte Debatte führen. Kannst du uns helfen, eine fundierte Diskussion zu diesem Thema zu organisieren?",
|
||||
"title": "Debattierclub"
|
||||
},
|
||||
"designReview": {
|
||||
"description": "Kooperative Feedback-Sitzungen zu Designkonzepten, Prototypen oder kreativen Arbeiten",
|
||||
"emoji": "🎨",
|
||||
"prompt": "Wir müssen einige Designarbeiten überprüfen. Kannst du uns helfen, konstruktives Feedback zu Designkonzepten und Prototypen zu geben?",
|
||||
"title": "Design-Review"
|
||||
},
|
||||
"ideation": {
|
||||
"description": "Kollaborative Ideengenerierung aus verschiedenen Perspektiven und kreative Problemlösung",
|
||||
"emoji": "🧠",
|
||||
"prompt": "Lass uns mit dem Brainstorming für das Projekt beginnen. Kannst du uns helfen, kreative Ideen und Lösungen zu entwickeln?",
|
||||
"title": "Brainstorming"
|
||||
}
|
||||
},
|
||||
"game": {
|
||||
"debateClub": {
|
||||
"description": "Strukturierte Diskussionen und Debatten zu verschiedenen Themen und aktuellen Ereignissen",
|
||||
"emoji": "⚖️",
|
||||
"prompt": "Lass uns eine strukturierte Debatte führen. Kannst du uns helfen, eine fundierte Diskussion zu diesem Thema zu organisieren?",
|
||||
"title": "Debattierclub"
|
||||
},
|
||||
"gameNight": {
|
||||
"description": "Unterhaltsame interaktive Spiele und Aktivitäten zur Teambildung und zum Spaß haben",
|
||||
"emoji": "🎲",
|
||||
"prompt": "Die Spielnacht beginnt! Kannst du uns helfen, einige unterhaltsame interaktive Spiele zur Teambildung zu organisieren?",
|
||||
"title": "Spielnacht"
|
||||
},
|
||||
"modelUN": {
|
||||
"description": "Simulation von UN-Debatten und diplomatischen Verhandlungen zu globalen Themen",
|
||||
"emoji": "🌍",
|
||||
"prompt": "Lass uns eine UN-Debatte simulieren. Kannst du uns helfen, eine diplomatische Verhandlung zu globalen Themen zu gestalten?",
|
||||
"title": "Model United Nations"
|
||||
},
|
||||
"werewolf": {
|
||||
"description": "Soziales Deduktionsspiel, bei dem Spieler durch Strategie und Diskussion die Werwölfe finden",
|
||||
"emoji": "🐺",
|
||||
"prompt": "Lass uns Werwolf spielen! Kannst du uns helfen, die Regeln festzulegen und das soziale Deduktionsspiel zu moderieren?",
|
||||
"title": "Werwolf-Spiel"
|
||||
}
|
||||
},
|
||||
"general": {
|
||||
"brainstorm": {
|
||||
"description": "Kollaborative Ideengenerierung aus verschiedenen Perspektiven und kreative Problemlösung",
|
||||
"emoji": "🧠",
|
||||
"prompt": "Lass uns mit dem Brainstorming für das Projekt beginnen. Kannst du uns helfen, kreative Ideen und Lösungen zu entwickeln?",
|
||||
"title": "Brainstorming"
|
||||
},
|
||||
"debate": {
|
||||
"description": "Strukturierte Diskussionen und Debatten zu verschiedenen Themen und aktuellen Ereignissen",
|
||||
"emoji": "⚖️",
|
||||
"prompt": "Lass uns eine strukturierte Debatte führen. Kannst du uns helfen, eine fundierte Diskussion zu diesem Thema zu organisieren?",
|
||||
"title": "Debattierclub"
|
||||
},
|
||||
"languagePractice": {
|
||||
"description": "Sprachpraxis mit Muttersprachlern zum Sprechen und Lernen neuer Sprachen",
|
||||
"emoji": "🗣️",
|
||||
"prompt": "Lass uns gemeinsam eine neue Sprache üben. Kannst du uns helfen, diese Sprache zu lernen und zu sprechen?",
|
||||
"title": "Sprachpraxis"
|
||||
},
|
||||
"studyGroup": {
|
||||
"description": "Kooperative Lernsitzungen, Diskussion von Konzepten und gemeinsames Lösen von Problemen",
|
||||
"emoji": "📚",
|
||||
"prompt": "Lass uns eine Lerngruppe bilden. Kannst du uns helfen, diese Konzepte zu verstehen und gemeinsam Probleme zu lösen?",
|
||||
"title": "Lerngruppe"
|
||||
}
|
||||
},
|
||||
"planning": {
|
||||
"cookingClass": {
|
||||
"description": "Lernen und Teilen von Kochtechniken, Rezepten und kulinarischen Traditionen",
|
||||
"emoji": "👨🍳",
|
||||
"prompt": "Lass uns einen Kochkurs machen! Kannst du uns helfen, neue Rezepte und Kochtechniken zu lernen?",
|
||||
"title": "Kochkurs"
|
||||
},
|
||||
"fitnessChallenge": {
|
||||
"description": "Setzen von Gruppenfitnesszielen, Teilen von Trainingsmethoden und gegenseitige Motivation",
|
||||
"emoji": "💪",
|
||||
"prompt": "Lass uns eine Fitness-Challenge starten! Kannst du uns helfen, Ziele zu setzen und uns gegenseitig zu motivieren, gesund zu bleiben?",
|
||||
"title": "Fitness-Challenge"
|
||||
},
|
||||
"planningPoker": {
|
||||
"description": "Agile Schätztechnik mit Karten zur Abschätzung von Projektaufgaben und Arbeitsaufwand",
|
||||
"emoji": "🃏",
|
||||
"prompt": "Wir machen gerade Planning Poker für das Projekt. Kannst du uns helfen, diese Aufgaben mit agilen Techniken zu schätzen?",
|
||||
"title": "Planning Poker"
|
||||
},
|
||||
"travelPlanning": {
|
||||
"description": "Reiseplanung, Teilen von Reiseerfahrungen und Entdecken neuer Ziele",
|
||||
"emoji": "✈️",
|
||||
"prompt": "Lass uns gemeinsam eine Reise planen! Kannst du uns helfen, Reiseziele zu recherchieren und die Reiseroute zu planen?",
|
||||
"title": "Reiseplanung"
|
||||
}
|
||||
},
|
||||
"product": {
|
||||
"codeReview": {
|
||||
"description": "Technische Diskussion und Peer-Review von Codeänderungen und Implementierungen",
|
||||
"emoji": "💻",
|
||||
"prompt": "Lass uns gemeinsam etwas Code überprüfen. Kannst du uns helfen, diesen Code zu analysieren und Verbesserungsmöglichkeiten zu identifizieren?",
|
||||
"title": "Code-Review"
|
||||
},
|
||||
"designReview": {
|
||||
"description": "Kooperative Feedback-Sitzungen zu Designkonzepten, Prototypen oder kreativen Arbeiten",
|
||||
"emoji": "🎨",
|
||||
"prompt": "Wir müssen einige Designarbeiten überprüfen. Kannst du uns helfen, konstruktives Feedback zu Designkonzepten und Prototypen zu geben?",
|
||||
"title": "Design-Review"
|
||||
},
|
||||
"sprintPlanning": {
|
||||
"description": "Agile Schätztechnik mit Karten zur Abschätzung von Projektaufgaben und Arbeitsaufwand",
|
||||
"emoji": "🃏",
|
||||
"prompt": "Wir machen gerade Planning Poker für das Projekt. Kannst du uns helfen, diese Aufgaben mit agilen Techniken zu schätzen?",
|
||||
"title": "Planning Poker"
|
||||
},
|
||||
"techExchange": {
|
||||
"description": "Diskussion über aufkommende Technologien, Innovationen und Branchentrends",
|
||||
"emoji": "🚀",
|
||||
"prompt": "Lass uns einen Technikaustausch machen! Kannst du uns helfen, über neue Technologien und Branchentrends zu diskutieren?",
|
||||
"title": "Technikaustausch"
|
||||
}
|
||||
},
|
||||
"title": "Empfohlene Nutzung des Gruppenchats",
|
||||
"writing": {
|
||||
"bookClub": {
|
||||
"description": "Literarische Diskussion und Analyse von Büchern, Geschichten und literarischen Werken",
|
||||
"emoji": "📖",
|
||||
"prompt": "Lass uns mit der Buchclub-Diskussion beginnen. Kannst du uns helfen, dieses Buch zu analysieren und seine Themen zu erkunden?",
|
||||
"title": "Buchclub"
|
||||
},
|
||||
"movieClub": {
|
||||
"description": "Gemeinsames Anschauen und Diskutieren von Filmen, Dokumentationen und visuellen Medien",
|
||||
"emoji": "🎬",
|
||||
"prompt": "Lass uns mit der Filmclub-Diskussion beginnen. Kannst du uns helfen, diesen Film zu analysieren und seine Themen zu erkunden?",
|
||||
"title": "Filmclub"
|
||||
},
|
||||
"musicSession": {
|
||||
"description": "Kooperative Musikproduktion, Teilen und Wertschätzung von Musik",
|
||||
"emoji": "🎵",
|
||||
"prompt": "Lass uns eine musikalische Jam-Session machen! Kannst du uns helfen, gemeinsam Musik zu kreieren und zu genießen?",
|
||||
"title": "Musik-Jam"
|
||||
},
|
||||
"studyGroup": {
|
||||
"description": "Kooperative Lernsitzungen, Diskussion von Konzepten und gemeinsames Lösen von Problemen",
|
||||
"emoji": "📚",
|
||||
"prompt": "Lass uns eine Lerngruppe bilden. Kannst du uns helfen, diese Konzepte zu verstehen und gemeinsam Probleme zu lösen?",
|
||||
"title": "Lerngruppe"
|
||||
}
|
||||
}
|
||||
},
|
||||
"groupMessage": "Willkommen im Gruppenchat! Kollaborieren Sie mit mehreren KI-Assistenten in einem gemeinsamen Gesprächsraum.",
|
||||
"groupTemplates": {
|
||||
"analysis": {
|
||||
"description": "Datengetriebene Erkenntnisse, tiefgehende Forschung und Analyse",
|
||||
"members": [
|
||||
{
|
||||
"avatar": "📊",
|
||||
"backgroundColor": "#E8F8F5",
|
||||
"plugins": ["steam"],
|
||||
"systemRole": "Du bist spezialisiert auf die Verarbeitung und Interpretation von Daten und deckst durch Diagramme und statistische Analysen Muster und Trends hinter den Daten auf.",
|
||||
"title": "Datenanalyst"
|
||||
},
|
||||
{
|
||||
"avatar": "🧑🔬",
|
||||
"backgroundColor": "#E8F5FF",
|
||||
"systemRole": "Du bist Forschungsexperte, zuständig für Informationssammlung und tiefgehende Untersuchungen, analysierst Probleme aus verschiedenen Perspektiven umfassend.",
|
||||
"title": "Forschungsexperte"
|
||||
},
|
||||
{
|
||||
"avatar": "📈",
|
||||
"backgroundColor": "#FFF7E8",
|
||||
"systemRole": "Du bist Statistikexperte, versiert in verschiedenen statistischen Methoden und Modellen, extrahierst wertvolle geschäftliche Erkenntnisse aus Daten.",
|
||||
"title": "Statistikexperte"
|
||||
},
|
||||
{
|
||||
"avatar": "🧮",
|
||||
"backgroundColor": "#F0F8FF",
|
||||
"systemRole": "Du bist quantitativer Analyst, spezialisiert auf quantitative Modellierung und Risikobewertung, löst komplexe Probleme mit mathematischen Methoden.",
|
||||
"title": "Quantitativer Analyst"
|
||||
}
|
||||
],
|
||||
"title": "Analyse-Team"
|
||||
},
|
||||
"brainstorm": {
|
||||
"description": "Kreatives Denken aus mehreren Blickwinkeln, unendliche Möglichkeiten entfesseln",
|
||||
"members": [
|
||||
{
|
||||
"avatar": "🧠",
|
||||
"backgroundColor": "#E8F5FF",
|
||||
"systemRole": "Du bist Kreativdirektor, meisterst die kreative Ausrichtung aus makroskopischer Sicht, verwandelst abstrakte Konzepte in konkrete, umsetzbare Ideen.",
|
||||
"title": "Kreativdirektor"
|
||||
},
|
||||
{
|
||||
"avatar": "🧑🔬",
|
||||
"backgroundColor": "#FFF7E8",
|
||||
"systemRole": "Du bist Innovationsspezialist, findest neuartige Lösungen und bahnbrechende Denkansätze, denkst außerhalb gewohnter Rahmen.",
|
||||
"title": "Innovationsspezialist"
|
||||
},
|
||||
{
|
||||
"avatar": "🎨",
|
||||
"backgroundColor": "#F6E8FF",
|
||||
"systemRole": "Du bist Design-Thinking-Experte, betrachtest Probleme aus Nutzererlebnis- und visueller Perspektive, legst Wert auf kreative Visualisierung.",
|
||||
"title": "Design-Thinking-Experte"
|
||||
}
|
||||
],
|
||||
"title": "Brainstorming-Gruppe"
|
||||
},
|
||||
"game": {
|
||||
"description": "Spiele verschiedene Mehrspieler-Textspiele wie Werwolf und Wer ist der Maulwurf",
|
||||
"members": [
|
||||
null,
|
||||
{
|
||||
"avatar": "🧑🔬",
|
||||
"backgroundColor": "#FFF7E8",
|
||||
"systemRole": "Du bist erfahren in der Teilnahme an verschiedenen Mehrspieler-Textspielen und kannst nach den Spielregeln spielen.",
|
||||
"title": "Spieler"
|
||||
},
|
||||
{
|
||||
"avatar": "🎨",
|
||||
"backgroundColor": "#F6E8FF",
|
||||
"systemRole": "Du bist erfahren in der Teilnahme an verschiedenen Mehrspieler-Textspielen und kannst nach den Spielregeln spielen.",
|
||||
"title": "Spieler"
|
||||
},
|
||||
{
|
||||
"avatar": "🧑🎨",
|
||||
"backgroundColor": "#F6E8FF",
|
||||
"systemRole": "Du bist erfahren in der Teilnahme an verschiedenen Mehrspieler-Textspielen und kannst nach den Spielregeln spielen.",
|
||||
"title": "Spieler"
|
||||
}
|
||||
],
|
||||
"title": "Spielhalle"
|
||||
},
|
||||
"planning": {
|
||||
"description": "Strategische Planung und Projektmanagement, Gesamtkoordination",
|
||||
"members": [
|
||||
{
|
||||
"avatar": "📋",
|
||||
"backgroundColor": "#E8F5FF",
|
||||
"systemRole": "Du bist verantwortlich für die Gesamtplanung, Fortschrittskontrolle und Ressourcenkoordination des Projekts, um eine termingerechte und qualitativ hochwertige Fertigstellung sicherzustellen.",
|
||||
"title": "Koch"
|
||||
},
|
||||
{
|
||||
"avatar": "🎯",
|
||||
"backgroundColor": "#FFF7E8",
|
||||
"systemRole": "Du bist verantwortlich für die Entwicklung langfristiger strategischer Pläne, Marktanalysen, Zielsetzungen und Umsetzungswege.",
|
||||
"title": "Einkaufsspezialist"
|
||||
},
|
||||
{
|
||||
"avatar": "🧑🎨",
|
||||
"backgroundColor": "#F0F8FF",
|
||||
"systemRole": "Du bist verantwortlich für die Erstellung detaillierter Ausführungspläne, Koordination der Ressourcen verschiedener Abteilungen und Sicherstellung der Umsetzbarkeit der Pläne.",
|
||||
"title": "Experte für Lebensmittelentwicklung"
|
||||
}
|
||||
],
|
||||
"title": "Lebensmittelentwicklungsteam"
|
||||
},
|
||||
"product": {
|
||||
"description": "Produktdesign und -entwicklung, hochwertige Produkte schaffen",
|
||||
"members": [
|
||||
{
|
||||
"avatar": "🎨",
|
||||
"backgroundColor": "#F6E8FF",
|
||||
"systemRole": "Du bist Designer, spezialisiert auf die Gestaltung verschiedener Produkttypen, entwirfst entsprechend den Produktanforderungen.",
|
||||
"title": "Designer"
|
||||
},
|
||||
{
|
||||
"avatar": "🧑",
|
||||
"backgroundColor": "#E8F5FF",
|
||||
"systemRole": "Du bist Produktmanager, verantwortlich für Planung, Design, Entwicklung und Wartung des Produkts, sicherst Qualität und Nutzererlebnis.",
|
||||
"title": "Produktmanager"
|
||||
},
|
||||
{
|
||||
"avatar": "🧑💻",
|
||||
"backgroundColor": "#E8F8F5",
|
||||
"systemRole": "Du bist erfahrener Full-Stack-Entwickler, entwickelst verschiedene Produkttypen, setzt Produktanforderungen um.",
|
||||
"title": "Full-Stack-Entwickler"
|
||||
}
|
||||
],
|
||||
"title": "Produktentwicklungsteam"
|
||||
},
|
||||
"writing": {
|
||||
"description": "Inhaltserstellung und Redaktion, hochwertige Texte gestalten",
|
||||
"members": [
|
||||
{
|
||||
"avatar": "✍️",
|
||||
"backgroundColor": "#F6E8FF",
|
||||
"systemRole": "Du bist erfahren im Verfassen von Inhalten verschiedener Stilrichtungen und kannst den Schreibstil je nach Szenario und Zielgruppe anpassen.",
|
||||
"title": "Content-Autor"
|
||||
},
|
||||
{
|
||||
"avatar": "🧑🎨",
|
||||
"backgroundColor": "#E8F8F5",
|
||||
"systemRole": "Du bist Redakteur, verantwortlich für Korrektur, Überarbeitung und Optimierung von Texten, sicherst Genauigkeit, Flüssigkeit und Professionalität.",
|
||||
"title": "Redakteur"
|
||||
}
|
||||
],
|
||||
"title": "Schreibteam"
|
||||
}
|
||||
},
|
||||
"questions": {
|
||||
"moreBtn": "Mehr erfahren",
|
||||
"title": "Häufig gestellte Fragen:"
|
||||
"title": "Versuchen Sie zu fragen:"
|
||||
},
|
||||
"welcome": {
|
||||
"afternoon": "Guten Nachmittag",
|
||||
|
||||
+111
-1
@@ -2,6 +2,7 @@
|
||||
"ModelSwitch": {
|
||||
"title": "Model"
|
||||
},
|
||||
"active": "Active",
|
||||
"agentDefaultMessage": "Hello, I am **{{name}}**. You can start a conversation with me right away, or you can go to [Assistant Settings]({{url}}) to complete my information.",
|
||||
"agentDefaultMessageWithSystemRole": "Hello, I am **{{name}}**. How can I assist you today?",
|
||||
"agentDefaultMessageWithoutEdit": "Hello, I am **{{name}}**. How can I assist you today?",
|
||||
@@ -13,17 +14,28 @@
|
||||
"thought": "Thought",
|
||||
"unknownTitle": "Untitled Work"
|
||||
},
|
||||
"availableAgents": "Available assistants",
|
||||
"backToBottom": "Back to bottom",
|
||||
"chatList": {
|
||||
"longMessageDetail": "View Details"
|
||||
},
|
||||
"clearCurrentMessages": "Clear current session messages",
|
||||
"confirmClearCurrentMessages": "You are about to clear the current session messages. Once cleared, they cannot be retrieved. Please confirm your action.",
|
||||
"confirmRemoveChatGroupItemAlert": "This Agent team will be deleted. Team members will not be affected. Please confirm your action.",
|
||||
"confirmRemoveGroupItemAlert": "You are about to delete this group. After deletion, its assistants will be moved to the default list. Please confirm your action.",
|
||||
"confirmRemoveGroupSuccess": "Agent team deleted successfully",
|
||||
"confirmRemoveSessionItemAlert": "You are about to delete this assistant. Once deleted, it cannot be retrieved. Please confirm your action.",
|
||||
"confirmRemoveSessionSuccess": "Assistant removed successfully",
|
||||
"defaultAgent": "Default Assistant",
|
||||
"defaultGroupChat": "Agent Team",
|
||||
"defaultList": "Default List",
|
||||
"defaultSession": "Default Assistant",
|
||||
"dm": {
|
||||
"placeholder": "Your private messages with {{agentTitle}} will appear here.",
|
||||
"tooltip": "Send a private message",
|
||||
"visibleTo": "Visible to {{target}} only",
|
||||
"you": "You"
|
||||
},
|
||||
"duplicateSession": {
|
||||
"loading": "Copying...",
|
||||
"success": "Copy successful",
|
||||
@@ -58,11 +70,56 @@
|
||||
"title": "Extract Webpage Link Content"
|
||||
}
|
||||
},
|
||||
"group": {
|
||||
"desc": "Collaborate with multiple AI assistants in a shared conversation space.",
|
||||
"memberTooltip": "There are {{count}} members in the group",
|
||||
"orchestratorThinking": "The host is thinking...",
|
||||
"removeMember": "Remove Member",
|
||||
"title": "Group"
|
||||
},
|
||||
"groupDescription": "Team Description",
|
||||
"groupSidebar": {
|
||||
"members": {
|
||||
"addMember": "Add Member",
|
||||
"memberSettings": "Member Settings",
|
||||
"orchestrator": "Host",
|
||||
"orchestratorThinking": "The host is thinking...",
|
||||
"removeMember": "Remove Member",
|
||||
"stopOrchestrator": "Stop Thinking",
|
||||
"triggerOrchestrator": "Start Group Chat"
|
||||
},
|
||||
"tabs": {
|
||||
"host": "Host",
|
||||
"members": "Members",
|
||||
"role": "Settings"
|
||||
}
|
||||
},
|
||||
"groupWizard": {
|
||||
"chooseMembers": "Select existing assistants...",
|
||||
"createGroup": "Create Team",
|
||||
"existingMembers": "Current Agents",
|
||||
"groupMembers": "These assistants will also be added to your list",
|
||||
"host": {
|
||||
"description": "Enable the team to operate independently",
|
||||
"title": "Enable Host",
|
||||
"tooltip": "If the team host is disabled, you'll need to manually @mention members to get their responses"
|
||||
},
|
||||
"memberCount": "{{count}} members",
|
||||
"noMatchingTemplates": "No matching templates",
|
||||
"noSelectedTemplates": "No templates selected",
|
||||
"noTemplateMembers": "No members in the template",
|
||||
"noTemplates": "No templates available",
|
||||
"searchTemplates": "Search templates...",
|
||||
"title": "Create Agent Team",
|
||||
"useTemplate": "Use Template"
|
||||
},
|
||||
"hideForYou": "Direct message content is hidden. Please enable 'Show Direct Message Content' in settings to view.",
|
||||
"history": {
|
||||
"title": "The assistant will only remember the last {{count}} messages."
|
||||
},
|
||||
"historyRange": "History Range",
|
||||
"historySummary": "Historical Message Summary",
|
||||
"inactive": "Inactive",
|
||||
"inbox": {
|
||||
"desc": "Activate the brain cluster and spark creative thinking. Your virtual assistant is here to communicate with you about everything.",
|
||||
"title": "Just Chat"
|
||||
@@ -83,6 +140,7 @@
|
||||
"intentUnderstanding": {
|
||||
"title": "Understanding and analyzing your intent..."
|
||||
},
|
||||
"inviteMembers": "Invite members",
|
||||
"knowledgeBase": {
|
||||
"all": "All Content",
|
||||
"allFiles": "All Files",
|
||||
@@ -101,12 +159,29 @@
|
||||
"uploadGuide": "Uploaded files can be viewed in the 'Knowledge Base'.",
|
||||
"viewMore": "View More"
|
||||
},
|
||||
"memberSelection": {
|
||||
"addMember": "Add Member",
|
||||
"allMembers": "All members",
|
||||
"createGroup": "Create Agent Team",
|
||||
"noAvailableAgents": "No assistants available to invite",
|
||||
"noSelectedAgents": "No assistants selected yet",
|
||||
"searchAgents": "Search assistants...",
|
||||
"setInitialMembers": "Select Team Members"
|
||||
},
|
||||
"members": "Members",
|
||||
"mention": {
|
||||
"title": "Mention Members"
|
||||
},
|
||||
"messageAction": {
|
||||
"delAndRegenerate": "Delete and Regenerate",
|
||||
"deleteDisabledByThreads": "There are subtopics, deletion is not allowed",
|
||||
"regenerate": "Regenerate"
|
||||
},
|
||||
"messages": {
|
||||
"dm": {
|
||||
"sentTo": "Visible only to {{name}}",
|
||||
"title": "Direct Message"
|
||||
},
|
||||
"modelCard": {
|
||||
"credit": "Credits",
|
||||
"creditPricing": "Pricing",
|
||||
@@ -153,9 +228,18 @@
|
||||
"minimap": {
|
||||
"jumpToMessage": "Jump to message {{index}}",
|
||||
"nextMessage": "Next message",
|
||||
"previousMessage": "Previous message"
|
||||
"previousMessage": "Previous message",
|
||||
"senderAssistant": "Assistant",
|
||||
"senderUser": "You"
|
||||
},
|
||||
"newAgent": "New Assistant",
|
||||
"newGroupChat": "New Agent Team",
|
||||
"noAgentsYet": "This Agent Team has no members yet. Click the + button to invite assistants.",
|
||||
"noAvailableAgents": "No members available to invite",
|
||||
"noMatchingAgents": "No matching members found",
|
||||
"noMembersYet": "This group doesn't have any members yet. Click the + button to invite assistants.",
|
||||
"noSelectedAgents": "No members selected yet",
|
||||
"owner": "Group Owner",
|
||||
"pin": "Pin",
|
||||
"pinOff": "Unpin",
|
||||
"rag": {
|
||||
@@ -196,12 +280,16 @@
|
||||
"title": "Online Search"
|
||||
},
|
||||
"searchAgentPlaceholder": "Search assistants...",
|
||||
"searchAgents": "Search assistants...",
|
||||
"selectedAgents": "Selected agents",
|
||||
"sendPlaceholder": "Type your message here...",
|
||||
"sessionGroup": {
|
||||
"config": "Group Management",
|
||||
"confirmRemoveGroupAlert": "This group is about to be deleted. After deletion, the assistants in this group will be moved to the default list. Please confirm your operation.",
|
||||
"createAgentSuccess": "Assistant created successfully",
|
||||
"createGroup": "Add New Group",
|
||||
"createGroupFailed": "Failed to create group chat",
|
||||
"createGroupSuccess": "Group chat created successfully",
|
||||
"createSuccess": "Created successfully",
|
||||
"creatingAgent": "Creating assistant...",
|
||||
"inputPlaceholder": "Please enter group name...",
|
||||
@@ -216,11 +304,24 @@
|
||||
"shareModal": {
|
||||
"copy": "Copy",
|
||||
"download": "Download Screenshot",
|
||||
"downloadError": "Download failed",
|
||||
"downloadFile": "Download File",
|
||||
"downloadPdf": "Download PDF",
|
||||
"downloadSuccess": "Download successful",
|
||||
"exportPdf": "Export as PDF",
|
||||
"exportTitle": "Default Title",
|
||||
"generatePdf": "Generate PDF",
|
||||
"generatingPdf": "Generating PDF...",
|
||||
"imageType": "Image Format",
|
||||
"includeTool": "Include Plugin Messages",
|
||||
"includeUser": "Include User Messages",
|
||||
"loadingPdf": "Loading PDF...",
|
||||
"noPdfData": "No PDF data available",
|
||||
"pdf": "PDF",
|
||||
"pdfErrorDescription": "An error occurred while generating the PDF, please try again",
|
||||
"pdfGenerationError": "PDF generation failed",
|
||||
"pdfReady": "PDF is ready",
|
||||
"regeneratePdf": "Regenerate PDF",
|
||||
"screenshot": "Screenshot",
|
||||
"settings": "Export Settings",
|
||||
"text": "Text",
|
||||
@@ -235,6 +336,12 @@
|
||||
"loading": "Recognizing...",
|
||||
"prettifying": "Polishing..."
|
||||
},
|
||||
"supervisor": {
|
||||
"todoList": {
|
||||
"allComplete": "All tasks completed",
|
||||
"title": "Tasks Completed"
|
||||
}
|
||||
},
|
||||
"thread": {
|
||||
"divider": "Subtopic",
|
||||
"threadMessageCount": "{{messageCount}} messages",
|
||||
@@ -248,6 +355,7 @@
|
||||
"chats": "Chat Messages",
|
||||
"historySummary": "History Summary",
|
||||
"rest": "Remaining",
|
||||
"supervisor": "Group Host",
|
||||
"systemRole": "Role Settings",
|
||||
"title": "Context Details",
|
||||
"tools": "Plugin Settings",
|
||||
@@ -273,6 +381,7 @@
|
||||
"action": "Text-to-Speech",
|
||||
"clear": "Clear Speech"
|
||||
},
|
||||
"untitledAgent": "Untitled Assistant",
|
||||
"updateAgent": "Update Assistant Information",
|
||||
"upload": {
|
||||
"action": {
|
||||
@@ -300,5 +409,6 @@
|
||||
"videoSizeExceeded": "Video file size must not exceed 20MB. Current file size is {{actualSize}}."
|
||||
}
|
||||
},
|
||||
"you": "you",
|
||||
"zenMode": "Zen Mode"
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
"batchDelete": "Batch Delete",
|
||||
"blog": "Product Blog",
|
||||
"branching": "Create Subtopic",
|
||||
"branchingDisable": "The 'Subtopic' feature is only available in the server version. If you need this feature, please switch to server deployment mode or use LobeChat Cloud.",
|
||||
"branchingDisable": "The \"Sub-topic\" feature is unavailable in the current mode. To use this feature, please switch to Postgres/Pglite DB mode or use LobeHub Cloud.",
|
||||
"branchingRequiresSavedTopic": "Current topic is not saved, please save it first to use subtopic feature",
|
||||
"cancel": "Cancel",
|
||||
"changelog": "Changelog",
|
||||
@@ -338,6 +338,7 @@
|
||||
"chat": "Chat",
|
||||
"discover": "Discover",
|
||||
"files": "Files",
|
||||
"knowledgeBase": "Knowledge Base",
|
||||
"me": "Me",
|
||||
"setting": "Settings"
|
||||
},
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user