mirror of
https://github.com/lobehub/lobe-chat.git
synced 2026-06-14 03:30:19 +00:00
Compare commits
93 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0cbe27e13c | |||
| c37a39d9b8 | |||
| efd661483a | |||
| 59e5781a97 | |||
| b60a6fe340 | |||
| a0c4baf1aa | |||
| 1e20edef3d | |||
| 949873adbc | |||
| 5030177f3d | |||
| 38e1adba2f | |||
| f91acfca95 | |||
| 1f1c49fc52 | |||
| 8db783b5b8 | |||
| b3e87f6cd4 | |||
| abbf53feda | |||
| 3f432a43d8 | |||
| 8b0d1ec9e3 | |||
| b43cbae2e1 | |||
| d2a042cd95 | |||
| c1916a1996 | |||
| 502d94bd4c | |||
| f4bd332d11 | |||
| 7df81ffaa1 | |||
| ed076b3cf5 | |||
| 0abde1623d | |||
| 481e5c0066 | |||
| 8719354282 | |||
| 5957bd4578 | |||
| 335e246ac5 | |||
| 918d048b3d | |||
| 398d8b7f3c | |||
| 1529f31dff | |||
| b4bd5b288c | |||
| 448cfb2cfd | |||
| d8c3ef3232 | |||
| 2a23fb9a10 | |||
| 82f9cb4486 | |||
| 6419fd32b1 | |||
| 927fe3fd22 | |||
| 03bda41c07 | |||
| e804773a7e | |||
| 67875bd60a | |||
| 916d4841f4 | |||
| d5b1ff20e0 | |||
| 212348eafe | |||
| 43820eeb2e | |||
| 7397d6f8c1 | |||
| 85d5bc9e08 | |||
| 3fbc46b23a | |||
| 6e2ef05270 | |||
| 06d65e9ce5 | |||
| 6002863c17 | |||
| 8f2e72d1b8 | |||
| fcf2444fa8 | |||
| 661f1a80b4 | |||
| 57772d1f3b | |||
| abe4c969a5 | |||
| b767a66d38 | |||
| 53e4228ea7 | |||
| 7efcdd2f7c | |||
| bde1503309 | |||
| 487713361a | |||
| 7bad876259 | |||
| 229200853a | |||
| 5ec89941f3 | |||
| f46916a74d | |||
| 2ee46b8693 | |||
| baf0b56f64 | |||
| 12dc7f90be | |||
| 1b905ede31 | |||
| cfaa911153 | |||
| e17bf4b0cc | |||
| 58cf27dcf8 | |||
| f12d9fbd22 | |||
| d4f72eb752 | |||
| e112cd6f7f | |||
| 9a9147ca7e | |||
| 2d1eec4482 | |||
| c11d6de7db | |||
| bbbe3a8d09 | |||
| e51fbba881 | |||
| 1bfeeea6f4 | |||
| 12d0ec21d0 | |||
| 2bf0a08919 | |||
| 79e146f1a3 | |||
| 0e42ca5ca2 | |||
| 823aa29c67 | |||
| d225da96df | |||
| 0acaf01f9a | |||
| 5a8911b72d | |||
| e6596e94a5 | |||
| 9c09160154 | |||
| d7d186df1a |
@@ -38,13 +38,3 @@ ALTER TABLE "users" ADD COLUMN "avatar" text;
|
||||
DROP TABLE "old_table";
|
||||
CREATE INDEX "users_email_idx" ON "users" ("email");
|
||||
```
|
||||
|
||||
## Important
|
||||
|
||||
After modifying migration SQL (e.g., adding `IF NOT EXISTS` clauses), run:
|
||||
|
||||
```bash
|
||||
bun run db:generate:client
|
||||
```
|
||||
|
||||
This updates the hash in `packages/database/src/core/migrations.json`.
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
const config = require('@lobehub/lint').eslint;
|
||||
|
||||
config.root = true;
|
||||
config.extends.push('plugin:@next/next/recommended-legacy');
|
||||
|
||||
config.rules['unicorn/no-negated-condition'] = 0;
|
||||
config.rules['unicorn/prefer-type-error'] = 0;
|
||||
config.rules['unicorn/prefer-logical-operator-over-ternary'] = 0;
|
||||
config.rules['unicorn/no-null'] = 0;
|
||||
config.rules['unicorn/no-typeof-undefined'] = 0;
|
||||
config.rules['unicorn/explicit-length-check'] = 0;
|
||||
config.rules['unicorn/prefer-code-point'] = 0;
|
||||
config.rules['no-extra-boolean-cast'] = 0;
|
||||
config.rules['unicorn/no-useless-undefined'] = 0;
|
||||
config.rules['react/no-unknown-property'] = 0;
|
||||
config.rules['unicorn/prefer-ternary'] = 0;
|
||||
config.rules['unicorn/prefer-spread'] = 0;
|
||||
config.rules['unicorn/catch-error-name'] = 0;
|
||||
config.rules['unicorn/no-array-for-each'] = 0;
|
||||
config.rules['unicorn/prefer-number-properties'] = 0;
|
||||
config.rules['unicorn/prefer-query-selector'] = 0;
|
||||
config.rules['unicorn/no-array-callback-reference'] = 0;
|
||||
config.rules['unicorn/text-encoding-identifier-case'] = 0;
|
||||
config.rules['@typescript-eslint/no-use-before-define'] = 0;
|
||||
// FIXME: Linting error in src/app/[variants]/(main)/chat/features/Migration/DBReader.ts, the fundamental solution should be upgrading typescript-eslint
|
||||
config.rules['@typescript-eslint/no-useless-constructor'] = 0;
|
||||
config.rules['@next/next/no-img-element'] = 0;
|
||||
|
||||
config.overrides = [
|
||||
{
|
||||
extends: ['plugin:mdx/recommended'],
|
||||
files: ['*.mdx'],
|
||||
rules: {
|
||||
'@typescript-eslint/no-unused-vars': 1,
|
||||
'micromark-extension-mdx-jsx': 0,
|
||||
'no-undef': 0,
|
||||
'react/jsx-no-undef': 0,
|
||||
'react/no-unescaped-entities': 0,
|
||||
},
|
||||
settings: {
|
||||
'mdx/code-blocks': false,
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['src/store/image/**/*', 'src/types/generation/**/*'],
|
||||
rules: {
|
||||
'@typescript-eslint/no-empty-interface': 0,
|
||||
'sort-keys-fix/sort-keys-fix': 0,
|
||||
'typescript-sort-keys/interface': 0,
|
||||
'typescript-sort-keys/string-enum': 0,
|
||||
},
|
||||
},
|
||||
// CLI scripts legitimately use process.exit() and async IIFE patterns
|
||||
{
|
||||
files: ['scripts/**/*'],
|
||||
rules: {
|
||||
'unicorn/no-process-exit': 0,
|
||||
'unicorn/prefer-top-level-await': 0,
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
module.exports = config;
|
||||
@@ -2,8 +2,7 @@
|
||||
* Generate PR comment with download links for desktop builds
|
||||
* and handle comment creation/update logic
|
||||
*/
|
||||
module.exports = async ({ github, context, releaseUrl, version, tag }) => {
|
||||
// 用于识别构建评论的标识符
|
||||
const prComment = async ({ github, context, releaseUrl, artifactsUrl, version, tag }) => {
|
||||
const COMMENT_IDENTIFIER = '<!-- DESKTOP-BUILD-COMMENT -->';
|
||||
|
||||
/**
|
||||
@@ -69,7 +68,7 @@ module.exports = async ({ github, context, releaseUrl, version, tag }) => {
|
||||
**Version**: \`${version}\`
|
||||
**Build Time**: \`${new Date().toISOString()}\`
|
||||
|
||||
📦 [View All Build Artifacts](${releaseUrl})
|
||||
📦 [Release Download](${releaseUrl}) · 📥 [Actions Artifacts](${artifactsUrl || `https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`})
|
||||
|
||||
|
||||
## Build Artifacts
|
||||
@@ -88,7 +87,7 @@ ${assetTable}
|
||||
**Version**: \`${version}\`
|
||||
**Build Time**: \`${new Date().toISOString()}\`
|
||||
|
||||
## 📦 [View All Build Artifacts](${releaseUrl})
|
||||
📦 [Release Download](${releaseUrl}) · 📥 [Actions Artifacts](${artifactsUrl || `https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`})
|
||||
|
||||
> Note: This is a temporary build for testing purposes only.
|
||||
`;
|
||||
@@ -96,45 +95,41 @@ ${assetTable}
|
||||
};
|
||||
|
||||
/**
|
||||
* 查找并更新或创建PR评论
|
||||
* Find and update or create the PR comment
|
||||
*/
|
||||
const updateOrCreateComment = async () => {
|
||||
// 生成评论内容
|
||||
const body = await generateCommentBody();
|
||||
|
||||
// 查找我们之前可能创建的评论
|
||||
const { data: comments } = await github.rest.issues.listComments({
|
||||
issue_number: context.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
});
|
||||
|
||||
// 查找包含我们标识符的评论
|
||||
const buildComment = comments.find((comment) => comment.body.includes(COMMENT_IDENTIFIER));
|
||||
|
||||
if (buildComment) {
|
||||
// 如果找到现有评论,则更新它
|
||||
await github.rest.issues.updateComment({
|
||||
comment_id: buildComment.id,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: body,
|
||||
});
|
||||
console.log(`已更新现有评论 ID: ${buildComment.id}`);
|
||||
console.log(`Updated existing comment ID: ${buildComment.id}`);
|
||||
return { updated: true, id: buildComment.id };
|
||||
} else {
|
||||
// 如果没有找到现有评论,则创建新评论
|
||||
const result = await github.rest.issues.createComment({
|
||||
issue_number: context.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: body,
|
||||
});
|
||||
console.log(`已创建新评论 ID: ${result.data.id}`);
|
||||
console.log(`Created new comment ID: ${result.data.id}`);
|
||||
return { updated: false, id: result.data.id };
|
||||
}
|
||||
};
|
||||
|
||||
// 执行评论更新或创建
|
||||
return await updateOrCreateComment();
|
||||
};
|
||||
|
||||
module.exports = prComment;
|
||||
|
||||
@@ -0,0 +1,219 @@
|
||||
name: Auto Tag Release
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [closed]
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
auto-tag:
|
||||
name: Auto Tag Release
|
||||
runs-on: ubuntu-latest
|
||||
# Only trigger when PR is merged
|
||||
if: github.event.pull_request.merged == true
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
token: ${{ secrets.GH_TOKEN }}
|
||||
# Fetch full history for proper tagging
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Detect release PR (version from title)
|
||||
id: release
|
||||
run: |
|
||||
PR_TITLE="${{ github.event.pull_request.title }}"
|
||||
echo "PR Title: $PR_TITLE"
|
||||
|
||||
# Match "🚀 release: v{x.x.x}" format (strict semver: x.y.z with optional -prerelease or +build)
|
||||
if [[ "$PR_TITLE" =~ ^🚀[[:space:]]+release:[[:space:]]*v([0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.-]+)?(\+[a-zA-Z0-9.-]+)?)$ ]]; then
|
||||
VERSION="${BASH_REMATCH[1]}"
|
||||
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
||||
echo "should_tag=true" >> $GITHUB_OUTPUT
|
||||
echo "✅ Detected release PR, version: v$VERSION"
|
||||
else
|
||||
echo "should_tag=false" >> $GITHUB_OUTPUT
|
||||
echo "⏭️ Not a release PR"
|
||||
fi
|
||||
|
||||
- name: Detect hotfix PR (branch first, title fallback)
|
||||
id: hotfix
|
||||
if: steps.release.outputs.should_tag != 'true'
|
||||
run: |
|
||||
HEAD_REF="${{ github.event.pull_request.head.ref }}"
|
||||
PR_TITLE="${{ github.event.pull_request.title }}"
|
||||
echo "Head ref: $HEAD_REF"
|
||||
echo "PR Title: $PR_TITLE"
|
||||
|
||||
# Priority 1: hotfix/* branch always counts as hotfix, ignore PR title gate.
|
||||
if [[ "$HEAD_REF" == hotfix/* ]]; then
|
||||
echo "should_tag=true" >> $GITHUB_OUTPUT
|
||||
echo "✅ Detected hotfix PR from hotfix/* branch (title gate bypassed)"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Priority 2: fallback to PR title prefix gate (legacy behavior).
|
||||
if echo "$PR_TITLE" | grep -qiE '^(💄[[:space:]]*)?style(\(.+\))?:|^(✨[[:space:]]*)?feat(\(.+\))?:|^(🐛[[:space:]]*)?fix(\(.+\))?:|^(♻️[[:space:]]*)?refactor(\(.+\))?:|^((🐛|🩹)[[:space:]]*)?hotfix(\(.+\))?:'; then
|
||||
echo "should_tag=true" >> $GITHUB_OUTPUT
|
||||
echo "✅ Detected hotfix PR from title prefix gate"
|
||||
else
|
||||
echo "should_tag=false" >> $GITHUB_OUTPUT
|
||||
echo "⏭️ Not a hotfix PR (neither hotfix/* branch nor style/feat/fix/refactor/hotfix title prefix)"
|
||||
fi
|
||||
|
||||
- name: Prepare main branch
|
||||
if: steps.release.outputs.should_tag == 'true' || steps.hotfix.outputs.should_tag == 'true'
|
||||
run: |
|
||||
git checkout main
|
||||
git pull --rebase origin main
|
||||
|
||||
- name: Resolve hotfix version (patch bump)
|
||||
id: hotfix-version
|
||||
if: steps.hotfix.outputs.should_tag == 'true'
|
||||
run: |
|
||||
CURRENT_VERSION="$(node -p "require('./package.json').version")"
|
||||
echo "Current version: ${CURRENT_VERSION}"
|
||||
|
||||
# Coerce to stable base (e.g. 2.0.0-beta.1 -> 2.0.0), then bump patch (-> 2.0.1)
|
||||
BASE_VERSION="$(npx -y semver@7 "${CURRENT_VERSION}" -c)"
|
||||
if [ -z "${BASE_VERSION}" ]; then
|
||||
echo "❌ Invalid version in package.json: ${CURRENT_VERSION}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
NEXT_VERSION="$(npx -y semver@7 -i patch "${BASE_VERSION}")"
|
||||
echo "📦 Hotfix version: ${NEXT_VERSION}"
|
||||
echo "version=${NEXT_VERSION}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Set context (release)
|
||||
if: steps.release.outputs.should_tag == 'true'
|
||||
run: |
|
||||
echo "SHOULD_TAG=true" >> $GITHUB_ENV
|
||||
echo "KIND=release" >> $GITHUB_ENV
|
||||
echo "VERSION=${{ steps.release.outputs.version }}" >> $GITHUB_ENV
|
||||
|
||||
- name: Set context (hotfix)
|
||||
if: steps.hotfix.outputs.should_tag == 'true'
|
||||
run: |
|
||||
echo "SHOULD_TAG=true" >> $GITHUB_ENV
|
||||
echo "KIND=hotfix" >> $GITHUB_ENV
|
||||
echo "VERSION=${{ steps.hotfix-version.outputs.version }}" >> $GITHUB_ENV
|
||||
|
||||
- name: Check if tag already exists
|
||||
if: env.SHOULD_TAG == 'true'
|
||||
id: check-tag
|
||||
run: |
|
||||
VERSION="${{ env.VERSION }}"
|
||||
if git rev-parse "v$VERSION" >/dev/null 2>&1; then
|
||||
echo "exists=true" >> $GITHUB_OUTPUT
|
||||
echo "⚠️ Tag v$VERSION already exists"
|
||||
else
|
||||
echo "exists=false" >> $GITHUB_OUTPUT
|
||||
echo "✅ Tag v$VERSION does not exist, can create"
|
||||
fi
|
||||
|
||||
- name: Bump package.json version (before tagging)
|
||||
if: env.SHOULD_TAG == 'true' && steps.check-tag.outputs.exists == 'false'
|
||||
id: bump-version
|
||||
run: |
|
||||
VERSION="${{ env.VERSION }}"
|
||||
KIND="${{ env.KIND }}"
|
||||
echo "📝 Bumping package.json version to: $VERSION"
|
||||
|
||||
# Validate VERSION is strict semver before writing
|
||||
if ! npx -y semver@7 "$VERSION" >/dev/null 2>&1; then
|
||||
echo "❌ Invalid semver version: $VERSION"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Configure git
|
||||
git config --global user.name "lobehubbot"
|
||||
git config --global user.email "i@lobehub.com"
|
||||
|
||||
# Update package.json using Node.js
|
||||
node -e "
|
||||
const fs = require('fs');
|
||||
const pkg = JSON.parse(fs.readFileSync('./package.json', 'utf8'));
|
||||
const target = '$VERSION';
|
||||
if (pkg.version === target) {
|
||||
console.log('✅ package.json already at version', target);
|
||||
process.exit(0);
|
||||
}
|
||||
pkg.version = target;
|
||||
fs.writeFileSync('./package.json', JSON.stringify(pkg, null, 2) + '\n');
|
||||
console.log('✅ package.json updated to', target);
|
||||
"
|
||||
|
||||
# Commit changes (if any) and push
|
||||
git add package.json
|
||||
if [ "$KIND" == "hotfix" ]; then
|
||||
COMMIT_MSG="🐛 chore(hotfix): bump version to v$VERSION [skip ci]"
|
||||
else
|
||||
COMMIT_MSG="🔧 chore(release): bump version to v$VERSION [skip ci]"
|
||||
fi
|
||||
git commit -m "$COMMIT_MSG" || echo "Nothing to commit"
|
||||
git push origin HEAD:main
|
||||
|
||||
# Output the SHA we will tag
|
||||
echo "tag_sha=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Create Tag
|
||||
if: env.SHOULD_TAG == 'true' && steps.check-tag.outputs.exists == 'false'
|
||||
run: |
|
||||
VERSION="${{ env.VERSION }}"
|
||||
KIND="${{ env.KIND }}"
|
||||
echo "🏷️ Creating tag: v$VERSION"
|
||||
|
||||
# Tag the bumped version commit SHA (not the PR merge commit SHA)
|
||||
TAG_SHA="${{ steps.bump-version.outputs.tag_sha }}"
|
||||
|
||||
if [ "$KIND" == "hotfix" ]; then
|
||||
PREFIX="🐛 hotfix"
|
||||
else
|
||||
PREFIX="🚀 release"
|
||||
fi
|
||||
|
||||
# Create annotated tag with single line message
|
||||
git tag -a "v$VERSION" "$TAG_SHA" -m "$PREFIX: v$VERSION | PR #${{ github.event.pull_request.number }} | Author: ${{ github.event.pull_request.user.login }}"
|
||||
|
||||
# Push tag
|
||||
git push origin "v$VERSION"
|
||||
|
||||
echo "✅ Tag v$VERSION created successfully!"
|
||||
|
||||
- name: Create GitHub Release
|
||||
if: env.SHOULD_TAG == 'true' && steps.check-tag.outputs.exists == 'false'
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
tag_name: v${{ env.VERSION }}
|
||||
name: 🚀 Release v${{ env.VERSION }}
|
||||
body: |
|
||||
## 📦 Release v${{ env.VERSION }}
|
||||
|
||||
This release was automatically published from PR #${{ github.event.pull_request.number }}.
|
||||
|
||||
### Changes
|
||||
See PR description: ${{ github.event.pull_request.html_url }}
|
||||
|
||||
### Commit Message
|
||||
${{ github.event.pull_request.body }}
|
||||
draft: false
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
|
||||
|
||||
- name: Output result
|
||||
run: |
|
||||
if [ "${{ env.SHOULD_TAG }}" == "true" ]; then
|
||||
if [ "${{ steps.check-tag.outputs.exists }}" == "true" ]; then
|
||||
echo "⚠️ Result: Tag v${{ env.VERSION }} already exists, skipping creation"
|
||||
else
|
||||
echo "✅ Result: Tag v${{ env.VERSION }} created successfully!"
|
||||
fi
|
||||
else
|
||||
echo "ℹ️ Result: Not a release/hotfix PR, no tag created"
|
||||
fi
|
||||
@@ -39,7 +39,10 @@ jobs:
|
||||
|
||||
e2e:
|
||||
needs: check-duplicate-run
|
||||
if: needs.check-duplicate-run.outputs.should_skip != 'true'
|
||||
if: >-
|
||||
github.ref == 'refs/heads/main' ||
|
||||
github.ref == 'refs/heads/canary' ||
|
||||
needs.check-duplicate-run.outputs.should_skip != 'true'
|
||||
name: Test Web App
|
||||
runs-on: ubuntu-latest
|
||||
services:
|
||||
+4
-2
@@ -340,21 +340,23 @@ jobs:
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
# 在 PR 上添加评论,包含构建信息和下载链接
|
||||
# Post comment on PR with build info, release download link, and Actions artifacts link
|
||||
- name: Comment on PR
|
||||
uses: actions/github-script@v8
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
const releaseUrl = "${{ steps.create_release.outputs.url }}";
|
||||
const artifactsUrl = "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}";
|
||||
const prCommentGenerator = require('${{ github.workspace }}/.github/scripts/pr-comment.js');
|
||||
|
||||
const result = await prCommentGenerator({
|
||||
github,
|
||||
context,
|
||||
releaseUrl,
|
||||
artifactsUrl,
|
||||
version: "${{ needs.version.outputs.version }}",
|
||||
tag: "v${{ needs.version.outputs.version }}"
|
||||
});
|
||||
|
||||
console.log(`评论状态: ${result.updated ? '已更新' : '已创建'}, ID: ${result.id}`);
|
||||
console.log(`Comment ${result.updated ? 'updated' : 'created'}, ID: ${result.id}`);
|
||||
@@ -0,0 +1,399 @@
|
||||
name: Release Desktop Canary
|
||||
|
||||
# ============================================
|
||||
# Canary 自动发版工作流
|
||||
# ============================================
|
||||
# 触发条件:
|
||||
# 1. canary 分支有 push (合入 PR) 且 commit 前缀为 style/feat/fix/refactor/release (支持 gitmoji)
|
||||
# 2. 手动触发 (workflow_dispatch)
|
||||
#
|
||||
# 并发策略:
|
||||
# 同一 workflow 仅保留最新一次运行,自动取消排队中的旧 build
|
||||
#
|
||||
# 版本策略:
|
||||
# 基于最新 stable tag 的 patch+1, postfix 为递增序号
|
||||
# 格式: X.Y.(Z+1)-canary.N
|
||||
# 例: 当前 tag v2.1.28 → v2.1.29-canary.1, 下次 → v2.1.29-canary.2
|
||||
# ============================================
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- canary
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
force:
|
||||
description: 'Force build (skip commit message check)'
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}
|
||||
cancel-in-progress: true
|
||||
|
||||
permissions: read-all
|
||||
|
||||
env:
|
||||
NODE_VERSION: '24.11.1'
|
||||
|
||||
jobs:
|
||||
# ============================================
|
||||
# 检查 commit 前缀并计算版本号
|
||||
# ============================================
|
||||
calculate-version:
|
||||
name: Calculate Canary Version
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
version: ${{ steps.version.outputs.version }}
|
||||
tag: ${{ steps.version.outputs.tag }}
|
||||
should_build: ${{ steps.check.outputs.should_build }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
fetch-tags: true
|
||||
|
||||
- name: Check commit message prefix
|
||||
id: check
|
||||
run: |
|
||||
# 手动触发 + force 时跳过检查
|
||||
if [ "${{ inputs.force }}" == "true" ]; then
|
||||
echo "should_build=true" >> $GITHUB_OUTPUT
|
||||
echo "🔧 Force build requested, skipping commit check"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# 手动触发 (无 force) 也直接构建
|
||||
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
|
||||
echo "should_build=true" >> $GITHUB_OUTPUT
|
||||
echo "🔧 Manual trigger, proceeding with build"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# 获取本次 push 的 head commit message
|
||||
commit_msg=$(git log -1 --pretty=%s HEAD)
|
||||
echo "📝 Head commit: $commit_msg"
|
||||
|
||||
# 检查是否匹配 style/feat/fix/refactor/release 前缀 (支持 gitmoji 前缀)
|
||||
if echo "$commit_msg" | grep -qiE '^(💄\s*)?style(\(.+\))?:|^(✨\s*)?feat(\(.+\))?:|^(🐛\s*)?fix(\(.+\))?:|^(♻️\s*)?refactor(\(.+\))?:|^(🚀\s*)?release(\(.+\))?:'; then
|
||||
echo "should_build=true" >> $GITHUB_OUTPUT
|
||||
echo "✅ Commit matches canary build trigger: $commit_msg"
|
||||
else
|
||||
echo "should_build=false" >> $GITHUB_OUTPUT
|
||||
echo "⏭️ Commit does not match style/feat/fix/refactor/release prefix, skipping: $commit_msg"
|
||||
fi
|
||||
|
||||
- name: Calculate canary version
|
||||
if: steps.check.outputs.should_build == 'true'
|
||||
id: version
|
||||
run: |
|
||||
# 获取最新的 stable tag (排除 nightly/canary/beta 等)
|
||||
latest_tag=$(git tag --sort=-v:refname | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | head -n 1)
|
||||
|
||||
if [ -z "$latest_tag" ]; then
|
||||
echo "❌ No stable tag found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "📌 Latest stable tag: $latest_tag"
|
||||
|
||||
# 去掉 v 前缀,解析 major.minor.patch → a.b.c 取 c+1
|
||||
base_version="${latest_tag#v}"
|
||||
IFS='.' read -r major minor patch <<< "$base_version"
|
||||
new_patch=$((patch + 1))
|
||||
base_canary="${major}.${minor}.${new_patch}"
|
||||
|
||||
# postfix: 同 base 下已有 canary 标签的最大序号 + 1
|
||||
max_seq=0
|
||||
for t in $(git tag -l "v${base_canary}-canary.*" 2>/dev/null || true); do
|
||||
seq=$(echo "$t" | grep -oE '[0-9]+$' || true)
|
||||
if [ -n "$seq" ] && [ "$seq" -gt "$max_seq" ] 2>/dev/null; then
|
||||
max_seq=$seq
|
||||
fi
|
||||
done
|
||||
next_seq=$((max_seq + 1))
|
||||
|
||||
version="${base_canary}-canary.${next_seq}"
|
||||
tag="v${version}"
|
||||
|
||||
echo "version=${version}" >> $GITHUB_OUTPUT
|
||||
echo "tag=${tag}" >> $GITHUB_OUTPUT
|
||||
echo "✅ Canary version: ${version}"
|
||||
echo "🏷️ Tag: ${tag}"
|
||||
|
||||
# ============================================
|
||||
# 代码质量检查
|
||||
# ============================================
|
||||
test:
|
||||
name: Code quality check
|
||||
needs: [calculate-version]
|
||||
if: needs.calculate-version.outputs.should_build == 'true'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout base
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
package-manager-cache: false
|
||||
|
||||
- name: Install bun
|
||||
uses: oven-sh/setup-bun@v2
|
||||
with:
|
||||
bun-version: latest
|
||||
|
||||
- name: Install deps
|
||||
run: bun i
|
||||
|
||||
- name: Lint
|
||||
run: bun run lint
|
||||
|
||||
# ============================================
|
||||
# 多平台构建
|
||||
# ============================================
|
||||
build:
|
||||
needs: [calculate-version, test]
|
||||
if: needs.calculate-version.outputs.should_build == 'true'
|
||||
name: Build Desktop App
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [macos-15, macos-15-intel, windows-2025, ubuntu-latest]
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup build environment
|
||||
uses: ./.github/actions/desktop-build-setup
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
|
||||
- name: Set package version
|
||||
run: npm run workflow:set-desktop-version ${{ needs.calculate-version.outputs.version }} canary
|
||||
|
||||
# macOS 构建前清理 (修复 hdiutil 问题)
|
||||
- name: Clean previous build artifacts (macOS)
|
||||
if: runner.os == 'macOS'
|
||||
run: |
|
||||
sudo rm -rf apps/desktop/release || true
|
||||
sudo rm -rf apps/desktop/dist || true
|
||||
sudo rm -rf /tmp/electron-builder* || true
|
||||
|
||||
# macOS 构建
|
||||
- name: Build artifact on macOS
|
||||
if: runner.os == 'macOS'
|
||||
run: npm run desktop:package:app
|
||||
env:
|
||||
UPDATE_CHANNEL: canary
|
||||
APP_URL: http://localhost:3015
|
||||
DATABASE_URL: 'postgresql://postgres@localhost:5432/postgres'
|
||||
KEY_VAULTS_SECRET: 'oLXWIiR/AKF+rWaqy9lHkrYgzpATbW3CtJp3UfkVgpE='
|
||||
CSC_LINK: ${{ secrets.APPLE_CERTIFICATE_BASE64 }}
|
||||
CSC_KEY_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
|
||||
CSC_FOR_PULL_REQUEST: true
|
||||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
||||
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }}
|
||||
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
||||
NEXT_PUBLIC_DESKTOP_PROJECT_ID: ${{ secrets.UMAMI_BETA_DESKTOP_PROJECT_ID }}
|
||||
NEXT_PUBLIC_DESKTOP_UMAMI_BASE_URL: ${{ secrets.UMAMI_BETA_DESKTOP_BASE_URL }}
|
||||
|
||||
# Windows 构建
|
||||
- name: Build artifact on Windows
|
||||
if: runner.os == 'Windows'
|
||||
run: npm run desktop:package:app
|
||||
env:
|
||||
UPDATE_CHANNEL: canary
|
||||
APP_URL: http://localhost:3015
|
||||
DATABASE_URL: 'postgresql://postgres@localhost:5432/postgres'
|
||||
KEY_VAULTS_SECRET: 'oLXWIiR/AKF+rWaqy9lHkrYgzpATbW3CtJp3UfkVgpE='
|
||||
NEXT_PUBLIC_DESKTOP_PROJECT_ID: ${{ secrets.UMAMI_BETA_DESKTOP_PROJECT_ID }}
|
||||
NEXT_PUBLIC_DESKTOP_UMAMI_BASE_URL: ${{ secrets.UMAMI_BETA_DESKTOP_BASE_URL }}
|
||||
TEMP: C:\temp
|
||||
TMP: C:\temp
|
||||
|
||||
# Linux 构建
|
||||
- name: Build artifact on Linux
|
||||
if: runner.os == 'Linux'
|
||||
run: npm run desktop:package:app
|
||||
env:
|
||||
UPDATE_CHANNEL: canary
|
||||
APP_URL: http://localhost:3015
|
||||
DATABASE_URL: 'postgresql://postgres@localhost:5432/postgres'
|
||||
KEY_VAULTS_SECRET: 'oLXWIiR/AKF+rWaqy9lHkrYgzpATbW3CtJp3UfkVgpE='
|
||||
NEXT_PUBLIC_DESKTOP_PROJECT_ID: ${{ secrets.UMAMI_BETA_DESKTOP_PROJECT_ID }}
|
||||
NEXT_PUBLIC_DESKTOP_UMAMI_BASE_URL: ${{ secrets.UMAMI_BETA_DESKTOP_BASE_URL }}
|
||||
|
||||
- name: Upload artifacts
|
||||
uses: ./.github/actions/desktop-upload-artifacts
|
||||
with:
|
||||
artifact-name: release-${{ matrix.os }}
|
||||
retention-days: 3
|
||||
|
||||
# ============================================
|
||||
# 合并 macOS 多架构 latest-mac.yml 文件
|
||||
# ============================================
|
||||
merge-mac-files:
|
||||
needs: [build]
|
||||
name: Merge macOS Release Files
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
package-manager-cache: false
|
||||
|
||||
- name: Install bun
|
||||
uses: oven-sh/setup-bun@v2
|
||||
with:
|
||||
bun-version: latest
|
||||
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v7
|
||||
with:
|
||||
path: release
|
||||
pattern: release-*
|
||||
merge-multiple: true
|
||||
|
||||
- name: List downloaded artifacts
|
||||
run: ls -R release
|
||||
|
||||
- name: Install yaml only for merge step
|
||||
run: |
|
||||
cd scripts/electronWorkflow
|
||||
if [ ! -f package.json ]; then
|
||||
echo '{"name":"merge-mac-release","private":true}' > package.json
|
||||
fi
|
||||
bun add --no-save yaml@2.8.1
|
||||
|
||||
- name: Merge latest-mac.yml files
|
||||
run: bun run scripts/electronWorkflow/mergeMacReleaseFiles.js
|
||||
|
||||
- name: Upload artifacts with merged macOS files
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: merged-release
|
||||
path: release/
|
||||
retention-days: 1
|
||||
|
||||
# ============================================
|
||||
# 创建 Canary Release
|
||||
# ============================================
|
||||
publish-release:
|
||||
needs: [merge-mac-files, calculate-version]
|
||||
name: Publish Canary Release
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- name: Download merged artifacts
|
||||
uses: actions/download-artifact@v7
|
||||
with:
|
||||
name: merged-release
|
||||
path: release
|
||||
|
||||
- name: List final artifacts
|
||||
run: ls -R release
|
||||
|
||||
- name: Create Canary Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
tag_name: ${{ needs.calculate-version.outputs.tag }}
|
||||
name: 'Desktop Canary ${{ needs.calculate-version.outputs.tag }}'
|
||||
prerelease: true
|
||||
body: |
|
||||
## 🐤 Canary Build — ${{ needs.calculate-version.outputs.tag }}
|
||||
|
||||
> Automated canary build from `canary` branch.
|
||||
|
||||
### ⚠️ Important Notes
|
||||
|
||||
- **This is an automated canary build and is NOT intended for production use.**
|
||||
- Canary builds are triggered by `build`/`fix`/`style` commits on the `canary` branch.
|
||||
- May contain **unstable or incomplete changes**. **Use at your own risk.**
|
||||
- It is strongly recommended to **back up your data** before using a canary build.
|
||||
|
||||
### 📦 Installation
|
||||
|
||||
Download the appropriate installer for your platform from the assets below.
|
||||
|
||||
| Platform | File |
|
||||
|----------|------|
|
||||
| macOS (Apple Silicon) | `.dmg` (arm64) |
|
||||
| macOS (Intel) | `.dmg` (x64) |
|
||||
| Windows | `.exe` |
|
||||
| Linux | `.AppImage` / `.deb` |
|
||||
files: |
|
||||
release/latest*
|
||||
release/*.dmg*
|
||||
release/*.zip*
|
||||
release/*.exe*
|
||||
release/*.AppImage
|
||||
release/*.deb*
|
||||
release/*.snap*
|
||||
release/*.rpm*
|
||||
release/*.tar.gz*
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
# ============================================
|
||||
# 清理旧的 Canary Releases (保留最近 7 个)
|
||||
# ============================================
|
||||
cleanup-old-canaries:
|
||||
needs: [publish-release]
|
||||
name: Cleanup Old Canary Releases
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- name: Delete old canary releases
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const { data: releases } = await github.rest.repos.listReleases({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
per_page: 100,
|
||||
});
|
||||
|
||||
const canaryReleases = releases
|
||||
.filter(r => r.tag_name.includes('-canary.'))
|
||||
.sort((a, b) => new Date(b.created_at) - new Date(a.created_at));
|
||||
|
||||
const toDelete = canaryReleases.slice(7);
|
||||
|
||||
for (const release of toDelete) {
|
||||
console.log(`🗑️ Deleting old canary release: ${release.tag_name}`);
|
||||
|
||||
// Delete the release
|
||||
await github.rest.repos.deleteRelease({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
release_id: release.id,
|
||||
});
|
||||
|
||||
// Delete the tag
|
||||
try {
|
||||
await github.rest.git.deleteRef({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
ref: `tags/${release.tag_name}`,
|
||||
});
|
||||
} catch (e) {
|
||||
console.log(`⚠️ Could not delete tag ${release.tag_name}: ${e.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`✅ Cleanup complete. Kept ${Math.min(canaryReleases.length, 7)} canary releases, deleted ${toDelete.length}.`);
|
||||
+3
-1
@@ -84,6 +84,8 @@ jobs:
|
||||
steps:
|
||||
- name: Check release info
|
||||
id: check
|
||||
env:
|
||||
RELEASE_BODY: ${{ github.event.release.body || '' }}
|
||||
run: |
|
||||
# 判断触发方式
|
||||
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
|
||||
@@ -100,7 +102,7 @@ jobs:
|
||||
version="${version#v}"
|
||||
echo "is_manual=false" >> $GITHUB_OUTPUT
|
||||
echo "version=${version}" >> $GITHUB_OUTPUT
|
||||
release_body="${{ github.event.release.body }}"
|
||||
release_body="${RELEASE_BODY:-}"
|
||||
{
|
||||
echo "release_notes<<EOF"
|
||||
printf '%s\n' "$release_body"
|
||||
@@ -73,28 +73,22 @@ jobs:
|
||||
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
||||
echo "📦 Release version: v$VERSION"
|
||||
|
||||
- name: Update package.json version
|
||||
- name: Verify package.json version matches tag
|
||||
run: |
|
||||
VERSION="${{ steps.get-version.outputs.version }}"
|
||||
echo "📝 Updating package.json version to: $VERSION"
|
||||
# Update package.json using Node.js
|
||||
echo "🔎 Checking package.json version equals tag: $VERSION"
|
||||
node -e "
|
||||
const fs = require('fs');
|
||||
const pkg = JSON.parse(fs.readFileSync('./package.json', 'utf8'));
|
||||
pkg.version = '$VERSION';
|
||||
fs.writeFileSync('./package.json', JSON.stringify(pkg, null, 2) + '\\n');
|
||||
console.log('✅ package.json updated');
|
||||
const expected = '$VERSION';
|
||||
const actual = pkg.version;
|
||||
if (actual !== expected) {
|
||||
console.error('❌ Version mismatch: package.json=' + actual + ' tag=' + expected);
|
||||
process.exit(1);
|
||||
}
|
||||
console.log('✅ Version OK:', actual);
|
||||
"
|
||||
|
||||
# Commit changes
|
||||
git config --global user.name "lobehubbot"
|
||||
git config --global user.email "i@lobehub.com"
|
||||
git add package.json
|
||||
git commit -m "🔧 chore(release): bump version to v$VERSION [skip ci]" || echo "Nothing to commit"
|
||||
git push origin HEAD:main
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
||||
|
||||
- name: Release
|
||||
run: bun run release
|
||||
env:
|
||||
@@ -0,0 +1,128 @@
|
||||
name: 🔄 Branch Synchronization
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
concurrency:
|
||||
group: sync-main-to-canary
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
sync-branches:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
token: ${{ secrets.GH_TOKEN }}
|
||||
|
||||
- name: Set up Git
|
||||
run: |
|
||||
git config --global user.name 'lobehubbot'
|
||||
git config --global user.email 'i@lobehub.com'
|
||||
|
||||
- name: Sync main to canary
|
||||
if: github.ref == 'refs/heads/main'
|
||||
run: |
|
||||
# Find existing open sync PR by head branch prefix
|
||||
EXISTING_PR=$(gh pr list --base canary --state open --json number,headRefName \
|
||||
--jq '[.[] | select(.headRefName | startswith("sync/main-to-canary-"))][0] // empty')
|
||||
EXISTING_PR_NUMBER=$(echo "$EXISTING_PR" | jq -r '.number // empty' 2>/dev/null)
|
||||
|
||||
# Refresh remote refs to avoid stale comparisons
|
||||
git fetch origin canary main
|
||||
|
||||
# Check if there are actual changes to sync
|
||||
if [ "$(git rev-parse origin/main)" = "$(git rev-parse origin/canary)" ]; then
|
||||
echo "No changes to sync"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
close_stale_pr() {
|
||||
if [ -n "$EXISTING_PR_NUMBER" ]; then
|
||||
gh pr close "$EXISTING_PR_NUMBER" --comment "Superseded by $1." --delete-branch || true
|
||||
fi
|
||||
}
|
||||
|
||||
# 1) Fast-forward: canary is ancestor of main → just move canary pointer
|
||||
if git merge-base --is-ancestor origin/canary origin/main; then
|
||||
echo "canary is ancestor of main, fast-forwarding"
|
||||
git checkout canary
|
||||
git reset --hard origin/main
|
||||
if git push origin canary; then
|
||||
close_stale_pr "fast-forward push"
|
||||
exit 0
|
||||
fi
|
||||
echo "Fast-forward push failed, falling back to merge"
|
||||
fi
|
||||
|
||||
# 2) Merge: canary has unique commits but no conflicts
|
||||
git checkout canary
|
||||
git reset --hard origin/canary
|
||||
if git merge origin/main --no-edit; then
|
||||
echo "Merge succeeded, pushing directly"
|
||||
if git push origin canary; then
|
||||
close_stale_pr "direct merge push"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Direct push failed (e.g. non-fast-forward race), fall back to PR
|
||||
echo "Direct push failed, falling back to PR"
|
||||
SYNC_BRANCH="sync/main-to-canary-$(date +'%Y%m%d')-${GITHUB_RUN_ID}"
|
||||
git checkout -B "$SYNC_BRANCH"
|
||||
git push origin "$SYNC_BRANCH" -f
|
||||
gh pr create \
|
||||
--base canary \
|
||||
--head "$SYNC_BRANCH" \
|
||||
--title "🚀 release: sync main branch to canary" \
|
||||
--body "Automatic sync from main to canary. Direct push failed, please merge this PR." || true
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# 3) Conflicts: create or update PR for manual resolution
|
||||
echo "Merge conflicts detected, creating PR"
|
||||
git merge --abort
|
||||
|
||||
if [ -n "$EXISTING_PR_NUMBER" ]; then
|
||||
gh pr comment "$EXISTING_PR_NUMBER" --body "New commits on \`main\`. Please pull latest \`origin/main\` into this branch to include them."
|
||||
echo "Commented on existing PR #$EXISTING_PR_NUMBER"
|
||||
else
|
||||
SYNC_BRANCH="sync/main-to-canary-$(date +'%Y%m%d')-${GITHUB_RUN_ID}"
|
||||
git checkout -B "$SYNC_BRANCH" origin/canary
|
||||
if ! git merge origin/main --no-edit; then
|
||||
git add -A
|
||||
git commit --no-edit -m "chore: merge main into canary (has conflicts to resolve)"
|
||||
fi
|
||||
git push origin "$SYNC_BRANCH" -f
|
||||
|
||||
printf '%s\n' \
|
||||
'Automatic sync from main to canary. Merge conflicts detected.' \
|
||||
'' \
|
||||
'**Resolution steps:**' \
|
||||
'```bash' \
|
||||
'git fetch origin' \
|
||||
"git checkout $SYNC_BRANCH" \
|
||||
'git merge origin/main' \
|
||||
'# Resolve conflicts' \
|
||||
'git add -A && git commit' \
|
||||
'git push' \
|
||||
'```' \
|
||||
'' \
|
||||
'> Do NOT merge canary into a main-based branch — always merge main INTO the canary-based branch to keep a clean commit graph.' \
|
||||
> /tmp/pr-body.md
|
||||
|
||||
gh pr create \
|
||||
--base canary \
|
||||
--head "$SYNC_BRANCH" \
|
||||
--title "🚀 release: sync main branch to canary" \
|
||||
--body-file /tmp/pr-body.md
|
||||
fi
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
||||
@@ -1,108 +0,0 @@
|
||||
name: Auto Tag Release
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [closed]
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
auto-tag:
|
||||
name: Auto Tag Release
|
||||
runs-on: ubuntu-latest
|
||||
# Only trigger when PR is merged
|
||||
if: github.event.pull_request.merged == true
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
token: ${{ secrets.GH_TOKEN }}
|
||||
# Fetch full history for proper tagging
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Check and extract version from PR title
|
||||
id: extract-version
|
||||
run: |
|
||||
PR_TITLE="${{ github.event.pull_request.title }}"
|
||||
echo "PR Title: $PR_TITLE"
|
||||
|
||||
# Match "🚀 release: v{x.x.x}" format
|
||||
if [[ "$PR_TITLE" =~ ^🚀[[:space:]]+release:[[:space:]]*v([0-9]+\.[0-9]+\.[0-9]+.*)$ ]]; then
|
||||
VERSION="${BASH_REMATCH[1]}"
|
||||
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
||||
echo "should_tag=true" >> $GITHUB_OUTPUT
|
||||
echo "✅ Detected release PR, version: v$VERSION"
|
||||
else
|
||||
echo "should_tag=false" >> $GITHUB_OUTPUT
|
||||
echo "⏭️ Not a release PR, skipping tag creation"
|
||||
fi
|
||||
|
||||
- name: Check if tag already exists
|
||||
if: steps.extract-version.outputs.should_tag == 'true'
|
||||
id: check-tag
|
||||
run: |
|
||||
VERSION="${{ steps.extract-version.outputs.version }}"
|
||||
if git rev-parse "v$VERSION" >/dev/null 2>&1; then
|
||||
echo "exists=true" >> $GITHUB_OUTPUT
|
||||
echo "⚠️ Tag v$VERSION already exists"
|
||||
else
|
||||
echo "exists=false" >> $GITHUB_OUTPUT
|
||||
echo "✅ Tag v$VERSION does not exist, can create"
|
||||
fi
|
||||
|
||||
- name: Create Tag
|
||||
if: steps.extract-version.outputs.should_tag == 'true' && steps.check-tag.outputs.exists == 'false'
|
||||
run: |
|
||||
VERSION="${{ steps.extract-version.outputs.version }}"
|
||||
echo "🏷️ Creating tag: v$VERSION"
|
||||
|
||||
# Configure git
|
||||
git config --global user.name "github-actions[bot]"
|
||||
git config --global user.email "github-actions[bot]@users.noreply.github.com"
|
||||
|
||||
# Get PR merge commit SHA
|
||||
MERGE_SHA="${{ github.event.pull_request.merge_commit_sha }}"
|
||||
|
||||
# Create annotated tag with single line message
|
||||
git tag -a "v$VERSION" "$MERGE_SHA" -m "🚀 release: v$VERSION | PR #${{ github.event.pull_request.number }} | Author: ${{ github.event.pull_request.user.login }}"
|
||||
|
||||
# Push tag
|
||||
git push origin "v$VERSION"
|
||||
|
||||
echo "✅ Tag v$VERSION created successfully!"
|
||||
|
||||
- name: Create GitHub Release
|
||||
if: steps.extract-version.outputs.should_tag == 'true' && steps.check-tag.outputs.exists == 'false'
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
tag_name: v${{ steps.extract-version.outputs.version }}
|
||||
name: 🚀 Release v${{ steps.extract-version.outputs.version }}
|
||||
body: |
|
||||
## 📦 Release v${{ steps.extract-version.outputs.version }}
|
||||
|
||||
This release was automatically published from PR #${{ github.event.pull_request.number }}.
|
||||
|
||||
### Changes
|
||||
See PR description: ${{ github.event.pull_request.html_url }}
|
||||
|
||||
### Commit Message
|
||||
${{ github.event.pull_request.body }}
|
||||
draft: false
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
|
||||
|
||||
- name: Output result
|
||||
run: |
|
||||
if [ "${{ steps.extract-version.outputs.should_tag }}" == "true" ]; then
|
||||
if [ "${{ steps.check-tag.outputs.exists }}" == "true" ]; then
|
||||
echo "⚠️ Result: Tag v${{ steps.extract-version.outputs.version }} already exists, skipping creation"
|
||||
else
|
||||
echo "✅ Result: Tag v${{ steps.extract-version.outputs.version }} created successfully!"
|
||||
fi
|
||||
else
|
||||
echo "ℹ️ Result: Not a release PR, no tag created"
|
||||
fi
|
||||
@@ -1,42 +0,0 @@
|
||||
name: 🔄 Branch Synchronization
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
sync-branches:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Git
|
||||
run: |
|
||||
git config --global user.name 'GitHub Actions'
|
||||
git config --global user.email 'actions@github.com'
|
||||
|
||||
- name: Prepare sync branch
|
||||
id: branch
|
||||
run: |
|
||||
echo "SYNC_BRANCH_MAIN_DEV=sync/main-to-dev-$(date +'%Y%m%d')" >> $GITHUB_ENV
|
||||
|
||||
- name: Sync main to dev
|
||||
if: github.ref == 'refs/heads/main'
|
||||
run: |
|
||||
# Sync main to dev
|
||||
git checkout main
|
||||
SYNC_BRANCH_DEV=${{ env.SYNC_BRANCH_MAIN_DEV }}
|
||||
git checkout -B $SYNC_BRANCH_DEV
|
||||
DIFF=$(git diff origin/dev...)
|
||||
if [ -z "$DIFF" ]; then
|
||||
echo "No changes to sync"
|
||||
exit 0
|
||||
fi
|
||||
git push origin $SYNC_BRANCH_DEV -f
|
||||
gh pr create --base dev --head $SYNC_BRANCH_DEV --title "Sync main branch to dev branch" --body "Automatic sync" || exit 0
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
+5
-1
@@ -83,6 +83,7 @@ public/sw*
|
||||
public/swe-worker*
|
||||
|
||||
# Generated files
|
||||
public/spa/
|
||||
public/*.js
|
||||
public/sitemap.xml
|
||||
public/sitemap-index.xml
|
||||
@@ -127,4 +128,7 @@ out
|
||||
i18n-unused-keys-report.json
|
||||
.vitest-reports
|
||||
|
||||
pnpm-lock.yaml
|
||||
pnpm-lock.yaml
|
||||
.turbo
|
||||
|
||||
spaHtmlTemplates.ts
|
||||
Vendored
+2
-1
@@ -53,7 +53,8 @@
|
||||
"typescriptreact"
|
||||
],
|
||||
"typescript.tsdk": "node_modules/typescript/lib",
|
||||
"vitest.maximumConfigs": 20,
|
||||
"vitest.disableWorkspaceWarning": true,
|
||||
"vitest.maximumConfigs": 10,
|
||||
"workbench.editor.customLabels.patterns": {
|
||||
"**/app/**/[[]*[]]/[[]*[]]/page.tsx": "${dirname(2)}/${dirname(1)}/${dirname} • page component",
|
||||
"**/app/**/[[]*[]]/page.tsx": "${dirname(1)}/${dirname} • page component",
|
||||
|
||||
@@ -76,6 +76,7 @@ COPY patches ./patches
|
||||
# bring in desktop workspace manifest so pnpm can resolve it
|
||||
COPY apps/desktop/src/main/package.json ./apps/desktop/src/main/package.json
|
||||
|
||||
|
||||
RUN set -e && \
|
||||
if [ "${USE_CN_MIRROR:-false}" = "true" ]; then \
|
||||
export SENTRYCLI_CDNURL="https://npmmirror.com/mirrors/sentry-cli"; \
|
||||
@@ -116,6 +117,8 @@ COPY --from=base /distroless/ /
|
||||
# Automatically leverage output traces to reduce image size
|
||||
# https://nextjs.org/docs/advanced-features/output-file-tracing
|
||||
COPY --from=builder /app/.next/standalone /app/
|
||||
# Copy SPA build output (Vite)
|
||||
COPY --from=builder /app/public/spa /app/public/spa
|
||||
# Copy Next export output for desktop renderer
|
||||
COPY --from=builder /app/apps/desktop/dist/next /app/apps/desktop/dist/next
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import dotenv from 'dotenv';
|
||||
import fs from 'node:fs/promises';
|
||||
import os from 'node:os';
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
import dotenv from 'dotenv';
|
||||
|
||||
import {
|
||||
copyNativeModules,
|
||||
copyNativeModulesToSource,
|
||||
@@ -27,9 +28,11 @@ const updateServerUrl = process.env.UPDATE_SERVER_URL;
|
||||
console.log(`🚄 Build Version ${packageJSON.version}, Channel: ${channel}`);
|
||||
console.log(`🏗️ Building for architecture: ${arch}`);
|
||||
|
||||
// Channel identity derived solely from UPDATE_CHANNEL env var.
|
||||
// Adding a new channel won't break stable detection.
|
||||
const isStable = !channel || channel === 'stable';
|
||||
const isNightly = channel === 'nightly';
|
||||
const isBeta = packageJSON.name.includes('beta');
|
||||
const isStable = !isNightly && !isBeta;
|
||||
const isBeta = channel === 'beta';
|
||||
|
||||
// 根据 channel 配置不同的 publish provider
|
||||
// - Stable + UPDATE_SERVER_URL: 使用 generic (自定义 HTTP 服务器)
|
||||
@@ -80,9 +83,10 @@ const protocolScheme = getProtocolScheme();
|
||||
|
||||
// Determine icon file based on version type
|
||||
const getIconFileName = () => {
|
||||
if (isNightly) return 'Icon-nightly';
|
||||
if (isStable) return 'Icon';
|
||||
if (isBeta) return 'Icon-beta';
|
||||
return 'Icon';
|
||||
// nightly, canary, and any future pre-release channels share nightly icon
|
||||
return 'Icon-nightly';
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -196,6 +200,16 @@ const config = {
|
||||
|
||||
dmg: {
|
||||
artifactName: '${productName}-${version}-${arch}.${ext}',
|
||||
background: 'resources/dmg.png',
|
||||
contents: [
|
||||
{ type: 'file', x: 150, y: 240 },
|
||||
{ type: 'link', path: '/Applications', x: 450, y: 240 },
|
||||
],
|
||||
iconSize: 80,
|
||||
window: {
|
||||
height: 400,
|
||||
width: 600,
|
||||
},
|
||||
},
|
||||
|
||||
electronDownload: {
|
||||
@@ -208,6 +222,7 @@ const config = {
|
||||
// Ensure Next export assets are packaged
|
||||
'dist/next/**/*',
|
||||
'!resources/locales',
|
||||
'!resources/dmg.png',
|
||||
'!dist/next/docs',
|
||||
'!dist/next/packages',
|
||||
'!dist/next/.next/server/app/sitemap',
|
||||
@@ -249,15 +264,10 @@ const config = {
|
||||
hardenedRuntime: hasAppleCertificate,
|
||||
notarize: hasAppleCertificate,
|
||||
...(hasAppleCertificate ? {} : { identity: null }),
|
||||
target:
|
||||
// 降低构建时间,nightly 只打 dmg
|
||||
// 根据当前机器架构只构建对应架构的包
|
||||
isNightly
|
||||
? [{ arch: [arch === 'arm64' ? 'arm64' : 'x64'], target: 'dmg' }]
|
||||
: [
|
||||
{ arch: [arch === 'arm64' ? 'arm64' : 'x64'], target: 'dmg' },
|
||||
{ arch: [arch === 'arm64' ? 'arm64' : 'x64'], target: 'zip' },
|
||||
],
|
||||
target: [
|
||||
{ arch: [arch === 'arm64' ? 'arm64' : 'x64'], target: 'dmg' },
|
||||
{ arch: [arch === 'arm64' ? 'arm64' : 'x64'], target: 'zip' },
|
||||
],
|
||||
},
|
||||
npmRebuild: true,
|
||||
nsis: {
|
||||
|
||||
@@ -33,7 +33,7 @@ const isDarwin = getTargetPlatform() === 'darwin';
|
||||
*/
|
||||
export const nativeModules = [
|
||||
// macOS-only native modules
|
||||
...(isDarwin ? ['node-mac-permissions'] : []),
|
||||
...(isDarwin ? ['node-mac-permissions', 'electron-liquid-glass'] : []),
|
||||
'@napi-rs/canvas',
|
||||
// Add more native modules here as needed
|
||||
];
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@napi-rs/canvas": "^0.1.70",
|
||||
"electron-liquid-glass": "^1.1.1",
|
||||
"electron-updater": "^6.6.2",
|
||||
"electron-window-state": "^5.0.3",
|
||||
"fetch-socks": "^1.3.2",
|
||||
@@ -77,7 +78,7 @@
|
||||
"electron-store": "^8.2.0",
|
||||
"electron-vite": "^4.0.1",
|
||||
"es-toolkit": "^1.43.0",
|
||||
"eslint": "^9.18.0",
|
||||
"eslint": "10.0.0",
|
||||
"execa": "^9.6.1",
|
||||
"fast-glob": "^3.3.3",
|
||||
"fix-path": "^5.0.0",
|
||||
@@ -111,4 +112,4 @@
|
||||
"node-mac-permissions"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 71 KiB |
@@ -18,7 +18,6 @@ export const appBrowsers = {
|
||||
path: '/',
|
||||
showOnInit: true,
|
||||
titleBarStyle: 'hidden',
|
||||
vibrancy: 'under-window',
|
||||
width: 1200,
|
||||
},
|
||||
devtools: {
|
||||
@@ -31,7 +30,6 @@ export const appBrowsers = {
|
||||
parentIdentifier: 'app',
|
||||
path: '/desktop/devtools',
|
||||
titleBarStyle: 'hiddenInset',
|
||||
vibrancy: 'under-window',
|
||||
width: 1000,
|
||||
},
|
||||
} satisfies Record<string, BrowserWindowOpts>;
|
||||
@@ -39,7 +37,6 @@ export const appBrowsers = {
|
||||
// Window templates for multi-instance windows
|
||||
export interface WindowTemplate {
|
||||
allowMultipleInstances: boolean;
|
||||
// Include common BrowserWindow options
|
||||
autoHideMenuBar?: boolean;
|
||||
baseIdentifier: string;
|
||||
basePath: string;
|
||||
@@ -51,22 +48,8 @@ export interface WindowTemplate {
|
||||
showOnInit?: boolean;
|
||||
title?: string;
|
||||
titleBarStyle?: 'hidden' | 'default' | 'hiddenInset' | 'customButtonsOnHover';
|
||||
vibrancy?:
|
||||
| 'appearance-based'
|
||||
| 'content'
|
||||
| 'fullscreen-ui'
|
||||
| 'header'
|
||||
| 'hud'
|
||||
| 'menu'
|
||||
| 'popover'
|
||||
| 'selection'
|
||||
| 'sheet'
|
||||
| 'sidebar'
|
||||
| 'titlebar'
|
||||
| 'tooltip'
|
||||
| 'under-page'
|
||||
| 'under-window'
|
||||
| 'window';
|
||||
// Note: vibrancy / visualEffectState / transparent are intentionally omitted.
|
||||
// Platform visual effects are managed exclusively by WindowThemeManager.
|
||||
width?: number;
|
||||
}
|
||||
|
||||
@@ -81,7 +64,6 @@ export const windowTemplates = {
|
||||
minWidth: 400,
|
||||
parentIdentifier: 'app',
|
||||
titleBarStyle: 'hidden',
|
||||
vibrancy: 'under-window',
|
||||
width: 900,
|
||||
},
|
||||
} satisfies Record<string, WindowTemplate>;
|
||||
|
||||
@@ -11,6 +11,15 @@ export const isMac = macOS();
|
||||
export const isWindows = windows();
|
||||
export const isLinux = linux();
|
||||
|
||||
function getIsMacTahoe(): boolean {
|
||||
if (!isMac) return false;
|
||||
// macOS 26 (Tahoe) corresponds to Darwin kernel 25.x
|
||||
const darwinMajor = parseInt(os.release().split('.')[0], 10);
|
||||
return darwinMajor >= 25;
|
||||
}
|
||||
|
||||
export const isMacTahoe = getIsMacTahoe();
|
||||
|
||||
function getIsWindows11() {
|
||||
if (!isWindows) return false;
|
||||
// Get OS version (e.g., "10.0.22621")
|
||||
|
||||
@@ -1,33 +1,37 @@
|
||||
/* eslint-disable unicorn/no-array-push-push */
|
||||
import {
|
||||
EditLocalFileParams,
|
||||
EditLocalFileResult,
|
||||
GlobFilesParams,
|
||||
GlobFilesResult,
|
||||
GrepContentParams,
|
||||
GrepContentResult,
|
||||
ListLocalFileParams,
|
||||
LocalMoveFilesResultItem,
|
||||
LocalReadFileParams,
|
||||
LocalReadFileResult,
|
||||
LocalReadFilesParams,
|
||||
LocalSearchFilesParams,
|
||||
MoveLocalFilesParams,
|
||||
OpenLocalFileParams,
|
||||
OpenLocalFolderParams,
|
||||
RenameLocalFileResult,
|
||||
ShowSaveDialogParams,
|
||||
ShowSaveDialogResult,
|
||||
WriteLocalFileParams,
|
||||
} from '@lobechat/electron-client-ipc';
|
||||
import { SYSTEM_FILES_TO_IGNORE, loadFile } from '@lobechat/file-loaders';
|
||||
import { createPatch } from 'diff';
|
||||
import { dialog, shell } from 'electron';
|
||||
import { constants } from 'node:fs';
|
||||
import { access, mkdir, readFile, readdir, rename, stat, writeFile } from 'node:fs/promises';
|
||||
import { access, mkdir, readdir, readFile, rename, stat, writeFile } from 'node:fs/promises';
|
||||
import * as path from 'node:path';
|
||||
|
||||
import { FileResult, SearchOptions } from '@/modules/fileSearch';
|
||||
import {
|
||||
type EditLocalFileParams,
|
||||
type EditLocalFileResult,
|
||||
type GlobFilesParams,
|
||||
type GlobFilesResult,
|
||||
type GrepContentParams,
|
||||
type GrepContentResult,
|
||||
type ListLocalFileParams,
|
||||
type LocalMoveFilesResultItem,
|
||||
type LocalReadFileParams,
|
||||
type LocalReadFileResult,
|
||||
type LocalReadFilesParams,
|
||||
type LocalSearchFilesParams,
|
||||
type MoveLocalFilesParams,
|
||||
type OpenLocalFileParams,
|
||||
type OpenLocalFolderParams,
|
||||
type PickFileParams,
|
||||
type PickFileResult,
|
||||
type RenameLocalFileResult,
|
||||
type ShowOpenDialogParams,
|
||||
type ShowOpenDialogResult,
|
||||
type ShowSaveDialogParams,
|
||||
type ShowSaveDialogResult,
|
||||
type WriteLocalFileParams,
|
||||
} from '@lobechat/electron-client-ipc';
|
||||
import { loadFile, SYSTEM_FILES_TO_IGNORE } from '@lobechat/file-loaders';
|
||||
import { createPatch } from 'diff';
|
||||
import { dialog, shell } from 'electron';
|
||||
|
||||
import { type FileResult, type SearchOptions } from '@/modules/fileSearch';
|
||||
import ContentSearchService from '@/services/contentSearchSrv';
|
||||
import FileSearchService from '@/services/fileSearchSrv';
|
||||
import { makeSureDirExist } from '@/utils/file-system';
|
||||
@@ -85,6 +89,67 @@ export default class LocalFileCtr extends ControllerModule {
|
||||
}
|
||||
}
|
||||
|
||||
@IpcMethod()
|
||||
async handleShowOpenDialog({
|
||||
filters,
|
||||
multiple,
|
||||
title,
|
||||
}: ShowOpenDialogParams): Promise<ShowOpenDialogResult> {
|
||||
logger.debug('Showing open dialog:', { filters, multiple, title });
|
||||
|
||||
const result = await dialog.showOpenDialog({
|
||||
filters,
|
||||
properties: multiple ? ['openFile', 'multiSelections'] : ['openFile'],
|
||||
title,
|
||||
});
|
||||
|
||||
logger.debug('Open dialog result:', { canceled: result.canceled, filePaths: result.filePaths });
|
||||
|
||||
return {
|
||||
canceled: result.canceled,
|
||||
filePaths: result.filePaths,
|
||||
};
|
||||
}
|
||||
|
||||
@IpcMethod()
|
||||
async handlePickFile({ filters, title }: PickFileParams): Promise<PickFileResult> {
|
||||
logger.debug('Picking file:', { filters, title });
|
||||
|
||||
const result = await dialog.showOpenDialog({
|
||||
filters,
|
||||
properties: ['openFile'],
|
||||
title,
|
||||
});
|
||||
|
||||
if (result.canceled || result.filePaths.length === 0) {
|
||||
return { canceled: true };
|
||||
}
|
||||
|
||||
const filePath = result.filePaths[0];
|
||||
const data = await readFile(filePath);
|
||||
const name = path.basename(filePath);
|
||||
const ext = path.extname(filePath).toLowerCase().slice(1);
|
||||
|
||||
const MIME_MAP: Record<string, string> = {
|
||||
avif: 'image/avif',
|
||||
gif: 'image/gif',
|
||||
jpeg: 'image/jpeg',
|
||||
jpg: 'image/jpeg',
|
||||
png: 'image/png',
|
||||
svg: 'image/svg+xml',
|
||||
webp: 'image/webp',
|
||||
};
|
||||
|
||||
return {
|
||||
canceled: false,
|
||||
file: {
|
||||
data: new Uint8Array(data),
|
||||
mimeType: MIME_MAP[ext] || 'application/octet-stream',
|
||||
name,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@IpcMethod()
|
||||
async handleShowSaveDialog({
|
||||
defaultPath,
|
||||
|
||||
@@ -110,7 +110,18 @@ export default class Browser {
|
||||
// ==================== Window Creation ====================
|
||||
|
||||
private createBrowserWindow(): BrowserWindow {
|
||||
const { title, width, height, ...rest } = this.options;
|
||||
const {
|
||||
title,
|
||||
width,
|
||||
height,
|
||||
// Strip platform visual effect props — these are managed exclusively
|
||||
// by WindowThemeManager.getPlatformConfig() to prevent config leaking
|
||||
// from appBrowsers/windowTemplates into the BrowserWindow constructor.
|
||||
vibrancy: _vibrancy,
|
||||
visualEffectState: _visualEffectState,
|
||||
transparent: _transparent,
|
||||
...rest
|
||||
} = this.options;
|
||||
|
||||
const resolvedState = this.stateManager.resolveState({ height, width });
|
||||
logger.info(`Creating new BrowserWindow instance: ${this.identifier}`);
|
||||
@@ -125,9 +136,6 @@ export default class Browser {
|
||||
height: resolvedState.height,
|
||||
show: false,
|
||||
title,
|
||||
|
||||
vibrancy: 'sidebar',
|
||||
visualEffectState: 'active',
|
||||
webPreferences: {
|
||||
backgroundThrottling: false,
|
||||
contextIsolation: true,
|
||||
@@ -138,6 +146,7 @@ export default class Browser {
|
||||
width: resolvedState.width,
|
||||
x: resolvedState.x,
|
||||
y: resolvedState.y,
|
||||
// Platform visual config is the SOLE source of vibrancy / transparency / titleBarOverlay.
|
||||
...this.themeManager.getPlatformConfig(),
|
||||
});
|
||||
}
|
||||
@@ -145,7 +154,7 @@ export default class Browser {
|
||||
private setupWindow(browserWindow: BrowserWindow): void {
|
||||
logger.debug(`[${this.identifier}] BrowserWindow instance created.`);
|
||||
|
||||
// Setup theme management
|
||||
// Setup theme management (includes liquid glass lifecycle on macOS Tahoe)
|
||||
this.themeManager.attach(browserWindow);
|
||||
|
||||
// Setup network interceptors
|
||||
|
||||
@@ -211,10 +211,10 @@ export class BrowserManager {
|
||||
const identifier = options.identifier;
|
||||
this.browsers.set(identifier, browser);
|
||||
|
||||
// 记录 WebContents 和 identifier 的映射
|
||||
// Record the mapping between WebContents and identifier
|
||||
this.webContentsMap.set(browser.browserWindow.webContents, identifier);
|
||||
|
||||
// 当窗口关闭时清理映射
|
||||
// Clean up the mapping when the window is closed
|
||||
browser.browserWindow.on('close', () => {
|
||||
if (browser.webContents) this.webContentsMap.delete(browser.webContents);
|
||||
});
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
import { TITLE_BAR_HEIGHT } from '@lobechat/desktop-bridge';
|
||||
import { BrowserWindow, BrowserWindowConstructorOptions, nativeTheme } from 'electron';
|
||||
import { join } from 'node:path';
|
||||
|
||||
import { TITLE_BAR_HEIGHT } from '@lobechat/desktop-bridge';
|
||||
import { type BrowserWindow, type BrowserWindowConstructorOptions, nativeTheme } from 'electron';
|
||||
|
||||
import { buildDir } from '@/const/dir';
|
||||
import { isDev, isMac, isWindows } from '@/const/env';
|
||||
import { isDev, isMac, isMacTahoe, isWindows } from '@/const/env';
|
||||
import { createLogger } from '@/utils/logger';
|
||||
|
||||
import {
|
||||
BACKGROUND_DARK,
|
||||
BACKGROUND_LIGHT,
|
||||
@@ -11,7 +14,6 @@ import {
|
||||
SYMBOL_COLOR_LIGHT,
|
||||
THEME_CHANGE_DELAY,
|
||||
} from '../../const/theme';
|
||||
import { createLogger } from '@/utils/logger';
|
||||
|
||||
const logger = createLogger('core:WindowThemeManager');
|
||||
|
||||
@@ -26,6 +28,18 @@ interface WindowsThemeConfig {
|
||||
titleBarStyle: 'hidden';
|
||||
}
|
||||
|
||||
// Lazy-load liquid glass only on macOS Tahoe to avoid import errors on other platforms.
|
||||
// Dynamic require is intentional: native .node addons cannot be loaded via
|
||||
// async import() and must be synchronously required at module init time.
|
||||
let liquidGlass: typeof import('electron-liquid-glass').default | undefined;
|
||||
if (isMacTahoe) {
|
||||
try {
|
||||
liquidGlass = require('electron-liquid-glass');
|
||||
} catch {
|
||||
// Native module not available (e.g. wrong architecture or missing binary)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Manages window theme configuration and visual effects
|
||||
*/
|
||||
@@ -34,6 +48,7 @@ export class WindowThemeManager {
|
||||
private browserWindow?: BrowserWindow;
|
||||
private listenerSetup = false;
|
||||
private boundHandleThemeChange: () => void;
|
||||
private liquidGlassViewId?: number;
|
||||
|
||||
constructor(identifier: string) {
|
||||
this.identifier = identifier;
|
||||
@@ -52,12 +67,21 @@ export class WindowThemeManager {
|
||||
// ==================== Lifecycle ====================
|
||||
|
||||
/**
|
||||
* Attach to a browser window and setup theme handling
|
||||
* Attach to a browser window and setup theme handling.
|
||||
* Owns the full visual effect lifecycle including liquid glass on macOS Tahoe.
|
||||
*/
|
||||
attach(browserWindow: BrowserWindow): void {
|
||||
this.browserWindow = browserWindow;
|
||||
this.setupThemeListener();
|
||||
this.applyVisualEffects();
|
||||
|
||||
// Liquid glass must be applied after window content loads (native view needs
|
||||
// a rendered surface). The effect persists across subsequent in-window navigations.
|
||||
if (this.useLiquidGlass) {
|
||||
browserWindow.webContents.once('did-finish-load', () => {
|
||||
this.applyLiquidGlass();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -69,6 +93,7 @@ export class WindowThemeManager {
|
||||
this.listenerSetup = false;
|
||||
logger.debug(`[${this.identifier}] Theme listener cleaned up.`);
|
||||
}
|
||||
this.liquidGlassViewId = undefined;
|
||||
this.browserWindow = undefined;
|
||||
}
|
||||
|
||||
@@ -81,6 +106,13 @@ export class WindowThemeManager {
|
||||
return nativeTheme.shouldUseDarkColors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether liquid glass is available and should be used
|
||||
*/
|
||||
get useLiquidGlass(): boolean {
|
||||
return isMacTahoe && !!liquidGlass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get platform-specific theme configuration for window creation
|
||||
*/
|
||||
@@ -92,8 +124,19 @@ export class WindowThemeManager {
|
||||
// Calculate traffic light position to center vertically in title bar
|
||||
// Traffic light buttons are approximately 12px tall
|
||||
const trafficLightY = Math.round((TITLE_BAR_HEIGHT - 12) / 2);
|
||||
|
||||
if (this.useLiquidGlass) {
|
||||
// Liquid glass requires transparent window and must NOT use vibrancy — they conflict.
|
||||
return {
|
||||
trafficLightPosition: { x: 12, y: trafficLightY },
|
||||
transparent: true,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
trafficLightPosition: { x: 12, y: trafficLightY },
|
||||
vibrancy: 'sidebar',
|
||||
visualEffectState: 'active',
|
||||
};
|
||||
}
|
||||
return {};
|
||||
@@ -135,58 +178,37 @@ export class WindowThemeManager {
|
||||
logger.debug(`[${this.identifier}] App theme mode changed, reapplying visual effects.`);
|
||||
setTimeout(() => {
|
||||
this.applyVisualEffects();
|
||||
this.applyWindowsTitleBarOverlay();
|
||||
}, THEME_CHANGE_DELAY);
|
||||
}
|
||||
|
||||
// ==================== Visual Effects ====================
|
||||
|
||||
private resolveWindowsIsDarkModeFromElectron(): boolean {
|
||||
/**
|
||||
* Resolve dark mode from Electron theme source for runtime visual effect updates.
|
||||
* Checks explicit themeSource first to handle app-level theme overrides correctly.
|
||||
*/
|
||||
private resolveIsDarkMode(): boolean {
|
||||
if (nativeTheme.themeSource === 'dark') return true;
|
||||
if (nativeTheme.themeSource === 'light') return false;
|
||||
return nativeTheme.shouldUseDarkColors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply Windows title bar overlay based on Electron theme mode.
|
||||
* Mirror the structure of `applyVisualEffects`, but only updates title bar overlay.
|
||||
*/
|
||||
private applyWindowsTitleBarOverlay(): void {
|
||||
if (!this.browserWindow || this.browserWindow.isDestroyed()) return;
|
||||
|
||||
logger.debug(`[${this.identifier}] Applying Windows title bar overlay`);
|
||||
const isDarkMode = this.resolveWindowsIsDarkModeFromElectron();
|
||||
|
||||
try {
|
||||
if (!isWindows) return;
|
||||
|
||||
this.browserWindow.setTitleBarOverlay(this.getWindowsTitleBarOverlay(isDarkMode));
|
||||
|
||||
logger.debug(
|
||||
`[${this.identifier}] Windows title bar overlay applied successfully (dark mode: ${isDarkMode})`,
|
||||
);
|
||||
} catch (error) {
|
||||
logger.error(`[${this.identifier}] Failed to apply Windows title bar overlay:`, error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply visual effects based on current theme
|
||||
* Apply visual effects based on current theme.
|
||||
* Single entry point for ALL platform visual effects.
|
||||
*/
|
||||
applyVisualEffects(): void {
|
||||
if (!this.browserWindow || this.browserWindow.isDestroyed()) return;
|
||||
|
||||
logger.debug(`[${this.identifier}] Applying visual effects for platform`);
|
||||
const isDarkMode = this.isDarkMode;
|
||||
const isDarkMode = this.resolveIsDarkMode();
|
||||
logger.debug(`[${this.identifier}] Applying visual effects (dark: ${isDarkMode})`);
|
||||
|
||||
try {
|
||||
if (isWindows) {
|
||||
this.applyWindowsVisualEffects(isDarkMode);
|
||||
} else if (isMac) {
|
||||
this.applyMacVisualEffects();
|
||||
}
|
||||
|
||||
logger.debug(
|
||||
`[${this.identifier}] Visual effects applied successfully (dark mode: ${isDarkMode})`,
|
||||
);
|
||||
} catch (error) {
|
||||
logger.error(`[${this.identifier}] Failed to apply visual effects:`, error);
|
||||
}
|
||||
@@ -207,4 +229,44 @@ export class WindowThemeManager {
|
||||
this.browserWindow.setBackgroundColor(config.backgroundColor);
|
||||
this.browserWindow.setTitleBarOverlay(config.titleBarOverlay);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply macOS visual effects.
|
||||
* - Tahoe+: liquid glass auto-adapts to dark mode; ensure it's applied if not yet.
|
||||
* - Pre-Tahoe: vibrancy is managed natively by Electron, no runtime action needed.
|
||||
*/
|
||||
private applyMacVisualEffects(): void {
|
||||
if (!this.browserWindow) return;
|
||||
|
||||
if (this.useLiquidGlass) {
|
||||
// Attempt apply if not yet done (e.g. initial load failed, or window recreated)
|
||||
this.applyLiquidGlass();
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== Liquid Glass ====================
|
||||
|
||||
/**
|
||||
* Apply liquid glass native view to the window.
|
||||
* Idempotent — guards against double-application via `liquidGlassViewId`.
|
||||
*/
|
||||
applyLiquidGlass(): void {
|
||||
if (!this.useLiquidGlass || !liquidGlass) return;
|
||||
if (!this.browserWindow || this.browserWindow.isDestroyed()) return;
|
||||
if (this.liquidGlassViewId !== undefined) return;
|
||||
|
||||
try {
|
||||
// Ensure traffic light buttons remain visible with transparent window
|
||||
this.browserWindow.setWindowButtonVisibility(true);
|
||||
|
||||
const handle = this.browserWindow.getNativeWindowHandle();
|
||||
|
||||
this.liquidGlassViewId = liquidGlass.addView(handle);
|
||||
liquidGlass.unstable_setVariant(this.liquidGlassViewId, 15);
|
||||
|
||||
logger.info(`[${this.identifier}] Liquid glass applied (viewId: ${this.liquidGlassViewId})`);
|
||||
} catch (error) {
|
||||
logger.error(`[${this.identifier}] Failed to apply liquid glass:`, error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
import type { App as AppCore } from '../../App';
|
||||
import Browser, { BrowserWindowOpts } from '../Browser';
|
||||
import { type App as AppCore } from '../../App';
|
||||
import Browser, { type BrowserWindowOpts } from '../Browser';
|
||||
|
||||
// Use vi.hoisted to define mocks before hoisting
|
||||
const { mockBrowserWindow, mockNativeTheme, mockIpcMain, mockScreen, MockBrowserWindow } =
|
||||
@@ -100,6 +100,7 @@ vi.mock('@/const/dir', () => ({
|
||||
vi.mock('@/const/env', () => ({
|
||||
isDev: false,
|
||||
isMac: false,
|
||||
isMacTahoe: false,
|
||||
isWindows: true,
|
||||
}));
|
||||
|
||||
@@ -605,9 +606,9 @@ describe('Browser', () => {
|
||||
const keepAliveBrowser = new Browser(keepAliveOptions, mockApp);
|
||||
|
||||
// Get the new close handler
|
||||
const keepAliveCloseHandler = mockBrowserWindow.on.mock.calls
|
||||
.filter((call) => call[0] === 'close')
|
||||
.pop()?.[1];
|
||||
const keepAliveCloseHandler = mockBrowserWindow.on.mock.calls.findLast(
|
||||
(call) => call[0] === 'close',
|
||||
)?.[1];
|
||||
|
||||
const mockEvent = { preventDefault: vi.fn() };
|
||||
keepAliveCloseHandler(mockEvent);
|
||||
|
||||
@@ -13,6 +13,7 @@ const { mockNativeTheme, mockBrowserWindow } = vi.hoisted(() => ({
|
||||
off: vi.fn(),
|
||||
on: vi.fn(),
|
||||
shouldUseDarkColors: false,
|
||||
themeSource: 'system' as string,
|
||||
},
|
||||
}));
|
||||
|
||||
@@ -35,6 +36,8 @@ vi.mock('@/const/dir', () => ({
|
||||
|
||||
vi.mock('@/const/env', () => ({
|
||||
isDev: false,
|
||||
isMac: false,
|
||||
isMacTahoe: false,
|
||||
isWindows: true,
|
||||
}));
|
||||
|
||||
@@ -58,6 +61,7 @@ describe('WindowThemeManager', () => {
|
||||
vi.useFakeTimers();
|
||||
|
||||
mockNativeTheme.shouldUseDarkColors = false;
|
||||
mockNativeTheme.themeSource = 'system';
|
||||
mockBrowserWindow.isDestroyed.mockReturnValue(false);
|
||||
|
||||
manager = new WindowThemeManager('test-window');
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* 存储应用中需要用装饰器的类
|
||||
* Stores classes in the application that require decorators
|
||||
*/
|
||||
export class IoCContainer {
|
||||
static shortcuts: WeakMap<any, { methodName: string; name: string }[]> = new WeakMap();
|
||||
|
||||
@@ -36,7 +36,7 @@ export class StaticFileServerManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化静态文件管理器
|
||||
* Initialize the static file manager
|
||||
*/
|
||||
async initialize(): Promise<void> {
|
||||
if (this.isInitialized) {
|
||||
@@ -47,7 +47,7 @@ export class StaticFileServerManager {
|
||||
logger.info('Initializing StaticFileServerManager');
|
||||
|
||||
try {
|
||||
// 启动 HTTP 文件服务器
|
||||
// Start the HTTP file server
|
||||
await this.startHttpServer();
|
||||
|
||||
this.isInitialized = true;
|
||||
@@ -61,17 +61,17 @@ export class StaticFileServerManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动 HTTP 文件服务器
|
||||
* Start the HTTP file server
|
||||
*/
|
||||
private async startHttpServer(): Promise<void> {
|
||||
try {
|
||||
// 使用 get-port-please 获取可用端口
|
||||
// Use get-port-please to find an available port
|
||||
this.serverPort = await getPort({
|
||||
// 备用端口
|
||||
// Fallback port
|
||||
host: '127.0.0.1',
|
||||
|
||||
port: 33_250,
|
||||
// 首选端口
|
||||
// Preferred ports
|
||||
ports: [33_251, 33_252, 33_253, 33_254, 33_255],
|
||||
});
|
||||
|
||||
@@ -79,7 +79,7 @@ export class StaticFileServerManager {
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const server = createServer(async (req, res) => {
|
||||
// 设置请求超时
|
||||
// Set request timeout
|
||||
req.setTimeout(30_000, () => {
|
||||
logger.warn('Request timeout, closing connection');
|
||||
if (!res.destroyed && !res.headersSent) {
|
||||
@@ -88,7 +88,7 @@ export class StaticFileServerManager {
|
||||
}
|
||||
});
|
||||
|
||||
// 监听客户端断开连接
|
||||
// Listen for client disconnection
|
||||
req.on('close', () => {
|
||||
logger.debug('Client disconnected during request processing');
|
||||
});
|
||||
@@ -98,7 +98,7 @@ export class StaticFileServerManager {
|
||||
} catch (error) {
|
||||
logger.error('Unhandled error in HTTP request handler:', error);
|
||||
|
||||
// 尝试发送错误响应,但确保不会导致进一步错误
|
||||
// Attempt to send error response, but ensure it does not cause further errors
|
||||
try {
|
||||
if (!res.destroyed && !res.headersSent) {
|
||||
res.writeHead(500, { 'Content-Type': 'text/plain' });
|
||||
@@ -110,7 +110,7 @@ export class StaticFileServerManager {
|
||||
}
|
||||
});
|
||||
|
||||
// 监听指定端口
|
||||
// Listen on the specified port
|
||||
server.listen(this.serverPort, '127.0.0.1', () => {
|
||||
this.httpServer = server;
|
||||
logger.info(`HTTP file server started on port ${this.serverPort}`);
|
||||
@@ -129,21 +129,21 @@ export class StaticFileServerManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理 HTTP 请求
|
||||
* Handle HTTP requests
|
||||
*/
|
||||
private async handleHttpRequest(req: any, res: any): Promise<void> {
|
||||
try {
|
||||
// 检查响应是否已经结束
|
||||
// Check if the response has already ended
|
||||
if (res.destroyed || res.headersSent) {
|
||||
logger.warn('Response already ended, skipping request processing');
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取请求的 Origin 并设置 CORS
|
||||
// Get the request Origin and set CORS
|
||||
const origin = req.headers.origin || req.headers.referer;
|
||||
const allowedOrigin = getAllowedOrigin(origin);
|
||||
|
||||
// 处理 CORS 预检请求
|
||||
// Handle CORS preflight requests
|
||||
if (req.method === 'OPTIONS') {
|
||||
res.writeHead(204, {
|
||||
'Access-Control-Allow-Headers': 'Content-Type',
|
||||
@@ -160,12 +160,12 @@ export class StaticFileServerManager {
|
||||
logger.debug(`Request method: ${req.method}`);
|
||||
logger.debug(`Request headers: ${JSON.stringify(req.headers)}`);
|
||||
|
||||
// 提取File path:从 /desktop-file/path/to/file.png 中提取相对路径
|
||||
let filePath = decodeURIComponent(url.pathname.slice(1)); // 移除开头的 /
|
||||
// Extract file path: extract the relative path from /desktop-file/path/to/file.png
|
||||
let filePath = decodeURIComponent(url.pathname.slice(1)); // Remove the leading /
|
||||
logger.debug(`Initial file path after decode: ${filePath}`);
|
||||
|
||||
// 如果路径以 desktop-file/ 开头,则移除该前缀
|
||||
const prefixWithoutSlash = LOCAL_STORAGE_URL_PREFIX.slice(1) + '/'; // 移除开头的 / 并添加结尾的 /
|
||||
// If the path starts with desktop-file/, remove that prefix
|
||||
const prefixWithoutSlash = LOCAL_STORAGE_URL_PREFIX.slice(1) + '/'; // Remove the leading / and add a trailing /
|
||||
logger.debug(`Prefix to remove: ${prefixWithoutSlash}`);
|
||||
|
||||
if (filePath.startsWith(prefixWithoutSlash)) {
|
||||
@@ -182,7 +182,7 @@ export class StaticFileServerManager {
|
||||
return;
|
||||
}
|
||||
|
||||
// 使用 FileService 获取文件
|
||||
// Use FileService to retrieve the file
|
||||
const desktopPath = `desktop://${filePath}`;
|
||||
logger.debug(`Attempting to get file: ${desktopPath}`);
|
||||
const fileResult = await this.fileService.getFile(desktopPath);
|
||||
@@ -190,13 +190,13 @@ export class StaticFileServerManager {
|
||||
`File retrieved successfully, mime type: ${fileResult.mimeType}, size: ${fileResult.content.byteLength} bytes`,
|
||||
);
|
||||
|
||||
// 再次检查响应状态
|
||||
// Check the response status again
|
||||
if (res.destroyed || res.headersSent) {
|
||||
logger.warn('Response ended during file processing');
|
||||
return;
|
||||
}
|
||||
|
||||
// 设置响应头
|
||||
// Set response headers
|
||||
res.writeHead(200, {
|
||||
'Access-Control-Allow-Origin': allowedOrigin,
|
||||
'Cache-Control': 'public, max-age=31536000',
|
||||
@@ -204,7 +204,7 @@ export class StaticFileServerManager {
|
||||
'Content-Type': fileResult.mimeType,
|
||||
});
|
||||
|
||||
// 发送文件内容
|
||||
// Send file content
|
||||
res.end(Buffer.from(fileResult.content));
|
||||
|
||||
logger.debug(`HTTP file served successfully: desktop://${filePath}`);
|
||||
@@ -212,14 +212,14 @@ export class StaticFileServerManager {
|
||||
logger.error(`Error serving HTTP file: ${error}`);
|
||||
logger.error(`Error stack: ${error.stack}`);
|
||||
|
||||
// 检查响应是否仍然可写
|
||||
// Check if the response is still writable
|
||||
if (!res.destroyed && !res.headersSent) {
|
||||
try {
|
||||
// 获取请求的 Origin 并设置 CORS(错误响应也需要!)
|
||||
// Get the request Origin and set CORS (error responses also need this!)
|
||||
const origin = req.headers.origin || req.headers.referer;
|
||||
const allowedOrigin = getAllowedOrigin(origin);
|
||||
|
||||
// 判断是否是文件未找到错误
|
||||
// Determine whether it is a file not found error
|
||||
if (error.name === 'FileNotFoundError') {
|
||||
res.writeHead(404, {
|
||||
'Access-Control-Allow-Origin': allowedOrigin,
|
||||
@@ -255,7 +255,7 @@ export class StaticFileServerManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* 销毁静态文件管理器
|
||||
* Destroy the static file manager
|
||||
*/
|
||||
destroy() {
|
||||
logger.info('Destroying StaticFileServerManager');
|
||||
|
||||
@@ -67,56 +67,56 @@ export class TrayManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过标识符获取托盘实例
|
||||
* @param identifier 托盘标识符
|
||||
* Retrieve a tray instance by identifier
|
||||
* @param identifier Tray identifier
|
||||
*/
|
||||
retrieveByIdentifier(identifier: TrayIdentifiers) {
|
||||
logger.debug(`通过标识符获取托盘: ${identifier}`);
|
||||
logger.debug(`Retrieving tray by identifier: ${identifier}`);
|
||||
return this.trays.get(identifier);
|
||||
}
|
||||
|
||||
/**
|
||||
* 向所有托盘广播消息
|
||||
* @param event 事件名称
|
||||
* @param data 事件数据
|
||||
* Broadcast a message to all trays
|
||||
* @param event Event name
|
||||
* @param data Event data
|
||||
*/
|
||||
broadcastToAllTrays = <T extends MainBroadcastEventKey>(
|
||||
event: T,
|
||||
data: MainBroadcastParams<T>,
|
||||
) => {
|
||||
logger.debug(`向所有托盘广播事件 ${event}`);
|
||||
logger.debug(`Broadcasting event ${event} to all trays`);
|
||||
this.trays.forEach((tray) => {
|
||||
tray.broadcast(event, data);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 向指定托盘广播消息
|
||||
* @param identifier 托盘标识符
|
||||
* @param event 事件名称
|
||||
* @param data 事件数据
|
||||
* Broadcast a message to a specific tray
|
||||
* @param identifier Tray identifier
|
||||
* @param event Event name
|
||||
* @param data Event data
|
||||
*/
|
||||
broadcastToTray = <T extends MainBroadcastEventKey>(
|
||||
identifier: TrayIdentifiers,
|
||||
event: T,
|
||||
data: MainBroadcastParams<T>,
|
||||
) => {
|
||||
logger.debug(`向托盘 ${identifier} 广播事件 ${event}`);
|
||||
logger.debug(`Broadcasting event ${event} to tray ${identifier}`);
|
||||
this.trays.get(identifier)?.broadcast(event, data);
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取或创建托盘实例
|
||||
* @param options 托盘选项
|
||||
* Retrieve or create a tray instance
|
||||
* @param options Tray options
|
||||
*/
|
||||
private retrieveOrInitialize(options: TrayOptions) {
|
||||
let tray = this.trays.get(options.identifier as TrayIdentifiers);
|
||||
if (tray) {
|
||||
logger.debug(`获取现有托盘: ${options.identifier}`);
|
||||
logger.debug(`Retrieved existing tray: ${options.identifier}`);
|
||||
return tray;
|
||||
}
|
||||
|
||||
logger.debug(`创建新托盘: ${options.identifier}`);
|
||||
logger.debug(`Creating new tray: ${options.identifier}`);
|
||||
tray = new Tray(options, this.app);
|
||||
|
||||
this.trays.set(options.identifier as TrayIdentifiers, tray);
|
||||
@@ -125,10 +125,10 @@ export class TrayManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* 销毁所有托盘
|
||||
* Destroy all trays
|
||||
*/
|
||||
destroyAll() {
|
||||
logger.debug('销毁所有托盘');
|
||||
logger.debug('Destroying all trays');
|
||||
this.trays.forEach((tray) => {
|
||||
tray.destroy();
|
||||
});
|
||||
|
||||
@@ -24,7 +24,7 @@ export const createMenuImpl = (app: App): IMenuPlatform => {
|
||||
}
|
||||
|
||||
default: {
|
||||
// 提供一个备用或抛出错误
|
||||
// Provide a fallback or throw an error
|
||||
console.warn(
|
||||
`Unsupported platform for menu: ${currentPlatform}, using Windows implementation as fallback.`,
|
||||
);
|
||||
|
||||
@@ -158,7 +158,7 @@ export default class FileService extends ServiceModule {
|
||||
async getFile(path: string): Promise<{ content: ArrayBuffer; mimeType: string }> {
|
||||
logger.info(`Getting file content: ${path}`);
|
||||
try {
|
||||
// 处理desktop://路径
|
||||
// Handle desktop:// paths
|
||||
if (!path.startsWith('desktop://')) {
|
||||
logger.error(`Invalid desktop file path: ${path}`);
|
||||
throw new Error(`Invalid desktop file path: ${path}`);
|
||||
@@ -208,7 +208,7 @@ export default class FileService extends ServiceModule {
|
||||
logger.error(
|
||||
`Both legacy and fallback paths failed. Legacy error: ${(firstError as Error).message}, Fallback error: ${(fallbackError as Error).message}`,
|
||||
);
|
||||
throw firstError; // 抛出原始错误
|
||||
throw firstError; // Re-throw the original error
|
||||
}
|
||||
} else {
|
||||
throw firstError;
|
||||
@@ -286,7 +286,7 @@ export default class FileService extends ServiceModule {
|
||||
async deleteFile(path: string): Promise<{ success: boolean }> {
|
||||
logger.info(`Deleting file: ${path}`);
|
||||
try {
|
||||
// 处理desktop://路径
|
||||
// Handle desktop:// paths
|
||||
if (!path.startsWith('desktop://')) {
|
||||
logger.error(`Invalid desktop file path: ${path}`);
|
||||
throw new Error(`Invalid desktop file path: ${path}`);
|
||||
@@ -333,7 +333,7 @@ export default class FileService extends ServiceModule {
|
||||
logger.error(
|
||||
`Both legacy and fallback deletion failed. Legacy error: ${(firstError as Error).message}, Fallback error: ${(fallbackError as Error).message}`,
|
||||
);
|
||||
throw firstError; // 抛出原始错误
|
||||
throw firstError; // Re-throw the original error
|
||||
}
|
||||
} else {
|
||||
throw firstError;
|
||||
|
||||
@@ -51,7 +51,7 @@ describe('setupElectronApi', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should expose lobeEnv with darwinMajorVersion', () => {
|
||||
it('should expose lobeEnv with darwinMajorVersion and isMacTahoe', () => {
|
||||
setupElectronApi();
|
||||
|
||||
const call = mockContextBridgeExposeInMainWorld.mock.calls.find((i) => i[0] === 'lobeEnv');
|
||||
@@ -63,6 +63,9 @@ describe('setupElectronApi', () => {
|
||||
exposedEnv.darwinMajorVersion === undefined ||
|
||||
typeof exposedEnv.darwinMajorVersion === 'number',
|
||||
).toBe(true);
|
||||
|
||||
expect(Object.prototype.hasOwnProperty.call(exposedEnv, 'isMacTahoe')).toBe(true);
|
||||
expect(typeof exposedEnv.isMacTahoe).toBe('boolean');
|
||||
});
|
||||
|
||||
it('should expose both APIs in correct order', () => {
|
||||
|
||||
@@ -22,9 +22,10 @@ export const setupElectronApi = () => {
|
||||
|
||||
const os = require('node:os');
|
||||
const osInfo = os.release();
|
||||
const darwinMajorVersion = osInfo.split('.')[0];
|
||||
const darwinMajorVersion = Number(osInfo.split('.')[0]);
|
||||
|
||||
contextBridge.exposeInMainWorld('lobeEnv', {
|
||||
darwinMajorVersion: Number(darwinMajorVersion),
|
||||
darwinMajorVersion,
|
||||
isMacTahoe: process.platform === 'darwin' && darwinMajorVersion >= 25,
|
||||
});
|
||||
};
|
||||
|
||||
@@ -201,6 +201,7 @@ table async_tasks {
|
||||
type text
|
||||
status text
|
||||
error jsonb
|
||||
inference_id text
|
||||
user_id text [not null]
|
||||
duration integer
|
||||
parent_id uuid
|
||||
@@ -213,6 +214,7 @@ table async_tasks {
|
||||
user_id [name: 'async_tasks_user_id_idx']
|
||||
parent_id [name: 'async_tasks_parent_id_idx']
|
||||
(type, status) [name: 'async_tasks_type_status_idx']
|
||||
inference_id [name: 'async_tasks_inference_id_idx']
|
||||
metadata [name: 'async_tasks_metadata_idx']
|
||||
}
|
||||
}
|
||||
@@ -479,6 +481,7 @@ table generation_topics {
|
||||
user_id text [not null]
|
||||
title text
|
||||
cover_url text
|
||||
type varchar(32) [not null, default: 'image']
|
||||
accessed_at "timestamp with time zone" [not null, default: `now()`]
|
||||
created_at "timestamp with time zone" [not null, default: `now()`]
|
||||
updated_at "timestamp with time zone" [not null, default: `now()`]
|
||||
|
||||
@@ -10,7 +10,7 @@ import { Given, Then, When } from '@cucumber/cucumber';
|
||||
import { expect } from '@playwright/test';
|
||||
|
||||
import { TEST_USER } from '../../support/seedTestUser';
|
||||
import { CustomWorld, WAIT_TIMEOUT } from '../../support/world';
|
||||
import { type CustomWorld, WAIT_TIMEOUT } from '../../support/world';
|
||||
|
||||
// ============================================
|
||||
// Helper Functions
|
||||
@@ -23,67 +23,29 @@ async function inputNewName(
|
||||
): Promise<void> {
|
||||
await this.page.waitForTimeout(300);
|
||||
|
||||
// Try to find the popover input
|
||||
const popoverInputSelectors = [
|
||||
'.ant-popover-inner input',
|
||||
'.ant-popover-content input',
|
||||
'.ant-popover input',
|
||||
];
|
||||
// Primary: find input inside EditingPopover (data-testid) or antd Popover
|
||||
const renameInput = this.page
|
||||
.locator('[data-testid="editing-popover"] input, .ant-popover input')
|
||||
.first();
|
||||
|
||||
let renameInput = null;
|
||||
await renameInput.waitFor({ state: 'visible', timeout: 5000 });
|
||||
await renameInput.click();
|
||||
await renameInput.clear();
|
||||
await renameInput.fill(newName);
|
||||
|
||||
for (const selector of popoverInputSelectors) {
|
||||
try {
|
||||
const locator = this.page.locator(selector).first();
|
||||
await locator.waitFor({ state: 'visible', timeout: 2000 });
|
||||
renameInput = locator;
|
||||
break;
|
||||
} catch {
|
||||
// Try next selector
|
||||
}
|
||||
}
|
||||
|
||||
if (!renameInput) {
|
||||
// Fallback: find any visible input
|
||||
const allInputs = this.page.locator('input:visible');
|
||||
const count = await allInputs.count();
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
const input = allInputs.nth(i);
|
||||
const placeholder = (await input.getAttribute('placeholder').catch(() => '')) || '';
|
||||
if (placeholder.includes('Search') || placeholder.includes('搜索')) continue;
|
||||
|
||||
const isInPopover = await input.evaluate((el) => {
|
||||
return el.closest('.ant-popover') !== null || el.closest('[class*="popover"]') !== null;
|
||||
});
|
||||
|
||||
if (isInPopover || count <= 2) {
|
||||
renameInput = input;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (renameInput) {
|
||||
await renameInput.click();
|
||||
await renameInput.clear();
|
||||
await renameInput.fill(newName);
|
||||
|
||||
if (pressEnter) {
|
||||
await renameInput.press('Enter');
|
||||
} else {
|
||||
await this.page.click('body', { position: { x: 10, y: 10 } });
|
||||
}
|
||||
if (pressEnter) {
|
||||
await renameInput.press('Enter');
|
||||
} else {
|
||||
// Keyboard fallback
|
||||
await this.page.keyboard.press('Meta+A');
|
||||
await this.page.waitForTimeout(50);
|
||||
await this.page.keyboard.type(newName, { delay: 20 });
|
||||
|
||||
if (pressEnter) {
|
||||
await this.page.keyboard.press('Enter');
|
||||
} else {
|
||||
await this.page.click('body', { position: { x: 10, y: 10 } });
|
||||
// Click the save button (ActionIcon with Check icon) next to the input
|
||||
const saveButton = this.page
|
||||
.locator('[data-testid="editing-popover"] svg.lucide-check, .ant-popover svg.lucide-check')
|
||||
.first();
|
||||
try {
|
||||
await saveButton.waitFor({ state: 'visible', timeout: 2000 });
|
||||
await saveButton.click();
|
||||
} catch {
|
||||
// Fallback: press Enter to save
|
||||
await renameInput.press('Enter');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-console */
|
||||
/**
|
||||
* Home Starter Steps
|
||||
*
|
||||
@@ -12,7 +13,7 @@ import { Given, Then, When } from '@cucumber/cucumber';
|
||||
import { expect } from '@playwright/test';
|
||||
|
||||
import { llmMockManager, presetResponses } from '../../mocks/llm';
|
||||
import { CustomWorld, WAIT_TIMEOUT } from '../../support/world';
|
||||
import { type CustomWorld, WAIT_TIMEOUT } from '../../support/world';
|
||||
|
||||
// Store created IDs for verification
|
||||
let createdAgentId: string | null = null;
|
||||
@@ -61,7 +62,9 @@ When('用户点击创建 Agent 按钮', async function (this: CustomWorld) {
|
||||
|
||||
await expect(createAgentButton).toBeVisible({ timeout: WAIT_TIMEOUT });
|
||||
await createAgentButton.click();
|
||||
await this.page.waitForTimeout(500);
|
||||
|
||||
// Wait for mode switch animation and ChatInput scroll-into-view to settle
|
||||
await this.page.waitForTimeout(800);
|
||||
|
||||
console.log(' ✅ 已点击创建 Agent 按钮');
|
||||
});
|
||||
@@ -76,7 +79,9 @@ When('用户点击创建 Group 按钮', async function (this: CustomWorld) {
|
||||
|
||||
await expect(createGroupButton).toBeVisible({ timeout: WAIT_TIMEOUT });
|
||||
await createGroupButton.click();
|
||||
await this.page.waitForTimeout(500);
|
||||
|
||||
// Wait for mode switch animation and ChatInput scroll-into-view to settle
|
||||
await this.page.waitForTimeout(800);
|
||||
|
||||
console.log(' ✅ 已点击创建 Group 按钮');
|
||||
});
|
||||
@@ -89,7 +94,9 @@ When('用户点击写作按钮', async function (this: CustomWorld) {
|
||||
|
||||
await expect(writeButton).toBeVisible({ timeout: WAIT_TIMEOUT });
|
||||
await writeButton.click();
|
||||
await this.page.waitForTimeout(500);
|
||||
|
||||
// Wait for mode switch animation and ChatInput scroll-into-view to settle
|
||||
await this.page.waitForTimeout(800);
|
||||
|
||||
console.log(' ✅ 已点击写作按钮');
|
||||
});
|
||||
@@ -97,36 +104,28 @@ When('用户点击写作按钮', async function (this: CustomWorld) {
|
||||
When('用户在输入框中输入 {string}', async function (this: CustomWorld, message: string) {
|
||||
console.log(` 📍 Step: 在输入框中输入 "${message}"...`);
|
||||
|
||||
// The chat input is a contenteditable editor, need to click first then type
|
||||
// The chat input is a contenteditable editor, need to click first then type.
|
||||
// Target the contenteditable element INSIDE the ChatInput container directly,
|
||||
// since clicking the container might hit the action bar/footer area instead.
|
||||
const chatInputContainer = this.page.locator('[data-testid="chat-input"]').first();
|
||||
await expect(chatInputContainer).toBeVisible({ timeout: WAIT_TIMEOUT });
|
||||
|
||||
// If data-testid not found, try alternative selectors
|
||||
let inputFound = false;
|
||||
if ((await chatInputContainer.count()) > 0) {
|
||||
await chatInputContainer.click();
|
||||
inputFound = true;
|
||||
} else {
|
||||
// Try to find the editor by its contenteditable attribute
|
||||
const editor = this.page.locator('[contenteditable="true"]').first();
|
||||
if ((await editor.count()) > 0) {
|
||||
await editor.click();
|
||||
inputFound = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!inputFound) {
|
||||
throw new Error('Could not find chat input');
|
||||
}
|
||||
|
||||
const editor = chatInputContainer.locator('[contenteditable="true"]').first();
|
||||
await editor.click();
|
||||
await this.page.waitForTimeout(300);
|
||||
await this.page.keyboard.type(message, { delay: 30 });
|
||||
|
||||
console.log(` ✅ 已输入 "${message}"`);
|
||||
});
|
||||
|
||||
When('用户按 Enter 发送', async function (this: CustomWorld) {
|
||||
When('用户按 Enter 发送', { timeout: 30_000 }, async function (this: CustomWorld) {
|
||||
console.log(' 📍 Step: 按 Enter 发送...');
|
||||
|
||||
// Wait for editor's debounced onChange (100ms default) to sync inputMessage to store.
|
||||
// The send() function reads directly from the editor as a fallback, but this wait
|
||||
// ensures maximum reliability.
|
||||
await this.page.waitForTimeout(200);
|
||||
|
||||
// Listen for navigation to capture the agent/group ID
|
||||
const navigationPromise = this.page.waitForURL(/\/(agent|group)\/.*\/profile/, {
|
||||
timeout: 30_000,
|
||||
@@ -156,9 +155,12 @@ When('用户按 Enter 发送', async function (this: CustomWorld) {
|
||||
console.log(' ✅ 已发送消息');
|
||||
});
|
||||
|
||||
When('用户按 Enter 发送创建文档', async function (this: CustomWorld) {
|
||||
When('用户按 Enter 发送创建文档', { timeout: 30_000 }, async function (this: CustomWorld) {
|
||||
console.log(' 📍 Step: 按 Enter 发送创建文档...');
|
||||
|
||||
// Wait for editor's debounced onChange (100ms default) to sync inputMessage to store
|
||||
await this.page.waitForTimeout(200);
|
||||
|
||||
// Listen for navigation to capture the document ID
|
||||
const navigationPromise = this.page.waitForURL(/\/page\/[^/]+/, {
|
||||
timeout: 30_000,
|
||||
|
||||
+128
-108
@@ -1,77 +1,26 @@
|
||||
{
|
||||
"src/app/[variants]/(desktop)/desktop-onboarding/features/WelcomeStep.tsx": {
|
||||
"@eslint-react/no-nested-component-definitions": {
|
||||
"src/app/(backend)/api/dev/memory-user-memory/benchmark-locomo/route.ts": {
|
||||
"no-console": {
|
||||
"count": 6
|
||||
}
|
||||
},
|
||||
"src/app/(backend)/api/webhooks/logto/route.ts": {
|
||||
"no-console": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/app/[variants]/(main)/agent/profile/features/Header/AgentPublishButton/PublishButton.tsx": {
|
||||
"import-x/consistent-type-specifier-style": {
|
||||
"src/app/(backend)/trpc/async/[trpc]/route.ts": {
|
||||
"no-console": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/app/[variants]/(main)/community/(detail)/agent/features/Details/Capabilities/PluginItem.tsx": {
|
||||
"simple-import-sort/imports": {
|
||||
"src/app/(backend)/trpc/mobile/[trpc]/route.ts": {
|
||||
"no-console": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/app/[variants]/(main)/community/(detail)/agent/features/Header.tsx": {
|
||||
"simple-import-sort/imports": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/app/[variants]/(main)/community/components/VirtuosoGridList/index.tsx": {
|
||||
"@eslint-react/no-nested-component-definitions": {
|
||||
"count": 2
|
||||
}
|
||||
},
|
||||
"src/app/[variants]/(main)/home/_layout/Body/Agent/Modals/ConfigGroupModal/GroupItem.tsx": {
|
||||
"import-x/consistent-type-specifier-style": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/app/[variants]/(main)/home/_layout/Body/Agent/Modals/ConfigGroupModal/index.tsx": {
|
||||
"@typescript-eslint/consistent-type-imports": {
|
||||
"count": 1
|
||||
},
|
||||
"simple-import-sort/imports": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/app/[variants]/(main)/home/features/RecentPage/Item.tsx": {
|
||||
"regexp/no-super-linear-backtracking": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/app/[variants]/(main)/home/features/index.tsx": {
|
||||
"@eslint-react/no-nested-component-definitions": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/app/[variants]/(main)/memory/features/GridView/index.tsx": {
|
||||
"@eslint-react/no-nested-component-definitions": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/app/[variants]/(main)/resource/features/hooks/useResourceManagerUrlSync.ts": {
|
||||
"react-hooks/exhaustive-deps": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/app/[variants]/(main)/settings/provider/detail/ollama/CheckError.tsx": {
|
||||
"regexp/no-dupe-characters-character-class": {
|
||||
"count": 1
|
||||
},
|
||||
"regexp/no-obscure-range": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/app/[variants]/onboarding/features/ResponseLanguageStep.tsx": {
|
||||
"@eslint-react/no-nested-component-definitions": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/app/[variants]/onboarding/features/TelemetryStep.tsx": {
|
||||
"@eslint-react/no-nested-component-definitions": {
|
||||
"src/app/(backend)/webapi/chat/[provider]/route.ts": {
|
||||
"no-console": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
@@ -88,6 +37,16 @@
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/components/DebugNode.tsx": {
|
||||
"no-console": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/components/FeedbackModal/index.tsx": {
|
||||
"no-console": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/components/Loading/CircleLoading/index.tsx": {
|
||||
"unicorn/no-anonymous-default-export": {
|
||||
"count": 1
|
||||
@@ -114,9 +73,6 @@
|
||||
}
|
||||
},
|
||||
"src/envs/auth.ts": {
|
||||
"perfectionist/sort-interfaces": {
|
||||
"count": 19
|
||||
},
|
||||
"sort-keys-fix/sort-keys-fix": {
|
||||
"count": 1
|
||||
},
|
||||
@@ -150,6 +106,21 @@
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/features/ChatInput/ActionBar/Tools/KlavisServerItem.tsx": {
|
||||
"no-console": {
|
||||
"count": 2
|
||||
}
|
||||
},
|
||||
"src/features/ChatInput/ActionBar/Tools/LobehubSkillServerItem.tsx": {
|
||||
"no-console": {
|
||||
"count": 3
|
||||
}
|
||||
},
|
||||
"src/features/CommandMenu/SearchResults.tsx": {
|
||||
"no-console": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/features/Conversation/Error/OllamaBizError/index.tsx": {
|
||||
"regexp/no-dupe-characters-character-class": {
|
||||
"count": 1
|
||||
@@ -158,13 +129,8 @@
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/features/Conversation/Messages/CompressedGroup/index.tsx": {
|
||||
"import-x/consistent-type-specifier-style": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/features/Conversation/Messages/Supervisor/components/ContentBlock.tsx": {
|
||||
"simple-import-sort/imports": {
|
||||
"src/features/Conversation/store/slices/message/action/sendMessage.ts": {
|
||||
"no-console": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
@@ -183,11 +149,6 @@
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/features/NavPanel/SideBarHeaderLayout.tsx": {
|
||||
"@eslint-react/dom/no-flush-sync": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/features/PluginsUI/Render/utils/iframeOnReady.test.ts": {
|
||||
"unicorn/no-invalid-remove-event-listener": {
|
||||
"count": 1
|
||||
@@ -228,7 +189,20 @@
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/hooks/useAgentOwnershipCheck.ts": {
|
||||
"no-console": {
|
||||
"count": 6
|
||||
}
|
||||
},
|
||||
"src/hooks/useHotkeys/useHotkeyById.ts": {
|
||||
"no-console": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/layout/AuthProvider/MarketAuth/oidc.ts": {
|
||||
"no-console": {
|
||||
"count": 17
|
||||
},
|
||||
"prefer-const": {
|
||||
"count": 1
|
||||
}
|
||||
@@ -241,6 +215,11 @@
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/libs/next/proxy/define-config.ts": {
|
||||
"no-console": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/libs/observability/traceparent.test.ts": {
|
||||
"import/first": {
|
||||
"count": 1
|
||||
@@ -254,6 +233,16 @@
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/libs/swr/localStorageProvider.ts": {
|
||||
"no-console": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/libs/traces/index.ts": {
|
||||
"no-console": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/libs/trpc/middleware/openTelemetry.test.ts": {
|
||||
"import/first": {
|
||||
"count": 1
|
||||
@@ -287,6 +276,16 @@
|
||||
"count": 2
|
||||
}
|
||||
},
|
||||
"src/server/routers/lambda/agent.ts": {
|
||||
"no-console": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/server/routers/lambda/aiAgent.ts": {
|
||||
"no-console": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/server/routers/lambda/aiChat.ts": {
|
||||
"prefer-const": {
|
||||
"count": 1
|
||||
@@ -302,32 +301,26 @@
|
||||
"count": 2
|
||||
}
|
||||
},
|
||||
"src/server/routers/lambda/knowledge.ts": {
|
||||
"no-console": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/server/routers/lambda/ragEval.ts": {
|
||||
"sort-keys-fix/sort-keys-fix": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/server/routers/lambda/sessionGroup.ts": {
|
||||
"no-console": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/server/routers/lambda/user.ts": {
|
||||
"sort-keys-fix/sort-keys-fix": {
|
||||
"count": 2
|
||||
}
|
||||
},
|
||||
"src/server/routers/lambda/userMemory.ts": {
|
||||
"@typescript-eslint/consistent-type-imports": {
|
||||
"count": 1
|
||||
},
|
||||
"import-x/no-duplicates": {
|
||||
"count": 2
|
||||
},
|
||||
"simple-import-sort/imports": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/server/routers/tools/_helpers/scheduleToolCallReport.test.ts": {
|
||||
"simple-import-sort/imports": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/server/routers/tools/mcp.ts": {
|
||||
"sort-keys-fix/sort-keys-fix": {
|
||||
"count": 1
|
||||
@@ -431,16 +424,26 @@
|
||||
"count": 7
|
||||
}
|
||||
},
|
||||
"src/server/services/webhookUser/index.ts": {
|
||||
"no-console": {
|
||||
"count": 2
|
||||
}
|
||||
},
|
||||
"src/services/_url.ts": {
|
||||
"sort-keys-fix/sort-keys-fix": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/services/chat/mecha/contextEngineering.ts": {
|
||||
"sort-keys-fix/sort-keys-fix": {
|
||||
"src/services/models.ts": {
|
||||
"no-console": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/services/tableViewer/client.ts": {
|
||||
"no-console": {
|
||||
"count": 2
|
||||
}
|
||||
},
|
||||
"src/store/agent/slices/cron/action.ts": {
|
||||
"no-unused-private-class-members": {
|
||||
"count": 1
|
||||
@@ -485,14 +488,6 @@
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/store/chat/slices/aiChat/actions/__tests__/StreamingHandler.test.ts": {
|
||||
"import-x/consistent-type-specifier-style": {
|
||||
"count": 1
|
||||
},
|
||||
"unused-imports/no-unused-imports": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/store/chat/slices/aiChat/actions/conversationControl.ts": {
|
||||
"no-unused-private-class-members": {
|
||||
"count": 1
|
||||
@@ -538,6 +533,11 @@
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/store/chat/slices/message/supervisor.ts": {
|
||||
"no-console": {
|
||||
"count": 5
|
||||
}
|
||||
},
|
||||
"src/store/chat/slices/operation/types.ts": {
|
||||
"sort-keys-fix/sort-keys-fix": {
|
||||
"count": 1
|
||||
@@ -680,6 +680,11 @@
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/store/file/slices/chat/action.ts": {
|
||||
"no-console": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/store/file/slices/chunk/action.ts": {
|
||||
"no-unused-private-class-members": {
|
||||
"count": 1
|
||||
@@ -710,6 +715,11 @@
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/store/home/slices/homeInput/action.ts": {
|
||||
"no-console": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/store/image/slices/generationConfig/initialState.ts": {
|
||||
"sort-keys-fix/sort-keys-fix": {
|
||||
"count": 1
|
||||
@@ -733,6 +743,11 @@
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/store/session/slices/homeInput/action.ts": {
|
||||
"no-console": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/store/session/slices/session/action.ts": {
|
||||
"typescript-sort-keys/interface": {
|
||||
"count": 1
|
||||
@@ -746,8 +761,13 @@
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/store/tool/slices/builtin/executors/index.ts": {
|
||||
"import-x/consistent-type-specifier-style": {
|
||||
"src/store/tool/slices/klavisStore/action.ts": {
|
||||
"no-console": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/store/tool/slices/mcpStore/action.ts": {
|
||||
"no-console": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
@@ -779,4 +799,4 @@
|
||||
"count": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,10 @@
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
import { eslint } from '@lobehub/lint';
|
||||
import { flat as mdxFlat } from 'eslint-plugin-mdx';
|
||||
|
||||
const tsconfigRootDir = fileURLToPath(new URL('.', import.meta.url));
|
||||
|
||||
export default eslint(
|
||||
{
|
||||
ignores: [
|
||||
@@ -40,6 +44,13 @@ export default eslint(
|
||||
next: true,
|
||||
react: 'next',
|
||||
},
|
||||
{
|
||||
languageOptions: {
|
||||
parserOptions: {
|
||||
tsconfigRootDir,
|
||||
},
|
||||
},
|
||||
},
|
||||
// Global rule overrides
|
||||
{
|
||||
rules: {
|
||||
@@ -81,4 +92,11 @@ export default eslint(
|
||||
'unicorn/prefer-top-level-await': 0,
|
||||
},
|
||||
},
|
||||
// E2E and test files - allow console.log for debugging
|
||||
{
|
||||
files: ['e2e/**/*', '**/*.test.ts', '**/*.test.tsx'],
|
||||
rules: {
|
||||
'no-console': 0,
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
<!doctype html>
|
||||
<html lang="<!--LOCALE-->" dir="<!--DIR-->">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<style>
|
||||
#root {
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
<!--SEO_META-->
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script>
|
||||
// window.__SERVER_CONFIG__ = <!--SERVER_CONFIG-->;
|
||||
window.__SERVER_CONFIG__ = undefined; /* SERVER_CONFIG */
|
||||
</script>
|
||||
<!--ANALYTICS_SCRIPTS-->
|
||||
<script type="module" src="/src/spa/entry.desktop.tsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,16 @@
|
||||
<!doctype html>
|
||||
<html lang="<!--LOCALE-->" dir="<!--DIR-->">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<!--SEO_META-->
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script>
|
||||
window.__SERVER_CONFIG__ = undefined; /* SERVER_CONFIG */
|
||||
</script>
|
||||
<!--ANALYTICS_SCRIPTS-->
|
||||
<script type="module" src="/src/spa/entry.mobile.tsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -58,13 +58,13 @@
|
||||
"duplicateTitle": "نسخة {{title}}",
|
||||
"emptyAgent": "لا يوجد وكلاء بعد. ابدأ بأول وكيل لك — وابنِ نظامك بمرور الوقت.",
|
||||
"emptyAgentAction": "إنشاء وكيل",
|
||||
"extendParams.disableContextCaching.desc": "يقلل ما يصل إلى 90٪ من تكلفة توليد محادثة واحدة ويوفر سرعة تصل إلى 4 أضعاف. تفعيل هذا سيقوم تلقائيًا بإلغاء الحد على عدد الرسائل التاريخية. <1>اعرف المزيد</1>",
|
||||
"extendParams.disableContextCaching.desc": "قلل تكلفة إنشاء محادثة واحدة بنسبة تصل إلى 90٪ وزد السرعة حتى 4 أضعاف. <1>اعرف المزيد</1>",
|
||||
"extendParams.disableContextCaching.title": "تفعيل تخزين السياق المؤقت",
|
||||
"extendParams.effort.desc": "تحكم في عدد الرموز التي يستخدمها كلود عند الرد باستخدام معلمة الجهد.",
|
||||
"extendParams.effort.title": "الجهد",
|
||||
"extendParams.enableAdaptiveThinking.desc": "اسمح لكلود باتخاذ قرارات ديناميكية حول متى وكم يفكر باستخدام وضع التفكير التكيفي.",
|
||||
"extendParams.enableAdaptiveThinking.title": "تفعيل التفكير التكيفي",
|
||||
"extendParams.enableReasoning.desc": "استنادًا إلى آلية التفكير في Claude، فإن تفعيل هذا سيقوم تلقائيًا بإلغاء الحد على عدد الرسائل التاريخية. <1>اعرف المزيد</1>",
|
||||
"extendParams.enableReasoning.desc": "استنادًا إلى حد آلية التفكير في Claude. <1>اعرف المزيد</1>",
|
||||
"extendParams.enableReasoning.title": "تفعيل التفكير العميق",
|
||||
"extendParams.imageAspectRatio.title": "نسبة أبعاد الصورة",
|
||||
"extendParams.imageResolution.title": "دقة الصورة",
|
||||
@@ -165,6 +165,7 @@
|
||||
"messageAction.delAndRegenerate": "حذف وإعادة التوليد",
|
||||
"messageAction.deleteDisabledByThreads": "لا يمكن حذف هذه الرسالة لأنها تحتوي على موضوع فرعي",
|
||||
"messageAction.expand": "توسيع الرسالة",
|
||||
"messageAction.reaction": "إضافة تفاعل",
|
||||
"messageAction.regenerate": "إعادة التوليد",
|
||||
"messages.dm.sentTo": "مرئي فقط لـ {{name}}",
|
||||
"messages.dm.title": "رسالة خاصة",
|
||||
|
||||
@@ -143,6 +143,7 @@
|
||||
"cmdk.keywords.stats": "إحصائيات تحليلات بيانات",
|
||||
"cmdk.keywords.submitIssue": "مشكلة خلل عطل ملاحظات",
|
||||
"cmdk.keywords.usage": "الاستخدام الإحصائيات الاستهلاك الحصة",
|
||||
"cmdk.keywords.video": "فيديو،إنشاء،سيدانص،كلينغ",
|
||||
"cmdk.memory": "الذاكرة",
|
||||
"cmdk.mentionAgent": "اذكر الوكيل",
|
||||
"cmdk.navigate": "تنقل",
|
||||
@@ -193,6 +194,7 @@
|
||||
"cmdk.themeLight": "فاتح",
|
||||
"cmdk.toOpen": "فتح",
|
||||
"cmdk.toSelect": "تحديد",
|
||||
"cmdk.video": "فيديو بالذكاء الاصطناعي",
|
||||
"confirm": "تأكيد",
|
||||
"contact": "اتصل بنا",
|
||||
"copy": "نسخ",
|
||||
|
||||
@@ -43,6 +43,8 @@
|
||||
"FileManager.emptyStatus.or": "أو",
|
||||
"FileManager.emptyStatus.title": "اسحب الملفات أو المجلدات إلى هنا",
|
||||
"FileManager.noFolders": "لا توجد مجلدات متاحة",
|
||||
"FileManager.search.noResults": "لم يتم العثور على ملفات",
|
||||
"FileManager.search.placeholder": "ابحث في الملفات...",
|
||||
"FileManager.sort.dateAdded": "تاريخ الإضافة",
|
||||
"FileManager.sort.name": "الاسم",
|
||||
"FileManager.sort.size": "الحجم",
|
||||
@@ -94,6 +96,35 @@
|
||||
"ModelSelect.removed": "النموذج غير موجود في القائمة. سيتم حذفه تلقائيًا إذا تم إلغاء تحديده.",
|
||||
"ModelSwitchPanel.byModel": "حسب النموذج",
|
||||
"ModelSwitchPanel.byProvider": "حسب المزوّد",
|
||||
"ModelSwitchPanel.detail.abilities": "القدرات",
|
||||
"ModelSwitchPanel.detail.abilities.files": "الملفات",
|
||||
"ModelSwitchPanel.detail.abilities.functionCall": "استدعاء الأداة",
|
||||
"ModelSwitchPanel.detail.abilities.imageOutput": "إخراج الصورة",
|
||||
"ModelSwitchPanel.detail.abilities.reasoning": "الاستدلال",
|
||||
"ModelSwitchPanel.detail.abilities.search": "البحث",
|
||||
"ModelSwitchPanel.detail.abilities.video": "الفيديو",
|
||||
"ModelSwitchPanel.detail.abilities.vision": "الرؤية",
|
||||
"ModelSwitchPanel.detail.config": "إعداد النموذج",
|
||||
"ModelSwitchPanel.detail.context": "طول السياق",
|
||||
"ModelSwitchPanel.detail.pricing": "الأسعار",
|
||||
"ModelSwitchPanel.detail.pricing.cachedInput": "المدخلات المخزنة ${{amount}}/مليون",
|
||||
"ModelSwitchPanel.detail.pricing.group.audio": "الصوت",
|
||||
"ModelSwitchPanel.detail.pricing.group.image": "الصورة",
|
||||
"ModelSwitchPanel.detail.pricing.group.text": "النص",
|
||||
"ModelSwitchPanel.detail.pricing.input": "المدخلات ${{amount}}/مليون",
|
||||
"ModelSwitchPanel.detail.pricing.output": "المخرجات ${{amount}}/مليون",
|
||||
"ModelSwitchPanel.detail.pricing.unit.audioInput": "مدخل صوتي",
|
||||
"ModelSwitchPanel.detail.pricing.unit.audioInput_cacheRead": "مدخل صوتي (مخزن)",
|
||||
"ModelSwitchPanel.detail.pricing.unit.audioOutput": "مخرج صوتي",
|
||||
"ModelSwitchPanel.detail.pricing.unit.imageGeneration": "توليد الصور",
|
||||
"ModelSwitchPanel.detail.pricing.unit.imageInput": "مدخل صورة",
|
||||
"ModelSwitchPanel.detail.pricing.unit.imageInput_cacheRead": "مدخل صورة (مخزن)",
|
||||
"ModelSwitchPanel.detail.pricing.unit.imageOutput": "مخرج صورة",
|
||||
"ModelSwitchPanel.detail.pricing.unit.textInput": "مدخل",
|
||||
"ModelSwitchPanel.detail.pricing.unit.textInput_cacheRead": "مدخل (مخزن)",
|
||||
"ModelSwitchPanel.detail.pricing.unit.textInput_cacheWrite": "مدخل (كتابة في التخزين)",
|
||||
"ModelSwitchPanel.detail.pricing.unit.textOutput": "مخرج",
|
||||
"ModelSwitchPanel.detail.releasedAt": "تم الإصدار في {{date}}",
|
||||
"ModelSwitchPanel.emptyModel": "لا يوجد نموذج مفعل. يرجى الذهاب إلى الإعدادات لتفعيله.",
|
||||
"ModelSwitchPanel.emptyProvider": "لا يوجد مزود مفعل. يرجى الذهاب إلى الإعدادات لتفعيل أحدهم.",
|
||||
"ModelSwitchPanel.goToSettings": "الذهاب إلى الإعدادات",
|
||||
|
||||
@@ -150,6 +150,9 @@
|
||||
"groupAgents.tag": "مجموعة",
|
||||
"groupAgents.underReview": "قيد المراجعة",
|
||||
"home.communityAgents": "وكلاء المجتمع",
|
||||
"home.creatorReward.action": "قدّم الآن",
|
||||
"home.creatorReward.subtitle": "برنامج مكافآت المبدعين لعام 2026 أصبح متاحًا رسميًا.",
|
||||
"home.creatorReward.title": "أنشئ. شارك. واحصل على مقابل.",
|
||||
"home.featuredAssistants": "وكلاء مميزون",
|
||||
"home.featuredModels": "نماذج مميزة",
|
||||
"home.featuredPlugins": "مهارات مميزة",
|
||||
@@ -194,6 +197,8 @@
|
||||
"mcp.categories.tools.name": "أدوات مساعدة",
|
||||
"mcp.categories.travel-transport.description": "تخطيط السفر والمواصلات",
|
||||
"mcp.categories.travel-transport.name": "السفر والمواصلات",
|
||||
"mcp.categories.utility.description": "خدمات التنبؤ بالطقس والأرصاد الجوية",
|
||||
"mcp.categories.utility.name": "الخدمات",
|
||||
"mcp.categories.weather.description": "توقعات الطقس وخدمات الأرصاد الجوية",
|
||||
"mcp.categories.weather.name": "الطقس",
|
||||
"mcp.categories.web-search.description": "البحث على الويب واسترجاع المعلومات",
|
||||
@@ -478,6 +483,10 @@
|
||||
"tab.plugin": "المهارة",
|
||||
"tab.provider": "المزود",
|
||||
"tab.user": "المستخدم",
|
||||
"time.formatOtherYear": "D MMM، YYYY",
|
||||
"time.formatThisYear": "D MMM",
|
||||
"time.today": "اليوم",
|
||||
"time.yesterday": "أمس",
|
||||
"user.agents": "الوكلاء",
|
||||
"user.downloads": "التنزيلات",
|
||||
"user.editProfile": "تعديل الملف الشخصي",
|
||||
|
||||
@@ -10,5 +10,6 @@
|
||||
"starter.deepResearch": "بحث معمق",
|
||||
"starter.developing": "قريبًا",
|
||||
"starter.image": "صورة",
|
||||
"starter.seedance": "سيدانس 2.0",
|
||||
"starter.write": "كتابة"
|
||||
}
|
||||
|
||||
@@ -9,7 +9,10 @@
|
||||
"addToKnowledgeBase.title": "إضافة إلى المكتبة",
|
||||
"addToKnowledgeBase.totalFiles": "{{count}} ملف/ملفات محددة",
|
||||
"createNew.confirm": "إنشاء جديد",
|
||||
"createNew.description.placeholder": "وصف المكتبة (اختياري)",
|
||||
"createNew.description.label": "وصف المكتبة (اختياري)",
|
||||
"createNew.description.placeholder": "يساعد الوصف نموذج اللغة الكبير على فهم مكتبتك بشكل أفضل",
|
||||
"createNew.edit.confirm": "حفظ التغييرات",
|
||||
"createNew.edit.title": "تعديل المكتبة",
|
||||
"createNew.formTitle": "المعلومات الأساسية",
|
||||
"createNew.name.placeholder": "اسم المكتبة",
|
||||
"createNew.name.required": "يرجى إدخال اسم المكتبة",
|
||||
|
||||
@@ -38,6 +38,10 @@
|
||||
"messages.success.submit": "تم التفويض بنجاح! يمكنك الآن نشر وكيلك.",
|
||||
"messages.success.upload": "تم التفويض بنجاح! يمكنك الآن نشر إصدار جديد.",
|
||||
"profileSetup.cancel": "إلغاء",
|
||||
"profileSetup.confirmChangeUserId.cancel": "إلغاء",
|
||||
"profileSetup.confirmChangeUserId.confirm": "تغيير معرف المستخدم",
|
||||
"profileSetup.confirmChangeUserId.description": "بمجرد التبديل إلى @{{newId}}، يمكن لأي شخص المطالبة بمعرفك القديم @{{oldId}} وستتوقف جميع الروابط الحالية إلى ملفك الشخصي عن العمل. لا يمكن التراجع عن هذا الإجراء. هل أنت متأكد أنك تريد المتابعة؟",
|
||||
"profileSetup.confirmChangeUserId.title": "تغيير معرف المستخدم؟",
|
||||
"profileSetup.descriptionEdit": "قم بتحديث معلومات ملفك الشخصي في المجتمع.",
|
||||
"profileSetup.descriptionFirstTime": "قم بإعداد ملفك لإكمال ملفك الشخصي في المجتمع.",
|
||||
"profileSetup.errors.fileTooLarge": "حجم الملف لا يمكن أن يتجاوز 2 ميغابايت",
|
||||
|
||||
@@ -260,8 +260,8 @@
|
||||
"providerModels.item.modelConfig.type.options.realtime": "دردشة فورية",
|
||||
"providerModels.item.modelConfig.type.options.stt": "تحويل الكلام إلى نص",
|
||||
"providerModels.item.modelConfig.type.options.text2music": "نص إلى موسيقى",
|
||||
"providerModels.item.modelConfig.type.options.text2video": "نص إلى فيديو",
|
||||
"providerModels.item.modelConfig.type.options.tts": "تحويل النص إلى كلام",
|
||||
"providerModels.item.modelConfig.type.options.video": "توليد الفيديو",
|
||||
"providerModels.item.modelConfig.type.placeholder": "يرجى اختيار نوع النموذج",
|
||||
"providerModels.item.modelConfig.type.title": "نوع النموذج",
|
||||
"providerModels.item.modelConfig.video.extra": "يُمكّن هذا الإعداد تكوين التعرف على الفيديو داخل التطبيق. يعتمد الدعم على النموذج نفسه. يرجى اختباره.",
|
||||
|
||||
+42
-12
@@ -74,7 +74,11 @@
|
||||
"MiniMax-M1.description": "نموذج استدلال داخلي جديد بسلسلة تفكير تصل إلى 80K ومدخلات حتى 1M، يقدم أداءً مماثلاً لأفضل النماذج العالمية.",
|
||||
"MiniMax-M2-Stable.description": "مصمم لتدفقات العمل البرمجية والوكلاء بكفاءة عالية، مع قدرة تزامن أعلى للاستخدام التجاري.",
|
||||
"MiniMax-M2.1-Lightning.description": "قدرات برمجة متعددة اللغات قوية وتجربة برمجة مطورة بالكامل. أسرع وأكثر كفاءة.",
|
||||
"MiniMax-M2.1-highspeed.description": "قدرات برمجة متعددة اللغات قوية مع استنتاج أسرع وأكثر كفاءة.",
|
||||
"MiniMax-M2.1.description": "MiniMax-M2.1 هو نموذج مفتوح المصدر رائد من MiniMax، يركز على حل المهام الواقعية المعقدة. يتميز بقدرات برمجة متعددة اللغات والقدرة على أداء المهام المعقدة كوكلاء ذكي.",
|
||||
"MiniMax-M2.5-Lightning.description": "M2.5 Lightning: نفس الأداء، أسرع وأكثر رشاقة (تقريباً 100 tps).",
|
||||
"MiniMax-M2.5-highspeed.description": "نفس أداء M2.5 مع استنتاج أسرع بشكل ملحوظ.",
|
||||
"MiniMax-M2.5.description": "أداء من الدرجة الأولى وفعالية تكلفة قصوى، يتعامل بسهولة مع المهام المعقدة (تقريباً 60 tps).",
|
||||
"MiniMax-M2.description": "مصمم خصيصًا للبرمجة الفعالة وتدفقات عمل الوكلاء.",
|
||||
"MiniMax-Text-01.description": "MiniMax-01 يقدم انتباهًا خطيًا واسع النطاق يتجاوز Transformers التقليدية، مع 456 مليار معامل و45.9 مليار مفعّلة في كل تمرير. يحقق أداءً من الدرجة الأولى ويدعم حتى 4 ملايين رمز سياقي (32× GPT-4o، 20× Claude-3.5-Sonnet).",
|
||||
"MiniMaxAI/MiniMax-M1-80k.description": "MiniMax-M1 هو نموذج استدلال واسع النطاق بوزن مفتوح يستخدم انتباهًا هجينًا، يحتوي على 456 مليار معامل إجماليًا و~45.9 مليار مفعّلة لكل رمز. يدعم سياقًا يصل إلى 1M ويستخدم Flash Attention لتقليل FLOPs بنسبة 75% عند توليد 100K رمز مقارنة بـ DeepSeek R1. بهيكل MoE وتدريب RL هجين، يحقق أداءً رائدًا في الاستدلال طويل المدخلات ومهام هندسة البرمجيات الواقعية.",
|
||||
@@ -107,6 +111,7 @@
|
||||
"Pro/moonshotai/Kimi-K2-Thinking.description": "Kimi K2 Thinking Turbo هو إصدار Turbo محسّن لسرعة الاستدلال والإنتاجية مع الحفاظ على قدرات التفكير متعدد الخطوات واستخدام الأدوات في K2 Thinking. إنه نموذج MoE يحتوي على حوالي 1 تريليون معلمة إجمالية، ويدعم سياقًا أصليًا بطول 256 ألف رمز، واستدعاء أدوات واسع النطاق ومستقر لسيناريوهات الإنتاج التي تتطلب زمن استجابة وتزامنًا صارمين.",
|
||||
"Pro/moonshotai/Kimi-K2.5.description": "Kimi K2.5 هو نموذج وكيل متعدد الوسائط مفتوح المصدر، مبني على Kimi-K2-Base، ومدرب على حوالي 1.5 تريليون رمز من النصوص والرؤية. يستخدم بنية MoE بعدد إجمالي 1 تريليون مع 32 مليار معلمات نشطة، ويدعم نافذة سياق تصل إلى 256 ألف، مما يدمج الفهم البصري واللغوي بسلاسة.",
|
||||
"Pro/zai-org/glm-4.7.description": "GLM-4.7 هو النموذج الرائد من الجيل الجديد لشركة Zhipu، يحتوي على 355 مليار معلمة إجمالية و32 مليار معلمة نشطة، وقد تم تطويره بالكامل في مجالات الحوار العام، والاستدلال، وقدرات الوكلاء. يعزز GLM-4.7 التفكير المتداخل ويقدم مفاهيم التفكير المحفوظ والتفكير على مستوى الدور.",
|
||||
"Pro/zai-org/glm-5.description": "GLM-5 هو نموذج لغة كبير جديد من Z.ai، يركز على هندسة الأنظمة المعقدة ومهام الوكيل طويلة الأمد. توسعت معلمات النموذج إلى 744B معلمة (40B نشطة)، وتم دمج DeepSeek Sparse Attention.",
|
||||
"QwQ-32B-Preview.description": "Qwen QwQ هو نموذج بحث تجريبي يركز على تحسين الاستدلال.",
|
||||
"Qwen/QVQ-72B-Preview.description": "QVQ-72B-Preview هو نموذج بحث من Qwen يركز على الاستدلال البصري، يتميز بفهم المشاهد المعقدة وحل مسائل الرياضيات البصرية.",
|
||||
"Qwen/QwQ-32B-Preview.description": "Qwen QwQ هو نموذج بحث تجريبي يركز على تحسين استدلال الذكاء الاصطناعي.",
|
||||
@@ -274,22 +279,28 @@
|
||||
"chatgpt-4o-latest.description": "ChatGPT-4o هو نموذج ديناميكي يتم تحديثه في الوقت الفعلي، يجمع بين الفهم العميق والقدرة على التوليد لتلبية احتياجات الاستخدام الواسعة مثل دعم العملاء والتعليم والدعم الفني.",
|
||||
"claude-2.0.description": "Claude 2 يقدم تحسينات رئيسية للمؤسسات، بما في ذلك سياق 200 ألف رمز، تقليل الهلوسة، دعم التعليمات النظامية، وميزة جديدة: استدعاء الأدوات.",
|
||||
"claude-2.1.description": "Claude 2 يقدم تحسينات رئيسية للمؤسسات، بما في ذلك سياق 200 ألف رمز، تقليل الهلوسة، دعم التعليمات النظامية، وميزة جديدة: استدعاء الأدوات.",
|
||||
"claude-3-5-haiku-20241022.description": "Claude 3.5 Haiku هو أسرع نموذج من الجيل الجديد تقدمه Anthropic. مقارنةً بـ Claude 3 Haiku، فإنه يُظهر تحسنًا في المهارات ويتفوق على أكبر نموذج سابق Claude 3 Opus في العديد من اختبارات الذكاء.",
|
||||
"claude-3-5-haiku-20241022.description": "Claude 3.5 Haiku هو أسرع نموذج من الجيل الجديد من Anthropic، يتميز بتحسينات في المهارات ويتفوق على النموذج الرائد السابق Claude 3 Opus في العديد من المعايير.",
|
||||
"claude-3-5-haiku-latest.description": "Claude 3.5 Haiku يقدم استجابات سريعة للمهام الخفيفة.",
|
||||
"claude-3-7-sonnet-20250219.description": "Claude 3.7 Sonnet هو أذكى نموذج من Anthropic وأول نموذج هجيني للاستدلال في السوق. يمكنه تقديم ردود شبه فورية أو استدلالات متسلسلة خطوة بخطوة يمكن للمستخدمين متابعتها. يتميز Sonnet بقوة خاصة في البرمجة وعلوم البيانات والرؤية والمهام المعتمدة على الوكلاء.",
|
||||
"claude-3-7-sonnet-20250219.description": "Claude Sonnet 3.7 هو أذكى نموذج من Anthropic وأول نموذج هجيني للاستدلال في السوق، يدعم الاستجابات الفورية أو التفكير المطول مع تحكم دقيق.",
|
||||
"claude-3-7-sonnet-latest.description": "Claude 3.7 Sonnet هو أحدث وأقوى نموذج من Anthropic للمهام المعقدة، يتميز بالأداء العالي، الذكاء، الطلاقة، والفهم العميق.",
|
||||
"claude-3-haiku-20240307.description": "Claude 3 Haiku هو أسرع وأصغر نموذج من Anthropic، مصمم لتقديم استجابات شبه فورية بأداء سريع ودقيق.",
|
||||
"claude-3-opus-20240229.description": "Claude 3 Opus هو أقوى نموذج من Anthropic للمهام المعقدة، يتميز بالأداء العالي، الذكاء، الطلاقة، والفهم.",
|
||||
"claude-3-sonnet-20240229.description": "Claude 3 Sonnet يوازن بين الذكاء والسرعة لتلبية احتياجات المؤسسات، ويوفر فائدة عالية بتكلفة أقل ونشر موثوق على نطاق واسع.",
|
||||
"claude-haiku-4-5-20251001.description": "Claude Haiku 4.5 هو أسرع وأذكى نموذج Haiku من Anthropic، يتميز بسرعة فائقة وقدرة على الاستدلال الموسع.",
|
||||
"claude-3.5-sonnet.description": "يتميز Claude 3.5 Sonnet بقدرات عالية في البرمجة والكتابة والتفكير المعقد.",
|
||||
"claude-3.7-sonnet-thought.description": "Claude 3.7 Sonnet مزود بقدرات تفكير موسعة للمهام التي تتطلب استدلالًا معقدًا.",
|
||||
"claude-3.7-sonnet.description": "Claude 3.7 Sonnet هو إصدار مطور يتمتع بسياق موسع وقدرات محسّنة.",
|
||||
"claude-haiku-4-5-20251001.description": "Claude Haiku 4.5 هو أسرع وأذكى نموذج Haiku من Anthropic، يتميز بسرعة فائقة وقدرة على التفكير المتعمق.",
|
||||
"claude-haiku-4.5.description": "Claude Haiku 4.5 نموذج سريع وفعّال لمجموعة متنوعة من المهام.",
|
||||
"claude-opus-4-1-20250805-thinking.description": "Claude Opus 4.1 Thinking هو إصدار متقدم يمكنه عرض عملية تفكيره.",
|
||||
"claude-opus-4-1-20250805.description": "Claude Opus 4.1 هو أحدث وأقوى نموذج من Anthropic للمهام المعقدة للغاية، يتميز بالأداء العالي والذكاء والطلاقة والفهم العميق.",
|
||||
"claude-opus-4-20250514.description": "Claude Opus 4 هو أقوى نموذج من Anthropic للمهام المعقدة للغاية، يتميز بالأداء والذكاء والطلاقة والاستيعاب.",
|
||||
"claude-opus-4-1-20250805.description": "Claude Opus 4.1 هو أحدث وأقوى نموذج من Anthropic للمهام المعقدة للغاية، يتفوق في الأداء والذكاء والطلاقة والفهم.",
|
||||
"claude-opus-4-20250514.description": "Claude Opus 4 هو أقوى نموذج من Anthropic للمهام المعقدة للغاية، يتميز بأداء فائق وذكاء وطلاقة وفهم عميق.",
|
||||
"claude-opus-4-5-20251101.description": "Claude Opus 4.5 هو النموذج الرائد من Anthropic، يجمع بين الذكاء الاستثنائي والأداء القابل للتوسع، مثالي للمهام المعقدة التي تتطلب استجابات عالية الجودة وتفكير متقدم.",
|
||||
"claude-opus-4-6.description": "Claude Opus 4.6 هو أذكى نموذج من Anthropic لتطوير الوكلاء والبرمجة.",
|
||||
"claude-sonnet-4-20250514-thinking.description": "Claude Sonnet 4 Thinking يمكنه تقديم استجابات شبه فورية أو تفكير متسلسل مرئي.",
|
||||
"claude-sonnet-4-20250514.description": "Claude Sonnet 4 يمكنه تقديم ردود شبه فورية أو تفكير متسلسل خطوة بخطوة مع عرض واضح للعملية.",
|
||||
"claude-sonnet-4-5-20250929.description": "Claude Sonnet 4.5 هو أذكى نموذج قدمته Anthropic حتى الآن.",
|
||||
"claude-sonnet-4-20250514.description": "Claude Sonnet 4 هو أذكى نموذج من Anthropic حتى الآن، يوفر استجابات شبه فورية أو تفكيرًا متسلسلًا بخطوات دقيقة لمستخدمي واجهة البرمجة.",
|
||||
"claude-sonnet-4-5-20250929.description": "Claude Sonnet 4.5 هو أذكى نموذج من Anthropic حتى الآن.",
|
||||
"claude-sonnet-4-6.description": "Claude Sonnet 4.6 هو أفضل مزيج من السرعة والذكاء من Anthropic.",
|
||||
"claude-sonnet-4.description": "Claude Sonnet 4 هو الجيل الأحدث مع أداء محسّن في جميع المهام.",
|
||||
"codegeex-4.description": "CodeGeeX-4 هو مساعد برمجة ذكي يدعم الأسئلة والأجوبة متعددة اللغات وإكمال الشيفرة لزيادة إنتاجية المطورين.",
|
||||
"codegeex4-all-9b.description": "CodeGeeX4-ALL-9B هو نموذج توليد شيفرة متعدد اللغات يدعم الإكمال والتوليد، تفسير الشيفرة، البحث عبر الإنترنت، استدعاء الوظائف، وأسئلة وأجوبة على مستوى المستودع، ويغطي مجموعة واسعة من سيناريوهات تطوير البرمجيات. يُعد من أفضل نماذج الشيفرة تحت 10B.",
|
||||
"codegemma.description": "CodeGemma هو نموذج خفيف الوزن لمهام البرمجة المتنوعة، يتيح التكرار السريع والتكامل السلس.",
|
||||
@@ -358,7 +369,7 @@
|
||||
"deepseek-ai/deepseek-v3.1-terminus.description": "DeepSeek V3.1 هو نموذج تفكير من الجيل التالي يتمتع بقدرات أقوى في التفكير المعقد وسلسلة التفكير لمهام التحليل العميق.",
|
||||
"deepseek-ai/deepseek-v3.1.description": "DeepSeek V3.1 هو نموذج تفكير من الجيل التالي يتمتع بقدرات أقوى في التفكير المعقد وسلسلة التفكير لمهام التحليل العميق.",
|
||||
"deepseek-ai/deepseek-vl2.description": "DeepSeek-VL2 هو نموذج رؤية-لغة MoE يعتمد على DeepSeekMoE-27B مع تنشيط متفرق، ويحقق أداءً قويًا باستخدام 4.5 مليار معلمة نشطة فقط. يتميز في الأسئلة البصرية، وOCR، وفهم المستندات/الجداول/المخططات، والتأريض البصري.",
|
||||
"deepseek-chat.description": "نموذج مفتوح المصدر جديد يجمع بين القدرات العامة والبرمجية. يحافظ على حوار النموذج العام وقوة النموذج البرمجي، مع تحسين التوافق مع تفضيلات المستخدم. كما يُحسن DeepSeek-V2.5 من مهارات الكتابة واتباع التعليمات.",
|
||||
"deepseek-chat.description": "DeepSeek V3.2 يوازن بين الاستدلال وطول المخرجات لمهام الأسئلة والأجوبة اليومية وتطبيقات الوكلاء. يحقق نتائج تضاهي GPT-5 في المعايير العامة، وهو الأول في دمج التفكير مع استخدام الأدوات، مما يجعله رائدًا في تقييمات الوكلاء مفتوحة المصدر.",
|
||||
"deepseek-coder-33B-instruct.description": "DeepSeek Coder 33B هو نموذج لغة برمجية تم تدريبه على 2 تريليون رمز (87٪ كود، 13٪ نص صيني/إنجليزي). يقدم نافذة سياق 16K ومهام الإكمال في المنتصف، ويوفر إكمال كود على مستوى المشاريع وملء مقاطع الكود.",
|
||||
"deepseek-coder-v2.description": "DeepSeek Coder V2 هو نموذج كود MoE مفتوح المصدر يتميز بأداء قوي في مهام البرمجة، ويضاهي GPT-4 Turbo.",
|
||||
"deepseek-coder-v2:236b.description": "DeepSeek Coder V2 هو نموذج كود MoE مفتوح المصدر يتميز بأداء قوي في مهام البرمجة، ويضاهي GPT-4 Turbo.",
|
||||
@@ -381,7 +392,7 @@
|
||||
"deepseek-r1-fast-online.description": "الإصدار الكامل السريع من DeepSeek R1 مع بحث ويب في الوقت الحقيقي، يجمع بين قدرات بحجم 671B واستجابة أسرع.",
|
||||
"deepseek-r1-online.description": "الإصدار الكامل من DeepSeek R1 مع 671 مليار معلمة وبحث ويب في الوقت الحقيقي، يوفر فهمًا وتوليدًا أقوى.",
|
||||
"deepseek-r1.description": "يستخدم DeepSeek-R1 بيانات البداية الباردة قبل التعلم المعزز ويؤدي أداءً مماثلًا لـ OpenAI-o1 في الرياضيات، والبرمجة، والتفكير.",
|
||||
"deepseek-reasoner.description": "وضع التفكير في DeepSeek V3.2 يُنتج سلسلة من الأفكار قبل الإجابة النهائية لتحسين الدقة.",
|
||||
"deepseek-reasoner.description": "DeepSeek V3.2 Thinking هو نموذج استدلال عميق يولد سلسلة من الأفكار قبل المخرجات لتحقيق دقة أعلى، ويحقق نتائج تنافسية عالية واستدلالًا يقارن بـ Gemini-3.0-Pro.",
|
||||
"deepseek-v2.description": "DeepSeek V2 هو نموذج MoE فعال لمعالجة منخفضة التكلفة.",
|
||||
"deepseek-v2:236b.description": "DeepSeek V2 236B هو نموذج DeepSeek الموجه للبرمجة مع قدرات قوية في توليد الكود.",
|
||||
"deepseek-v3-0324.description": "DeepSeek-V3-0324 هو نموذج MoE يحتوي على 671 مليار معلمة يتميز بقوة في البرمجة، والقدرات التقنية، وفهم السياق، والتعامل مع النصوص الطويلة.",
|
||||
@@ -439,6 +450,10 @@
|
||||
"doubao-seed-1.6-vision.description": "Doubao-Seed-1.6-vision هو نموذج استدلال بصري عميق يوفر فهمًا واستدلالًا متعدد الوسائط أقوى للتعليم، ومراجعة الصور، والتفتيش/الأمن، والبحث الذكي. يدعم نافذة سياق بحجم 256k وما يصل إلى 64k من الرموز الناتجة.",
|
||||
"doubao-seed-1.6.description": "Doubao-Seed-1.6 هو نموذج استدلال عميق متعدد الوسائط جديد يدعم أوضاع التفكير التلقائي، والتفكير، وعدم التفكير. في وضع عدم التفكير، يتفوق بشكل كبير على Doubao-1.5-pro/250115. يدعم نافذة سياق بحجم 256k وما يصل إلى 16k من الرموز الناتجة.",
|
||||
"doubao-seed-1.8.description": "Doubao-Seed-1.8 يتمتع بفهم متعدد الوسائط أقوى وقدرات وكيل متقدمة، ويدعم إدخال النصوص/الصور/الفيديو وتخزين السياق المؤقت، ويقدم أداءً ممتازًا في المهام المعقدة.",
|
||||
"doubao-seed-2.0-code.description": "Doubao-Seed-2.0-code مُحسن بشكل عميق للبرمجة الوكيلية، يدعم المدخلات متعددة الوسائط ونافذة سياق تصل إلى 256k، مناسب للبرمجة وفهم الرؤية وتدفقات عمل الوكيل.",
|
||||
"doubao-seed-2.0-lite.description": "Doubao-Seed-2.0-lite هو نموذج جديد للتفكير العميق متعدد الوسائط يقدم قيمة أفضل وخيار قوي للمهام الشائعة، مع نافذة سياق تصل إلى 256k.",
|
||||
"doubao-seed-2.0-mini.description": "Doubao-Seed-2.0-mini هو نموذج خفيف الوزن مع استجابة سريعة وأداء عالي، مناسب للمهام الصغيرة وسيناريوهات التزامن العالي.",
|
||||
"doubao-seed-2.0-pro.description": "Doubao-Seed-2.0-pro هو النموذج العام الرائد من ByteDance، مع قفزات شاملة في تخطيط وتنفيذ المهام المعقدة.",
|
||||
"doubao-seed-code.description": "Doubao-Seed-Code مُحسَّن بعمق للبرمجة الوكيلة، ويدعم إدخالات متعددة الوسائط (نص/صورة/فيديو) ونافذة سياق بحجم 256k، ومتوافق مع واجهة Anthropic API، ومناسب للبرمجة، وفهم الرؤية، وسير عمل الوكلاء.",
|
||||
"doubao-seededit-3-0-i2i-250628.description": "نموذج الصور Doubao من ByteDance Seed يدعم إدخال النصوص والصور مع توليد صور عالية الجودة وقابلة للتحكم بدرجة كبيرة. يدعم تحرير الصور الموجه بالنص، مع أحجام إخراج تتراوح بين 512 و1536 على الجانب الطويل.",
|
||||
"doubao-seedream-3-0-t2i-250415.description": "Seedream 3.0 هو نموذج توليد صور من ByteDance Seed، يدعم إدخال النصوص والصور مع توليد صور عالية الجودة وقابلة للتحكم بدرجة كبيرة. يُولّد الصور من التعليمات النصية.",
|
||||
@@ -471,7 +486,8 @@
|
||||
"ernie-speed-pro-128k.description": "ERNIE Speed Pro 128K هو نموذج عالي التوازي وعالي القيمة للخدمات عبر الإنترنت واسعة النطاق وتطبيقات المؤسسات.",
|
||||
"ernie-x1-turbo-32k.description": "ERNIE X1 Turbo 32K هو نموذج تفكير سريع بسياق 32K للاستدلال المعقد والدردشة متعددة الأدوار.",
|
||||
"ernie-x1.1-preview.description": "معاينة ERNIE X1.1 هو نموذج تفكير مخصص للتقييم والاختبار.",
|
||||
"fal-ai/bytedance/seedream/v4.description": "Seedream 4.0 هو نموذج توليد صور من ByteDance Seed، يدعم إدخال النصوص والصور ويتميز بإنتاج صور عالية الجودة وقابلة للتحكم بدرجة كبيرة. يُولّد الصور من التعليمات النصية.",
|
||||
"fal-ai/bytedance/seedream/v4.5.description": "Seedream 4.5، من تطوير فريق Seed في ByteDance، يدعم تحرير الصور المتعددة وتركيبها. يتميز بثبات أكبر في العناصر، ودقة في تنفيذ التعليمات، وفهم للمنطق المكاني، وتعبير جمالي، وتصميم الملصقات والشعارات مع عرض دقيق للنصوص والصور.",
|
||||
"fal-ai/bytedance/seedream/v4.description": "Seedream 4.0، من تطوير فريق Seed في ByteDance، يدعم إدخال النصوص والصور لتوليد صور عالية الجودة وقابلة للتحكم بدرجة كبيرة من خلال الأوامر.",
|
||||
"fal-ai/flux-kontext/dev.description": "نموذج FLUX.1 يركز على تحرير الصور، ويدعم إدخال النصوص والصور.",
|
||||
"fal-ai/flux-pro/kontext.description": "FLUX.1 Kontext [pro] يقبل النصوص وصور مرجعية كمدخلات، مما يتيح تعديلات محلية مستهدفة وتحولات معقدة في المشهد العام.",
|
||||
"fal-ai/flux/krea.description": "Flux Krea [dev] هو نموذج لتوليد الصور يتميز بميول جمالية نحو صور أكثر واقعية وطبيعية.",
|
||||
@@ -479,8 +495,8 @@
|
||||
"fal-ai/hunyuan-image/v3.description": "نموذج قوي لتوليد الصور متعدد الوسائط أصلي.",
|
||||
"fal-ai/imagen4/preview.description": "نموذج عالي الجودة لتوليد الصور من Google.",
|
||||
"fal-ai/nano-banana.description": "Nano Banana هو أحدث وأسرع وأكثر نماذج Google كفاءةً لتوليد وتحرير الصور من خلال المحادثة.",
|
||||
"fal-ai/qwen-image-edit.description": "نموذج احترافي لتحرير الصور من فريق Qwen، يدعم التعديلات الدلالية والمظهرية، ويحرر النصوص الصينية والإنجليزية بدقة، كما يتيح تعديلات عالية الجودة مثل نقل الأسلوب وتدوير العناصر.",
|
||||
"fal-ai/qwen-image.description": "نموذج قوي لتوليد الصور من فريق Qwen يتميز بعرض مميز للنصوص الصينية وأنماط بصرية متنوعة.",
|
||||
"fal-ai/qwen-image-edit.description": "نموذج احترافي لتحرير الصور من فريق Qwen، يدعم التعديلات الدلالية والمظهرية، وتحرير النصوص بدقة باللغتين الصينية والإنجليزية، ونقل الأسلوب، والتدوير، والمزيد.",
|
||||
"fal-ai/qwen-image.description": "نموذج قوي لتوليد الصور من فريق Qwen يتميز بعرض قوي للنصوص الصينية وأنماط بصرية متنوعة.",
|
||||
"flux-1-schnell.description": "نموذج تحويل النص إلى صورة يحتوي على 12 مليار معلمة من Black Forest Labs يستخدم تقنيات تقطير الانتشار العدائي الكامن لتوليد صور عالية الجودة في 1-4 خطوات. ينافس البدائل المغلقة ومتاح بموجب ترخيص Apache-2.0 للاستخدام الشخصي والبحثي والتجاري.",
|
||||
"flux-dev.description": "FLUX.1 [dev] هو نموذج مفتوح الأوزان ومقطر للاستخدام غير التجاري. يحافظ على جودة صور قريبة من المستوى الاحترافي واتباع التعليمات مع كفاءة تشغيل أعلى مقارنة بالنماذج القياسية من نفس الحجم.",
|
||||
"flux-kontext-max.description": "توليد وتحرير صور سياقية متقدمة، تجمع بين النصوص والصور لتحقيق نتائج دقيقة ومتسقة.",
|
||||
@@ -511,6 +527,8 @@
|
||||
"gemini-2.0-flash-lite-001.description": "إصدار من Gemini 2.0 Flash محسن لتقليل التكلفة وتقليل التأخير.",
|
||||
"gemini-2.0-flash-lite.description": "إصدار من Gemini 2.0 Flash محسن لتقليل التكلفة وتقليل التأخير.",
|
||||
"gemini-2.0-flash.description": "Gemini 2.0 Flash يقدم ميزات الجيل التالي بما في ذلك السرعة الاستثنائية، واستخدام الأدوات الأصلية، والتوليد متعدد الوسائط، وسياق يصل إلى مليون رمز.",
|
||||
"gemini-2.5-flash-image-preview.description": "Nano Banana هو أحدث وأسرع وأكثر النماذج متعددة الوسائط كفاءة من Google، يتيح توليد الصور وتحريرها من خلال المحادثة.",
|
||||
"gemini-2.5-flash-image-preview:image.description": "Nano Banana هو أحدث وأسرع وأكثر النماذج متعددة الوسائط كفاءة من Google، يتيح توليد الصور وتحريرها من خلال المحادثة.",
|
||||
"gemini-2.5-flash-image.description": "Nano Banana هو أحدث وأسرع وأكثر نماذج Google متعددة الوسائط كفاءة، يتيح توليد الصور وتحريرها عبر المحادثة.",
|
||||
"gemini-2.5-flash-image:image.description": "Nano Banana هو أحدث وأسرع وأكثر نماذج Google متعددة الوسائط كفاءة، يتيح توليد الصور وتحريرها عبر المحادثة.",
|
||||
"gemini-2.5-flash-lite-preview-06-17.description": "Gemini 2.5 Flash-Lite Preview هو أصغر نموذج من Google وأفضلها من حيث القيمة، مصمم للاستخدام واسع النطاق.",
|
||||
@@ -565,6 +583,7 @@
|
||||
"glm-4v-plus-0111.description": "GLM-4V-Plus يفهم الفيديو والصور المتعددة، مما يجعله مناسبًا للمهام متعددة الوسائط.",
|
||||
"glm-4v-plus.description": "GLM-4V-Plus يفهم الفيديو والصور المتعددة، مما يجعله مناسبًا للمهام متعددة الوسائط.",
|
||||
"glm-4v.description": "GLM-4V يقدم فهمًا قويًا للصور واستدلالًا عبر المهام البصرية.",
|
||||
"glm-5.description": "نموذج قوي للتفكير والوكالة من Z.ai مع 744B إجمالي المعلمات (40B نشطة)، مصمم لهندسة الأنظمة المعقدة والمهام طويلة الأمد.",
|
||||
"glm-z1-air.description": "نموذج استدلال يتمتع بقدرات استنتاج قوية للمهام التي تتطلب استدلالًا عميقًا.",
|
||||
"glm-z1-airx.description": "استدلال فائق السرعة مع جودة استدلال عالية.",
|
||||
"glm-z1-flash.description": "سلسلة GLM-Z1 تقدم استدلالًا معقدًا قويًا، وتتفوق في المنطق، الرياضيات، والبرمجة.",
|
||||
@@ -604,6 +623,7 @@
|
||||
"google/text-embedding-005.description": "نموذج تضمين نصي يركز على اللغة الإنجليزية، محسّن لمهام البرمجة واللغة الإنجليزية.",
|
||||
"google/text-multilingual-embedding-002.description": "نموذج تضمين نصي متعدد اللغات محسّن للمهام عبر اللغات المختلفة.",
|
||||
"gpt-3.5-turbo-0125.description": "GPT 3.5 Turbo لتوليد النصوص وفهمها؛ يشير حاليًا إلى gpt-3.5-turbo-0125.",
|
||||
"gpt-3.5-turbo-0613.description": "GPT 3.5 Turbo نموذج سريع وفعّال لمهام متعددة.",
|
||||
"gpt-3.5-turbo-1106.description": "GPT 3.5 Turbo لتوليد النصوص وفهمها؛ يشير حاليًا إلى gpt-3.5-turbo-0125.",
|
||||
"gpt-3.5-turbo-instruct.description": "GPT 3.5 Turbo لمهام توليد النصوص والفهم، محسّن لاتباع التعليمات.",
|
||||
"gpt-3.5-turbo.description": "GPT 3.5 Turbo لتوليد النصوص وفهمها؛ يشير حاليًا إلى gpt-3.5-turbo-0125.",
|
||||
@@ -614,10 +634,12 @@
|
||||
"gpt-4-1106-preview.description": "أحدث إصدار من GPT-4 Turbo يدعم الرؤية. الطلبات البصرية تدعم وضع JSON واستدعاء الوظائف. إنه نموذج متعدد الوسائط فعال من حيث التكلفة يوازن بين الدقة والكفاءة للتطبيقات في الوقت الحقيقي.",
|
||||
"gpt-4-32k-0613.description": "يوفر GPT-4 نافذة سياق أكبر للتعامل مع مدخلات أطول في السيناريوهات التي تتطلب دمج معلومات واسع وتحليل بيانات.",
|
||||
"gpt-4-32k.description": "يوفر GPT-4 نافذة سياق أكبر للتعامل مع مدخلات أطول في السيناريوهات التي تتطلب دمج معلومات واسع وتحليل بيانات.",
|
||||
"gpt-4-o-preview.description": "GPT-4o هو النموذج متعدد الوسائط الأكثر تقدمًا، يدعم إدخال النصوص والصور.",
|
||||
"gpt-4-turbo-2024-04-09.description": "أحدث إصدار من GPT-4 Turbo يدعم الرؤية. الطلبات البصرية تدعم وضع JSON واستدعاء الوظائف. إنه نموذج متعدد الوسائط فعال من حيث التكلفة يوازن بين الدقة والكفاءة للتطبيقات في الوقت الحقيقي.",
|
||||
"gpt-4-turbo-preview.description": "أحدث إصدار من GPT-4 Turbo يدعم الرؤية. الطلبات البصرية تدعم وضع JSON واستدعاء الوظائف. إنه نموذج متعدد الوسائط فعال من حيث التكلفة يوازن بين الدقة والكفاءة للتطبيقات في الوقت الحقيقي.",
|
||||
"gpt-4-turbo.description": "أحدث إصدار من GPT-4 Turbo يدعم الرؤية. الطلبات البصرية تدعم وضع JSON واستدعاء الوظائف. إنه نموذج متعدد الوسائط فعال من حيث التكلفة يوازن بين الدقة والكفاءة للتطبيقات في الوقت الحقيقي.",
|
||||
"gpt-4-vision-preview.description": "معاينة GPT-4 Vision، مصمم لمهام تحليل ومعالجة الصور.",
|
||||
"gpt-4.1-2025-04-14.description": "GPT-4.1 هو النموذج الرائد للمهام المعقدة، مثالي لحل المشكلات متعددة المجالات.",
|
||||
"gpt-4.1-mini.description": "GPT-4.1 mini يوازن بين الذكاء والسرعة والتكلفة، مما يجعله جذابًا للعديد من الاستخدامات.",
|
||||
"gpt-4.1-nano.description": "GPT-4.1 nano هو الأسرع والأكثر فعالية من حيث التكلفة بين نماذج GPT-4.1.",
|
||||
"gpt-4.1.description": "GPT-4.1 هو نموذجنا الرائد للمهام المعقدة وحل المشكلات عبر المجالات.",
|
||||
@@ -627,6 +649,7 @@
|
||||
"gpt-4o-2024-08-06.description": "ChatGPT-4o هو نموذج ديناميكي يتم تحديثه في الوقت الحقيقي، يجمع بين الفهم القوي والتوليد لتطبيقات واسعة النطاق مثل دعم العملاء والتعليم والمساعدة التقنية.",
|
||||
"gpt-4o-2024-11-20.description": "ChatGPT-4o هو نموذج ديناميكي يتم تحديثه في الوقت الحقيقي، يجمع بين الفهم القوي والتوليد لتطبيقات واسعة النطاق مثل دعم العملاء والتعليم والدعم الفني.",
|
||||
"gpt-4o-audio-preview.description": "نموذج معاينة GPT-4o Audio مع إدخال وإخراج صوتي.",
|
||||
"gpt-4o-mini-2024-07-18.description": "GPT-4o mini هو حل اقتصادي لمجموعة واسعة من مهام النصوص والصور.",
|
||||
"gpt-4o-mini-audio-preview.description": "نموذج GPT-4o mini Audio مع إدخال وإخراج صوتي.",
|
||||
"gpt-4o-mini-realtime-preview.description": "إصدار GPT-4o-mini الفوري مع إدخال وإخراج صوتي ونصي في الوقت الحقيقي.",
|
||||
"gpt-4o-mini-search-preview.description": "GPT-4o mini Search Preview مدرب على فهم وتنفيذ استعلامات البحث عبر الإنترنت من خلال واجهة Chat Completions API. يتم احتساب تكلفة البحث عبر الإنترنت لكل استخدام أداة بالإضافة إلى تكلفة الرموز.",
|
||||
@@ -863,6 +886,7 @@
|
||||
"mimo-v2-flash.description": "MiMo-V2-Flash: نموذج فعال للاستدلال، والبرمجة، وبناء الأسس للوكيل الذكي.",
|
||||
"minicpm-v.description": "MiniCPM-V هو نموذج متعدد الوسائط من الجيل التالي من OpenBMB يتميز بقدرات ممتازة في التعرف البصري للنصوص وفهم الوسائط المتعددة لمجموعة واسعة من الاستخدامات.",
|
||||
"minimax-m2.1.description": "MiniMax-M2.1 هو أحدث إصدار من سلسلة MiniMax، مُحسّن للبرمجة متعددة اللغات والمهام المعقدة الواقعية. كنموذج أصلي للذكاء الاصطناعي، يحقق MiniMax-M2.1 تحسينات كبيرة في الأداء، ودعم أطر الوكلاء، والتكيف مع سيناريوهات متعددة، بهدف مساعدة الأفراد والشركات على تبني نمط حياة وعمل قائم على الذكاء الاصطناعي بسرعة أكبر.",
|
||||
"minimax-m2.5.description": "MiniMax-M2.5 هو نموذج لغة كبير متقدم مصمم للإنتاجية الواقعية ومهام البرمجة.",
|
||||
"minimax-m2.description": "MiniMax M2 هو نموذج لغوي كبير وفعّال صُمم خصيصًا للبرمجة وسير عمل الوكلاء.",
|
||||
"minimax/minimax-m2.1.description": "MiniMax-M2.1 هو نموذج لغوي كبير وخفيف الوزن ومتطور، مُحسّن للبرمجة وسير عمل الوكلاء وتطوير التطبيقات الحديثة، ويقدم مخرجات أنظف وأكثر إيجازًا واستجابة أسرع.",
|
||||
"minimax/minimax-m2.description": "MiniMax-M2 هو نموذج عالي القيمة يتميز في مهام البرمجة والوكلاء في العديد من سيناريوهات الهندسة.",
|
||||
@@ -980,6 +1004,8 @@
|
||||
"openai/text-embedding-3-small.description": "إصدار محسّن عالي الأداء من نموذج تضمين ada.",
|
||||
"openai/text-embedding-ada-002.description": "نموذج تضمين النصوص القديم من OpenAI.",
|
||||
"openrouter/auto.description": "استنادًا إلى طول السياق والموضوع والتعقيد، يتم توجيه طلبك إلى Llama 3 70B Instruct أو Claude 3.5 Sonnet (بمراقبة ذاتية) أو GPT-4o.",
|
||||
"oswe-vscode-prime.description": "Raptor mini هو نموذج تجريبي محسن لمهام البرمجة.",
|
||||
"oswe-vscode-secondary.description": "Raptor mini هو نموذج تجريبي محسن لمهام البرمجة.",
|
||||
"perplexity/sonar-pro.description": "المنتج الرائد من Perplexity مع دعم البحث، يدعم الاستفسارات المتقدمة والمتابعة.",
|
||||
"perplexity/sonar-reasoning-pro.description": "نموذج متقدم يركز على التفكير، ينتج سلسلة تفكير (CoT) مع بحث محسّن، بما في ذلك استعلامات بحث متعددة لكل طلب.",
|
||||
"perplexity/sonar-reasoning.description": "نموذج يركز على التفكير، ينتج سلسلة تفكير (CoT) مع شروحات مفصلة مدعومة بالبحث.",
|
||||
@@ -1122,6 +1148,7 @@
|
||||
"qwq.description": "QwQ هو نموذج استدلال من عائلة Qwen. مقارنة بالنماذج المضبوطة على التعليمات، يقدم قدرات تفكير واستدلال تعزز الأداء بشكل كبير، خاصة في المشكلات الصعبة. QwQ-32B هو نموذج متوسط الحجم ينافس أفضل نماذج الاستدلال مثل DeepSeek-R1 و o1-mini.",
|
||||
"qwq_32b.description": "نموذج استدلال متوسط الحجم من عائلة Qwen. مقارنة بالنماذج المضبوطة على التعليمات، تعزز قدرات التفكير والاستدلال في QwQ الأداء بشكل كبير، خاصة في المشكلات الصعبة.",
|
||||
"r1-1776.description": "R1-1776 هو إصدار ما بعد التدريب من DeepSeek R1 مصمم لتقديم معلومات واقعية غير خاضعة للرقابة أو التحيز.",
|
||||
"seedance-1-5-pro-251215.description": "Seedance 1.5 Pro من ByteDance يدعم تحويل النصوص إلى فيديو، والصور إلى فيديو (الإطار الأول، أو الإطار الأول والأخير)، وتوليد الصوت المتزامن مع العناصر البصرية.",
|
||||
"solar-mini-ja.description": "Solar Mini (Ja) يوسع Solar Mini مع تركيز على اللغة اليابانية مع الحفاظ على الأداء القوي والكفاءة في الإنجليزية والكورية.",
|
||||
"solar-mini.description": "Solar Mini هو نموذج لغة مدمج يتفوق على GPT-3.5، يتميز بقدرات متعددة اللغات قوية تدعم الإنجليزية والكورية، ويقدم حلاً فعالاً بصمة صغيرة.",
|
||||
"solar-pro.description": "Solar Pro هو نموذج لغة عالي الذكاء من Upstage، يركز على اتباع التعليمات باستخدام وحدة معالجة رسومات واحدة، مع درجات IFEval تتجاوز 80. حالياً يدعم اللغة الإنجليزية؛ وكان من المقرر إصدار النسخة الكاملة في نوفمبر 2024 مع دعم لغات موسع وسياق أطول.",
|
||||
@@ -1162,7 +1189,9 @@
|
||||
"tencent/Hunyuan-A13B-Instruct.description": "Hunyuan-A13B-Instruct يستخدم 80 مليار معلمة إجمالية مع 13 مليار نشطة لمضاهاة النماذج الأكبر. يدعم الاستدلال الهجين السريع/البطيء، وفهم النصوص الطويلة بثبات، وقدرات وكيل رائدة على BFCL-v3 وτ-Bench. تدعم تنسيقات GQA والتكميم المتعدد الاستدلال بكفاءة.",
|
||||
"tencent/Hunyuan-MT-7B.description": "نموذج الترجمة Hunyuan يشمل Hunyuan-MT-7B وHunyuan-MT-Chimera. Hunyuan-MT-7B هو نموذج ترجمة خفيف بسعة 7B يدعم 33 لغة بالإضافة إلى 5 لغات صينية محلية. حصل على المركز الأول في 30 من أصل 31 زوج لغوي في WMT25. يستخدم Hunyuan من Tencent سلسلة تدريب كاملة من التدريب المسبق إلى SFT إلى الترجمة بالتعلم المعزز، محققًا أداءً رائدًا بحجمه وسهولة في النشر.",
|
||||
"text-embedding-3-large.description": "أقوى نموذج تضمين للمهام باللغة الإنجليزية وغير الإنجليزية.",
|
||||
"text-embedding-3-small-inference.description": "نموذج Embedding V3 صغير (للاستدلال) لتضمين النصوص.",
|
||||
"text-embedding-3-small.description": "نموذج تضمين من الجيل التالي فعال من حيث التكلفة ومناسب للاسترجاع وسيناريوهات RAG.",
|
||||
"text-embedding-ada-002.description": "نموذج Embedding V2 Ada لتضمين النصوص.",
|
||||
"thudm/glm-4-32b.description": "GLM-4-32B-0414 هو نموذج ثنائي اللغة (صيني/إنجليزي) بسعة 32B وأوزان مفتوحة، مُحسَّن لتوليد الشيفرات، واستدعاء الوظائف، ومهام الوكلاء. تم تدريبه مسبقًا على 15 تريليون رمز عالي الجودة ومليء بالاستدلال، وتم تحسينه بموازنة تفضيلات البشر، وأخذ العينات بالرفض، والتعلم المعزز. يتفوق في الاستدلال المعقد، وتوليد المخرجات المنظمة، ويصل إلى مستوى أداء GPT-4o وDeepSeek-V3-0324 في العديد من المعايير.",
|
||||
"thudm/glm-4-32b:free.description": "GLM-4-32B-0414 هو نموذج ثنائي اللغة (صيني/إنجليزي) بسعة 32B وأوزان مفتوحة، مُحسَّن لتوليد الشيفرات، واستدعاء الوظائف، ومهام الوكلاء. تم تدريبه مسبقًا على 15 تريليون رمز عالي الجودة ومليء بالاستدلال، وتم تحسينه بموازنة تفضيلات البشر، وأخذ العينات بالرفض، والتعلم المعزز. يتفوق في الاستدلال المعقد، وتوليد المخرجات المنظمة، ويصل إلى مستوى أداء GPT-4o وDeepSeek-V3-0324 في العديد من المعايير.",
|
||||
"thudm/glm-4-9b-chat.description": "الإصدار مفتوح المصدر من نموذج GLM-4 الأحدث من Zhipu AI.",
|
||||
@@ -1222,6 +1251,7 @@
|
||||
"z-ai/glm-4.5.description": "GLM 4.5 هو النموذج الرائد من Z.AI باستدلال هجين مُحسّن للهندسة والمهام طويلة السياق.",
|
||||
"z-ai/glm-4.6.description": "GLM 4.6 هو النموذج الرائد من Z.AI مع طول سياق ممتد وقدرات برمجية متقدمة.",
|
||||
"z-ai/glm-4.7.description": "GLM-4.7 هو النموذج الرائد الأحدث من Zhipu، يقدم قدرات عامة محسَّنة، وردودًا أبسط وأكثر طبيعية، وتجربة كتابة أكثر تفاعلية.",
|
||||
"z-ai/glm5.description": "نموذج قوي للتفكير والوكالة من Z.ai مع 744B إجمالي المعلمات (40B نشطة)، مصمم لهندسة الأنظمة المعقدة والمهام طويلة الأمد.",
|
||||
"zai-org/GLM-4.5-Air.description": "GLM-4.5-Air هو نموذج أساسي لتطبيقات الوكلاء يستخدم بنية Mixture-of-Experts. مُحسّن لاستخدام الأدوات، وتصفح الويب، والهندسة البرمجية، وبرمجة الواجهات، ويتكامل مع وكلاء البرمجة مثل Claude Code وRoo Code. يستخدم استدلالًا هجينًا للتعامل مع السيناريوهات المعقدة واليومية.",
|
||||
"zai-org/GLM-4.5.description": "GLM-4.5 هو نموذج أساسي لتطبيقات الوكلاء يستخدم بنية Mixture-of-Experts. مُحسّن بعمق لاستخدام الأدوات، وتصفح الويب، والهندسة البرمجية، وبرمجة الواجهات، ويتكامل مع وكلاء البرمجة مثل Claude Code وRoo Code. يستخدم استدلالًا هجينًا للتعامل مع السيناريوهات المعقدة واليومية.",
|
||||
"zai-org/GLM-4.5V.description": "GLM-4.5V هو أحدث نموذج رؤية من Zhipu AI، مبني على نموذج النص الرائد GLM-4.5-Air (إجمالي 106 مليار، 12 مليار نشط) باستخدام بنية MoE لأداء قوي بتكلفة أقل. يتبع مسار GLM-4.1V-Thinking ويضيف 3D-RoPE لتحسين الاستدلال المكاني ثلاثي الأبعاد. مُحسّن من خلال التدريب المسبق، والتعلم الخاضع للإشراف، والتعلم المعزز، ويتعامل مع الصور، والفيديو، والمستندات الطويلة، ويتصدر النماذج المفتوحة في 41 معيارًا متعدد الوسائط. يتيح وضع التفكير للمستخدمين التوازن بين السرعة والعمق.",
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
"internlm.description": "منظمة مفتوحة المصدر تركز على أبحاث النماذج الكبيرة والأدوات، وتوفر منصة فعالة وسهلة الاستخدام تتيح الوصول إلى أحدث النماذج والخوارزميات.",
|
||||
"jina.description": "تأسست Jina AI في عام 2020، وهي شركة رائدة في مجال البحث الذكي. تشمل تقنياتها نماذج المتجهات، ومعيدو الترتيب، ونماذج لغوية صغيرة لبناء تطبيقات بحث توليدية ومتعددة الوسائط عالية الجودة.",
|
||||
"lmstudio.description": "LM Studio هو تطبيق سطح مكتب لتطوير وتجربة النماذج اللغوية الكبيرة على جهازك.",
|
||||
"lobehub.description": "يستخدم LobeHub Cloud واجهات برمجة التطبيقات الرسمية للوصول إلى نماذج الذكاء الاصطناعي، ويقيس الاستخدام من خلال الأرصدة المرتبطة برموز النماذج.",
|
||||
"minimax.description": "تأسست MiniMax في عام 2021، وتبني نماذج ذكاء اصطناعي متعددة الوسائط للأغراض العامة، بما في ذلك نماذج نصية بمليارات المعلمات، ونماذج صوتية وبصرية، بالإضافة إلى تطبيقات مثل Hailuo AI.",
|
||||
"mistral.description": "تقدم Mistral نماذج متقدمة عامة ومتخصصة وبحثية للتفكير المعقد، والمهام متعددة اللغات، وتوليد الأكواد، مع دعم استدعاء الوظائف للتكامل المخصص.",
|
||||
"modelscope.description": "ModelScope هي منصة نماذج كخدمة من Alibaba Cloud، تقدم مجموعة واسعة من النماذج وخدمات الاستدلال.",
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
"table.columns.totalTokens": "استخدام الرموز",
|
||||
"table.columns.type.enums.chat": "توليد نصوص",
|
||||
"table.columns.type.enums.imageGeneration": "توليد صور",
|
||||
"table.columns.type.enums.videoGeneration": "توليد الفيديو",
|
||||
"table.columns.type.title": "النوع",
|
||||
"table.desc": "تفاصيل استخدام الاعتمادات الحاسوبية لتوليد النصوص، التضمين، توليد الصور، وغيرها.",
|
||||
"table.more": "عرض التفاصيل",
|
||||
|
||||
@@ -131,6 +131,12 @@
|
||||
"limitation.providers.prompter.subTitle": "خدمة API المخصصة متاحة فقط للخطط المدفوعة. قم بالترقية الآن للاستفادة من خدمات النماذج العالمية",
|
||||
"limitation.providers.prompter.title": "اشترك الآن لاستخدام خدمة API مخصصة",
|
||||
"limitation.providers.tooltip": "خدمة API المخصصة متاحة فقط للخطط المدفوعة",
|
||||
"limitation.video.success.action": "تابع التوليد",
|
||||
"limitation.video.success.desc": "تمت ترقية اشتراكك في خطة {{plan}} بنجاح. استمتع بتوليد الفيديو باستخدام الذكاء الاصطناعي. خطتك الحالية تتضمن:",
|
||||
"limitation.video.success.title": "تمت الترقية بنجاح",
|
||||
"limitation.video.topupSuccess.action": "تابع التوليد",
|
||||
"limitation.video.topupSuccess.desc": "تم تفعيل رصيد الشحن الخاص بك. استمتع بتوليد الفيديو باستخدام الذكاء الاصطناعي. خطتك الحالية تتضمن:",
|
||||
"limitation.video.topupSuccess.title": "تم الشحن بنجاح",
|
||||
"modelPricing.button": "عرض مستندات التسعير",
|
||||
"modelPricing.desc": "يستخدم {{name}} الأرصدة لقياس استخدام نموذج الذكاء الاصطناعي. يوضح الجدول أدناه أرصدة الحوسبة لكل 1M رموز.",
|
||||
"modelPricing.title": "تسعير نموذج النص",
|
||||
|
||||
@@ -86,6 +86,10 @@
|
||||
"localFiles.editFile.replaceFirst": "استبدال التكرار الأول فقط",
|
||||
"localFiles.file": "ملف",
|
||||
"localFiles.folder": "مجلد",
|
||||
"localFiles.globFiles.pattern": "النمط",
|
||||
"localFiles.grepContent.glob": "تصفية الملفات",
|
||||
"localFiles.grepContent.pattern": "نمط البحث",
|
||||
"localFiles.grepContent.type": "نوع الملف",
|
||||
"localFiles.moveFiles.itemsMoved": "تم نقل {{count}} عنصر(عناصر):",
|
||||
"localFiles.moveFiles.itemsMoved_one": "تم نقل عنصر واحد:",
|
||||
"localFiles.moveFiles.itemsMoved_other": "تم نقل {{count}} عناصر:",
|
||||
@@ -95,11 +99,17 @@
|
||||
"localFiles.open": "فتح",
|
||||
"localFiles.openFile": "فتح ملف",
|
||||
"localFiles.openFolder": "فتح مجلد",
|
||||
"localFiles.outOfScope.requestedPaths": "المسارات المطلوبة",
|
||||
"localFiles.outOfScope.warning": "تحذير: المسار(ات) التالية تقع خارج دليل العمل المُحدد. يرجى التأكيد إذا كنت ترغب في السماح بالوصول.",
|
||||
"localFiles.outOfScope.workingDirectory": "دليل العمل",
|
||||
"localFiles.read.more": "عرض المزيد",
|
||||
"localFiles.readFile": "قراءة الملف",
|
||||
"localFiles.readFile.lineRange": "الأسطر {{start}} - {{end}}",
|
||||
"localFiles.readFileError": "فشل في قراءة الملف، يرجى التحقق من صحة المسار",
|
||||
"localFiles.readFiles": "قراءة الملفات",
|
||||
"localFiles.readFilesError": "فشل في قراءة الملفات، يرجى التحقق من صحة المسار",
|
||||
"localFiles.searchFiles.keywords": "الكلمات المفتاحية",
|
||||
"localFiles.securityBlacklist.warning": "تنبيه أمني: تم تمييز هذه العملية بواسطة قواعد الأمان وتتطلب موافقتك الصريحة.",
|
||||
"localFiles.writeFile.characters": "أحرف",
|
||||
"localFiles.writeFile.preview": "معاينة المحتوى",
|
||||
"localFiles.writeFile.truncated": "مقتطع",
|
||||
@@ -136,6 +146,31 @@
|
||||
"search.summary": "الملخص",
|
||||
"search.summaryTooltip": "تلخيص المحتوى الحالي",
|
||||
"search.viewMoreResults": "عرض {{results}} نتيجة إضافية",
|
||||
"securityBlacklist.awsCredentials": "الوصول إلى بيانات اعتماد AWS قد يؤدي إلى تسريب مفاتيح الوصول السحابية",
|
||||
"securityBlacklist.browserCredentials": "الوصول إلى تخزين بيانات اعتماد المتصفح قد يؤدي إلى تسريب كلمات المرور",
|
||||
"securityBlacklist.chownSystemDirs": "تغيير ملكية مجلدات النظام أمر خطير",
|
||||
"securityBlacklist.ddDiskWrite": "كتابة بيانات عشوائية على أجهزة التخزين قد يؤدي إلى تدمير البيانات",
|
||||
"securityBlacklist.directMemoryAccess": "الوصول المباشر إلى الذاكرة أمر بالغ الخطورة",
|
||||
"securityBlacklist.disableFirewall": "تعطيل جدار الحماية يعرض النظام للهجمات",
|
||||
"securityBlacklist.dockerConfig": "قراءة إعدادات Docker قد تكشف بيانات اعتماد التسجيل",
|
||||
"securityBlacklist.envFiles": "قراءة ملفات .env قد تؤدي إلى تسريب بيانات اعتماد حساسة ومفاتيح API",
|
||||
"securityBlacklist.etcPasswd": "تعديل /etc/passwd قد يؤدي إلى فقدان الوصول إلى النظام",
|
||||
"securityBlacklist.forkBomb": "قنبلة fork قد تتسبب في انهيار النظام",
|
||||
"securityBlacklist.formatPartition": "تهيئة أقسام النظام ستؤدي إلى تدمير البيانات",
|
||||
"securityBlacklist.gcpCredentials": "قراءة بيانات اعتماد GCP قد تؤدي إلى تسريب مفاتيح حسابات الخدمات السحابية",
|
||||
"securityBlacklist.gitCredentials": "قراءة ملف بيانات اعتماد Git قد يؤدي إلى تسريب رموز الوصول",
|
||||
"securityBlacklist.historyFiles": "قراءة ملفات السجل قد تكشف أوامر وبيانات اعتماد حساسة",
|
||||
"securityBlacklist.kernelParams": "تعديل معلمات النواة بدون فهم قد يؤدي إلى انهيار النظام",
|
||||
"securityBlacklist.kubeConfig": "قراءة إعدادات Kubernetes قد تكشف بيانات اعتماد الكتلة",
|
||||
"securityBlacklist.npmrc": "قراءة ملف رمز npm قد يؤدي إلى تسريب بيانات اعتماد مستودع الحزم",
|
||||
"securityBlacklist.removeSystemPackages": "إزالة حزم النظام الأساسية قد تؤدي إلى تعطل النظام",
|
||||
"securityBlacklist.rmForceRecursive": "الحذف القسري التكراري بدون هدف محدد أمر بالغ الخطورة",
|
||||
"securityBlacklist.rmHomeDir": "الحذف التكراري لمجلد المنزل أمر بالغ الخطورة",
|
||||
"securityBlacklist.rmRootDir": "الحذف التكراري لمجلد الجذر سيؤدي إلى تدمير النظام",
|
||||
"securityBlacklist.sshConfig": "تغيير إعدادات SSH قد يؤدي إلى فقدان الوصول",
|
||||
"securityBlacklist.sshPrivateKeys": "قراءة مفاتيح SSH الخاصة قد تعرض أمان النظام للخطر",
|
||||
"securityBlacklist.sudoers": "تعديل ملف sudoers بدون تحقق مناسب أمر خطير",
|
||||
"securityBlacklist.suidShells": "تعيين SUID للأصداف أو المفسرات يمثل خطراً أمنياً",
|
||||
"updateArgs.duplicateKeyError": "يجب أن يكون مفتاح الحقل فريدًا",
|
||||
"updateArgs.form.add": "إضافة عنصر",
|
||||
"updateArgs.form.key": "مفتاح الحقل",
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"config.aspectRatio.label": "نسبة العرض إلى الارتفاع",
|
||||
"config.cameraFixed.label": "كاميرا ثابتة",
|
||||
"config.duration.label": "المدة",
|
||||
"config.endImageUrl.label": "الإطار النهائي",
|
||||
"config.generateAudio.label": "توليد صوت",
|
||||
"config.header.title": "فيديو",
|
||||
"config.imageUrl.label": "الإطار الابتدائي",
|
||||
"config.prompt.placeholder": "صف الفيديو الذي ترغب في إنشائه",
|
||||
"config.referenceImage.label": "صورة مرجعية",
|
||||
"config.resolution.label": "الدقة",
|
||||
"config.seed.label": "البذرة",
|
||||
"config.seed.random": "عشوائي",
|
||||
"generation.actions.copyError": "نسخ رسالة الخطأ",
|
||||
"generation.actions.errorCopied": "تم نسخ رسالة الخطأ إلى الحافظة",
|
||||
"generation.actions.errorCopyFailed": "فشل في نسخ رسالة الخطأ",
|
||||
"generation.actions.generate": "إنشاء",
|
||||
"generation.freeQuota.exhausted": "🎁 تم استهلاك الحصة المجانية، سيتم استخدام الرصيد",
|
||||
"generation.freeQuota.remaining": "🎁 {{remaining}} فيديو مجاني متبقٍ اليوم",
|
||||
"generation.status.failed": "فشل في الإنشاء",
|
||||
"generation.status.generating": "جارٍ الإنشاء...",
|
||||
"generation.validation.endFrameRequiresStartFrame": "لا يمكن استخدام الإطار النهائي بدون إطار ابتدائي. يرجى تعيين إطار ابتدائي أولاً.",
|
||||
"topic.createNew": "موضوع جديد",
|
||||
"topic.deleteConfirm": "حذف موضوع الفيديو",
|
||||
"topic.deleteConfirmDesc": "أنت على وشك حذف موضوع الفيديو هذا. لا يمكن التراجع عن هذا الإجراء.",
|
||||
"topic.title": "مواضيع الفيديو",
|
||||
"topic.untitled": "موضوع افتراضي"
|
||||
}
|
||||
@@ -58,13 +58,13 @@
|
||||
"duplicateTitle": "{{title}} - Копие",
|
||||
"emptyAgent": "Все още няма Агенти. Започнете с първия си Агент — изградете системата си с времето.",
|
||||
"emptyAgentAction": "Създай Агент",
|
||||
"extendParams.disableContextCaching.desc": "Намалява до 90% от разходите за генериране на един разговор и увеличава скоростта до 4 пъти. Активирането автоматично премахва ограничението за брой исторически съобщения. <1>Научете повече</1>",
|
||||
"extendParams.disableContextCaching.desc": "Намалете до 90% от разходите за генериране на един разговор и постигнете до 4 пъти по-висока скорост. <1>Научете повече</1>",
|
||||
"extendParams.disableContextCaching.title": "Активирай кеширане на контекста",
|
||||
"extendParams.effort.desc": "Контролирайте колко токени използва Claude при отговор чрез параметъра за усилие.",
|
||||
"extendParams.effort.title": "Усилие",
|
||||
"extendParams.enableAdaptiveThinking.desc": "Позволете на Claude динамично да решава кога и колко да мисли с режима за адаптивно мислене.",
|
||||
"extendParams.enableAdaptiveThinking.title": "Активирай адаптивно мислене",
|
||||
"extendParams.enableReasoning.desc": "Въз основа на ограничението на механизма Claude Thinking, активирането автоматично премахва ограничението за брой исторически съобщения. <1>Научете повече</1>",
|
||||
"extendParams.enableReasoning.desc": "Базирано на ограничението на механизма за мислене на Claude. <1>Научете повече</1>",
|
||||
"extendParams.enableReasoning.title": "Активирай дълбоко мислене",
|
||||
"extendParams.imageAspectRatio.title": "Съотношение на изображението",
|
||||
"extendParams.imageResolution.title": "Резолюция на изображението",
|
||||
@@ -165,6 +165,7 @@
|
||||
"messageAction.delAndRegenerate": "Изтрий и генерирай отново",
|
||||
"messageAction.deleteDisabledByThreads": "Това съобщение има подтема и не може да бъде изтрито",
|
||||
"messageAction.expand": "Разгъни съобщението",
|
||||
"messageAction.reaction": "Добави реакция",
|
||||
"messageAction.regenerate": "Генерирай отново",
|
||||
"messages.dm.sentTo": "Видимо само за {{name}}",
|
||||
"messages.dm.title": "ЛС",
|
||||
|
||||
@@ -143,6 +143,7 @@
|
||||
"cmdk.keywords.stats": "статистики анализи",
|
||||
"cmdk.keywords.submitIssue": "проблем бъг обратна връзка",
|
||||
"cmdk.keywords.usage": "използване статистика консумация квота",
|
||||
"cmdk.keywords.video": "видео,генерирай,seedance,kling",
|
||||
"cmdk.memory": "Памет",
|
||||
"cmdk.mentionAgent": "Спомени агент",
|
||||
"cmdk.navigate": "Навигирай",
|
||||
@@ -193,6 +194,7 @@
|
||||
"cmdk.themeLight": "Светла",
|
||||
"cmdk.toOpen": "Отвори",
|
||||
"cmdk.toSelect": "Избери",
|
||||
"cmdk.video": "AI Видео",
|
||||
"confirm": "Потвърди",
|
||||
"contact": "Свържете се с нас",
|
||||
"copy": "Копирай",
|
||||
|
||||
@@ -43,6 +43,8 @@
|
||||
"FileManager.emptyStatus.or": "или",
|
||||
"FileManager.emptyStatus.title": "Плъзнете файлове или папки тук",
|
||||
"FileManager.noFolders": "Няма налични папки",
|
||||
"FileManager.search.noResults": "Няма намерени файлове",
|
||||
"FileManager.search.placeholder": "Търсене на файлове...",
|
||||
"FileManager.sort.dateAdded": "Дата на добавяне",
|
||||
"FileManager.sort.name": "Име",
|
||||
"FileManager.sort.size": "Размер",
|
||||
@@ -94,6 +96,35 @@
|
||||
"ModelSelect.removed": "Моделът не е в списъка. Ще бъде автоматично премахнат, ако бъде деселектиран.",
|
||||
"ModelSwitchPanel.byModel": "По модел",
|
||||
"ModelSwitchPanel.byProvider": "По доставчик",
|
||||
"ModelSwitchPanel.detail.abilities": "Възможности",
|
||||
"ModelSwitchPanel.detail.abilities.files": "Файлове",
|
||||
"ModelSwitchPanel.detail.abilities.functionCall": "Извикване на инструмент",
|
||||
"ModelSwitchPanel.detail.abilities.imageOutput": "Изход на изображение",
|
||||
"ModelSwitchPanel.detail.abilities.reasoning": "Разсъждение",
|
||||
"ModelSwitchPanel.detail.abilities.search": "Търсене",
|
||||
"ModelSwitchPanel.detail.abilities.video": "Видео",
|
||||
"ModelSwitchPanel.detail.abilities.vision": "Визия",
|
||||
"ModelSwitchPanel.detail.config": "Конфигурация на модела",
|
||||
"ModelSwitchPanel.detail.context": "Дължина на контекста",
|
||||
"ModelSwitchPanel.detail.pricing": "Ценообразуване",
|
||||
"ModelSwitchPanel.detail.pricing.cachedInput": "Кеширан вход ${{amount}}/М",
|
||||
"ModelSwitchPanel.detail.pricing.group.audio": "Аудио",
|
||||
"ModelSwitchPanel.detail.pricing.group.image": "Изображение",
|
||||
"ModelSwitchPanel.detail.pricing.group.text": "Текст",
|
||||
"ModelSwitchPanel.detail.pricing.input": "Вход ${{amount}}/М",
|
||||
"ModelSwitchPanel.detail.pricing.output": "Изход ${{amount}}/М",
|
||||
"ModelSwitchPanel.detail.pricing.unit.audioInput": "Аудио вход",
|
||||
"ModelSwitchPanel.detail.pricing.unit.audioInput_cacheRead": "Аудио вход (кеширан)",
|
||||
"ModelSwitchPanel.detail.pricing.unit.audioOutput": "Аудио изход",
|
||||
"ModelSwitchPanel.detail.pricing.unit.imageGeneration": "Генериране на изображение",
|
||||
"ModelSwitchPanel.detail.pricing.unit.imageInput": "Вход на изображение",
|
||||
"ModelSwitchPanel.detail.pricing.unit.imageInput_cacheRead": "Вход на изображение (кеширан)",
|
||||
"ModelSwitchPanel.detail.pricing.unit.imageOutput": "Изход на изображение",
|
||||
"ModelSwitchPanel.detail.pricing.unit.textInput": "Вход",
|
||||
"ModelSwitchPanel.detail.pricing.unit.textInput_cacheRead": "Вход (кеширан)",
|
||||
"ModelSwitchPanel.detail.pricing.unit.textInput_cacheWrite": "Вход (запис в кеш)",
|
||||
"ModelSwitchPanel.detail.pricing.unit.textOutput": "Изход",
|
||||
"ModelSwitchPanel.detail.releasedAt": "Пуснат на {{date}}",
|
||||
"ModelSwitchPanel.emptyModel": "Няма активиран модел. Моля, отидете в настройките, за да активирате.",
|
||||
"ModelSwitchPanel.emptyProvider": "Няма активирани доставчици. Моля, отидете в настройките, за да активирате такъв.",
|
||||
"ModelSwitchPanel.goToSettings": "Отиди в настройките",
|
||||
|
||||
@@ -150,6 +150,9 @@
|
||||
"groupAgents.tag": "Група",
|
||||
"groupAgents.underReview": "В процес на преглед",
|
||||
"home.communityAgents": "Агенти от общността",
|
||||
"home.creatorReward.action": "Кандидатствай сега",
|
||||
"home.creatorReward.subtitle": "Програмата за възнаграждение на създатели за 2026 г. е официално стартирана.",
|
||||
"home.creatorReward.title": "Създавай. Споделяй. Получавай възнаграждение.",
|
||||
"home.featuredAssistants": "Препоръчани агенти",
|
||||
"home.featuredModels": "Препоръчани модели",
|
||||
"home.featuredPlugins": "Препоръчани умения",
|
||||
@@ -194,6 +197,8 @@
|
||||
"mcp.categories.tools.name": "Помощни инструменти",
|
||||
"mcp.categories.travel-transport.description": "Планиране на пътувания и транспорт",
|
||||
"mcp.categories.travel-transport.name": "Пътуване и транспорт",
|
||||
"mcp.categories.utility.description": "Прогноза за времето и метеорологични услуги",
|
||||
"mcp.categories.utility.name": "Услуги",
|
||||
"mcp.categories.weather.description": "Прогноза за времето и метеорологични услуги",
|
||||
"mcp.categories.weather.name": "Времето",
|
||||
"mcp.categories.web-search.description": "Уеб търсене и извличане на информация",
|
||||
@@ -478,6 +483,10 @@
|
||||
"tab.plugin": "Умение",
|
||||
"tab.provider": "Доставчик",
|
||||
"tab.user": "Потребител",
|
||||
"time.formatOtherYear": "D MMM, YYYY",
|
||||
"time.formatThisYear": "D MMM",
|
||||
"time.today": "Днес",
|
||||
"time.yesterday": "Вчера",
|
||||
"user.agents": "Агенти",
|
||||
"user.downloads": "Изтегляния",
|
||||
"user.editProfile": "Редактирай профил",
|
||||
|
||||
@@ -10,5 +10,6 @@
|
||||
"starter.deepResearch": "Задълбочено проучване",
|
||||
"starter.developing": "Очаквайте скоро",
|
||||
"starter.image": "Изображение",
|
||||
"starter.seedance": "Seedance 2.0",
|
||||
"starter.write": "Писане"
|
||||
}
|
||||
|
||||
@@ -9,7 +9,10 @@
|
||||
"addToKnowledgeBase.title": "Добавяне към библиотека",
|
||||
"addToKnowledgeBase.totalFiles": "{{count}} избрани файла",
|
||||
"createNew.confirm": "Създай нова",
|
||||
"createNew.description.placeholder": "Описание на библиотеката (по избор)",
|
||||
"createNew.description.label": "Описание на библиотеката (по избор)",
|
||||
"createNew.description.placeholder": "Описанието помага на LLM да разбере по-добре вашата библиотека",
|
||||
"createNew.edit.confirm": "Запази промените",
|
||||
"createNew.edit.title": "Редактиране на библиотека",
|
||||
"createNew.formTitle": "Основна информация",
|
||||
"createNew.name.placeholder": "Име на библиотеката",
|
||||
"createNew.name.required": "Моля, въведете име на библиотеката",
|
||||
|
||||
@@ -38,6 +38,10 @@
|
||||
"messages.success.submit": "Удостоверяването е успешно! Вече можете да публикувате своя агент.",
|
||||
"messages.success.upload": "Удостоверяването е успешно! Вече можете да публикувате нова версия.",
|
||||
"profileSetup.cancel": "Отказ",
|
||||
"profileSetup.confirmChangeUserId.cancel": "Отказ",
|
||||
"profileSetup.confirmChangeUserId.confirm": "Промени потребителското име",
|
||||
"profileSetup.confirmChangeUserId.description": "След като преминете към @{{newId}}, всеки ще може да заеме старото ви потребителско име @{{oldId}} и всички съществуващи връзки към вашия профил ще спрат да работят. Това действие не може да бъде отменено. Сигурни ли сте, че искате да продължите?",
|
||||
"profileSetup.confirmChangeUserId.title": "Промяна на потребителското име?",
|
||||
"profileSetup.descriptionEdit": "Актуализирай информацията в профила си в общността.",
|
||||
"profileSetup.descriptionFirstTime": "Настрой профила си, за да го завършиш.",
|
||||
"profileSetup.errors.fileTooLarge": "Размерът на файла не може да надвишава 2MB",
|
||||
|
||||
@@ -260,8 +260,8 @@
|
||||
"providerModels.item.modelConfig.type.options.realtime": "Чат в реално време",
|
||||
"providerModels.item.modelConfig.type.options.stt": "Реч към текст",
|
||||
"providerModels.item.modelConfig.type.options.text2music": "Текст към музика",
|
||||
"providerModels.item.modelConfig.type.options.text2video": "Текст към видео",
|
||||
"providerModels.item.modelConfig.type.options.tts": "Текст към реч",
|
||||
"providerModels.item.modelConfig.type.options.video": "Генериране на видео",
|
||||
"providerModels.item.modelConfig.type.placeholder": "Изберете тип модел",
|
||||
"providerModels.item.modelConfig.type.title": "Тип модел",
|
||||
"providerModels.item.modelConfig.video.extra": "Активира конфигурация за разпознаване на видео. Поддръжката зависи от модела. Моля, тествайте.",
|
||||
|
||||
+83
-11
@@ -74,7 +74,11 @@
|
||||
"MiniMax-M1.description": "Нов вътрешен модел за разсъждение с 80K верига на мисълта и 1M вход, предлагащ производителност, сравнима с водещите глобални модели.",
|
||||
"MiniMax-M2-Stable.description": "Създаден за ефективно програмиране и агентски работни потоци, с по-висока едновременност за търговска употреба.",
|
||||
"MiniMax-M2.1-Lightning.description": "Мощни многоезични възможности за програмиране и цялостно подобрено програмистко изживяване. По-бързо и по-ефективно.",
|
||||
"MiniMax-M2.1-highspeed.description": "Мощни многоезични програмни възможности с по-бързо и ефективно извеждане.",
|
||||
"MiniMax-M2.1.description": "MiniMax-M2.1 е водеща отворена голяма езикова система от MiniMax, фокусирана върху решаването на сложни реални задачи. Основните ѝ предимства са възможностите за програмиране на множество езици и способността да действа като агент за решаване на сложни задачи.",
|
||||
"MiniMax-M2.5-Lightning.description": "M2.5 Lightning: Същата производителност, по-бърз и по-агилен (приблизително 100 tps).",
|
||||
"MiniMax-M2.5-highspeed.description": "Същата производителност като M2.5 с значително по-бързо извеждане.",
|
||||
"MiniMax-M2.5.description": "Висококласна производителност и максимална икономичност, лесно справяне със сложни задачи (приблизително 60 tps).",
|
||||
"MiniMax-M2.description": "Създаден специално за ефективно програмиране и работни потоци с агенти",
|
||||
"MiniMax-Text-01.description": "MiniMax-01 въвежда мащабно линейно внимание отвъд класическите трансформери, с 456B параметри и 45.9B активирани на преминаване. Постига водеща производителност и поддържа до 4M токена контекст (32× GPT-4o, 20× Claude-3.5-Sonnet).",
|
||||
"MiniMaxAI/MiniMax-M1-80k.description": "MiniMax-M1 е отворен модел с голям мащаб и хибридно внимание, с общо 456B параметри и ~45.9B активни на токен. Поддържа нативно 1M контекст и използва Flash Attention за 75% по-малко FLOPs при генериране на 100K токена спрямо DeepSeek R1. С MoE архитектура, CISPO и хибридно обучение с внимание и RL, постига водеща производителност при дълги входове и реални задачи по софтуерно инженерство.",
|
||||
@@ -107,6 +111,7 @@
|
||||
"Pro/moonshotai/Kimi-K2-Thinking.description": "Kimi K2 Thinking Turbo е ускорен вариант, оптимизиран за скорост на разсъждение и пропускателна способност, като запазва многoетапното разсъждение и използване на инструменти от K2 Thinking. Това е MoE модел с ~1T общи параметри, роден 256K контекст и стабилно мащабируемо извикване на инструменти за производствени сценарии с по-строги изисквания за латентност и едновременност.",
|
||||
"Pro/moonshotai/Kimi-K2.5.description": "Kimi K2.5 е отворен мултимодален агентен модел, базиран на Kimi-K2-Base, обучен върху приблизително 1.5 трилиона смесени визуални и текстови токени. Моделът използва MoE архитектура с общо 1T параметри и 32B активни параметри, поддържа контекстен прозорец от 256K и безпроблемно интегрира визуално и езиково разбиране.",
|
||||
"Pro/zai-org/glm-4.7.description": "GLM-4.7 е най-новият флагмански модел на Zhipu с общо 355 милиарда параметъра и 32 милиарда активни параметъра. Той е напълно обновен в областите на общ диалог, логическо мислене и агентни способности. GLM-4.7 подобрява Междинното мислене и въвежда Запазено мислене и Мислене на ниво обръщение.",
|
||||
"Pro/zai-org/glm-5.description": "GLM-5 е новото поколение голям езиков модел, представен от Zhipu, фокусиран върху сложни системни инженерни задачи и дългосрочни агентски задачи. Моделът разширява параметрите до 744B (40B активни) и интегрира DeepSeek Sparse Attention.",
|
||||
"QwQ-32B-Preview.description": "Qwen QwQ е експериментален изследователски модел, фокусиран върху подобряване на разсъждението.",
|
||||
"Qwen/QVQ-72B-Preview.description": "QVQ-72B-Preview е изследователски модел от Qwen, насочен към визуално разсъждение, със силни страни в разбирането на сложни сцени и визуални математически задачи.",
|
||||
"Qwen/QwQ-32B-Preview.description": "Qwen QwQ е експериментален изследователски модел, фокусиран върху подобрено AI разсъждение.",
|
||||
@@ -274,22 +279,28 @@
|
||||
"chatgpt-4o-latest.description": "ChatGPT-4o е динамичен модел, актуализиран в реално време, комбиниращ силно разбиране и генериране за мащабни приложения като клиентска поддръжка, образование и техническа помощ.",
|
||||
"claude-2.0.description": "Claude 2 предлага ключови подобрения за предприятия, включително водещ контекст от 200 000 токена, намалени халюцинации, системни подканвания и нова тестова функция: използване на инструменти.",
|
||||
"claude-2.1.description": "Claude 2 предлага ключови подобрения за предприятия, включително водещ контекст от 200 000 токена, намалени халюцинации, системни подканвания и нова тестова функция: използване на инструменти.",
|
||||
"claude-3-5-haiku-20241022.description": "Claude 3.5 Haiku е най-бързият модел от ново поколение на Anthropic. В сравнение с Claude 3 Haiku, той показва подобрения в различни умения и надминава предишния най-голям модел Claude 3 Opus в много интелигентни бенчмаркове.",
|
||||
"claude-3-5-haiku-20241022.description": "Claude 3.5 Haiku е най-бързият модел от ново поколение на Anthropic, с подобрени умения и превъзхождащ предишния водещ модел Claude 3 Opus в много бенчмаркове.",
|
||||
"claude-3-5-haiku-latest.description": "Claude 3.5 Haiku осигурява бързи отговори за леки задачи.",
|
||||
"claude-3-7-sonnet-20250219.description": "Claude 3.7 Sonnet е най-интелигентният модел на Anthropic и първият хибриден модел за разсъждение на пазара. Той може да генерира почти мигновени отговори или разширено поетапно разсъждение, което потребителите могат да проследят. Sonnet е особено силен в програмиране, анализ на данни, визуални задачи и задачи за агенти.",
|
||||
"claude-3-7-sonnet-20250219.description": "Claude Sonnet 3.7 е най-интелигентният модел на Anthropic и първият хибриден модел за разсъждение на пазара, предлагащ почти мигновени отговори или разширено мислене с прецизен контрол.",
|
||||
"claude-3-7-sonnet-latest.description": "Claude 3.7 Sonnet е най-новият и най-способен модел на Anthropic за силно сложни задачи, отличаващ се с производителност, интелигентност, плавност и разбиране.",
|
||||
"claude-3-haiku-20240307.description": "Claude 3 Haiku е най-бързият и най-компактен модел на Anthropic, проектиран за почти мигновени отговори с бърза и точна производителност.",
|
||||
"claude-3-opus-20240229.description": "Claude 3 Opus е най-мощният модел на Anthropic за силно сложни задачи, отличаващ се с производителност, интелигентност, плавност и разбиране.",
|
||||
"claude-3-sonnet-20240229.description": "Claude 3 Sonnet балансира интелигентност и скорост за корпоративни натоварвания, осигурявайки висока полезност на по-ниска цена и надеждно мащабно внедряване.",
|
||||
"claude-haiku-4-5-20251001.description": "Claude Haiku 4.5 е най-бързият и най-интелигентен Haiku модел на Anthropic, с мълниеносна скорост и разширено разсъждение.",
|
||||
"claude-3.5-sonnet.description": "Claude 3.5 Sonnet се отличава в програмиране, писане и сложни разсъждения.",
|
||||
"claude-3.7-sonnet-thought.description": "Claude 3.7 Sonnet с разширено мислене за задачи, изискващи сложни разсъждения.",
|
||||
"claude-3.7-sonnet.description": "Claude 3.7 Sonnet е надградена версия с разширен контекст и възможности.",
|
||||
"claude-haiku-4-5-20251001.description": "Claude Haiku 4.5 е най-бързият и най-интелигентен Haiku модел на Anthropic, с мълниеносна скорост и разширено мислене.",
|
||||
"claude-haiku-4.5.description": "Claude Haiku 4.5 е бърз и ефективен модел за различни задачи.",
|
||||
"claude-opus-4-1-20250805-thinking.description": "Claude Opus 4.1 Thinking е усъвършенстван вариант, който може да разкрие процеса си на разсъждение.",
|
||||
"claude-opus-4-1-20250805.description": "Claude Opus 4.1 е най-новият и най-способен модел на Anthropic за изключително сложни задачи, отличаващ се с висока производителност, интелигентност, плавност и разбиране.",
|
||||
"claude-opus-4-20250514.description": "Claude Opus 4 е най-мощният модел на Anthropic за изключително сложни задачи, отличаващ се с висока производителност, интелигентност, плавност и разбиране.",
|
||||
"claude-opus-4-5-20251101.description": "Claude Opus 4.5 е флагманският модел на Anthropic, комбиниращ изключителна интелигентност с мащабируема производителност, идеален за сложни задачи, изискващи най-висококачествени отговори и разсъждение.",
|
||||
"claude-opus-4-6.description": "Claude Opus 4.6 е най-интелигентният модел на Anthropic за изграждане на агенти и програмиране.",
|
||||
"claude-sonnet-4-20250514-thinking.description": "Claude Sonnet 4 Thinking може да генерира почти мигновени отговори или разширено стъпково мислене с видим процес.",
|
||||
"claude-sonnet-4-20250514.description": "Claude Sonnet 4 може да генерира почти мигновени отговори или разширено поетапно мислене с видим процес.",
|
||||
"claude-sonnet-4-5-20250929.description": "Claude Sonnet 4.5 е най-интелигентният модел на Anthropic до момента.",
|
||||
"claude-sonnet-4-20250514.description": "Claude Sonnet 4 е най-интелигентният модел на Anthropic досега, предлагащ почти мигновени отговори или разширено поетапно мислене с прецизен контрол за потребителите на API.",
|
||||
"claude-sonnet-4-5-20250929.description": "Claude Sonnet 4.5 е най-интелигентният модел на Anthropic досега.",
|
||||
"claude-sonnet-4-6.description": "Claude Sonnet 4.6 е най-добрата комбинация от скорост и интелигентност на Anthropic.",
|
||||
"claude-sonnet-4.description": "Claude Sonnet 4 е най-новото поколение с подобрена производителност във всички задачи.",
|
||||
"codegeex-4.description": "CodeGeeX-4 е мощен AI асистент за програмиране, който поддържа многоезични въпроси и допълване на код, повишавайки продуктивността на разработчиците.",
|
||||
"codegeex4-all-9b.description": "CodeGeeX4-ALL-9B е многоезичен модел за генериране на код, който поддържа допълване и създаване на код, интерпретиране, уеб търсене, извикване на функции и въпроси на ниво хранилище. Подходящ е за широк спектър от софтуерни сценарии и е водещ модел под 10 милиарда параметри.",
|
||||
"codegemma.description": "CodeGemma е лек модел за разнообразни програмни задачи, позволяващ бърза итерация и интеграция.",
|
||||
@@ -358,7 +369,7 @@
|
||||
"deepseek-ai/deepseek-v3.1-terminus.description": "DeepSeek V3.1 е модел за разсъждение от ново поколение с по-силни способности за сложни разсъждения и верига от мисли за задълбочени аналитични задачи.",
|
||||
"deepseek-ai/deepseek-v3.1.description": "DeepSeek V3.1 е модел за разсъждение от ново поколение с по-силни способности за сложни разсъждения и верига от мисли за задълбочени аналитични задачи.",
|
||||
"deepseek-ai/deepseek-vl2.description": "DeepSeek-VL2 е MoE модел за визия и език, базиран на DeepSeekMoE-27B със слаба активация, постигайки висока производителност с едва 4.5 милиарда активни параметъра. Отличава се в визуални въпроси и отговори, OCR, разбиране на документи/таблици/графики и визуално привързване.",
|
||||
"deepseek-chat.description": "Нов отворен модел, съчетаващ общи и програмни способности. Съхранява общия диалогов капацитет на чат модела и силните програмни умения на кодиращия модел, с по-добро съответствие с предпочитанията. DeepSeek-V2.5 също така подобрява писането и следването на инструкции.",
|
||||
"deepseek-chat.description": "DeepSeek V3.2 балансира разсъждението и дължината на отговорите за ежедневни въпроси и задачи на агенти. Публичните бенчмаркове достигат нивата на GPT-5, а това е първият модел, който интегрира мислене в използването на инструменти, водещ в оценките на отворен код за агенти.",
|
||||
"deepseek-coder-33B-instruct.description": "DeepSeek Coder 33B е езиков модел за програмиране, обучен върху 2 трилиона токени (87% код, 13% китайски/английски текст). Въвежда 16K контекстен прозорец и задачи за попълване в средата, осигурявайки допълване на код на ниво проект и попълване на фрагменти.",
|
||||
"deepseek-coder-v2.description": "DeepSeek Coder V2 е отворен MoE модел за програмиране, който се представя на ниво GPT-4 Turbo.",
|
||||
"deepseek-coder-v2:236b.description": "DeepSeek Coder V2 е отворен MoE модел за програмиране, който се представя на ниво GPT-4 Turbo.",
|
||||
@@ -381,7 +392,7 @@
|
||||
"deepseek-r1-fast-online.description": "Пълна бърза версия на DeepSeek R1 с търсене в реално време в уеб, комбинираща възможности от мащаб 671B и по-бърз отговор.",
|
||||
"deepseek-r1-online.description": "Пълна версия на DeepSeek R1 с 671 милиарда параметъра и търсене в реално време в уеб, предлагаща по-силно разбиране и генериране.",
|
||||
"deepseek-r1.description": "DeepSeek-R1 използва данни от студен старт преди подсиленото обучение и се представя наравно с OpenAI-o1 в математика, програмиране и разсъждение.",
|
||||
"deepseek-reasoner.description": "Режимът на мислене DeepSeek V3.2 извежда верига от мисли преди крайния отговор за повишена точност.",
|
||||
"deepseek-reasoner.description": "DeepSeek V3.2 Thinking е дълбок разсъждаващ модел, който генерира верига от мисли преди отговорите за по-висока точност, с водещи резултати в състезания и разсъждение, сравнимо с Gemini-3.0-Pro.",
|
||||
"deepseek-v2.description": "DeepSeek V2 е ефективен MoE модел за икономична обработка.",
|
||||
"deepseek-v2:236b.description": "DeepSeek V2 236B е модел на DeepSeek, фокусиран върху програмиране, с висока производителност при генериране на код.",
|
||||
"deepseek-v3-0324.description": "DeepSeek-V3-0324 е MoE модел с 671 милиарда параметъра, с изключителни способности в програмиране, технически задачи, разбиране на контекст и обработка на дълги текстове.",
|
||||
@@ -439,6 +450,10 @@
|
||||
"doubao-seed-1.6-vision.description": "Doubao-Seed-1.6-vision е визуален дълбок разсъждаващ модел, който осигурява по-силно мултимодално разбиране и разсъждение за образование, преглед на изображения, инспекция/сигурност и AI търсене с въпроси и отговори. Поддържа контекстен прозорец от 256k и до 64k изходни токена.",
|
||||
"doubao-seed-1.6.description": "Doubao-Seed-1.6 е нов мултимодален дълбок разсъждаващ модел с режими auto, thinking и non-thinking. В non-thinking режим значително превъзхожда Doubao-1.5-pro/250115. Поддържа контекстен прозорец от 256k и до 16k изходни токена.",
|
||||
"doubao-seed-1.8.description": "Doubao-Seed-1.8 притежава по-силно мултимодално разбиране и агентни способности, поддържа вход от текст/изображение/видео и кеширане на контекст, като осигурява отлична производителност при сложни задачи.",
|
||||
"doubao-seed-2.0-code.description": "Doubao-Seed-2.0-code е дълбоко оптимизиран за агентско програмиране, поддържа мултимодални входове и контекстен прозорец от 256k, подходящ за програмиране, разбиране на визия и агентски работни потоци.",
|
||||
"doubao-seed-2.0-lite.description": "Doubao-Seed-2.0-lite е нов мултимодален модел за дълбоко разсъждение, който предлага по-добра стойност и е силен избор за общи задачи, с контекстен прозорец до 256k.",
|
||||
"doubao-seed-2.0-mini.description": "Doubao-Seed-2.0-mini е лек модел с бърз отговор и висока производителност, подходящ за малки задачи и сценарии с висока конкуренция.",
|
||||
"doubao-seed-2.0-pro.description": "Doubao-Seed-2.0-pro е водещият общ агентски модел на ByteDance, с цялостни подобрения в планирането и изпълнението на сложни задачи.",
|
||||
"doubao-seed-code.description": "Doubao-Seed-Code е дълбоко оптимизиран за агентно програмиране, поддържа мултимодални входове (текст/изображение/видео) и контекстен прозорец от 256k, съвместим е с Anthropic API и е подходящ за програмиране, разбиране на визия и работни потоци с агенти.",
|
||||
"doubao-seededit-3-0-i2i-250628.description": "Моделът за изображения на Doubao от ByteDance Seed поддържа вход от текст и изображения с високо контролируемо, висококачествено генериране на изображения. Поддържа редактиране на изображения, водено от текст, с размери на изхода между 512 и 1536 по дългата страна.",
|
||||
"doubao-seedream-3-0-t2i-250415.description": "Seedream 3.0 е модел за генериране на изображения от ByteDance Seed, поддържащ вход от текст и изображения с високо контролируемо, висококачествено генериране на изображения. Генерира изображения от текстови подсказки.",
|
||||
@@ -471,7 +486,8 @@
|
||||
"ernie-speed-pro-128k.description": "ERNIE Speed Pro 128K е модел с висока едновременност и висока стойност за мащабни онлайн услуги и корпоративни приложения.",
|
||||
"ernie-x1-turbo-32k.description": "ERNIE X1 Turbo 32K е бърз мислещ модел с 32K контекст за сложни разсъждения и многозавойни разговори.",
|
||||
"ernie-x1.1-preview.description": "ERNIE X1.1 Preview е предварителен модел за мислене, предназначен за оценка и тестване.",
|
||||
"fal-ai/bytedance/seedream/v4.description": "Seedream 4.0 е модел за генериране на изображения от ByteDance Seed, поддържащ вход от текст и изображения с висока степен на контрол и качество. Генерира изображения от текстови подсказки.",
|
||||
"fal-ai/bytedance/seedream/v4.5.description": "Seedream 4.5, разработен от екипа Seed на ByteDance, поддържа редактиране и композиране на множество изображения. Отличава се с подобрена последователност на обектите, точно следване на инструкции, разбиране на пространствена логика, естетическо изразяване, оформление на постери и дизайн на лога с високопрецизно визуално-текстово рендиране.",
|
||||
"fal-ai/bytedance/seedream/v4.description": "Seedream 4.0, разработен от ByteDance Seed, поддържа текстови и визуални входове за висококачествено и силно контролируемо генериране на изображения от подсказки.",
|
||||
"fal-ai/flux-kontext/dev.description": "FLUX.1 модел, фокусиран върху редактиране на изображения, поддържащ вход от текст и изображения.",
|
||||
"fal-ai/flux-pro/kontext.description": "FLUX.1 Kontext [pro] приема текст и референтни изображения като вход, позволявайки целенасочени локални редакции и сложни глобални трансформации на сцени.",
|
||||
"fal-ai/flux/krea.description": "Flux Krea [dev] е модел за генериране на изображения с естетично предпочитание към по-реалистични и естествени изображения.",
|
||||
@@ -479,8 +495,8 @@
|
||||
"fal-ai/hunyuan-image/v3.description": "Мощен роден мултимодален модел за генериране на изображения.",
|
||||
"fal-ai/imagen4/preview.description": "Модел за висококачествено генериране на изображения от Google.",
|
||||
"fal-ai/nano-banana.description": "Nano Banana е най-новият, най-бърз и най-ефективен роден мултимодален модел на Google, позволяващ генериране и редактиране на изображения чрез разговор.",
|
||||
"fal-ai/qwen-image-edit.description": "Професионален модел за редактиране на изображения от екипа на Qwen, който поддържа семантични и визуални редакции, прецизно редактира китайски и английски текст и позволява висококачествени трансформации като смяна на стил и завъртане на обекти.",
|
||||
"fal-ai/qwen-image.description": "Мощен модел за генериране на изображения от екипа на Qwen с впечатляващо визуализиране на китайски текст и разнообразни визуални стилове.",
|
||||
"fal-ai/qwen-image-edit.description": "Професионален модел за редактиране на изображения от екипа Qwen, поддържащ семантични и визуални редакции, прецизно редактиране на текст на китайски/английски, трансфер на стил, завъртане и други.",
|
||||
"fal-ai/qwen-image.description": "Мощен модел за генериране на изображения от екипа Qwen с отлично визуализиране на китайски текст и разнообразни визуални стилове.",
|
||||
"flux-1-schnell.description": "Модел за преобразуване на текст в изображение с 12 милиарда параметъра от Black Forest Labs, използващ латентна дифузионна дестилация за генериране на висококачествени изображения в 1–4 стъпки. Съперничи на затворени алтернативи и е пуснат под лиценз Apache-2.0 за лична, изследователска и търговска употреба.",
|
||||
"flux-dev.description": "FLUX.1 [dev] е дестилиран модел с отворени тегла за нетърговска употреба. Запазва почти професионално качество на изображенията и следване на инструкции, като същевременно работи по-ефективно и използва ресурсите по-добре от стандартни модели със същия размер.",
|
||||
"flux-kontext-max.description": "Съвременно генериране и редактиране на изображения с контекст, комбиниращо текст и изображения за прецизни и последователни резултати.",
|
||||
@@ -511,6 +527,8 @@
|
||||
"gemini-2.0-flash-lite-001.description": "Вариант на Gemini 2.0 Flash, оптимизиран за ниска цена и ниска латентност.",
|
||||
"gemini-2.0-flash-lite.description": "Вариант на Gemini 2.0 Flash, оптимизиран за ниска цена и ниска латентност.",
|
||||
"gemini-2.0-flash.description": "Gemini 2.0 Flash предлага функции от ново поколение, включително изключителна скорост, вградена употреба на инструменти, мултимодално генериране и контекстен прозорец от 1 милион токена.",
|
||||
"gemini-2.5-flash-image-preview.description": "Nano Banana е най-новият, най-бърз и най-ефективен роден мултимодален модел на Google, позволяващ разговорно генериране и редактиране на изображения.",
|
||||
"gemini-2.5-flash-image-preview:image.description": "Nano Banana е най-новият, най-бърз и най-ефективен роден мултимодален модел на Google, позволяващ разговорно генериране и редактиране на изображения.",
|
||||
"gemini-2.5-flash-image.description": "Nano Banana е най-новият, най-бърз и най-ефективен роден мултимодален модел на Google, позволяващ разговорно генериране и редактиране на изображения.",
|
||||
"gemini-2.5-flash-image:image.description": "Nano Banana е най-новият, най-бърз и най-ефективен роден мултимодален модел на Google, позволяващ разговорно генериране и редактиране на изображения.",
|
||||
"gemini-2.5-flash-lite-preview-06-17.description": "Gemini 2.5 Flash-Lite Preview е най-малкият и най-изгоден модел на Google, проектиран за мащабна употреба.",
|
||||
@@ -525,7 +543,7 @@
|
||||
"gemini-2.5-pro.description": "Gemini 2.5 Pro е най-усъвършенстваният модел за разсъждение на Google, способен да разсъждава върху код, математика и STEM проблеми и да анализира големи набори от данни, кодови бази и документи с дълъг контекст.",
|
||||
"gemini-3-flash-preview.description": "Gemini 3 Flash е най-интелигентният модел, създаден за скорост, съчетаващ авангардна интелигентност с отлично търсене и обоснованост.",
|
||||
"gemini-3-pro-image-preview.description": "Gemini 3 Pro Image(Nano Banana Pro)е модел на Google за генериране на изображения, който също така поддържа мултимодален диалог.",
|
||||
"gemini-3-pro-image-preview:image.description": "Gemini 3 Pro Image (Nano Banana Pro) е модел на Google за генериране на изображения, който също поддържа мултимодален чат.",
|
||||
"gemini-3-pro-image-preview:image.description": "Gemini 3 Pro Image (Nano Banana Pro) е моделът на Google за генериране на изображения и поддържа мултимодален чат.",
|
||||
"gemini-3-pro-preview.description": "Gemini 3 Pro е най-мощният агентен и „vibe-coding“ модел на Google, който предлага по-богати визуализации и по-дълбоко взаимодействие, базирано на съвременно логическо мислене.",
|
||||
"gemini-flash-latest.description": "Най-новата версия на Gemini Flash",
|
||||
"gemini-flash-lite-latest.description": "Най-новата версия на Gemini Flash-Lite",
|
||||
@@ -565,6 +583,7 @@
|
||||
"glm-4v-plus-0111.description": "GLM-4V-Plus разбира видео и множество изображения, подходящ за мултимодални задачи.",
|
||||
"glm-4v-plus.description": "GLM-4V-Plus разбира видео и множество изображения, подходящ за мултимодални задачи.",
|
||||
"glm-4v.description": "GLM-4V осигурява силно разбиране на изображения и логическо мислене в различни визуални задачи.",
|
||||
"glm-5.description": "Силен модел за разсъждение и агентски задачи от Z.ai с общо 744B параметри (40B активни), създаден за сложни системни инженерни задачи и дългосрочни задачи.",
|
||||
"glm-z1-air.description": "Модел за логическо мислене със силни способности за дълбоко разсъждение при сложни задачи.",
|
||||
"glm-z1-airx.description": "Ултра-бързо логическо мислене с високо качество на разсъжденията.",
|
||||
"glm-z1-flash.description": "Серията GLM-Z1 осигурява силно логическо мислене при сложни задачи, отличавайки се в логика, математика и програмиране.",
|
||||
@@ -604,6 +623,7 @@
|
||||
"google/text-embedding-005.description": "Модел за вграждане на текст, фокусиран върху английски език, оптимизиран за задачи с код и английски език.",
|
||||
"google/text-multilingual-embedding-002.description": "Многоезичен модел за вграждане на текст, оптимизиран за задачи с кръстосан езиков обхват на много езици.",
|
||||
"gpt-3.5-turbo-0125.description": "GPT 3.5 Turbo за генериране и разбиране на текст; в момента сочи към gpt-3.5-turbo-0125.",
|
||||
"gpt-3.5-turbo-0613.description": "GPT 3.5 Turbo е бърз и ефективен модел за различни задачи.",
|
||||
"gpt-3.5-turbo-1106.description": "GPT 3.5 Turbo за генериране и разбиране на текст; в момента сочи към gpt-3.5-turbo-0125.",
|
||||
"gpt-3.5-turbo-instruct.description": "GPT 3.5 Turbo за задачи с генериране и разбиране на текст, оптимизиран за следване на инструкции.",
|
||||
"gpt-3.5-turbo.description": "GPT 3.5 Turbo за генериране и разбиране на текст; в момента сочи към gpt-3.5-turbo-0125.",
|
||||
@@ -614,10 +634,12 @@
|
||||
"gpt-4-1106-preview.description": "Най-новият GPT-4 Turbo добавя възможности за визуално разпознаване. Визуалните заявки поддържат JSON режим и извикване на функции. Това е рентабилен мултимодален модел, който балансира точността и ефективността за приложения в реално време.",
|
||||
"gpt-4-32k-0613.description": "GPT-4 предлага по-голям контекстов прозорец за обработка на по-дълги входове в сценарии, изискващи интеграция на широка информация и анализ на данни.",
|
||||
"gpt-4-32k.description": "GPT-4 предлага по-голям контекстов прозорец за обработка на по-дълги входове в сценарии, изискващи интеграция на широка информация и анализ на данни.",
|
||||
"gpt-4-o-preview.description": "GPT-4o е най-усъвършенстваният мултимодален модел, който обработва текстови и визуални входове.",
|
||||
"gpt-4-turbo-2024-04-09.description": "Най-новият GPT-4 Turbo добавя възможности за визуално разпознаване. Визуалните заявки поддържат JSON режим и извикване на функции. Това е рентабилен мултимодален модел, който балансира точността и ефективността за приложения в реално време.",
|
||||
"gpt-4-turbo-preview.description": "Най-новият GPT-4 Turbo добавя възможности за визуално разпознаване. Визуалните заявки поддържат JSON режим и извикване на функции. Това е рентабилен мултимодален модел, който балансира точността и ефективността за приложения в реално време.",
|
||||
"gpt-4-turbo.description": "Най-новият GPT-4 Turbo добавя възможности за визуално разпознаване. Визуалните заявки поддържат JSON режим и извикване на функции. Това е рентабилен мултимодален модел, който балансира точността и ефективността за приложения в реално време.",
|
||||
"gpt-4-vision-preview.description": "Предварителен преглед на GPT-4 Vision, създаден за задачи по анализ и обработка на изображения.",
|
||||
"gpt-4.1-2025-04-14.description": "GPT-4.1 е водещият модел за сложни задачи, идеален за междудисциплинарно решаване на проблеми.",
|
||||
"gpt-4.1-mini.description": "GPT-4.1 mini балансира интелигентност, скорост и цена, което го прави привлекателен за множество приложения.",
|
||||
"gpt-4.1-nano.description": "GPT-4.1 nano е най-бързият и най-рентабилен модел от серията GPT-4.1.",
|
||||
"gpt-4.1.description": "GPT-4.1 е водещият ни модел за сложни задачи и решаване на проблеми в различни области.",
|
||||
@@ -627,6 +649,7 @@
|
||||
"gpt-4o-2024-08-06.description": "ChatGPT-4o е динамичен модел, актуализиран в реално време. Съчетава силно езиково разбиране и генериране за мащабни приложения като клиентска поддръжка, образование и техническа помощ.",
|
||||
"gpt-4o-2024-11-20.description": "ChatGPT-4o е динамичен модел, актуализиран в реално време, който съчетава силно разбиране и генериране за мащабни приложения като клиентска поддръжка, образование и техническа помощ.",
|
||||
"gpt-4o-audio-preview.description": "Предварителен преглед на GPT-4o Audio модел с аудио вход и изход.",
|
||||
"gpt-4o-mini-2024-07-18.description": "GPT-4o mini е икономично решение за широк спектър от текстови и визуални задачи.",
|
||||
"gpt-4o-mini-audio-preview.description": "GPT-4o mini Audio модел с аудио вход и изход.",
|
||||
"gpt-4o-mini-realtime-preview.description": "GPT-4o-mini вариант в реално време с аудио и текстов вход/изход в реално време.",
|
||||
"gpt-4o-mini-search-preview.description": "GPT-4o mini Search Preview е обучен да разбира и изпълнява заявки за уеб търсене чрез Chat Completions API. Уеб търсенето се таксува на извикване на инструмент в допълнение към разходите за токени.",
|
||||
@@ -779,6 +802,49 @@
|
||||
"llava.description": "LLaVA е мултимодален модел, комбиниращ визуален енкодер и Vicuna за силно разбиране на визия и език.",
|
||||
"llava:13b.description": "LLaVA е мултимодален модел, комбиниращ визуален енкодер и Vicuna за силно разбиране на визия и език.",
|
||||
"llava:34b.description": "LLaVA е мултимодален модел, комбиниращ визуален енкодер и Vicuna за силно разбиране на визия и език.",
|
||||
"magistral-medium-latest.description": "Magistral Medium 1.2 е авангарден модел за разсъждение от Mistral AI (септември 2025) с поддръжка на визуални данни.",
|
||||
"magistral-small-2509.description": "Magistral Small 1.2 е малък, с отворен код модел за разсъждение от Mistral AI (септември 2025) с поддръжка на визуални данни.",
|
||||
"mathstral.description": "MathΣtral е създаден за научни изследвания и математическо разсъждение, с мощни изчислителни и обяснителни способности.",
|
||||
"max-32k.description": "Spark Max 32K предлага обработка на голям контекст с по-добро разбиране и логическо разсъждение, поддържайки входове до 32K токена за четене на дълги документи и въпроси с частни знания.",
|
||||
"megrez-3b-instruct.description": "Megrez 3B Instruct е малък, ефективен модел от Wuwen Xinqiong.",
|
||||
"meituan/longcat-flash-chat.description": "Модел с отворен код от Meituan, оптимизиран за диалог и агентски задачи, силен в използването на инструменти и сложни многократни взаимодействия.",
|
||||
"meta-llama-3-70b-instruct.description": "Мощен модел с 70 милиарда параметъра, който се отличава в разсъждение, програмиране и широк спектър от езикови задачи.",
|
||||
"meta-llama-3-8b-instruct.description": "Универсален модел с 8 милиарда параметъра, оптимизиран за чат и генериране на текст.",
|
||||
"meta-llama-3.1-405b-instruct.description": "Llama 3.1 е текстов модел, обучен с инструкции, оптимизиран за многоезичен чат, с високи резултати в индустриалните бенчмаркове сред отворени и затворени модели.",
|
||||
"meta-llama-3.1-70b-instruct.description": "Llama 3.1 е текстов модел, обучен с инструкции, оптимизиран за многоезичен чат, с високи резултати в индустриалните бенчмаркове сред отворени и затворени модели.",
|
||||
"meta-llama-3.1-8b-instruct.description": "Llama 3.1 е текстов модел, обучен с инструкции, оптимизиран за многоезичен чат, с високи резултати в индустриалните бенчмаркове сред отворени и затворени модели.",
|
||||
"meta-llama/Llama-2-13b-chat-hf.description": "LLaMA-2 Chat (13B) предлага силна езикова обработка и стабилно чат изживяване.",
|
||||
"meta-llama/Llama-2-70b-hf.description": "LLaMA-2 предлага силна езикова обработка и стабилно взаимодействие.",
|
||||
"meta-llama/Llama-3-70b-chat-hf.description": "Llama 3 70B Instruct Reference е мощен чат модел за сложни диалози.",
|
||||
"meta-llama/Llama-3-8b-chat-hf.description": "Llama 3 8B Instruct Reference предлага многоезична поддръжка и обширни познания в различни области.",
|
||||
"meta-llama/Llama-3.2-11B-Vision-Instruct-Turbo.description": "LLaMA 3.2 е създаден за задачи, съчетаващи визия и текст. Отличава се в описване на изображения и визуални въпроси, свързвайки езиковото генериране с визуалното разсъждение.",
|
||||
"meta-llama/Llama-3.2-3B-Instruct-Turbo.description": "LLaMA 3.2 е създаден за задачи, съчетаващи визия и текст. Отличава се в описване на изображения и визуални въпроси, свързвайки езиковото генериране с визуалното разсъждение.",
|
||||
"meta-llama/Llama-3.2-90B-Vision-Instruct-Turbo.description": "LLaMA 3.2 е създаден за задачи, съчетаващи визия и текст. Отличава се в описване на изображения и визуални въпроси, свързвайки езиковото генериране с визуалното разсъждение.",
|
||||
"meta-llama/Llama-3.3-70B-Instruct-Turbo.description": "Meta Llama 3.3 е многоезичен LLM с 70 милиарда параметъра (текстов вход/изход), предварително обучен и настроен с инструкции. Версията, обучена с инструкции, е оптимизирана за многоезичен чат и превъзхожда много отворени и затворени модели в индустриалните бенчмаркове.",
|
||||
"meta-llama/Llama-Vision-Free.description": "LLaMA 3.2 е създаден за задачи, съчетаващи визия и текст. Отличава се в описване на изображения и визуални въпроси, свързвайки езиковото генериране с визуалното разсъждение.",
|
||||
"meta-llama/Meta-Llama-3-70B-Instruct-Lite.description": "Llama 3 70B Instruct Lite е създаден за висока производителност с ниска латентност.",
|
||||
"meta-llama/Meta-Llama-3-70B-Instruct-Turbo.description": "Llama 3 70B Instruct Turbo предлага силно разбиране и генериране за най-взискателните натоварвания.",
|
||||
"meta-llama/Meta-Llama-3-8B-Instruct-Lite.description": "Llama 3 8B Instruct Lite балансира производителността за среди с ограничени ресурси.",
|
||||
"meta-llama/Meta-Llama-3-8B-Instruct-Turbo.description": "Llama 3 8B Instruct Turbo е високопроизводителен LLM за широк спектър от приложения.",
|
||||
"meta-llama/Meta-Llama-3.1-405B-Instruct-Turbo.description": "Моделът Llama 3.1 Turbo с 405 милиарда параметъра предлага огромен контекстов капацитет за обработка на големи данни и се отличава в мащабни AI приложения.",
|
||||
"meta-llama/Meta-Llama-3.1-405B-Instruct.description": "Llama 3.1 е водещото семейство модели на Meta, достигащо до 405 милиарда параметъра за сложни диалози, многоезичен превод и анализ на данни.",
|
||||
"meta-llama/Meta-Llama-3.1-70B-Instruct-Turbo.description": "Llama 3.1 70B е фино настроен за приложения с високо натоварване; FP8 квантизацията осигурява ефективни изчисления и точност при сложни сценарии.",
|
||||
"meta-llama/Meta-Llama-3.1-70B.description": "Llama 3.1 е водещото семейство модели на Meta, достигащо до 405 милиарда параметъра за сложни диалози, многоезичен превод и анализ на данни.",
|
||||
"meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo.description": "Llama 3.1 8B използва FP8 квантизация, поддържа до 131 072 токена контекст и е сред водещите отворени модели за сложни задачи според множество бенчмаркове.",
|
||||
"meta-llama/llama-3-70b-instruct.description": "Llama 3 70B Instruct е оптимизиран за висококачествени диалози и показва отлични резултати в човешки оценки.",
|
||||
"meta-llama/llama-3-8b-instruct.description": "Llama 3 8B Instruct е оптимизиран за висококачествени диалози, превъзхождайки много затворени модели.",
|
||||
"meta-llama/llama-3.1-70b-instruct.description": "Най-новата серия Llama 3.1 на Meta, 70B вариант, обучен с инструкции, оптимизиран за висококачествени диалози. В индустриални оценки показва силна производителност спрямо водещи затворени модели. (Достъпен само за потвърдени бизнес потребители.)",
|
||||
"meta-llama/llama-3.1-8b-instruct.description": "Най-новата серия Llama 3.1 на Meta, 8B вариант, обучен с инструкции, е особено бърз и ефективен. В индустриални оценки показва силна производителност, надминавайки много водещи затворени модели. (Достъпен само за потвърдени бизнес потребители.)",
|
||||
"meta-llama/llama-3.1-8b-instruct:free.description": "LLaMA 3.1 предлага многоезична поддръжка и е сред водещите генеративни модели.",
|
||||
"meta-llama/llama-3.2-11b-vision-instruct.description": "LLaMA 3.2 е създаден за задачи, съчетаващи визия и текст. Отличава се в описване на изображения и визуални въпроси, свързвайки езиковото генериране с визуалното разсъждение.",
|
||||
"meta-llama/llama-3.2-3b-instruct.description": "meta-llama/llama-3.2-3b-instruct",
|
||||
"meta-llama/llama-3.2-90b-vision-instruct.description": "LLaMA 3.2 е създаден за задачи, съчетаващи визия и текст. Отличава се в описване на изображения и визуални въпроси, свързвайки езиковото генериране с визуалното разсъждение.",
|
||||
"meta-llama/llama-3.3-70b-instruct.description": "Llama 3.3 е най-усъвършенстваният многоезичен отворен модел от серията Llama, предлагащ производителност, близка до 405B, на много ниска цена. Базиран е на Transformer архитектура и подобрен чрез SFT и RLHF за полезност и безопасност. Версията, обучена с инструкции, е оптимизирана за многоезичен чат и превъзхожда много отворени и затворени модели в индустриалните бенчмаркове. Край на знанията: декември 2023.",
|
||||
"meta-llama/llama-3.3-70b-instruct:free.description": "Llama 3.3 е най-усъвършенстваният многоезичен отворен модел от серията Llama, предлагащ производителност, близка до 405B, на много ниска цена. Базиран е на Transformer архитектура и подобрен чрез SFT и RLHF за полезност и безопасност. Версията, обучена с инструкции, е оптимизирана за многоезичен чат и превъзхожда много отворени и затворени модели в индустриалните бенчмаркове. Край на знанията: декември 2023.",
|
||||
"meta.llama3-1-405b-instruct-v1:0.description": "Meta Llama 3.1 405B Instruct е най-големият и най-мощен модел от серията Llama 3.1 Instruct – изключително напреднал модел за диалогово разсъждение и генериране на синтетични данни, отлична основа за дообучение в специфични домейни. Многоезичните LLM модели Llama 3.1 са предварително обучени и настроени с инструкции в размери 8B, 70B и 405B (текстов вход/изход). Моделите, обучени с инструкции, са оптимизирани за многоезичен диалог и превъзхождат много отворени чат модели в индустриалните бенчмаркове. Llama 3.1 е предназначен за търговска и изследователска употреба на различни езици. Моделите, обучени с инструкции, са подходящи за чат в стил асистент, докато предварително обучените модели са подходящи за по-широки задачи по генериране на естествен език. Изходите от Llama 3.1 могат да се използват и за подобряване на други модели, включително чрез генериране и прецизиране на синтетични данни. Llama 3.1 е автогенеративен Transformer модел с оптимизирана архитектура. Настроените версии използват SFT и RLHF за съответствие с човешките предпочитания за полезност и безопасност.",
|
||||
"meta.llama3-1-70b-instruct-v1:0.description": "Обновен Meta Llama 3.1 70B Instruct с разширен контекст до 128K токена, многоезична поддръжка и подобрено разсъждение. Многоезичните LLM модели Llama 3.1 са предварително обучени и настроени с инструкции в размери 8B, 70B и 405B (текстов вход/изход). Моделите, обучени с инструкции, са оптимизирани за многоезичен диалог и превъзхождат много отворени чат модели в индустриалните бенчмаркове. Llama 3.1 е предназначен за търговска и изследователска употреба на различни езици. Моделите, обучени с инструкции, са подходящи за чат в стил асистент, докато предварително обучените модели са подходящи за по-широки задачи по генериране на естествен език. Изходите от Llama 3.1 могат да се използват и за подобряване на други модели, включително чрез генериране и прецизиране на синтетични данни. Llama 3.1 е автогенеративен Transformer модел с оптимизирана архитектура. Настроените версии използват SFT и RLHF за съответствие с човешките предпочитания за полезност и безопасност.",
|
||||
"meta.llama3-1-8b-instruct-v1:0.description": "Обновен Meta Llama 3.1 8B Instruct с контекст до 128K токена, многоезична поддръжка и подобрено разсъждение. Семейството Llama 3.1 включва 8B, 70B и 405B модели, обучени с инструкции, оптимизирани за многоезичен чат и висока производителност в бенчмаркове. Предназначен е за търговска и изследователска употреба на различни езици; моделите, обучени с инструкции, са подходящи за чат в стил асистент, а предварително обучените – за по-широки задачи по генериране. Изходите от Llama 3.1 могат да се използват и за подобряване на други модели (напр. синтетични данни и прецизиране). Това е автогенеративен Transformer модел с SFT и RLHF за съответствие с човешките предпочитания за полезност и безопасност.",
|
||||
"meta.llama3-70b-instruct-v1:0.description": "Meta Llama 3 е отворен LLM за разработчици, изследователи и предприятия, създаден да им помага да изграждат, експериментират и отговорно мащабират идеи в генеративния AI. Като част от основата за глобални иновации, той е подходящ за създаване на съдържание, разговорен AI, езиково разбиране, научноизследователска и развойна дейност и бизнес приложения.",
|
||||
"meta.llama3-8b-instruct-v1:0.description": "Meta Llama 3 е отворен LLM, предназначен за разработчици, изследователи и предприятия, създаден да им помага да изграждат, експериментират и отговорно мащабират идеи за генеративен ИИ. Като част от основата за глобални иновации в общността, той е подходящ за среди с ограничени изчислителни ресурси, крайни устройства и по-бързо обучение.",
|
||||
"meta/Llama-3.2-11B-Vision-Instruct.description": "Силен визуален анализ на изображения с висока резолюция, подходящ за приложения за визуално разбиране.",
|
||||
"meta/Llama-3.2-90B-Vision-Instruct.description": "Разширен визуален анализ за приложения с агенти за визуално разбиране.",
|
||||
@@ -820,6 +886,7 @@
|
||||
"mimo-v2-flash.description": "MiMo-V2-Flash: Ефективен модел за разсъждение, програмиране и основи на агентни системи.",
|
||||
"minicpm-v.description": "MiniCPM-V е следващо поколение мултимодален модел на OpenBMB с отлични OCR и мултимодални възможности за широк спектър от приложения.",
|
||||
"minimax-m2.1.description": "MiniMax-M2.1 е най-новата версия от серията MiniMax, оптимизирана за многоезично програмиране и реални сложни задачи. Като AI-нативен модел, MiniMax-M2.1 постига значителни подобрения в производителността, поддръжката на агентни рамки и адаптацията към различни сценарии, с цел да помогне на предприятия и индивидуални потребители да открият AI-нативен начин на работа и живот по-бързо.",
|
||||
"minimax-m2.5.description": "MiniMax-M2.5 е съвременен голям езиков модел, проектиран за реална продуктивност и задачи за програмиране.",
|
||||
"minimax-m2.description": "MiniMax M2 е ефективен голям езиков модел, създаден специално за програмиране и агентни работни потоци.",
|
||||
"minimax/minimax-m2.1.description": "MiniMax-M2.1 е лек, авангарден голям езиков модел, оптимизиран за програмиране, агентни работни потоци и съвременно разработване на приложения, осигуряващ по-чист, по-кратък изход и по-бърза реакция.",
|
||||
"minimax/minimax-m2.description": "MiniMax-M2 е високостойностен модел, който се отличава в програмиране и агентни задачи в множество инженерни сценарии.",
|
||||
@@ -1046,6 +1113,7 @@
|
||||
"qwen3-14b.description": "Qwen3 14B е среден по размер модел за многоезични въпроси и отговори и генериране на текст.",
|
||||
"qwen3-235b-a22b-instruct-2507.description": "Qwen3 235B A22B Instruct 2507 е водещ модел с инструкции за широк спектър от задачи по генериране и разсъждение.",
|
||||
"qwen3-235b-a22b-thinking-2507.description": "Qwen3 235B A22B Thinking 2507 е ултраголям модел за дълбоко разсъждение.",
|
||||
"qwen3-235b-a22b.description": "Qwen3 е следващо поколение модел Tongyi Qwen с големи подобрения в разсъждението, общите способности, агентските възможности и многоезичната производителност, с поддръжка на превключване между мисловни режими.",
|
||||
"qwen3-30b-a3b-instruct-2507.description": "Qwen3 30B A3B Instruct 2507 е средно-голям модел с инструкции за висококачествено генериране и въпроси и отговори.",
|
||||
"qwen3-30b-a3b-thinking-2507.description": "Qwen3 30B A3B Thinking 2507 е средно-голям модел за разсъждение, балансиращ точност и разходи.",
|
||||
"qwen3-30b-a3b.description": "Qwen3 30B A3B е средно-голям универсален модел, балансиращ между цена и качество.",
|
||||
@@ -1057,6 +1125,7 @@
|
||||
"qwen3-coder-flash.description": "Модел за програмиране Qwen. Най-новата серия Qwen3-Coder е базирана на Qwen3 и предлага силни способности за програмиране чрез агенти, използване на инструменти и взаимодействие със среди за автономно програмиране, с отлично представяне при код и стабилни общи възможности.",
|
||||
"qwen3-coder-plus.description": "Модел за програмиране Qwen. Най-новата серия Qwen3-Coder е базирана на Qwen3 и предлага силни способности за програмиране чрез агенти, използване на инструменти и взаимодействие със среди за автономно програмиране, с отлично представяне при код и стабилни общи възможности.",
|
||||
"qwen3-coder:480b.description": "Високопроизводителен модел на Alibaba с дълъг контекст за задачи с агенти и програмиране.",
|
||||
"qwen3-max-2026-01-23.description": "Моделите Qwen3 Max предлагат значителни подобрения спрямо серията 2.5 в общите способности, разбиране на китайски/английски, следване на сложни инструкции, субективни отворени задачи, многоезичност и използване на инструменти, с по-малко халюцинации. Най-новият qwen3-max подобрява агентското програмиране и използването на инструменти спрямо qwen3-max-preview. Това издание достига върхови резултати в областта и е насочено към по-сложни нужди на агентите.",
|
||||
"qwen3-max-preview.description": "Най-добре представящият се модел Qwen за сложни, многоетапни задачи. Прегледната версия поддържа разсъждение.",
|
||||
"qwen3-max.description": "Моделите Qwen3 Max предлагат значителни подобрения спрямо серията 2.5 в общите способности, разбиране на китайски/английски, следване на сложни инструкции, субективни отворени задачи, многоезичност и използване на инструменти, с по-малко халюцинации. Най-новият qwen3-max подобрява програмирането чрез агенти и използването на инструменти спрямо qwen3-max-preview. Тази версия достига водещи резултати в индустрията и е насочена към по-сложни нужди на агентите.",
|
||||
"qwen3-next-80b-a3b-instruct.description": "Следващо поколение отворен модел Qwen3 без мисловни способности. В сравнение с предишната версия (Qwen3-235B-A22B-Instruct-2507), предлага по-добро разбиране на китайски, по-силна логическа аргументация и подобрено генериране на текст.",
|
||||
@@ -1079,6 +1148,7 @@
|
||||
"qwq.description": "QwQ е модел за аргументация от семейството на Qwen. В сравнение със стандартните модели, обучени с инструкции, предлага мисловни и логически способности, които значително подобряват ефективността при трудни задачи. QwQ-32B е среден по размер модел, който се конкурира с водещи модели като DeepSeek-R1 и o1-mini.",
|
||||
"qwq_32b.description": "Среден по размер модел за аргументация от семейството на Qwen. В сравнение със стандартните модели, обучени с инструкции, мисловните и логическите способности на QwQ значително подобряват ефективността при трудни задачи.",
|
||||
"r1-1776.description": "R1-1776 е дообучен вариант на DeepSeek R1, създаден да предоставя неконфронтирана, обективна и фактическа информация.",
|
||||
"seedance-1-5-pro-251215.description": "Seedance 1.5 Pro от ByteDance поддържа генериране на видео от текст, от изображение към видео (първи кадър, първи+последен кадър) и синхронизирано с визуалното съдържание аудио.",
|
||||
"solar-mini-ja.description": "Solar Mini (Ja) разширява Solar Mini с фокус върху японски език, като запазва ефективността и силната производителност на английски и корейски.",
|
||||
"solar-mini.description": "Solar Mini е компактен LLM, който превъзхожда GPT-3.5, с мощни многоезични възможности, поддържащ английски и корейски, и предлага ефективно решение с малък отпечатък.",
|
||||
"solar-pro.description": "Solar Pro е интелигентен LLM от Upstage, фокусиран върху следване на инструкции на един GPU, с IFEval резултати над 80. Понастоящем поддържа английски; пълното издание е планирано за ноември 2024 с разширена езикова поддръжка и по-дълъг контекст.",
|
||||
@@ -1135,6 +1205,7 @@
|
||||
"us.anthropic.claude-3-5-sonnet-20241022-v2:0.description": "Claude 3.5 Sonnet поставя нов стандарт в индустрията, надминавайки конкурентите и Claude 3 Opus в широки оценки, като запазва средна скорост и цена.",
|
||||
"us.anthropic.claude-3-7-sonnet-20250219-v1:0.description": "Claude 3.7 Sonnet е най-бързият модел от ново поколение на Anthropic. В сравнение с Claude 3 Haiku, подобрява всички умения и надминава предишния флагман Claude 3 Opus в много интелектуални бенчмаркове.",
|
||||
"us.anthropic.claude-haiku-4-5-20251001-v1:0.description": "Claude Haiku 4.5 е най-бързият и интелигентен Haiku модел на Anthropic, с мълниеносна скорост и разширено мислене.",
|
||||
"us.anthropic.claude-opus-4-6-v1.description": "Claude Opus 4.6 е най-интелигентният модел на Anthropic за изграждане на агенти и програмиране.",
|
||||
"us.anthropic.claude-sonnet-4-5-20250929-v1:0.description": "Claude Sonnet 4.5 е най-интелигентният модел на Anthropic до момента.",
|
||||
"v0-1.0-md.description": "v0-1.0-md е наследен модел, достъпен чрез v0 API.",
|
||||
"v0-1.5-lg.description": "v0-1.5-lg е подходящ за напреднали мисловни или логически задачи.",
|
||||
@@ -1180,6 +1251,7 @@
|
||||
"z-ai/glm-4.5.description": "GLM 4.5 е флагманският модел на Z.AI с хибридно разсъждение, оптимизиран за инженерни и задачи с дълъг контекст.",
|
||||
"z-ai/glm-4.6.description": "GLM 4.6 е флагманският модел на Z.AI с разширен контекст и подобрени възможности за програмиране.",
|
||||
"z-ai/glm-4.7.description": "GLM-4.7 е най-новият водещ модел на Zhipu, предлагащ подобрени общи възможности, по-прости и естествени отговори и по-завладяващо писмено изживяване.",
|
||||
"z-ai/glm5.description": "Силен модел за разсъждение и агентски задачи от Z.ai с общо 744B параметри (40B активни), създаден за сложни системни инженерни задачи и дългосрочни задачи.",
|
||||
"zai-org/GLM-4.5-Air.description": "GLM-4.5-Air е базов модел за агентни приложения с архитектура Mixture-of-Experts. Оптимизиран е за използване на инструменти, уеб браузване, софтуерно инженерство и фронтенд програмиране, и се интегрира с кодови агенти като Claude Code и Roo Code. Използва хибридно разсъждение за справяне както със сложни, така и с ежедневни задачи.",
|
||||
"zai-org/GLM-4.5.description": "GLM-4.5 е базов модел, създаден за агентни приложения с архитектура Mixture-of-Experts. Дълбоко оптимизиран за използване на инструменти, уеб браузване, софтуерно инженерство и фронтенд програмиране, и се интегрира с кодови агенти като Claude Code и Roo Code. Използва хибридно разсъждение за справяне както със сложни, така и с ежедневни задачи.",
|
||||
"zai-org/GLM-4.5V.description": "GLM-4.5V е най-новият визуален езиков модел (VLM) на Zhipu AI, изграден върху флагманския текстов модел GLM-4.5-Air (106B общо, 12B активни) с MoE архитектура за висока производителност при по-ниска цена. Следва пътя на GLM-4.1V-Thinking и добавя 3D-RoPE за подобрено пространствено разсъждение в 3D. Оптимизиран чрез предварително обучение, SFT и RL, обработва изображения, видео и дълги документи и е сред водещите отворени модели в 41 публични мултимодални бенчмарка. Режимът Thinking позволява на потребителите да балансират между скорост и дълбочина.",
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
"internlm.description": "Open-source организация, фокусирана върху изследвания и инструменти за големи модели, предоставяща ефективна и лесна за използване платформа за достъп до водещи модели и алгоритми.",
|
||||
"jina.description": "Основана през 2020 г., Jina AI е водеща компания в областта на търсещия AI. Технологичният ѝ стек включва векторни модели, преоценители и малки езикови модели за създаване на надеждни генеративни и мултимодални търсещи приложения.",
|
||||
"lmstudio.description": "LM Studio е десктоп приложение за разработка и експериментиране с LLM на вашия компютър.",
|
||||
"lobehub.description": "LobeHub Cloud използва официални API-та за достъп до AI модели и измерва използването чрез Кредити, свързани с токени на модела.",
|
||||
"minimax.description": "Основана през 2021 г., MiniMax създава универсален AI с мултимодални базови модели, включително текстови модели с трилиони параметри, речеви и визуални модели, както и приложения като Hailuo AI.",
|
||||
"mistral.description": "Mistral предлага усъвършенствани универсални, специализирани и изследователски модели за сложни разсъждения, многоезични задачи и генериране на код, с извикване на функции за персонализирани интеграции.",
|
||||
"modelscope.description": "ModelScope е платформа на Alibaba Cloud за модели като услуга, предлагаща широка гама от AI модели и услуги за инференция.",
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
"table.columns.totalTokens": "Използвани токени",
|
||||
"table.columns.type.enums.chat": "Генериране на текст",
|
||||
"table.columns.type.enums.imageGeneration": "Генериране на изображения",
|
||||
"table.columns.type.enums.videoGeneration": "Генериране на видео",
|
||||
"table.columns.type.title": "Тип",
|
||||
"table.desc": "Подробности за използването на изчислителни кредити за генериране на текст, вграждане, генериране на изображения и др.",
|
||||
"table.more": "Виж подробности",
|
||||
|
||||
@@ -131,6 +131,12 @@
|
||||
"limitation.providers.prompter.subTitle": "Персонализираната API услуга е достъпна само за платени планове. Надстрой сега, за да използваш глобални водещи модели",
|
||||
"limitation.providers.prompter.title": "Абонирай се сега, за да използваш персонализирана API услуга",
|
||||
"limitation.providers.tooltip": "Персонализираната API услуга е достъпна само за платени планове",
|
||||
"limitation.video.success.action": "Продължи с генерирането",
|
||||
"limitation.video.success.desc": "Вашият абонамент {{plan}} беше успешно надграден. Насладете се на AI видео генериране. Текущият ви план включва:",
|
||||
"limitation.video.success.title": "Успешно надграждане",
|
||||
"limitation.video.topupSuccess.action": "Продължи с генерирането",
|
||||
"limitation.video.topupSuccess.desc": "Вашите допълнителни кредити вече са активни. Насладете се на AI видео генериране. Текущият ви план включва:",
|
||||
"limitation.video.topupSuccess.title": "Успешно зареждане",
|
||||
"modelPricing.button": "Виж документацията за ценообразуване",
|
||||
"modelPricing.desc": "{{name}} използва кредити за измерване на използването на AI модел. Таблицата по-долу показва изчислителните кредити на 1M токена.",
|
||||
"modelPricing.title": "Цени на текстови модели",
|
||||
|
||||
@@ -86,6 +86,10 @@
|
||||
"localFiles.editFile.replaceFirst": "Замени само първото срещане",
|
||||
"localFiles.file": "Файл",
|
||||
"localFiles.folder": "Папка",
|
||||
"localFiles.globFiles.pattern": "Шаблон",
|
||||
"localFiles.grepContent.glob": "Филтър за файлове",
|
||||
"localFiles.grepContent.pattern": "Шаблон за търсене",
|
||||
"localFiles.grepContent.type": "Тип файл",
|
||||
"localFiles.moveFiles.itemsMoved": "{{count}} елемент(а) преместени:",
|
||||
"localFiles.moveFiles.itemsMoved_one": "{{count}} елемент преместен:",
|
||||
"localFiles.moveFiles.itemsMoved_other": "{{count}} елемента преместени:",
|
||||
@@ -95,11 +99,17 @@
|
||||
"localFiles.open": "Отвори",
|
||||
"localFiles.openFile": "Отвори файл",
|
||||
"localFiles.openFolder": "Отвори папка",
|
||||
"localFiles.outOfScope.requestedPaths": "Заявени пътища",
|
||||
"localFiles.outOfScope.warning": "Предупреждение: Следните пътища са извън конфигурираната работна директория. Моля, потвърдете, че желаете да разрешите достъп.",
|
||||
"localFiles.outOfScope.workingDirectory": "Работна директория",
|
||||
"localFiles.read.more": "Виж повече",
|
||||
"localFiles.readFile": "Прочети файл",
|
||||
"localFiles.readFile.lineRange": "Редове {{start}} - {{end}}",
|
||||
"localFiles.readFileError": "Неуспешно четене на файл, моля проверете дали пътят е правилен",
|
||||
"localFiles.readFiles": "Прочети файлове",
|
||||
"localFiles.readFilesError": "Неуспешно четене на файлове, моля проверете дали пътят е правилен",
|
||||
"localFiles.searchFiles.keywords": "Ключови думи",
|
||||
"localFiles.securityBlacklist.warning": "Сигнал за сигурност: Тази операция е маркирана от правилата за сигурност и изисква вашето изрично одобрение.",
|
||||
"localFiles.writeFile.characters": "знаци",
|
||||
"localFiles.writeFile.preview": "Преглед на съдържанието",
|
||||
"localFiles.writeFile.truncated": "съкратено",
|
||||
@@ -136,6 +146,31 @@
|
||||
"search.summary": "Обобщение",
|
||||
"search.summaryTooltip": "Обобщи текущото съдържание",
|
||||
"search.viewMoreResults": "Виж още {{results}} резултата",
|
||||
"securityBlacklist.awsCredentials": "Достъпът до AWS идентификационни данни може да изтече ключове за достъп до облака",
|
||||
"securityBlacklist.browserCredentials": "Достъпът до съхранени в браузъра идентификационни данни може да разкрие пароли",
|
||||
"securityBlacklist.chownSystemDirs": "Промяната на собствеността на системни директории е опасна",
|
||||
"securityBlacklist.ddDiskWrite": "Записването на произволни данни върху дискови устройства може да унищожи данни",
|
||||
"securityBlacklist.directMemoryAccess": "Директният достъп до паметта е изключително опасен",
|
||||
"securityBlacklist.disableFirewall": "Изключването на защитната стена излага системата на атаки",
|
||||
"securityBlacklist.dockerConfig": "Четенето на Docker конфигурация може да разкрие идентификационни данни за регистъра",
|
||||
"securityBlacklist.envFiles": "Четенето на .env файлове може да разкрие чувствителни идентификационни данни и API ключове",
|
||||
"securityBlacklist.etcPasswd": "Промяната на /etc/passwd може да ви заключи извън системата",
|
||||
"securityBlacklist.forkBomb": "Fork бомба може да срине системата",
|
||||
"securityBlacklist.formatPartition": "Форматирането на системни дялове ще унищожи данни",
|
||||
"securityBlacklist.gcpCredentials": "Четенето на GCP идентификационни данни може да разкрие ключове за достъп до облачни услуги",
|
||||
"securityBlacklist.gitCredentials": "Четенето на Git файл с идентификационни данни може да разкрие токени за достъп",
|
||||
"securityBlacklist.historyFiles": "Четенето на файлове с история може да разкрие чувствителни команди и идентификационни данни",
|
||||
"securityBlacklist.kernelParams": "Промяната на параметри на ядрото без разбиране може да срине системата",
|
||||
"securityBlacklist.kubeConfig": "Четенето на Kubernetes конфигурация може да разкрие идентификационни данни за клъстера",
|
||||
"securityBlacklist.npmrc": "Четенето на npm токен файл може да разкрие идентификационни данни за регистъра на пакети",
|
||||
"securityBlacklist.removeSystemPackages": "Премахването на основни системни пакети може да повреди системата",
|
||||
"securityBlacklist.rmForceRecursive": "Принудително рекурсивно изтриване без конкретна цел е твърде опасно",
|
||||
"securityBlacklist.rmHomeDir": "Рекурсивното изтриване на домашната директория е изключително опасно",
|
||||
"securityBlacklist.rmRootDir": "Рекурсивното изтриване на root директорията ще унищожи системата",
|
||||
"securityBlacklist.sshConfig": "Промяната на SSH конфигурацията може да ви заключи извън системата",
|
||||
"securityBlacklist.sshPrivateKeys": "Четенето на SSH частни ключове може да компрометира сигурността на системата",
|
||||
"securityBlacklist.sudoers": "Промяната на файла sudoers без подходяща проверка е опасна",
|
||||
"securityBlacklist.suidShells": "Задаването на SUID на shell-ове или интерпретатори е риск за сигурността",
|
||||
"updateArgs.duplicateKeyError": "Ключът на полето трябва да е уникален",
|
||||
"updateArgs.form.add": "Добави елемент",
|
||||
"updateArgs.form.key": "Ключ на полето",
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"config.aspectRatio.label": "Съотношение на страните",
|
||||
"config.cameraFixed.label": "Фиксирана камера",
|
||||
"config.duration.label": "Продължителност",
|
||||
"config.endImageUrl.label": "Крайна рамка",
|
||||
"config.generateAudio.label": "Генерирай аудио",
|
||||
"config.header.title": "Видео",
|
||||
"config.imageUrl.label": "Начална рамка",
|
||||
"config.prompt.placeholder": "Опишете видеото, което искате да генерирате",
|
||||
"config.referenceImage.label": "Референтно изображение",
|
||||
"config.resolution.label": "Резолюция",
|
||||
"config.seed.label": "Сийд",
|
||||
"config.seed.random": "Случаен",
|
||||
"generation.actions.copyError": "Копирай съобщението за грешка",
|
||||
"generation.actions.errorCopied": "Съобщението за грешка е копирано в клипборда",
|
||||
"generation.actions.errorCopyFailed": "Неуспешно копиране на съобщението за грешка",
|
||||
"generation.actions.generate": "Генерирай",
|
||||
"generation.freeQuota.exhausted": "🎁 Използвахте безплатната квота, ще се използват кредити",
|
||||
"generation.freeQuota.remaining": "🎁 {{remaining}} безплатни видеа днес",
|
||||
"generation.status.failed": "Генерирането неуспешно",
|
||||
"generation.status.generating": "Генериране...",
|
||||
"generation.validation.endFrameRequiresStartFrame": "Крайната рамка не може да се използва без начална рамка. Моля, задайте първо начална рамка.",
|
||||
"topic.createNew": "Нова тема",
|
||||
"topic.deleteConfirm": "Изтриване на видео тема",
|
||||
"topic.deleteConfirmDesc": "Ще изтриете тази видео тема. Това действие не може да бъде отменено.",
|
||||
"topic.title": "Видео теми",
|
||||
"topic.untitled": "Тема по подразбиране"
|
||||
}
|
||||
@@ -58,13 +58,13 @@
|
||||
"duplicateTitle": "{{title}} – Kopie",
|
||||
"emptyAgent": "Noch keine Agenten. Beginnen Sie mit Ihrem ersten Agenten – bauen Sie Ihr System nach und nach auf.",
|
||||
"emptyAgentAction": "Agent erstellen",
|
||||
"extendParams.disableContextCaching.desc": "Reduziert die Kosten pro Gespräch um bis zu 90 % und erhöht die Geschwindigkeit um bis zu das 4-Fache. Aktivieren Sie dies, um die Begrenzung der historischen Nachrichten automatisch zu deaktivieren. <1>Mehr erfahren</1>",
|
||||
"extendParams.disableContextCaching.desc": "Reduzieren Sie die Kosten für die Generierung eines einzelnen Gesprächs um bis zu 90 % und erreichen Sie eine bis zu 4-fache Geschwindigkeit. <1>Mehr erfahren</1>",
|
||||
"extendParams.disableContextCaching.title": "Kontext-Caching aktivieren",
|
||||
"extendParams.effort.desc": "Steuern Sie mit dem Parameter 'Aufwand', wie viele Tokens Claude bei der Antwort verwendet.",
|
||||
"extendParams.effort.title": "Aufwand",
|
||||
"extendParams.enableAdaptiveThinking.desc": "Ermöglicht Claude im adaptiven Denkmodus dynamisch zu entscheiden, wann und wie intensiv gedacht wird.",
|
||||
"extendParams.enableAdaptiveThinking.title": "Adaptives Denken aktivieren",
|
||||
"extendParams.enableReasoning.desc": "Basierend auf der Begrenzung des Claude-Denkmechanismus deaktiviert diese Option automatisch die Begrenzung der historischen Nachrichten. <1>Mehr erfahren</1>",
|
||||
"extendParams.enableReasoning.desc": "Basierend auf der Begrenzung des Claude-Denkmechanismus. <1>Mehr erfahren</1>",
|
||||
"extendParams.enableReasoning.title": "Tiefes Denken aktivieren",
|
||||
"extendParams.imageAspectRatio.title": "Bildseitenverhältnis",
|
||||
"extendParams.imageResolution.title": "Bildauflösung",
|
||||
@@ -165,6 +165,7 @@
|
||||
"messageAction.delAndRegenerate": "Löschen und neu generieren",
|
||||
"messageAction.deleteDisabledByThreads": "Diese Nachricht hat ein Unterthema und kann nicht gelöscht werden",
|
||||
"messageAction.expand": "Nachricht ausklappen",
|
||||
"messageAction.reaction": "Reaktion hinzufügen",
|
||||
"messageAction.regenerate": "Neu generieren",
|
||||
"messages.dm.sentTo": "Nur sichtbar für {{name}}",
|
||||
"messages.dm.title": "Direktnachricht",
|
||||
|
||||
@@ -143,6 +143,7 @@
|
||||
"cmdk.keywords.stats": "Statistiken Analyse Auswertung",
|
||||
"cmdk.keywords.submitIssue": "Problem Fehler Feedback Anliegen",
|
||||
"cmdk.keywords.usage": "Nutzung Statistik Verbrauch Kontingent",
|
||||
"cmdk.keywords.video": "video,erstellen,seedance,kling",
|
||||
"cmdk.memory": "Gedächtnis",
|
||||
"cmdk.mentionAgent": "Agent erwähnen",
|
||||
"cmdk.navigate": "Navigieren",
|
||||
@@ -193,6 +194,7 @@
|
||||
"cmdk.themeLight": "Hell",
|
||||
"cmdk.toOpen": "Öffnen",
|
||||
"cmdk.toSelect": "Auswählen",
|
||||
"cmdk.video": "KI-Video",
|
||||
"confirm": "Bestätigen",
|
||||
"contact": "Kontaktieren Sie uns",
|
||||
"copy": "Kopieren",
|
||||
|
||||
@@ -43,6 +43,8 @@
|
||||
"FileManager.emptyStatus.or": "oder",
|
||||
"FileManager.emptyStatus.title": "Dateien oder Ordner hierher ziehen",
|
||||
"FileManager.noFolders": "Keine Ordner verfügbar",
|
||||
"FileManager.search.noResults": "Keine Dateien gefunden",
|
||||
"FileManager.search.placeholder": "Dateien durchsuchen...",
|
||||
"FileManager.sort.dateAdded": "Hinzugefügt am",
|
||||
"FileManager.sort.name": "Name",
|
||||
"FileManager.sort.size": "Größe",
|
||||
@@ -94,6 +96,35 @@
|
||||
"ModelSelect.removed": "Das Modell ist nicht in der Liste. Es wird automatisch entfernt, wenn es abgewählt wird.",
|
||||
"ModelSwitchPanel.byModel": "Nach Modell",
|
||||
"ModelSwitchPanel.byProvider": "Nach Anbieter",
|
||||
"ModelSwitchPanel.detail.abilities": "Fähigkeiten",
|
||||
"ModelSwitchPanel.detail.abilities.files": "Dateien",
|
||||
"ModelSwitchPanel.detail.abilities.functionCall": "Werkzeugaufruf",
|
||||
"ModelSwitchPanel.detail.abilities.imageOutput": "Bildausgabe",
|
||||
"ModelSwitchPanel.detail.abilities.reasoning": "Schlussfolgerung",
|
||||
"ModelSwitchPanel.detail.abilities.search": "Suche",
|
||||
"ModelSwitchPanel.detail.abilities.video": "Video",
|
||||
"ModelSwitchPanel.detail.abilities.vision": "Visuelle Erkennung",
|
||||
"ModelSwitchPanel.detail.config": "Modellkonfiguration",
|
||||
"ModelSwitchPanel.detail.context": "Kontextlänge",
|
||||
"ModelSwitchPanel.detail.pricing": "Preise",
|
||||
"ModelSwitchPanel.detail.pricing.cachedInput": "Gecachter Input ${{amount}}/M",
|
||||
"ModelSwitchPanel.detail.pricing.group.audio": "Audio",
|
||||
"ModelSwitchPanel.detail.pricing.group.image": "Bild",
|
||||
"ModelSwitchPanel.detail.pricing.group.text": "Text",
|
||||
"ModelSwitchPanel.detail.pricing.input": "Input ${{amount}}/M",
|
||||
"ModelSwitchPanel.detail.pricing.output": "Output ${{amount}}/M",
|
||||
"ModelSwitchPanel.detail.pricing.unit.audioInput": "Audioeingabe",
|
||||
"ModelSwitchPanel.detail.pricing.unit.audioInput_cacheRead": "Audioeingabe (Cache)",
|
||||
"ModelSwitchPanel.detail.pricing.unit.audioOutput": "Audioausgabe",
|
||||
"ModelSwitchPanel.detail.pricing.unit.imageGeneration": "Bilderzeugung",
|
||||
"ModelSwitchPanel.detail.pricing.unit.imageInput": "Bildeingabe",
|
||||
"ModelSwitchPanel.detail.pricing.unit.imageInput_cacheRead": "Bildeingabe (Cache)",
|
||||
"ModelSwitchPanel.detail.pricing.unit.imageOutput": "Bildausgabe",
|
||||
"ModelSwitchPanel.detail.pricing.unit.textInput": "Eingabe",
|
||||
"ModelSwitchPanel.detail.pricing.unit.textInput_cacheRead": "Eingabe (Cache)",
|
||||
"ModelSwitchPanel.detail.pricing.unit.textInput_cacheWrite": "Eingabe (Cache-Schreiben)",
|
||||
"ModelSwitchPanel.detail.pricing.unit.textOutput": "Ausgabe",
|
||||
"ModelSwitchPanel.detail.releasedAt": "Veröffentlicht am {{date}}",
|
||||
"ModelSwitchPanel.emptyModel": "Kein Modell aktiviert. Bitte aktivieren Sie eines in den Einstellungen.",
|
||||
"ModelSwitchPanel.emptyProvider": "Keine Anbieter aktiviert. Bitte aktivieren Sie einen in den Einstellungen.",
|
||||
"ModelSwitchPanel.goToSettings": "Zu den Einstellungen",
|
||||
|
||||
@@ -150,6 +150,9 @@
|
||||
"groupAgents.tag": "Gruppe",
|
||||
"groupAgents.underReview": "Wird überprüft",
|
||||
"home.communityAgents": "Community-Agenten",
|
||||
"home.creatorReward.action": "Jetzt bewerben",
|
||||
"home.creatorReward.subtitle": "Das Creator-Belohnungsprogramm 2026 ist offiziell gestartet.",
|
||||
"home.creatorReward.title": "Kreieren. Teilen. Geld verdienen.",
|
||||
"home.featuredAssistants": "Empfohlene Agenten",
|
||||
"home.featuredModels": "Empfohlene Modelle",
|
||||
"home.featuredPlugins": "Empfohlene Fähigkeiten",
|
||||
@@ -194,6 +197,8 @@
|
||||
"mcp.categories.tools.name": "Hilfsprogramme",
|
||||
"mcp.categories.travel-transport.description": "Reiseplanung und Transport",
|
||||
"mcp.categories.travel-transport.name": "Reise & Transport",
|
||||
"mcp.categories.utility.description": "Wettervorhersage und meteorologische Dienste",
|
||||
"mcp.categories.utility.name": "Dienstprogramme",
|
||||
"mcp.categories.weather.description": "Wettervorhersage und meteorologische Dienste",
|
||||
"mcp.categories.weather.name": "Wetter",
|
||||
"mcp.categories.web-search.description": "Websuche und Informationsabruf",
|
||||
@@ -478,6 +483,10 @@
|
||||
"tab.plugin": "Fähigkeit",
|
||||
"tab.provider": "Anbieter",
|
||||
"tab.user": "Benutzer",
|
||||
"time.formatOtherYear": "D. MMM YYYY",
|
||||
"time.formatThisYear": "D. MMM",
|
||||
"time.today": "Heute",
|
||||
"time.yesterday": "Gestern",
|
||||
"user.agents": "Agenten",
|
||||
"user.downloads": "Downloads",
|
||||
"user.editProfile": "Profil bearbeiten",
|
||||
|
||||
@@ -10,5 +10,6 @@
|
||||
"starter.deepResearch": "Tiefgehende Recherche",
|
||||
"starter.developing": "Demnächst verfügbar",
|
||||
"starter.image": "Bild",
|
||||
"starter.seedance": "Seedance 2.0",
|
||||
"starter.write": "Schreiben"
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user