@lobehub/lobehub 2.0.0-next.353 → 2.0.0-next.355

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.
Files changed (144) hide show
  1. package/.agents/skills/add-provider-doc/SKILL.md +90 -0
  2. package/.agents/skills/add-setting-env/SKILL.md +106 -0
  3. package/.agents/skills/debug/SKILL.md +66 -0
  4. package/.agents/skills/desktop/SKILL.md +78 -0
  5. package/.agents/skills/desktop/references/feature-implementation.md +99 -0
  6. package/.agents/skills/desktop/references/local-tools.md +133 -0
  7. package/.agents/skills/desktop/references/menu-config.md +103 -0
  8. package/.agents/skills/desktop/references/window-management.md +143 -0
  9. package/.agents/skills/drizzle/SKILL.md +129 -0
  10. package/.agents/skills/drizzle/references/db-migrations.md +50 -0
  11. package/.agents/skills/hotkey/SKILL.md +90 -0
  12. package/{.cursor/rules/i18n.mdc → .agents/skills/i18n/SKILL.md} +14 -23
  13. package/.agents/skills/linear/SKILL.md +51 -0
  14. package/.agents/skills/microcopy/SKILL.md +83 -0
  15. package/.agents/skills/modal/SKILL.md +102 -0
  16. package/{.cursor/rules/project-structure.mdc → .agents/skills/project-overview/SKILL.md} +65 -37
  17. package/.agents/skills/react/SKILL.md +73 -0
  18. package/.agents/skills/react/references/layout-kit.md +100 -0
  19. package/.agents/skills/recent-data/SKILL.md +108 -0
  20. package/.agents/skills/testing/SKILL.md +89 -0
  21. package/.agents/skills/testing/references/agent-runtime-e2e.md +126 -0
  22. package/.agents/skills/testing/references/db-model-test.md +124 -0
  23. package/.agents/skills/testing/references/desktop-controller-test.md +124 -0
  24. package/.agents/skills/testing/references/electron-ipc-test.md +63 -0
  25. package/.agents/skills/testing/references/zustand-store-action-test.md +150 -0
  26. package/.agents/skills/typescript/SKILL.md +52 -0
  27. package/.agents/skills/zustand/SKILL.md +78 -0
  28. package/.agents/skills/zustand/references/action-patterns.md +125 -0
  29. package/.agents/skills/zustand/references/slice-organization.md +125 -0
  30. package/AGENTS.md +42 -55
  31. package/CHANGELOG.md +60 -0
  32. package/CLAUDE.md +57 -46
  33. package/GEMINI.md +47 -39
  34. package/changelog/v1.json +18 -0
  35. package/locales/en-US/plugin.json +3 -0
  36. package/locales/zh-CN/plugin.json +3 -0
  37. package/package.json +1 -1
  38. package/packages/builtin-tool-memory/src/client/Render/SearchUserMemory/index.tsx +3 -11
  39. package/packages/context-engine/src/engine/messages/MessagesEngine.ts +0 -13
  40. package/packages/context-engine/src/engine/messages/__tests__/MessagesEngine.test.ts +0 -25
  41. package/packages/database/src/models/__tests__/topics/topic.create.test.ts +3 -3
  42. package/src/app/[variants]/(main)/agent/_layout/Sidebar/Topic/List/Item/index.tsx +1 -0
  43. package/src/app/[variants]/(main)/agent/features/Conversation/ConversationArea.tsx +4 -0
  44. package/src/app/[variants]/(main)/group/_layout/Sidebar/Topic/List/Item/index.tsx +1 -0
  45. package/src/app/[variants]/(main)/home/_layout/Body/Agent/List/AgentItem/index.tsx +1 -1
  46. package/src/app/[variants]/(main)/home/_layout/Body/Agent/List/InboxItem.tsx +19 -29
  47. package/src/app/[variants]/(main)/home/_layout/Body/Agent/List/List.tsx +1 -1
  48. package/src/app/[variants]/(main)/home/_layout/Body/Agent/ModalProvider.tsx +1 -1
  49. package/src/features/FileViewer/Renderer/PDF/index.tsx +2 -3
  50. package/src/features/ShareModal/SharePdf/PdfPreview.tsx +1 -2
  51. package/src/libs/pdfjs/index.tsx +25 -0
  52. package/src/locales/default/plugin.ts +3 -0
  53. package/src/server/modules/Mecha/ContextEngineering/__tests__/serverMessagesEngine.test.ts +0 -25
  54. package/src/services/chat/chat.test.ts +19 -19
  55. package/src/services/chat/index.ts +8 -3
  56. package/src/services/chat/mecha/agentConfigResolver.test.ts +72 -55
  57. package/src/services/chat/mecha/agentConfigResolver.ts +28 -4
  58. package/src/services/chat/mecha/contextEngineering.test.ts +21 -14
  59. package/src/services/chat/mecha/contextEngineering.ts +12 -0
  60. package/src/services/chat/types.ts +7 -1
  61. package/src/store/chat/agents/createAgentExecutors.ts +15 -4
  62. package/src/store/chat/slices/aiChat/actions/conversationLifecycle.ts +1 -0
  63. package/src/store/chat/slices/aiChat/actions/streamingExecutor.ts +6 -2
  64. package/src/store/test-coverage.md +5 -5
  65. package/.cursor/rules/add-provider-doc.mdc +0 -183
  66. package/.cursor/rules/add-setting-env.mdc +0 -175
  67. package/.cursor/rules/cursor-rules.mdc +0 -28
  68. package/.cursor/rules/db-migrations.mdc +0 -46
  69. package/.cursor/rules/debug-usage.mdc +0 -86
  70. package/.cursor/rules/desktop-controller-tests.mdc +0 -189
  71. package/.cursor/rules/desktop-feature-implementation.mdc +0 -155
  72. package/.cursor/rules/desktop-local-tools-implement.mdc +0 -81
  73. package/.cursor/rules/desktop-menu-configuration.mdc +0 -209
  74. package/.cursor/rules/desktop-window-management.mdc +0 -301
  75. package/.cursor/rules/drizzle-schema-style-guide.mdc +0 -218
  76. package/.cursor/rules/hotkey.mdc +0 -162
  77. package/.cursor/rules/linear.mdc +0 -53
  78. package/.cursor/rules/microcopy-cn.mdc +0 -158
  79. package/.cursor/rules/microcopy-en.mdc +0 -148
  80. package/.cursor/rules/modal-imperative.mdc +0 -162
  81. package/.cursor/rules/packages/react-layout-kit.mdc +0 -122
  82. package/.cursor/rules/project-introduce.mdc +0 -36
  83. package/.cursor/rules/react.mdc +0 -169
  84. package/.cursor/rules/recent-data-usage.mdc +0 -139
  85. package/.cursor/rules/rules-index.mdc +0 -44
  86. package/.cursor/rules/testing-guide/agent-runtime-e2e.mdc +0 -285
  87. package/.cursor/rules/testing-guide/db-model-test.mdc +0 -455
  88. package/.cursor/rules/testing-guide/electron-ipc-test.mdc +0 -80
  89. package/.cursor/rules/testing-guide/testing-guide.mdc +0 -534
  90. package/.cursor/rules/testing-guide/zustand-store-action-test.mdc +0 -574
  91. package/.cursor/rules/typescript.mdc +0 -55
  92. package/.cursor/rules/zustand-action-patterns.mdc +0 -328
  93. package/.cursor/rules/zustand-slice-organization.mdc +0 -308
  94. package/src/libs/pdfjs/pdf.worker.ts +0 -1
  95. package/src/libs/pdfjs/worker.ts +0 -12
  96. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/AGENTS.md +0 -0
  97. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/SKILL.md +0 -0
  98. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/advanced-event-handler-refs.md +0 -0
  99. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/advanced-use-latest.md +0 -0
  100. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/async-api-routes.md +0 -0
  101. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/async-defer-await.md +0 -0
  102. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/async-dependencies.md +0 -0
  103. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/async-parallel.md +0 -0
  104. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/async-suspense-boundaries.md +0 -0
  105. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/bundle-barrel-imports.md +0 -0
  106. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/bundle-conditional.md +0 -0
  107. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/bundle-defer-third-party.md +0 -0
  108. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/bundle-dynamic-imports.md +0 -0
  109. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/bundle-preload.md +0 -0
  110. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/client-event-listeners.md +0 -0
  111. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/client-localstorage-schema.md +0 -0
  112. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/client-passive-event-listeners.md +0 -0
  113. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/client-swr-dedup.md +0 -0
  114. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/js-batch-dom-css.md +0 -0
  115. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/js-cache-function-results.md +0 -0
  116. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/js-cache-property-access.md +0 -0
  117. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/js-cache-storage.md +0 -0
  118. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/js-combine-iterations.md +0 -0
  119. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/js-early-exit.md +0 -0
  120. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/js-hoist-regexp.md +0 -0
  121. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/js-index-maps.md +0 -0
  122. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/js-length-check-first.md +0 -0
  123. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/js-min-max-loop.md +0 -0
  124. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/js-set-map-lookups.md +0 -0
  125. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/js-tosorted-immutable.md +0 -0
  126. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/rendering-activity.md +0 -0
  127. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/rendering-animate-svg-wrapper.md +0 -0
  128. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/rendering-conditional-render.md +0 -0
  129. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/rendering-content-visibility.md +0 -0
  130. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/rendering-hoist-jsx.md +0 -0
  131. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/rendering-hydration-no-flicker.md +0 -0
  132. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/rendering-svg-precision.md +0 -0
  133. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/rerender-defer-reads.md +0 -0
  134. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/rerender-dependencies.md +0 -0
  135. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/rerender-derived-state.md +0 -0
  136. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/rerender-functional-setstate.md +0 -0
  137. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/rerender-lazy-state-init.md +0 -0
  138. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/rerender-memo.md +0 -0
  139. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/rerender-transitions.md +0 -0
  140. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/server-after-nonblocking.md +0 -0
  141. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/server-cache-lru.md +0 -0
  142. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/server-cache-react.md +0 -0
  143. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/server-parallel-fetching.md +0 -0
  144. /package/.agents/{vercel-react-best-practices → skills/vercel-react-best-practices}/rules/server-serialization.md +0 -0
