mirror of
https://github.com/lobehub/lobehub.git
synced 2026-03-26 13:19:34 +07:00
* ✨ feat: add slash action tags in chat input Made-with: Cursor * ✨ feat: enhance editor with new slash actions and localization updates - Added new slash actions: change tone, condense, expand, polish, rewrite, summarize, and translate. - Updated localization files for English and Chinese to include new action tags and slash commands. - Removed deprecated useSlashItems component and integrated its functionality directly into InputEditor. Signed-off-by: Innei <tukon479@gmail.com> * ✨ feat: add slash placement configuration to chat input components - Introduced `slashPlacement` prop to `ChatInputProvider`, `StoreUpdater`, and `InputEditor` for customizable slash menu positioning. - Updated initial state to include `slashPlacement` with default value 'top'. - Adjusted `ChatInput` and `InputArea` components to utilize the new `slashPlacement` prop. This enhancement allows for better control over the user interface in chat input interactions. Signed-off-by: Innei <tukon479@gmail.com> * ✨ feat: implement command bus for slash action tags processing Add command bus system to parse and execute slash commands (compact context, new topic). Refactor action tag categories from ai/prompt to command/skill. Add useEnabledSkills hook for dynamic skill registration. * feat: compress command Signed-off-by: Innei <tukon479@gmail.com> * refactor: compress Signed-off-by: Innei <tukon479@gmail.com> * fix: skill inject * ✨ feat: slash action tags with context engine integration Made-with: Cursor * ✨ feat: add topic reference builtin tool and server runtime Made-with: Cursor * ✨ feat: add topic mention items and update ReferTopic integration Made-with: Cursor * 🐛 fix: preserve editorData through assistant-group edit flow and update RichTextMessage reactively - EditState now forwards editorData from EditorModal to modifyMessageContent - modifyMessageContent accepts and passes editorData to updateMessageContent - RichTextMessage uses useEditor + effect to update document on content change instead of key-based remount - Refactored RichTextMessage plugins to use shared createChatInputRichPlugins() * ✨ feat(context-engine): add metadata types and update processors/providers Made-with: Cursor * ✨ feat(chat-input): add slash action tags and restore failed input state * 🔧 chore: update package dependencies and enhance Vite configuration - Changed @lobehub/ui dependency to a specific package URL. - Added multiple SPA entry points and layout files to the Vite warmup configuration. - Removed unused monorepo packages from sharedOptimizeDeps and added various dayjs locales for better localization support. Signed-off-by: Innei <tukon479@gmail.com> * 🔧 chore: update @lobehub/ui dependency to version 5.4.0 in package.json Signed-off-by: Innei <tukon479@gmail.com> * 🐛 fix: correct SkillsApiName.runSkill to activateSkill and update trimmed content assertions * 🐛 fix: resolve type errors in context-engine tests and InputEditor slashPlacement * 🐛 fix: update runSkill to activateSkill in conversationLifecycle test * 🐛 fix: avoid regex backtracking in placeholder parser * ✨ feat(localization): add action tags and tooltips for slash commands across multiple languages Signed-off-by: Innei <tukon479@gmail.com> * 🐛 fix: preserve file attachments when /newTopic has no text content * cleanup Signed-off-by: Innei <tukon479@gmail.com> --------- Signed-off-by: Innei <tukon479@gmail.com>
198 lines
5.4 KiB
TypeScript
198 lines
5.4 KiB
TypeScript
import react from '@vitejs/plugin-react';
|
|
import { codeInspectorPlugin } from 'code-inspector-plugin';
|
|
import { nodePolyfills } from 'vite-plugin-node-polyfills';
|
|
import tsconfigPaths from 'vite-tsconfig-paths';
|
|
|
|
import { viteEmotionSpeedy } from './emotionSpeedy';
|
|
import { viteNodeModuleStub } from './nodeModuleStub';
|
|
import { vitePlatformResolve } from './platformResolve';
|
|
|
|
/**
|
|
* Shared manualChunks — groups leaf-node modules to reduce chunk file count.
|
|
* Only targets pure data modules (no downstream dependents) to avoid facade chunk issues.
|
|
*/
|
|
/** Large i18n namespaces that get their own per-locale chunk instead of merging into the locale bundle */
|
|
const HEAVY_NS = new Set(['models', 'modelProvider']);
|
|
|
|
/** antd locale filename → app locale */
|
|
const ANTD_LOCALE: Record<string, string> = {
|
|
ar_EG: 'ar',
|
|
bg_BG: 'bg-BG',
|
|
de_DE: 'de-DE',
|
|
en_US: 'en-US',
|
|
es_ES: 'es-ES',
|
|
fa_IR: 'fa-IR',
|
|
fr_FR: 'fr-FR',
|
|
it_IT: 'it-IT',
|
|
ja_JP: 'ja-JP',
|
|
ko_KR: 'ko-KR',
|
|
nl_NL: 'nl-NL',
|
|
pl_PL: 'pl-PL',
|
|
pt_BR: 'pt-BR',
|
|
ru_RU: 'ru-RU',
|
|
tr_TR: 'tr-TR',
|
|
vi_VN: 'vi-VN',
|
|
zh_CN: 'zh-CN',
|
|
zh_TW: 'zh-TW',
|
|
};
|
|
|
|
/** dayjs locale filename → app locale */
|
|
const DAYJS_LOCALE: Record<string, string> = {
|
|
'ar': 'ar',
|
|
'bg': 'bg-BG',
|
|
'de': 'de-DE',
|
|
'en': 'en-US',
|
|
'es': 'es-ES',
|
|
'fa': 'fa-IR',
|
|
'fr': 'fr-FR',
|
|
'it': 'it-IT',
|
|
'ja': 'ja-JP',
|
|
'ko': 'ko-KR',
|
|
'nl': 'nl-NL',
|
|
'pl': 'pl-PL',
|
|
'pt-br': 'pt-BR',
|
|
'ru': 'ru-RU',
|
|
'tr': 'tr-TR',
|
|
'vi': 'vi-VN',
|
|
'zh-cn': 'zh-CN',
|
|
'zh-tw': 'zh-TW',
|
|
};
|
|
|
|
function sharedManualChunks(id: string): string | undefined {
|
|
// i18n locale JSON/TS files
|
|
const localeMatch = id.match(/\/locales\/([^/]+)\/([^/.]+)/);
|
|
if (localeMatch) {
|
|
const [, locale, ns] = localeMatch;
|
|
if (locale === 'default') return 'i18n-default';
|
|
if (HEAVY_NS.has(ns)) return `i18n-${locale}-${ns}`;
|
|
return `i18n-${locale}`;
|
|
}
|
|
|
|
// model-bank (monorepo package — split before node_modules guard)
|
|
if (id.includes('model-bank')) return 'providerConfig';
|
|
|
|
if (!id.includes('node_modules')) return;
|
|
|
|
// antd locale → merge into i18n-{locale}
|
|
const antdMatch = id.match(/antd\/es\/locale\/([^/.]+)\.js/);
|
|
if (antdMatch) {
|
|
const locale = ANTD_LOCALE[antdMatch[1]];
|
|
if (locale) return `i18n-${locale}`;
|
|
}
|
|
|
|
// dayjs locale → merge into i18n-{locale}
|
|
const dayjsMatch = id.match(/dayjs\/locale\/([^/.]+)\.js/);
|
|
if (dayjsMatch) {
|
|
const locale = DAYJS_LOCALE[dayjsMatch[1]];
|
|
if (locale) return `i18n-${locale}`;
|
|
}
|
|
|
|
// Lucide icons
|
|
if (id.includes('lucide-react')) return 'vendor-icons';
|
|
|
|
// es-toolkit
|
|
if (id.includes('es-toolkit')) return 'vendor-es-toolkit';
|
|
|
|
// emotion (CSS-in-JS runtime)
|
|
if (id.includes('@emotion/')) return 'vendor-emotion';
|
|
|
|
// motion (framer-motion)
|
|
if (id.includes('/motion/') || id.includes('framer-motion')) return 'vendor-motion';
|
|
}
|
|
|
|
export const sharedRollupOutput = {
|
|
chunkFileNames: (chunkInfo: { name: string }) => {
|
|
const { name } = chunkInfo;
|
|
if (name.startsWith('i18n-')) return 'i18n/[name]-[hash].js';
|
|
if (name.startsWith('vendor-')) return 'vendor/[name]-[hash].js';
|
|
return 'assets/[name]-[hash].js';
|
|
},
|
|
manualChunks: sharedManualChunks,
|
|
};
|
|
|
|
type Platform = 'web' | 'mobile' | 'desktop';
|
|
|
|
const isDev = process.env.NODE_ENV !== 'production';
|
|
|
|
interface SharedRendererOptions {
|
|
platform: Platform;
|
|
tsconfigPaths?: boolean;
|
|
}
|
|
|
|
export function sharedRendererPlugins(options: SharedRendererOptions) {
|
|
const defaultTsconfigPaths = options.tsconfigPaths ?? true;
|
|
return [
|
|
viteEmotionSpeedy(),
|
|
nodePolyfills({ include: ['buffer'] }),
|
|
viteNodeModuleStub(),
|
|
vitePlatformResolve(options.platform),
|
|
defaultTsconfigPaths && tsconfigPaths({ projects: ['.'] }),
|
|
isDev &&
|
|
codeInspectorPlugin({
|
|
bundler: 'vite',
|
|
exclude: [/\.(css|json)$/],
|
|
hotKeys: ['altKey', 'ctrlKey'],
|
|
}),
|
|
react(),
|
|
];
|
|
}
|
|
|
|
export function sharedRendererDefine(options: { isElectron: boolean; isMobile: boolean }) {
|
|
const nextPublicDefine = Object.fromEntries(
|
|
Object.entries(process.env)
|
|
.filter(([key]) => key.toUpperCase().startsWith('NEXT_PUBLIC_'))
|
|
.map(([key, value]) => [`process.env.${key}`, JSON.stringify(value)]),
|
|
);
|
|
|
|
return {
|
|
'__CI__': process.env.CI === 'true' ? 'true' : 'false',
|
|
'__DEV__': process.env.NODE_ENV !== 'production' ? 'true' : 'false',
|
|
'__ELECTRON__': JSON.stringify(options.isElectron),
|
|
'__MOBILE__': JSON.stringify(options.isMobile),
|
|
...nextPublicDefine,
|
|
// Keep a safe fallback so generic `process.env` access won't crash in browser runtime.
|
|
'process.env': '{}',
|
|
};
|
|
}
|
|
|
|
export const sharedOptimizeDeps = {
|
|
include: [
|
|
'react',
|
|
'react-dom',
|
|
'react-dom/client',
|
|
'react-router-dom',
|
|
'antd',
|
|
'@ant-design/icons',
|
|
'@lobehub/ui',
|
|
'@lobehub/ui > @emotion/react',
|
|
'antd-style',
|
|
'zustand',
|
|
'zustand/middleware',
|
|
'swr',
|
|
'i18next',
|
|
'react-i18next',
|
|
'dayjs',
|
|
'dayjs/esm/locale/ar',
|
|
'dayjs/esm/locale/bg',
|
|
'dayjs/esm/locale/de',
|
|
'dayjs/esm/locale/en',
|
|
'dayjs/esm/locale/es',
|
|
'dayjs/esm/locale/fa',
|
|
'dayjs/esm/locale/fr',
|
|
'dayjs/esm/locale/it',
|
|
'dayjs/esm/locale/ja',
|
|
'dayjs/esm/locale/ko',
|
|
'dayjs/esm/locale/nl',
|
|
'dayjs/esm/locale/pl',
|
|
'dayjs/esm/locale/pt-br',
|
|
'dayjs/esm/locale/ru',
|
|
'dayjs/esm/locale/tr',
|
|
'dayjs/esm/locale/vi',
|
|
'dayjs/esm/locale/zh-cn',
|
|
'dayjs/esm/locale/zh-tw',
|
|
|
|
'ahooks',
|
|
'motion/react',
|
|
],
|
|
};
|