@lobehub/lobehub 2.0.0-next.352 → 2.0.0-next.354
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/skills/add-provider-doc/SKILL.md +90 -0
- package/.agents/skills/add-setting-env/SKILL.md +106 -0
- package/.agents/skills/debug/SKILL.md +66 -0
- package/.agents/skills/desktop/SKILL.md +78 -0
- package/.agents/skills/desktop/references/feature-implementation.md +99 -0
- package/.agents/skills/desktop/references/local-tools.md +133 -0
- package/.agents/skills/desktop/references/menu-config.md +103 -0
- package/.agents/skills/desktop/references/window-management.md +143 -0
- package/.agents/skills/drizzle/SKILL.md +129 -0
- package/.agents/skills/drizzle/references/db-migrations.md +50 -0
- package/.agents/skills/hotkey/SKILL.md +90 -0
- package/{.cursor/rules/i18n.mdc → .agents/skills/i18n/SKILL.md} +14 -23
- package/.agents/skills/linear/SKILL.md +51 -0
- package/.agents/skills/microcopy/SKILL.md +83 -0
- package/.agents/skills/modal/SKILL.md +102 -0
- package/{.cursor/rules/project-structure.mdc → .agents/skills/project-overview/SKILL.md} +65 -37
- package/.agents/skills/react/SKILL.md +73 -0
- package/.agents/skills/react/references/layout-kit.md +100 -0
- package/.agents/skills/recent-data/SKILL.md +108 -0
- package/.agents/skills/testing/SKILL.md +89 -0
- package/.agents/skills/testing/references/agent-runtime-e2e.md +126 -0
- package/.agents/skills/testing/references/db-model-test.md +124 -0
- package/.agents/skills/testing/references/desktop-controller-test.md +124 -0
- package/.agents/skills/testing/references/electron-ipc-test.md +63 -0
- package/.agents/skills/testing/references/zustand-store-action-test.md +150 -0
- package/.agents/skills/typescript/SKILL.md +52 -0
- package/.agents/skills/zustand/SKILL.md +78 -0
- package/.agents/skills/zustand/references/action-patterns.md +125 -0
- package/.agents/skills/zustand/references/slice-organization.md +125 -0
- package/AGENTS.md +42 -55
- package/CHANGELOG.md +58 -0
- package/CLAUDE.md +57 -46
- package/GEMINI.md +47 -39
- package/changelog/v1.json +14 -0
- package/docs/development/database-schema.dbml +5 -0
- package/package.json +1 -1
- package/packages/database/migrations/0071_add_async_task_extend.sql +5 -0
- package/packages/database/migrations/meta/0071_snapshot.json +10720 -0
- package/packages/database/migrations/meta/_journal.json +7 -0
- package/packages/database/src/schemas/asyncTask.ts +12 -2
- package/src/features/FileViewer/Renderer/PDF/index.tsx +2 -3
- package/src/features/ShareModal/SharePdf/PdfPreview.tsx +1 -2
- package/src/libs/pdfjs/index.tsx +25 -0
- package/src/store/test-coverage.md +5 -5
- package/.cursor/rules/add-provider-doc.mdc +0 -183
- package/.cursor/rules/add-setting-env.mdc +0 -175
- package/.cursor/rules/cursor-rules.mdc +0 -28
- package/.cursor/rules/db-migrations.mdc +0 -46
- package/.cursor/rules/debug-usage.mdc +0 -86
- package/.cursor/rules/desktop-controller-tests.mdc +0 -189
- package/.cursor/rules/desktop-feature-implementation.mdc +0 -155
- package/.cursor/rules/desktop-local-tools-implement.mdc +0 -81
- package/.cursor/rules/desktop-menu-configuration.mdc +0 -209
- package/.cursor/rules/desktop-window-management.mdc +0 -301
- package/.cursor/rules/drizzle-schema-style-guide.mdc +0 -218
- package/.cursor/rules/hotkey.mdc +0 -162
- package/.cursor/rules/linear.mdc +0 -53
- package/.cursor/rules/microcopy-cn.mdc +0 -158
- package/.cursor/rules/microcopy-en.mdc +0 -148
- package/.cursor/rules/modal-imperative.mdc +0 -162
- package/.cursor/rules/packages/react-layout-kit.mdc +0 -122
- package/.cursor/rules/project-introduce.mdc +0 -36
- package/.cursor/rules/react.mdc +0 -169
- package/.cursor/rules/recent-data-usage.mdc +0 -139
- package/.cursor/rules/rules-index.mdc +0 -44
- package/.cursor/rules/testing-guide/agent-runtime-e2e.mdc +0 -285
- package/.cursor/rules/testing-guide/db-model-test.mdc +0 -455
- package/.cursor/rules/testing-guide/electron-ipc-test.mdc +0 -80
- package/.cursor/rules/testing-guide/testing-guide.mdc +0 -534
- package/.cursor/rules/testing-guide/zustand-store-action-test.mdc +0 -574
- package/.cursor/rules/typescript.mdc +0 -55
- package/.cursor/rules/zustand-action-patterns.mdc +0 -328
- package/.cursor/rules/zustand-slice-organization.mdc +0 -308
- package/src/libs/pdfjs/pdf.worker.ts +0 -1
- package/src/libs/pdfjs/worker.ts +0 -12
- /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/AGENTS.md +0 -0
- /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/SKILL.md +0 -0
- /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/advanced-event-handler-refs.md +0 -0
- /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/advanced-use-latest.md +0 -0
- /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/async-api-routes.md +0 -0
- /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/async-defer-await.md +0 -0
- /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/async-dependencies.md +0 -0
- /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/async-parallel.md +0 -0
- /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/async-suspense-boundaries.md +0 -0
- /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/bundle-barrel-imports.md +0 -0
- /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/bundle-conditional.md +0 -0
- /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/bundle-defer-third-party.md +0 -0
- /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/bundle-dynamic-imports.md +0 -0
- /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/bundle-preload.md +0 -0
- /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/client-event-listeners.md +0 -0
- /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/client-localstorage-schema.md +0 -0
- /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/client-passive-event-listeners.md +0 -0
- /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/client-swr-dedup.md +0 -0
- /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/js-batch-dom-css.md +0 -0
- /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/js-cache-function-results.md +0 -0
- /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/js-cache-property-access.md +0 -0
- /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/js-cache-storage.md +0 -0
- /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/js-combine-iterations.md +0 -0
- /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/js-early-exit.md +0 -0
- /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/js-hoist-regexp.md +0 -0
- /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/js-index-maps.md +0 -0
- /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/js-length-check-first.md +0 -0
- /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/js-min-max-loop.md +0 -0
- /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/js-set-map-lookups.md +0 -0
- /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/js-tosorted-immutable.md +0 -0
- /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/rendering-activity.md +0 -0
- /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/rendering-animate-svg-wrapper.md +0 -0
- /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/rendering-conditional-render.md +0 -0
- /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/rendering-content-visibility.md +0 -0
- /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/rendering-hoist-jsx.md +0 -0
- /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/rendering-hydration-no-flicker.md +0 -0
- /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/rendering-svg-precision.md +0 -0
- /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/rerender-defer-reads.md +0 -0
- /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/rerender-dependencies.md +0 -0
- /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/rerender-derived-state.md +0 -0
- /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/rerender-functional-setstate.md +0 -0
- /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/rerender-lazy-state-init.md +0 -0
- /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/rerender-memo.md +0 -0
- /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/rerender-transitions.md +0 -0
- /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/server-after-nonblocking.md +0 -0
- /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/server-cache-lru.md +0 -0
- /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/server-cache-react.md +0 -0
- /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/server-parallel-fetching.md +0 -0
- /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/server-serialization.md +0 -0
|
@@ -497,6 +497,13 @@
|
|
|
497
497
|
"when": 1768999498635,
|
|
498
498
|
"tag": "0070_add_user_memory_activities",
|
|
499
499
|
"breakpoints": true
|
|
500
|
+
},
|
|
501
|
+
{
|
|
502
|
+
"idx": 71,
|
|
503
|
+
"version": "7",
|
|
504
|
+
"when": 1769093425330,
|
|
505
|
+
"tag": "0071_add_async_task_extend",
|
|
506
|
+
"breakpoints": true
|
|
500
507
|
}
|
|
501
508
|
],
|
|
502
509
|
"version": "6"
|
|
@@ -17,11 +17,21 @@ export const asyncTasks = pgTable(
|
|
|
17
17
|
.references(() => users.id, { onDelete: 'cascade' })
|
|
18
18
|
.notNull(),
|
|
19
19
|
duration: integer('duration'),
|
|
20
|
+
parentId: uuid('parent_id'),
|
|
21
|
+
metadata: jsonb('metadata').notNull().default('{}'),
|
|
20
22
|
|
|
21
23
|
...timestamps,
|
|
22
24
|
},
|
|
23
|
-
(t) => [
|
|
25
|
+
(t) => [
|
|
26
|
+
index('async_tasks_user_id_idx').on(t.userId),
|
|
27
|
+
index('async_tasks_parent_id_idx').on(t.parentId),
|
|
28
|
+
index('async_tasks_type_status_idx').on(t.type, t.status),
|
|
29
|
+
index('async_tasks_metadata_idx').using(
|
|
30
|
+
'gin',
|
|
31
|
+
t.metadata,
|
|
32
|
+
)
|
|
33
|
+
],
|
|
24
34
|
);
|
|
25
35
|
|
|
26
36
|
export type NewAsyncTaskItem = typeof asyncTasks.$inferInsert;
|
|
27
|
-
export type AsyncTaskSelectItem = typeof asyncTasks.$inferSelect
|
|
37
|
+
export type AsyncTaskSelectItem = Omit<typeof asyncTasks.$inferSelect, 'metadata' | 'parentId'> & Partial<Pick<typeof asyncTasks.$inferSelect, 'metadata' | 'parentId'>>;
|
|
@@ -2,12 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
import { Flexbox } from '@lobehub/ui';
|
|
4
4
|
import { Fragment, memo, useCallback, useState } from 'react';
|
|
5
|
-
import { Document, Page, pdfjs } from 'react-pdf';
|
|
6
5
|
import 'react-pdf/dist/Page/AnnotationLayer.css';
|
|
7
6
|
import 'react-pdf/dist/Page/TextLayer.css';
|
|
8
7
|
|
|
9
8
|
import NeuralNetworkLoading from '@/components/NeuralNetworkLoading';
|
|
10
|
-
import '@/libs/pdfjs
|
|
9
|
+
import { Document, Page, pdfjs } from '@/libs/pdfjs';
|
|
11
10
|
import { lambdaQuery } from '@/libs/trpc/client';
|
|
12
11
|
|
|
13
12
|
import HighlightLayer from './HighlightLayer';
|
|
@@ -71,7 +70,7 @@ const PDFViewer = memo<PDFViewerProps>(({ url, fileId }) => {
|
|
|
71
70
|
onLoadSuccess={onDocumentLoadSuccess}
|
|
72
71
|
options={options}
|
|
73
72
|
>
|
|
74
|
-
{Array.from({ length: numPages }, (
|
|
73
|
+
{Array.from({ length: numPages }, (_, index) => {
|
|
75
74
|
const width = containerWidth ? Math.min(containerWidth, maxWidth) : maxWidth;
|
|
76
75
|
|
|
77
76
|
return (
|
|
@@ -7,10 +7,9 @@ import { createStaticStyles, cx } from 'antd-style';
|
|
|
7
7
|
import { ChevronLeft, ChevronRight, Expand, FileText } from 'lucide-react';
|
|
8
8
|
import { memo, useState } from 'react';
|
|
9
9
|
import { useTranslation } from 'react-i18next';
|
|
10
|
-
import { Document, Page } from 'react-pdf';
|
|
11
10
|
|
|
12
11
|
import { useIsMobile } from '@/hooks/useIsMobile';
|
|
13
|
-
import '@/libs/pdfjs
|
|
12
|
+
import { Document, Page } from '@/libs/pdfjs';
|
|
14
13
|
|
|
15
14
|
import { containerStyles } from '../style';
|
|
16
15
|
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import type { ComponentProps } from 'react';
|
|
4
|
+
import { Document as PdfDocument, Page as PdfPage, pdfjs } from 'react-pdf';
|
|
5
|
+
|
|
6
|
+
const workerSrc = `https://registry.npmmirror.com/pdfjs-dist/${pdfjs.version}/files/build/pdf.worker.min.mjs`;
|
|
7
|
+
|
|
8
|
+
function ensureWorker() {
|
|
9
|
+
if (!pdfjs.GlobalWorkerOptions.workerSrc) {
|
|
10
|
+
pdfjs.GlobalWorkerOptions.workerSrc = workerSrc;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export type DocumentProps = ComponentProps<typeof PdfDocument>;
|
|
15
|
+
export type PageProps = ComponentProps<typeof PdfPage>;
|
|
16
|
+
|
|
17
|
+
export const Document = (props: DocumentProps) => {
|
|
18
|
+
ensureWorker();
|
|
19
|
+
return <PdfDocument {...props} />;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
export {Page, pdfjs} from 'react-pdf';
|
|
@@ -35,7 +35,7 @@ All 40 action files in the store now have comprehensive test coverage!
|
|
|
35
35
|
|
|
36
36
|
All store action tests should follow the patterns documented in:
|
|
37
37
|
|
|
38
|
-
- **Main Guide**:
|
|
38
|
+
- **Main Guide**: `.agents/skills/testing/references/zustand-store-action-test.md`
|
|
39
39
|
|
|
40
40
|
Key principles:
|
|
41
41
|
|
|
@@ -141,7 +141,7 @@ For files with multiple action files to test, use the Task tool to create subage
|
|
|
141
141
|
**Example subagent prompt**:
|
|
142
142
|
|
|
143
143
|
```
|
|
144
|
-
Write comprehensive tests for src/store/discover/slices/plugin/action.ts following
|
|
144
|
+
Write comprehensive tests for src/store/discover/slices/plugin/action.ts following .agents/skills/testing/references/zustand-store-action-test.md.
|
|
145
145
|
|
|
146
146
|
Requirements:
|
|
147
147
|
1. Write tests covering all actions in the file
|
|
@@ -315,7 +315,7 @@ Create 5 subagents, one for each action file:
|
|
|
315
315
|
Task({
|
|
316
316
|
subagent_type: 'general-purpose',
|
|
317
317
|
description: 'Test plugin action',
|
|
318
|
-
prompt: `Write comprehensive tests for src/store/discover/slices/plugin/action.ts following
|
|
318
|
+
prompt: `Write comprehensive tests for src/store/discover/slices/plugin/action.ts following .agents/skills/testing/references/zustand-store-action-test.md.
|
|
319
319
|
|
|
320
320
|
Requirements:
|
|
321
321
|
1. Write tests covering all actions (usePluginCategories, usePluginDetail, usePluginList, usePluginIdentifiers)
|
|
@@ -330,7 +330,7 @@ DO NOT commit changes or update test-coverage.md.`,
|
|
|
330
330
|
Task({
|
|
331
331
|
subagent_type: 'general-purpose',
|
|
332
332
|
description: 'Test mcp action',
|
|
333
|
-
prompt: `Write comprehensive tests for src/store/discover/slices/mcp/action.ts following
|
|
333
|
+
prompt: `Write comprehensive tests for src/store/discover/slices/mcp/action.ts following .agents/skills/testing/references/zustand-store-action-test.md.
|
|
334
334
|
|
|
335
335
|
Requirements:
|
|
336
336
|
1. Write tests covering all actions (useFetchMcpDetail, useFetchMcpList, useMcpCategories)
|
|
@@ -561,7 +561,7 @@ bunx eslint src/store/[domain]/
|
|
|
561
561
|
- 25 action files already have comprehensive tests (62.5% coverage)
|
|
562
562
|
- 742 tests written across 80 test files
|
|
563
563
|
- Well-tested stores: agent, chat (partial), file (partial), image, session, tool, user, global, aiInfra (partial)
|
|
564
|
-
- Following zustand testing best practices from
|
|
564
|
+
- Following zustand testing best practices from `.agents/skills/testing/references/zustand-store-action-test.md`
|
|
565
565
|
|
|
566
566
|
## Notes
|
|
567
567
|
|
|
@@ -1,183 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Complete guide for adding a new AI provider documentation to LobeChat
|
|
3
|
-
alwaysApply: false
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Adding New AI Provider Documentation
|
|
7
|
-
|
|
8
|
-
This document provides a step-by-step guide for adding documentation for a new AI provider to LobeChat, based on the complete workflow used for adding providers like BFL (Black Forest Labs) and FAL.
|
|
9
|
-
|
|
10
|
-
## Overview
|
|
11
|
-
|
|
12
|
-
Adding a new provider requires creating both user-facing documentation and technical configuration files. The process involves:
|
|
13
|
-
|
|
14
|
-
1. Creating usage documentation (EN + CN)
|
|
15
|
-
2. Adding environment variable documentation (EN + CN)
|
|
16
|
-
3. Updating Docker configuration files
|
|
17
|
-
4. Updating .env.example file
|
|
18
|
-
5. Preparing image resources
|
|
19
|
-
|
|
20
|
-
## Step 1: Create Provider Usage Documentation
|
|
21
|
-
|
|
22
|
-
Create user-facing documentation that explains how to use the new provider.
|
|
23
|
-
|
|
24
|
-
### Required Files
|
|
25
|
-
|
|
26
|
-
Create both English and Chinese versions:
|
|
27
|
-
- `docs/usage/providers/{provider-name}.mdx` (English)
|
|
28
|
-
- `docs/usage/providers/{provider-name}.zh-CN.mdx` (Chinese)
|
|
29
|
-
|
|
30
|
-
### Documentation Structure
|
|
31
|
-
|
|
32
|
-
Follow the structure and format used in existing provider documentation. For reference, see:
|
|
33
|
-
- `docs/usage/providers/fal.mdx` (English template)
|
|
34
|
-
- `docs/usage/providers/fal.zh-CN.mdx` (Chinese template)
|
|
35
|
-
|
|
36
|
-
### Key Requirements
|
|
37
|
-
|
|
38
|
-
- **Images**: Prepare 5-6 screenshots showing the process
|
|
39
|
-
- **Cover Image**: Create or obtain a cover image for the provider
|
|
40
|
-
- **Accurate URLs**: Use real registration and dashboard URLs
|
|
41
|
-
- **Service Type**: Specify whether it's for image generation, text generation, etc.
|
|
42
|
-
- **Pricing Warning**: Include pricing information callout
|
|
43
|
-
|
|
44
|
-
### Important Notes
|
|
45
|
-
|
|
46
|
-
- **🔒 API Key Security**: Never include real API keys in documentation. Always use placeholder format (e.g., `bfl-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx`)
|
|
47
|
-
- **🖼️ Image Hosting**: Use LobeHub's CDN for all images: `hub-apac-1.lobeobjects.space`
|
|
48
|
-
|
|
49
|
-
## Step 2: Update Environment Variables Documentation
|
|
50
|
-
|
|
51
|
-
Add the new provider's environment variables to the self-hosting documentation.
|
|
52
|
-
|
|
53
|
-
### Files to Update
|
|
54
|
-
|
|
55
|
-
- `docs/self-hosting/environment-variables/model-provider.mdx` (English)
|
|
56
|
-
- `docs/self-hosting/environment-variables/model-provider.zh-CN.mdx` (Chinese)
|
|
57
|
-
|
|
58
|
-
### Content to Add
|
|
59
|
-
|
|
60
|
-
Add two sections for each provider:
|
|
61
|
-
|
|
62
|
-
```markdown
|
|
63
|
-
### `{PROVIDER}_API_KEY`
|
|
64
|
-
|
|
65
|
-
- Type: Required
|
|
66
|
-
- Description: This is the API key you applied for in the {Provider Name} service.
|
|
67
|
-
- Default: -
|
|
68
|
-
- Example: `{api-key-format-example}`
|
|
69
|
-
|
|
70
|
-
### `{PROVIDER}_MODEL_LIST`
|
|
71
|
-
|
|
72
|
-
- Type: Optional
|
|
73
|
-
- Description: Used to control the {Provider Name} model list. Use `+` to add a model, `-` to hide a model, and `model_name=display_name` to customize the display name of a model. Separate multiple entries with commas. The definition syntax follows the same rules as other providers' model lists.
|
|
74
|
-
- Default: `-`
|
|
75
|
-
- Example: `-all,+{model-id-1},+{model-id-2}={display-name}`
|
|
76
|
-
|
|
77
|
-
The above example disables all models first, then enables `{model-id-1}` and `{model-id-2}` (displayed as `{display-name}`).
|
|
78
|
-
|
|
79
|
-
[model-list]: /docs/self-hosting/advanced/model-list
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
### Important Notes
|
|
83
|
-
|
|
84
|
-
- **API Key Format**: Use proper UUID format for examples (e.g., `12345678-1234-1234-1234-123456789abc`)
|
|
85
|
-
- **Real Model IDs**: Use actual model IDs from the codebase, not placeholders
|
|
86
|
-
- **Consistent Naming**: Follow the pattern `{PROVIDER}_API_KEY` and `{PROVIDER}_MODEL_LIST`
|
|
87
|
-
|
|
88
|
-
## Step 3: Update Docker Configuration Files
|
|
89
|
-
|
|
90
|
-
Add environment variables to all Docker configuration files to ensure the provider works in containerized deployments.
|
|
91
|
-
|
|
92
|
-
### Files to Update
|
|
93
|
-
|
|
94
|
-
All Dockerfile variants must be updated:
|
|
95
|
-
- `Dockerfile`
|
|
96
|
-
- `Dockerfile.database`
|
|
97
|
-
- `Dockerfile.pglite`
|
|
98
|
-
|
|
99
|
-
### Changes Required
|
|
100
|
-
|
|
101
|
-
Add the new provider's environment variables at the **end** of the ENV section, just before the final line:
|
|
102
|
-
|
|
103
|
-
```dockerfile
|
|
104
|
-
# Previous providers...
|
|
105
|
-
# 302.AI
|
|
106
|
-
AI302_API_KEY="" AI302_MODEL_LIST="" \
|
|
107
|
-
# {New Provider 1}
|
|
108
|
-
{PROVIDER1}_API_KEY="" {PROVIDER1}_MODEL_LIST="" \
|
|
109
|
-
# {New Provider 2}
|
|
110
|
-
{PROVIDER2}_API_KEY="" {PROVIDER2}_MODEL_LIST=""
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
### Important Rules
|
|
114
|
-
|
|
115
|
-
- **Position**: Add new providers at the **end** of the list
|
|
116
|
-
- **Ordering**: When adding multiple providers, use alphabetical order (e.g., FAL before BFL)
|
|
117
|
-
- **Consistency**: Maintain identical ordering across all Dockerfile variants
|
|
118
|
-
- **Format**: Follow the pattern `{PROVIDER}_API_KEY="" {PROVIDER}_MODEL_LIST="" \`
|
|
119
|
-
|
|
120
|
-
## Step 4: Update .env.example File
|
|
121
|
-
|
|
122
|
-
Add example configuration entries to help users understand how to configure the provider locally.
|
|
123
|
-
|
|
124
|
-
### File to Update
|
|
125
|
-
|
|
126
|
-
- `.env.example`
|
|
127
|
-
|
|
128
|
-
### Content to Add
|
|
129
|
-
|
|
130
|
-
Add new sections before the "Market Service" section:
|
|
131
|
-
|
|
132
|
-
```bash
|
|
133
|
-
### {Provider Name} ###
|
|
134
|
-
|
|
135
|
-
# {PROVIDER}_API_KEY={provider-prefix}-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
### Format Guidelines
|
|
139
|
-
|
|
140
|
-
- **Section Header**: Use `### {Provider Name} ###` format
|
|
141
|
-
- **Commented Example**: Use `#` to comment out the example
|
|
142
|
-
- **Key Format**: Use appropriate prefix for the provider (e.g., `bfl-`, `fal-`, `sk-`)
|
|
143
|
-
- **Position**: Add before the Market Service section
|
|
144
|
-
- **Spacing**: Maintain consistent spacing with existing entries
|
|
145
|
-
|
|
146
|
-
## Step 5: Image Resources
|
|
147
|
-
|
|
148
|
-
Prepare all necessary image resources for the documentation.
|
|
149
|
-
|
|
150
|
-
### Required Images
|
|
151
|
-
|
|
152
|
-
1. **Cover Image**: Provider logo or branded image
|
|
153
|
-
2. **API Dashboard Screenshots**: 3-4 screenshots showing API key creation process
|
|
154
|
-
3. **LobeChat Configuration Screenshots**: 2-3 screenshots showing provider setup in LobeChat
|
|
155
|
-
|
|
156
|
-
### Image Guidelines
|
|
157
|
-
|
|
158
|
-
- **Quality**: Use high-resolution screenshots
|
|
159
|
-
- **Consistency**: Maintain consistent styling across all screenshots
|
|
160
|
-
- **Privacy**: Remove or blur any sensitive information
|
|
161
|
-
- **Format**: Use PNG format for screenshots
|
|
162
|
-
- **Hosting**: Use LobeHub's CDN (`hub-apac-1.lobeobjects.space`) for all images
|
|
163
|
-
|
|
164
|
-
## Checklist
|
|
165
|
-
|
|
166
|
-
Before submitting your provider documentation:
|
|
167
|
-
|
|
168
|
-
- [ ] Created both English and Chinese usage documentation
|
|
169
|
-
- [ ] Added environment variable documentation (EN + CN)
|
|
170
|
-
- [ ] Updated all 3 Dockerfile variants with consistent ordering
|
|
171
|
-
- [ ] Updated .env.example with proper key format
|
|
172
|
-
- [ ] Prepared all required screenshots and images
|
|
173
|
-
- [ ] Used actual model IDs from the codebase
|
|
174
|
-
- [ ] Verified no real API keys are included in documentation
|
|
175
|
-
- [ ] Used LobeHub CDN for all image hosting
|
|
176
|
-
- [ ] Tested the documentation for clarity and accuracy
|
|
177
|
-
|
|
178
|
-
## Reference
|
|
179
|
-
|
|
180
|
-
This guide was created based on the implementation of BFL (Black Forest Labs) provider documentation. For a complete example, refer to:
|
|
181
|
-
- Commits: `d2da03e1a` (documentation) and `6a2e95868` (environment variables)
|
|
182
|
-
- Files: `docs/usage/providers/bfl.mdx`, `docs/usage/providers/bfl.zh-CN.mdx`
|
|
183
|
-
- PR: Current branch `tj/feat/bfl-docs`
|
|
@@ -1,175 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Guide for adding environment variables to configure user settings
|
|
3
|
-
alwaysApply: false
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Adding Environment Variable for User Settings
|
|
7
|
-
|
|
8
|
-
Add server-side environment variables to configure default values for user settings.
|
|
9
|
-
|
|
10
|
-
**Priority**: User Custom > Server Env Var > Hardcoded Default
|
|
11
|
-
|
|
12
|
-
## Steps
|
|
13
|
-
|
|
14
|
-
### 1. Define Environment Variable
|
|
15
|
-
|
|
16
|
-
Create `src/envs/<domain>.ts`:
|
|
17
|
-
|
|
18
|
-
```typescript
|
|
19
|
-
import { createEnv } from '@t3-oss/env-nextjs';
|
|
20
|
-
import { z } from 'zod';
|
|
21
|
-
|
|
22
|
-
export const get<Domain>Config = () => {
|
|
23
|
-
return createEnv({
|
|
24
|
-
server: {
|
|
25
|
-
YOUR_ENV_VAR: z.coerce.number().min(MIN).max(MAX).optional(),
|
|
26
|
-
},
|
|
27
|
-
runtimeEnv: {
|
|
28
|
-
YOUR_ENV_VAR: process.env.YOUR_ENV_VAR,
|
|
29
|
-
},
|
|
30
|
-
});
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
export const <domain>Env = get<Domain>Config();
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
### 2. Update Type (Optional)
|
|
37
|
-
|
|
38
|
-
**Skip this step if the domain field already exists in `GlobalServerConfig`.**
|
|
39
|
-
|
|
40
|
-
Add to `packages/types/src/serverConfig.ts`:
|
|
41
|
-
|
|
42
|
-
```typescript
|
|
43
|
-
export interface GlobalServerConfig {
|
|
44
|
-
<domain>?: {
|
|
45
|
-
<settingName>?: <type>;
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
**Prefer reusing existing types** from `packages/types/src/user/settings` with `PartialDeep`:
|
|
51
|
-
|
|
52
|
-
```typescript
|
|
53
|
-
import { User<Domain>Config } from './user/settings';
|
|
54
|
-
|
|
55
|
-
export interface GlobalServerConfig {
|
|
56
|
-
<domain>?: PartialDeep<User<Domain>Config>;
|
|
57
|
-
}
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
### 3. Assemble Server Config (Optional)
|
|
61
|
-
|
|
62
|
-
**Skip this step if the domain field already exists in server config.**
|
|
63
|
-
|
|
64
|
-
In `src/server/globalConfig/index.ts`:
|
|
65
|
-
|
|
66
|
-
```typescript
|
|
67
|
-
import { <domain>Env } from '@/envs/<domain>';
|
|
68
|
-
import { cleanObject } from '@/utils/object';
|
|
69
|
-
|
|
70
|
-
export const getServerGlobalConfig = async () => {
|
|
71
|
-
const config: GlobalServerConfig = {
|
|
72
|
-
// ...
|
|
73
|
-
<domain>: cleanObject({
|
|
74
|
-
<settingName>: <domain>Env.YOUR_ENV_VAR,
|
|
75
|
-
}),
|
|
76
|
-
};
|
|
77
|
-
return config;
|
|
78
|
-
};
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
If the domain already exists, just add the new field to the existing `cleanObject()`:
|
|
82
|
-
|
|
83
|
-
```typescript
|
|
84
|
-
<domain>: cleanObject({
|
|
85
|
-
existingField: <domain>Env.EXISTING_VAR,
|
|
86
|
-
<settingName>: <domain>Env.YOUR_ENV_VAR, // Add this line
|
|
87
|
-
}),
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
### 4. Merge to User Store (Optional)
|
|
91
|
-
|
|
92
|
-
**Skip this step if the domain field already exists in `serverSettings`.**
|
|
93
|
-
|
|
94
|
-
In `src/store/user/slices/common/action.ts`, add to `serverSettings`:
|
|
95
|
-
|
|
96
|
-
```typescript
|
|
97
|
-
const serverSettings: PartialDeep<UserSettings> = {
|
|
98
|
-
defaultAgent: serverConfig.defaultAgent,
|
|
99
|
-
<domain>: serverConfig.<domain>, // Add this line
|
|
100
|
-
// ...
|
|
101
|
-
};
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
### 5. Update .env.example
|
|
105
|
-
|
|
106
|
-
```bash
|
|
107
|
-
# <Description> (range/options, default: X)
|
|
108
|
-
# YOUR_ENV_VAR=<example>
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
### 6. Update Documentation
|
|
112
|
-
|
|
113
|
-
Update both English and Chinese documentation:
|
|
114
|
-
- `docs/self-hosting/environment-variables/basic.mdx`
|
|
115
|
-
- `docs/self-hosting/environment-variables/basic.zh-CN.mdx`
|
|
116
|
-
|
|
117
|
-
Add new section or subsection with environment variable details (type, description, default, example, range/constraints).
|
|
118
|
-
|
|
119
|
-
## Type Reuse
|
|
120
|
-
|
|
121
|
-
**Prefer reusing existing types** from `packages/types/src/user/settings` instead of defining inline types in `serverConfig.ts`.
|
|
122
|
-
|
|
123
|
-
```typescript
|
|
124
|
-
// ✅ Good - reuse existing type
|
|
125
|
-
import { UserImageConfig } from './user/settings';
|
|
126
|
-
|
|
127
|
-
export interface GlobalServerConfig {
|
|
128
|
-
image?: PartialDeep<UserImageConfig>;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// ❌ Bad - inline type definition
|
|
132
|
-
export interface GlobalServerConfig {
|
|
133
|
-
image?: {
|
|
134
|
-
defaultImageNum?: number;
|
|
135
|
-
};
|
|
136
|
-
}
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
## Example: AI_IMAGE_DEFAULT_IMAGE_NUM
|
|
140
|
-
|
|
141
|
-
```typescript
|
|
142
|
-
// src/envs/image.ts
|
|
143
|
-
export const getImageConfig = () => {
|
|
144
|
-
return createEnv({
|
|
145
|
-
server: {
|
|
146
|
-
AI_IMAGE_DEFAULT_IMAGE_NUM: z.coerce.number().min(1).max(20).optional(),
|
|
147
|
-
},
|
|
148
|
-
runtimeEnv: {
|
|
149
|
-
AI_IMAGE_DEFAULT_IMAGE_NUM: process.env.AI_IMAGE_DEFAULT_IMAGE_NUM,
|
|
150
|
-
},
|
|
151
|
-
});
|
|
152
|
-
};
|
|
153
|
-
|
|
154
|
-
// packages/types/src/serverConfig.ts
|
|
155
|
-
import { UserImageConfig } from './user/settings';
|
|
156
|
-
|
|
157
|
-
export interface GlobalServerConfig {
|
|
158
|
-
image?: PartialDeep<UserImageConfig>;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
// src/server/globalConfig/index.ts
|
|
162
|
-
image: cleanObject({
|
|
163
|
-
defaultImageNum: imageEnv.AI_IMAGE_DEFAULT_IMAGE_NUM,
|
|
164
|
-
}),
|
|
165
|
-
|
|
166
|
-
// src/store/user/slices/common/action.ts
|
|
167
|
-
const serverSettings: PartialDeep<UserSettings> = {
|
|
168
|
-
image: serverConfig.image,
|
|
169
|
-
// ...
|
|
170
|
-
};
|
|
171
|
-
|
|
172
|
-
// .env.example
|
|
173
|
-
# AI_IMAGE_DEFAULT_IMAGE_NUM=4
|
|
174
|
-
```
|
|
175
|
-
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: cursor rules writing and optimization guide
|
|
3
|
-
globs:
|
|
4
|
-
alwaysApply: false
|
|
5
|
-
---
|
|
6
|
-
当你编写或修改 Cursor Rule 时,请遵循以下准则:
|
|
7
|
-
|
|
8
|
-
- 当你知道 rule 的文件名时,使用 `read_file` 而不是 `fetch_rules` 去读取它们,它们都在项目根目录的 `.cursor/rules/` 文件夹下
|
|
9
|
-
|
|
10
|
-
- 代码示例
|
|
11
|
-
- 示例应尽量精简,仅保留演示核心
|
|
12
|
-
- 删除与示例无关的导入/导出语句,但保留必要的导入
|
|
13
|
-
- 同一文件存在多个示例时,若前文已演示模块导入,后续示例可省略重复导入
|
|
14
|
-
- 无需书写 `export`
|
|
15
|
-
- 可省略与演示无关或重复的 props、配置对象属性、try/catch、CSS 等代码
|
|
16
|
-
- 删除无关注释,保留有助理解的注释
|
|
17
|
-
|
|
18
|
-
- 格式
|
|
19
|
-
- 修改前请先确认原始文档语言,并保持一致
|
|
20
|
-
- 无序列表统一使用 `-`
|
|
21
|
-
- 列表末尾的句号是多余的
|
|
22
|
-
- 非必要不使用加粗、行内代码等样式,Rule 主要供 LLM 阅读
|
|
23
|
-
- 避免中英文逐句对照。若括号内容为示例而非翻译,可保留
|
|
24
|
-
|
|
25
|
-
- Review
|
|
26
|
-
- 修正 Markdown 语法问题
|
|
27
|
-
- 纠正错别字
|
|
28
|
-
- 指出示例与说明不一致之处
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
globs: packages/database/migrations/**/*
|
|
3
|
-
alwaysApply: false
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Database Migrations Guide
|
|
7
|
-
|
|
8
|
-
## Step1: Generate migrations
|
|
9
|
-
|
|
10
|
-
```bash
|
|
11
|
-
bun run db:generate
|
|
12
|
-
```
|
|
13
|
-
|
|
14
|
-
this step will generate following files:
|
|
15
|
-
|
|
16
|
-
- packages/database/migrations/0046_meaningless_file_name.sql
|
|
17
|
-
- packages/database/migrations/0046_meaningless_file_name.sql
|
|
18
|
-
|
|
19
|
-
and update the following files:
|
|
20
|
-
|
|
21
|
-
- packages/database/migrations/meta/\_journal.json
|
|
22
|
-
- packages/database/src/core/migrations.json
|
|
23
|
-
- docs/development/database-schema.dbml
|
|
24
|
-
|
|
25
|
-
## Step2: optimize the migration sql fileName
|
|
26
|
-
|
|
27
|
-
the migration sql file name is randomly generated, we need to optimize the file name to make it more readable and meaningful. For example, `0046_meaningless_file_name.sql` -> `0046_user_add_avatar_column.sql`
|
|
28
|
-
|
|
29
|
-
## Step3: Defensive Programming - Use Idempotent Clauses
|
|
30
|
-
|
|
31
|
-
Always use defensive clauses to make migrations idempotent:
|
|
32
|
-
|
|
33
|
-
```sql
|
|
34
|
-
-- ✅ Good: Idempotent operations
|
|
35
|
-
ALTER TABLE "users" ADD COLUMN IF NOT EXISTS "avatar" text;
|
|
36
|
-
DROP TABLE IF EXISTS "old_table";
|
|
37
|
-
CREATE INDEX IF NOT EXISTS "users_email_idx" ON "users" ("email");
|
|
38
|
-
ALTER TABLE "posts" DROP COLUMN IF EXISTS "deprecated_field";
|
|
39
|
-
|
|
40
|
-
-- ❌ Bad: Non-idempotent operations
|
|
41
|
-
ALTER TABLE "users" ADD COLUMN "avatar" text;
|
|
42
|
-
DROP TABLE "old_table";
|
|
43
|
-
CREATE INDEX "users_email_idx" ON "users" ("email");
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
**Important**: After modifying migration SQL (e.g., adding `IF NOT EXISTS` clauses), run `bun run db:generate:client` to update the hash in `packages/database/src/core/migrations.json`.
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: 包含添加 console.log 日志请求时
|
|
3
|
-
globs:
|
|
4
|
-
alwaysApply: false
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# Debug 包使用指南
|
|
8
|
-
|
|
9
|
-
本项目使用 `debug` 包进行调试日志记录。使用此规则来确保团队成员统一调试日志格式。
|
|
10
|
-
|
|
11
|
-
## 基本用法
|
|
12
|
-
|
|
13
|
-
1. 导入 debug 包:
|
|
14
|
-
|
|
15
|
-
```typescript
|
|
16
|
-
import debug from 'debug';
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
1. 创建一个命名空间的日志记录器:
|
|
20
|
-
|
|
21
|
-
```typescript
|
|
22
|
-
// 格式: lobe:[模块]:[子模块]
|
|
23
|
-
const log = debug('lobe-[模块名]:[子模块名]');
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
1. 使用日志记录器:
|
|
27
|
-
|
|
28
|
-
```typescript
|
|
29
|
-
log('简单消息');
|
|
30
|
-
log('带变量的消息: %O', object);
|
|
31
|
-
log('格式化数字: %d', number);
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
## 命名空间约定
|
|
35
|
-
|
|
36
|
-
- 桌面应用相关: `lobe-desktop:[模块]`
|
|
37
|
-
- 服务端相关: `lobe-server:[模块]`
|
|
38
|
-
- 客户端相关: `lobe-client:[模块]`
|
|
39
|
-
- 路由相关: `lobe-[类型]-router:[模块]`
|
|
40
|
-
|
|
41
|
-
## 格式说明符
|
|
42
|
-
|
|
43
|
-
- `%O` - 对象展开(推荐用于复杂对象)
|
|
44
|
-
- `%o` - 对象
|
|
45
|
-
- `%s` - 字符串
|
|
46
|
-
- `%d` - 数字
|
|
47
|
-
|
|
48
|
-
## 示例
|
|
49
|
-
|
|
50
|
-
查看 `src/server/routers/edge/market/index.ts` 中的使用示例:
|
|
51
|
-
|
|
52
|
-
```typescript
|
|
53
|
-
import debug from 'debug';
|
|
54
|
-
|
|
55
|
-
const log = debug('lobe-edge-router:market');
|
|
56
|
-
|
|
57
|
-
log('getAgent input: %O', input);
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
## 启用调试
|
|
61
|
-
|
|
62
|
-
要在开发时启用调试输出,需设置环境变量:
|
|
63
|
-
|
|
64
|
-
### 在浏览器中
|
|
65
|
-
|
|
66
|
-
在控制台执行:
|
|
67
|
-
|
|
68
|
-
```javascript
|
|
69
|
-
localStorage.debug = 'lobe-*';
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
### 在 Node.js 环境中
|
|
73
|
-
|
|
74
|
-
```bash
|
|
75
|
-
DEBUG=lobe-* npm run dev
|
|
76
|
-
# 或者
|
|
77
|
-
DEBUG=lobe-* pnpm dev
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
### 在 Electron 应用中
|
|
81
|
-
|
|
82
|
-
可以在主进程和渲染进程启动前设置环境变量:
|
|
83
|
-
|
|
84
|
-
```typescript
|
|
85
|
-
process.env.DEBUG = 'lobe-*';
|
|
86
|
-
```
|