@@ -0,0 +1,143 @@
1
+ # Desktop Window Management Guide
2
+
3
+ ## Window Management Overview
4
+
5
+ 1. Window creation and configuration
6
+ 2. Window state management (size, position, maximize)
7
+ 3. Multi-window coordination
8
+ 4. Window event handling
9
+
10
+ ## File Structure
11
+
12
+ ```plaintext
13
+ apps/desktop/src/main/
14
+ ├── appBrowsers.ts # Core window management
15
+ ├── controllers/
16
+ │ └── BrowserWindowsCtr.ts # Window controller
17
+ └── modules/
18
+ └── browserWindowManager.ts # Window manager module
19
+ ```
20
+
21
+ ## Window Creation
22
+
23
+ ```typescript
24
+ export const createMainWindow = () => {
25
+ const mainWindow = new BrowserWindow({
26
+ width: 1200,
27
+ height: 800,
28
+ minWidth: 600,
29
+ minHeight: 400,
30
+ webPreferences: {
31
+ preload: path.join(__dirname, '../preload/index.js'),
32
+ contextIsolation: true,
33
+ nodeIntegration: false,
34
+ },
35
+ });
36
+
37
+ if (isDev) {
38
+ mainWindow.loadURL('http://localhost:3000');
39
+ } else {
40
+ mainWindow.loadFile(path.join(__dirname, '../../renderer/index.html'));
41
+ }
42
+
43
+ return mainWindow;
44
+ };
45
+ ```
46
+
47
+ ## Window State Persistence
48
+
49
+ ```typescript
50
+ const saveWindowState = (window: BrowserWindow) => {
51
+ if (!window.isMinimized() && !window.isMaximized()) {
52
+ const [x, y] = window.getPosition();
53
+ const [width, height] = window.getSize();
54
+ settings.set('windowState', { x, y, width, height });
55
+ }
56
+ };
57
+
58
+ const restoreWindowState = (window: BrowserWindow) => {
59
+ const state = settings.get('windowState');
60
+ if (state) {
61
+ window.setBounds({ x: state.x, y: state.y, width: state.width, height: state.height });
62
+ }
63
+ };
64
+
65
+ window.on('close', () => saveWindowState(window));
66
+ ```
67
+
68
+ ## Multi-Window Management
69
+
70
+ ```typescript
71
+ export class WindowManager {
72
+ private windows: Map<string, BrowserWindow> = new Map();
73
+
74
+ createWindow(id: string, options: BrowserWindowConstructorOptions) {
75
+ const window = new BrowserWindow(options);
76
+ this.windows.set(id, window);
77
+ window.on('closed', () => this.windows.delete(id));
78
+ return window;
79
+ }
80
+
81
+ getWindow(id: string) {
82
+ return this.windows.get(id);
83
+ }
84
+ }
85
+ ```
86
+
87
+ ## Window IPC Controller
88
+
89
+ ```typescript
90
+ // apps/desktop/src/main/controllers/BrowserWindowsCtr.ts
91
+ export default class BrowserWindowsCtr extends ControllerModule {
92
+ static override readonly groupName = 'windows';
93
+
94
+ @IpcMethod()
95
+ minimizeWindow() {
96
+ BrowserWindow.getFocusedWindow()?.minimize();
97
+ return { success: true };
98
+ }
99
+
100
+ @IpcMethod()
101
+ maximizeWindow() {
102
+ const win = BrowserWindow.getFocusedWindow();
103
+ win?.isMaximized() ? win.restore() : win?.maximize();
104
+ return { success: true };
105
+ }
106
+ }
107
+ ```
108
+
109
+ ## Renderer Service
110
+
111
+ ```typescript
112
+ // src/services/electron/windowService.ts
113
+ import { ensureElectronIpc } from '@/utils/electron/ipc';
114
+
115
+ const ipc = ensureElectronIpc();
116
+
117
+ export const windowService = {
118
+ minimize: () => ipc.windows.minimizeWindow(),
119
+ maximize: () => ipc.windows.maximizeWindow(),
120
+ close: () => ipc.windows.closeWindow(),
121
+ };
122
+ ```
123
+
124
+ ## Frameless Window
125
+
126
+ ```typescript
127
+ const window = new BrowserWindow({
128
+ frame: false,
129
+ titleBarStyle: 'hidden',
130
+ });
131
+ ```
132
+
133
+ ```css
134
+ .titlebar { -webkit-app-region: drag; }
135
+ .titlebar-button { -webkit-app-region: no-drag; }
136
+ ```
137
+
138
+ ## Best Practices
139
+
140
+ 1. Use `show: false` initially, show after content loads
141
+ 2. Always set secure `webPreferences`
142
+ 3. Handle `webContents.on('crashed')` for recovery
143
+ 4. Clean up resources on `window.on('closed')`
@@ -0,0 +1,129 @@
1
+ ---
2
+ name: drizzle
3
+ description: Drizzle ORM schema and database guide. Use when working with database schemas (src/database/schemas/*), defining tables, creating migrations, or database model code. Triggers on Drizzle schema definition, database migrations, or ORM usage questions.
4
+ ---
5
+
6
+ # Drizzle ORM Schema Style Guide
7
+
8
+ ## Configuration
9
+
10
+ - Config: `drizzle.config.ts`
11
+ - Schemas: `src/database/schemas/`
12
+ - Migrations: `src/database/migrations/`
13
+ - Dialect: `postgresql` with `strict: true`
14
+
15
+ ## Helper Functions
16
+
17
+ Location: `src/database/schemas/_helpers.ts`
18
+
19
+ - `timestamptz(name)`: Timestamp with timezone
20
+ - `createdAt()`, `updatedAt()`, `accessedAt()`: Standard timestamp columns
21
+ - `timestamps`: Object with all three for easy spread
22
+
23
+ ## Naming Conventions
24
+
25
+ - **Tables**: Plural snake_case (`users`, `session_groups`)
26
+ - **Columns**: snake_case (`user_id`, `created_at`)
27
+
28
+ ## Column Definitions
29
+
30
+ ### Primary Keys
31
+
32
+ ```typescript
33
+ id: text('id')
34
+ .primaryKey()
35
+ .$defaultFn(() => idGenerator('agents'))
36
+ .notNull(),
37
+ ```
38
+
39
+ ID prefixes make entity types distinguishable. For internal tables, use `uuid`.
40
+
41
+ ### Foreign Keys
42
+
43
+ ```typescript
44
+ userId: text('user_id')
45
+ .references(() => users.id, { onDelete: 'cascade' })
46
+ .notNull(),
47
+ ```
48
+
49
+ ### Timestamps
50
+
51
+ ```typescript
52
+ ...timestamps, // Spread from _helpers.ts
53
+ ```
54
+
55
+ ### Indexes
56
+
57
+ ```typescript
58
+ // Return array (object style deprecated)
59
+ (t) => [uniqueIndex('client_id_user_id_unique').on(t.clientId, t.userId)],
60
+ ```
61
+
62
+ ## Type Inference
63
+
64
+ ```typescript
65
+ export const insertAgentSchema = createInsertSchema(agents);
66
+ export type NewAgent = typeof agents.$inferInsert;
67
+ export type AgentItem = typeof agents.$inferSelect;
68
+ ```
69
+
70
+ ## Example Pattern
71
+
72
+ ```typescript
73
+ export const agents = pgTable(
74
+ 'agents',
75
+ {
76
+ id: text('id').primaryKey().$defaultFn(() => idGenerator('agents')).notNull(),
77
+ slug: varchar('slug', { length: 100 }).$defaultFn(() => randomSlug(4)).unique(),
78
+ userId: text('user_id').references(() => users.id, { onDelete: 'cascade' }).notNull(),
79
+ clientId: text('client_id'),
80
+ chatConfig: jsonb('chat_config').$type<LobeAgentChatConfig>(),
81
+ ...timestamps,
82
+ },
83
+ (t) => [uniqueIndex('client_id_user_id_unique').on(t.clientId, t.userId)],
84
+ );
85
+ ```
86
+
87
+ ## Common Patterns
88
+
89
+ ### Junction Tables (Many-to-Many)
90
+
91
+ ```typescript
92
+ export const agentsKnowledgeBases = pgTable(
93
+ 'agents_knowledge_bases',
94
+ {
95
+ agentId: text('agent_id').references(() => agents.id, { onDelete: 'cascade' }).notNull(),
96
+ knowledgeBaseId: text('knowledge_base_id').references(() => knowledgeBases.id, { onDelete: 'cascade' }).notNull(),
97
+ userId: text('user_id').references(() => users.id, { onDelete: 'cascade' }).notNull(),
98
+ enabled: boolean('enabled').default(true),
99
+ ...timestamps,
100
+ },
101
+ (t) => [primaryKey({ columns: [t.agentId, t.knowledgeBaseId] })],
102
+ );
103
+ ```
104
+
105
+ ## Database Migrations
106
+
107
+ See `references/db-migrations.md` for detailed migration guide.
108
+
109
+ ```bash
110
+ # Generate migrations
111
+ bun run db:generate
112
+
113
+ # After modifying SQL (e.g., adding IF NOT EXISTS)
114
+ bun run db:generate:client
115
+ ```
116
+
117
+ ### Migration Best Practices
118
+
119
+ ```sql
120
+ -- ✅ Idempotent operations
121
+ ALTER TABLE "users" ADD COLUMN IF NOT EXISTS "avatar" text;
122
+ DROP TABLE IF EXISTS "old_table";
123
+ CREATE INDEX IF NOT EXISTS "users_email_idx" ON "users" ("email");
124
+
125
+ -- ❌ Non-idempotent
126
+ ALTER TABLE "users" ADD COLUMN "avatar" text;
127
+ ```
128
+
129
+ Rename migration files meaningfully: `0046_meaningless.sql` → `0046_user_add_avatar.sql`
@@ -0,0 +1,50 @@
1
+ # Database Migrations Guide
2
+
3
+ ## Step 1: Generate Migrations
4
+
5
+ ```bash
6
+ bun run db:generate
7
+ ```
8
+
9
+ This generates:
10
+
11
+ - `packages/database/migrations/0046_meaningless_file_name.sql`
12
+
13
+ And updates:
14
+
15
+ - `packages/database/migrations/meta/_journal.json`
16
+ - `packages/database/src/core/migrations.json`
17
+ - `docs/development/database-schema.dbml`
18
+
19
+ ## Step 2: Optimize Migration SQL Filename
20
+
21
+ Rename auto-generated filename to be meaningful:
22
+
23
+ `0046_meaningless_file_name.sql` → `0046_user_add_avatar_column.sql`
24
+
25
+ ## Step 3: Use Idempotent Clauses (Defensive Programming)
26
+
27
+ Always use defensive clauses to make migrations idempotent:
28
+
29
+ ```sql
30
+ -- ✅ Good: Idempotent operations
31
+ ALTER TABLE "users" ADD COLUMN IF NOT EXISTS "avatar" text;
32
+ DROP TABLE IF EXISTS "old_table";
33
+ CREATE INDEX IF NOT EXISTS "users_email_idx" ON "users" ("email");
34
+ ALTER TABLE "posts" DROP COLUMN IF EXISTS "deprecated_field";
35
+
36
+ -- ❌ Bad: Non-idempotent operations
37
+ ALTER TABLE "users" ADD COLUMN "avatar" text;
38
+ DROP TABLE "old_table";
39
+ CREATE INDEX "users_email_idx" ON "users" ("email");
40
+ ```
41
+
42
+ ## Important
43
+
44
+ After modifying migration SQL (e.g., adding `IF NOT EXISTS` clauses), run:
45
+
46
+ ```bash
47
+ bun run db:generate:client
48
+ ```
49
+
50
+ This updates the hash in `packages/database/src/core/migrations.json`.
@@ -0,0 +1,90 @@
1
+ ---
2
+ name: hotkey
3
+ description: Guide for adding keyboard shortcuts. Use when implementing new hotkeys, registering shortcuts, or working with keyboard interactions. Triggers on hotkey implementation or keyboard shortcut tasks.
4
+ ---
5
+
6
+ # Adding Keyboard Shortcuts Guide
7
+
8
+ ## Steps to Add a New Hotkey
9
+
10
+ ### 1. Update Hotkey Constant
11
+
12
+ In `src/types/hotkey.ts`:
13
+
14
+ ```typescript
15
+ export const HotkeyEnum = {
16
+ // existing...
17
+ ClearChat: 'clearChat', // Add new
18
+ } as const;
19
+ ```
20
+
21
+ ### 2. Register Default Hotkey
22
+
23
+ In `src/const/hotkeys.ts`:
24
+
25
+ ```typescript
26
+ import { KeyMapEnum as Key, combineKeys } from '@lobehub/ui';
27
+
28
+ export const HOTKEYS_REGISTRATION: HotkeyRegistration = [
29
+ {
30
+ group: HotkeyGroupEnum.Conversation,
31
+ id: HotkeyEnum.ClearChat,
32
+ keys: combineKeys([Key.Mod, Key.Shift, Key.Backspace]),
33
+ scopes: [HotkeyScopeEnum.Chat],
34
+ },
35
+ ];
36
+ ```
37
+
38
+ ### 3. Add i18n Translation
39
+
40
+ In `src/locales/default/hotkey.ts`:
41
+
42
+ ```typescript
43
+ const hotkey: HotkeyI18nTranslations = {
44
+ clearChat: {
45
+ desc: '清空当前会话的所有消息记录',
46
+ title: '清空聊天记录',
47
+ },
48
+ };
49
+ ```
50
+
51
+ ### 4. Create and Register Hook
52
+
53
+ In `src/hooks/useHotkeys/chatScope.ts`:
54
+
55
+ ```typescript
56
+ export const useClearChatHotkey = () => {
57
+ const clearMessages = useChatStore((s) => s.clearMessages);
58
+ return useHotkeyById(HotkeyEnum.ClearChat, clearMessages);
59
+ };
60
+
61
+ export const useRegisterChatHotkeys = () => {
62
+ useClearChatHotkey();
63
+ // ...other hotkeys
64
+ };
65
+ ```
66
+
67
+ ### 5. Add Tooltip (Optional)
68
+
69
+ ```tsx
70
+ const clearChatHotkey = useUserStore(settingsSelectors.getHotkeyById(HotkeyEnum.ClearChat));
71
+
72
+ <Tooltip hotkey={clearChatHotkey} title={t('clearChat.title', { ns: 'hotkey' })}>
73
+ <Button icon={<DeleteOutlined />} onClick={clearMessages} />
74
+ </Tooltip>
75
+ ```
76
+
77
+ ## Best Practices
78
+
79
+ 1. **Scope**: Choose global or chat scope based on functionality
80
+ 2. **Grouping**: Place in appropriate group (System/Layout/Conversation)
81
+ 3. **Conflict check**: Ensure no conflict with system/browser shortcuts
82
+ 4. **Platform**: Use `Key.Mod` instead of hardcoded `Ctrl` or `Cmd`
83
+ 5. **Clear description**: Provide title and description for users
84
+
85
+ ## Troubleshooting
86
+
87
+ - **Not working**: Check scope and RegisterHotkeys hook
88
+ - **Not in settings**: Verify HOTKEYS_REGISTRATION config
89
+ - **Conflict**: HotkeyInput component shows warnings
90
+ - **Page-specific**: Ensure correct scope activation
@@ -1,15 +1,14 @@
1
1
  ---
2
- globs: *.tsx
3
- alwaysApply: false
2
+ name: i18n
3
+ description: Internationalization guide using react-i18next. Use when adding translations, creating i18n keys, or working with localized text in React components (.tsx files). Triggers on translation tasks, locale management, or i18n implementation.
4
4
  ---
5
5
 
6
6
  # LobeChat Internationalization Guide
7
7
 
8
- ## Key Points
9
-
10
- - Default language: Chinese (zh-CN), Framework: react-i18next
8
+ - Default language: Chinese (zh-CN)
9
+ - Framework: react-i18next
11
10
  - **Only edit files in `src/locales/default/`** - Never edit JSON files in `locales/`
12
- - Run `pnpm i18n` to generate all translations (or manually translate zh-CN/en-US for dev preview)
11
+ - Run `pnpm i18n` to generate translations (or manually translate zh-CN/en-US for dev preview)
13
12
 
14
13
  ## Key Naming Convention
15
14
 
@@ -19,37 +18,30 @@ alwaysApply: false
19
18
  // ✅ Correct
20
19
  export default {
21
20
  'alert.cloud.action': '立即体验',
22
- 'clientDB.error.desc': '数据库初始化遇到问题',
23
21
  'sync.actions.sync': '立即同步',
24
22
  'sync.status.ready': '已连接',
25
23
  };
26
24
 
27
- // ❌ Avoid: Nested objects
25
+ // ❌ Avoid nested objects
28
26
  export default {
29
27
  alert: { cloud: { action: '...' } },
30
28
  };
31
29
  ```
32
30
 
33
- **Naming patterns:** `{feature}.{context}.{action|status}`
34
-
35
- - `clientDB.modal.title` - Feature + context + property
36
- - `sync.actions.sync` - Feature + group + action
37
- - `sync.status.ready` - Feature + group + status
31
+ **Patterns:** `{feature}.{context}.{action|status}`
38
32
 
39
33
  **Parameters:** Use `{{variableName}}` syntax
40
-
41
34
  ```typescript
42
35
  'alert.cloud.desc': '我们提供 {{credit}} 额度积分',
43
36
  ```
44
37
 
45
- **Avoid key conflicts:** Don't use both a leaf key and its parent path
46
-
38
+ **Avoid key conflicts:**
47
39
  ```typescript
48
- // ❌ Conflict: clientDB.solve exists as both leaf and parent
40
+ // ❌ Conflict
49
41
  'clientDB.solve': '自助解决',
50
42
  'clientDB.solve.backup.title': '数据备份',
51
43
 
52
- // ✅ Solution: Use different suffixes
44
+ // ✅ Solution
53
45
  'clientDB.solve.action': '自助解决',
54
46
  'clientDB.solve.backup.title': '数据备份',
55
47
  ```
@@ -68,17 +60,16 @@ import { useTranslation } from 'react-i18next';
68
60
 
69
61
  const { t } = useTranslation('common');
70
62
 
71
- // Basic
72
63
  t('newFeature.title')
73
- // With parameters
74
64
  t('alert.cloud.desc', { credit: '1000' })
65
+
75
66
  // Multiple namespaces
76
67
  const { t } = useTranslation(['common', 'chat']);
77
68
  t('common:save')
78
69
  ```
79
70
 
80
- ## Available Namespaces
81
-
82
- auth, authError, changelog, chat, color, **common**, components, discover, editor, electron, error, file, home, hotkey, image, knowledgeBase, labs, marketAuth, memory, metadata, migration, modelProvider, models, oauth, onboarding, plugin, portal, providers, ragEval, **setting**, subscription, thread, tool, topic, welcome
71
+ ## Common Namespaces
83
72
 
84
73
  **Most used:** `common` (shared UI), `chat` (chat features), `setting` (settings)
74
+
75
+ Others: auth, changelog, components, discover, editor, electron, error, file, hotkey, knowledgeBase, memory, models, plugin, portal, providers, tool, topic
@@ -0,0 +1,51 @@
1
+ ---
2
+ name: linear
3
+ description: Linear issue management guide. Use when working with Linear issues, creating issues, updating status, or adding comments. Triggers on Linear issue references (LOBE-xxx), issue tracking, or project management tasks. Requires Linear MCP tools to be available.
4
+ ---
5
+
6
+ # Linear Issue Management
7
+
8
+ Before using Linear workflows, search for `linear` MCP tools. If not found, treat as not installed.
9
+
10
+ ## Workflow
11
+
12
+ 1. **Retrieve issue details** before starting: `mcp__linear-server__get_issue`
13
+ 2. **Check for sub-issues**: Use `mcp__linear-server__list_issues` with `parentId` filter
14
+ 3. **Update issue status** when completing: `mcp__linear-server__update_issue`
15
+ 4. **Add completion comment** (REQUIRED): `mcp__linear-server__create_comment`
16
+
17
+ ## Creating Issues
18
+
19
+ When creating issues with `mcp__linear-server__create_issue`, **MUST add the `claude code` label**.
20
+
21
+ ## Completion Comment (REQUIRED)
22
+
23
+ Every completed issue MUST have a comment summarizing work done. This is critical for:
24
+ - Team visibility
25
+ - Code review context
26
+ - Future reference
27
+
28
+ ## PR Association (REQUIRED)
29
+
30
+ When creating PRs for Linear issues, include magic keywords in PR body:
31
+ - `Fixes LOBE-123`
32
+ - `Closes LOBE-123`
33
+ - `Resolves LOBE-123`
34
+
35
+ ## Per-Issue Completion Rule
36
+
37
+ When working on multiple issues, update EACH issue IMMEDIATELY after completing it:
38
+
39
+ 1. Complete implementation
40
+ 2. Run `bun run type-check`
41
+ 3. Run related tests
42
+ 4. Create PR if needed
43
+ 5. Update status to **"In Review"** (NOT "Done")
44
+ 6. Add completion comment
45
+ 7. Move to next issue
46
+
47
+ **Note:** Status → "In Review" when PR created. "Done" only after PR merged.
48
+
49
+ **❌ Wrong:** Complete all → Update all statuses → Add all comments
50
+
51
+ **✅ Correct:** Complete A → Update A → Comment A → Complete B → ...
@@ -0,0 +1,83 @@
1
+ ---
2
+ name: microcopy
3
+ description: UI copy and microcopy guidelines. Use when writing UI text, buttons, error messages, empty states, onboarding, or any user-facing copy. Triggers on i18n translation, UI text writing, or copy improvement tasks. Supports both Chinese and English.
4
+ ---
5
+
6
+ # LobeHub UI Microcopy Guidelines
7
+
8
+ Brand: **Where Agents Collaborate** - Focus on collaborative agent system, not just "generation".
9
+
10
+ ## Fixed Terminology
11
+
12
+ | Chinese | English |
13
+ |---------|---------|
14
+ | 空间 | Workspace |
15
+ | 助理 | Agent |
16
+ | 群组 | Group |
17
+ | 上下文 | Context |
18
+ | 记忆 | Memory |
19
+ | 连接器 | Integration |
20
+ | 技能 | Skill |
21
+ | 助理档案 | Agent Profile |
22
+ | 话题 | Topic |
23
+ | 文稿 | Page |
24
+ | 社区 | Community |
25
+ | 资源 | Resource |
26
+ | 库 | Library |
27
+ | 模型服务商 | Provider |
28
+
29
+ ## Brand Principles
30
+
31
+ 1. **Create**: One sentence → usable Agent; clear next step
32
+ 2. **Collaborate**: Multi-agent; shared Context; controlled
33
+ 3. **Evolve**: Remember with consent; explainable; replayable
34
+
35
+ ## Writing Rules
36
+
37
+ 1. **Clarity first**: Short sentences, strong verbs, minimal adjectives
38
+ 2. **Layered**: Main line (simple) + optional detail (precise)
39
+ 3. **Consistent verbs**: Create / Connect / Run / Pause / Retry / View details
40
+ 4. **Actionable**: Every message tells next step; avoid generic "OK/Cancel"
41
+
42
+ ## Human Warmth (Balanced)
43
+
44
+ Default: **80% information, 20% warmth**
45
+ Key moments: **70/30** (first-time, empty state, failures, long waits)
46
+
47
+ **Hard cap**: At most half sentence of warmth, followed by clear next step.
48
+
49
+ **Order**:
50
+ 1. Acknowledge situation (no judgment)
51
+ 2. Restore control (pause/replay/edit/undo/clear Memory)
52
+ 3. Provide next action
53
+
54
+ **Avoid**: Preachy encouragement, grand narratives, over-anthropomorphizing
55
+
56
+ ## Patterns
57
+
58
+ **Getting started**:
59
+ - "Starting with one sentence is enough. Describe your goal."
60
+ - "Not sure where to begin? Tell me the outcome."
61
+
62
+ **Long wait**:
63
+ - "Running… You can switch tasks—I'll notify you when done."
64
+ - "This may take a few minutes. To speed up: reduce Context / switch model."
65
+
66
+ **Failure**:
67
+ - "That didn't run through. Retry, or view details to fix."
68
+ - "Connection failed. Re-authorize in Settings, or try again later."
69
+
70
+ **Collaboration**:
71
+ - "Align everyone to the same Context."
72
+ - "Different opinions are fine. Write the goal first."
73
+
74
+ ## Errors/Exceptions
75
+
76
+ Must include:
77
+ 1. **What happened**
78
+ 2. (Optional) **Why**
79
+ 3. **What user can do next**
80
+
81
+ Provide: Retry / View details / Go to Settings / Contact support / Copy logs
82
+
83
+ Never blame user. Put error codes in "Details".