From 78e41a65b5b87de125f23105457a756b8b0b189e Mon Sep 17 00:00:00 2001 From: digua Date: Tue, 19 May 2026 21:33:00 +0800 Subject: [PATCH] refactor: migrate CLI from packages/server to apps/cli Move the CLI application from packages/server/ to apps/cli/ to align with the monorepo convention (apps/ for deployable applications, packages/ for shared libraries). Rename package to @openchatlab/chatlab. Also fix a bug in ensureToken() that used raw string manipulation to write config.toml, causing duplicate token fields that corrupted the TOML file. This led to config parse failures and user_data_dir being overwritten with defaults. Now uses writeConfigField() for safe writes. --- .gitignore | 2 +- {packages/server => apps/cli}/bin/chatlab.js | 4 +- {packages/server => apps/cli}/package.json | 2 +- .../cli}/scripts/ensure-native.mjs | 0 .../cli}/scripts/ensure-native.test.mjs | 4 +- .../cli}/scripts/rebuild-native.sh | 2 +- {packages/server => apps/cli}/src/ai/agent.ts | 0 .../cli}/src/ai/assistant-loader.ts | 0 .../cli}/src/ai/custom-store.ts | 0 .../server => apps/cli}/src/ai/llm-config.ts | 0 .../server => apps/cli}/src/ai/logger.ts | 0 .../cli}/src/ai/manager-factory.ts | 0 .../server => apps/cli}/src/ai/remote-api.ts | 0 .../cli}/src/ai/tool-adapter.ts | 0 {packages/server => apps/cli}/src/cli.ts | 0 .../server => apps/cli}/src/http/auth.ts | 0 .../server => apps/cli}/src/http/errors.ts | 0 .../server => apps/cli}/src/http/index.ts | 18 +--- .../server => apps/cli}/src/http/routes/ai.ts | 0 .../cli}/src/http/routes/nlp.ts | 0 .../cli}/src/http/routes/sessions.ts | 0 .../cli}/src/http/routes/system.ts | 0 .../cli}/src/http/routes/web.ts | 0 .../server => apps/cli}/src/http/server.ts | 0 .../cli}/src/import/chatlab-reader.ts | 0 .../cli}/src/import/importer.ts | 0 .../server => apps/cli}/src/import/index.ts | 0 .../cli}/src/import/stream-import.ts | 0 {packages/server => apps/cli}/src/index.ts | 0 {packages/server => apps/cli}/src/mcp.ts | 0 .../cli}/src/merger/merge-cache.ts | 0 .../server => apps/cli}/src/sync/adapters.ts | 0 .../server => apps/cli}/src/sync/index.ts | 0 .../server => apps/cli}/src/sync/routes.ts | 0 apps/cli/tsconfig.json | 17 ++++ apps/desktop/tsconfig.node.json | 2 +- package.json | 2 +- pnpm-lock.yaml | 86 +++++++++---------- scripts/dev-serve.sh | 2 +- vite.web.config.mts | 2 +- 40 files changed, 74 insertions(+), 69 deletions(-) rename {packages/server => apps/cli}/bin/chatlab.js (69%) rename {packages/server => apps/cli}/package.json (96%) rename {packages/server => apps/cli}/scripts/ensure-native.mjs (100%) rename {packages/server => apps/cli}/scripts/ensure-native.test.mjs (89%) rename {packages/server => apps/cli}/scripts/rebuild-native.sh (95%) rename {packages/server => apps/cli}/src/ai/agent.ts (100%) rename {packages/server => apps/cli}/src/ai/assistant-loader.ts (100%) rename {packages/server => apps/cli}/src/ai/custom-store.ts (100%) rename {packages/server => apps/cli}/src/ai/llm-config.ts (100%) rename {packages/server => apps/cli}/src/ai/logger.ts (100%) rename {packages/server => apps/cli}/src/ai/manager-factory.ts (100%) rename {packages/server => apps/cli}/src/ai/remote-api.ts (100%) rename {packages/server => apps/cli}/src/ai/tool-adapter.ts (100%) rename {packages/server => apps/cli}/src/cli.ts (100%) rename {packages/server => apps/cli}/src/http/auth.ts (100%) rename {packages/server => apps/cli}/src/http/errors.ts (100%) rename {packages/server => apps/cli}/src/http/index.ts (88%) rename {packages/server => apps/cli}/src/http/routes/ai.ts (100%) rename {packages/server => apps/cli}/src/http/routes/nlp.ts (100%) rename {packages/server => apps/cli}/src/http/routes/sessions.ts (100%) rename {packages/server => apps/cli}/src/http/routes/system.ts (100%) rename {packages/server => apps/cli}/src/http/routes/web.ts (100%) rename {packages/server => apps/cli}/src/http/server.ts (100%) rename {packages/server => apps/cli}/src/import/chatlab-reader.ts (100%) rename {packages/server => apps/cli}/src/import/importer.ts (100%) rename {packages/server => apps/cli}/src/import/index.ts (100%) rename {packages/server => apps/cli}/src/import/stream-import.ts (100%) rename {packages/server => apps/cli}/src/index.ts (100%) rename {packages/server => apps/cli}/src/mcp.ts (100%) rename {packages/server => apps/cli}/src/merger/merge-cache.ts (100%) rename {packages/server => apps/cli}/src/sync/adapters.ts (100%) rename {packages/server => apps/cli}/src/sync/index.ts (100%) rename {packages/server => apps/cli}/src/sync/routes.ts (100%) create mode 100644 apps/cli/tsconfig.json diff --git a/.gitignore b/.gitignore index 9d2ff90c..8e0d9db3 100644 --- a/.gitignore +++ b/.gitignore @@ -18,7 +18,7 @@ error-log-*.txt # Project dist/ dist-web/ -packages/server/native/ +apps/cli/native/ .history/ out .obskey diff --git a/packages/server/bin/chatlab.js b/apps/cli/bin/chatlab.js similarity index 69% rename from packages/server/bin/chatlab.js rename to apps/cli/bin/chatlab.js index 5ca5a568..5624b8d0 100755 --- a/packages/server/bin/chatlab.js +++ b/apps/cli/bin/chatlab.js @@ -8,6 +8,6 @@ */ // 开发阶段占位,实际通过 package.json scripts 的 tsx 运行 -console.error('Please run via: npx tsx packages/server/src/cli.ts') -console.error('Or use: pnpm --filter chatlab dev') +console.error('Please run via: npx tsx apps/cli/src/cli.ts') +console.error('Or use: pnpm --filter @openchatlab/chatlab cli') process.exit(1) diff --git a/packages/server/package.json b/apps/cli/package.json similarity index 96% rename from packages/server/package.json rename to apps/cli/package.json index b641a77d..d1d488cd 100644 --- a/packages/server/package.json +++ b/apps/cli/package.json @@ -1,5 +1,5 @@ { - "name": "chatlab", + "name": "@openchatlab/chatlab", "version": "0.0.1", "private": true, "description": "ChatLab CLI & Service - 聊天记录分析工具", diff --git a/packages/server/scripts/ensure-native.mjs b/apps/cli/scripts/ensure-native.mjs similarity index 100% rename from packages/server/scripts/ensure-native.mjs rename to apps/cli/scripts/ensure-native.mjs diff --git a/packages/server/scripts/ensure-native.test.mjs b/apps/cli/scripts/ensure-native.test.mjs similarity index 89% rename from packages/server/scripts/ensure-native.test.mjs rename to apps/cli/scripts/ensure-native.test.mjs index 7a596c6a..aeab2701 100644 --- a/packages/server/scripts/ensure-native.test.mjs +++ b/apps/cli/scripts/ensure-native.test.mjs @@ -34,14 +34,14 @@ test('reports invalid native binding load failure', () => { }) test('reports valid native binding when it can be loaded by current Node', () => { - const nativePath = path.resolve('packages/server/native/better_sqlite3.node') + const nativePath = path.resolve('apps/cli/native/better_sqlite3.node') const status = getNativeStatus(nativePath) assert.equal(status.ok, true) assert.equal(status.reason, 'valid') }) test('prints status to stderr so CLI stdout stays machine-readable', () => { - const result = spawnSync(process.execPath, ['packages/server/scripts/ensure-native.mjs', '--check'], { + const result = spawnSync(process.execPath, ['apps/cli/scripts/ensure-native.mjs', '--check'], { encoding: 'utf8', }) diff --git a/packages/server/scripts/rebuild-native.sh b/apps/cli/scripts/rebuild-native.sh similarity index 95% rename from packages/server/scripts/rebuild-native.sh rename to apps/cli/scripts/rebuild-native.sh index 0836486b..871bb950 100755 --- a/packages/server/scripts/rebuild-native.sh +++ b/apps/cli/scripts/rebuild-native.sh @@ -3,7 +3,7 @@ # 在隔离目录中编译 better-sqlite3 的系统 Node.js 原生模块, # 避免与 electron-rebuild 产生冲突。 # -# 产物:packages/server/native/better_sqlite3.node +# 产物:apps/cli/native/better_sqlite3.node # set -e diff --git a/packages/server/src/ai/agent.ts b/apps/cli/src/ai/agent.ts similarity index 100% rename from packages/server/src/ai/agent.ts rename to apps/cli/src/ai/agent.ts diff --git a/packages/server/src/ai/assistant-loader.ts b/apps/cli/src/ai/assistant-loader.ts similarity index 100% rename from packages/server/src/ai/assistant-loader.ts rename to apps/cli/src/ai/assistant-loader.ts diff --git a/packages/server/src/ai/custom-store.ts b/apps/cli/src/ai/custom-store.ts similarity index 100% rename from packages/server/src/ai/custom-store.ts rename to apps/cli/src/ai/custom-store.ts diff --git a/packages/server/src/ai/llm-config.ts b/apps/cli/src/ai/llm-config.ts similarity index 100% rename from packages/server/src/ai/llm-config.ts rename to apps/cli/src/ai/llm-config.ts diff --git a/packages/server/src/ai/logger.ts b/apps/cli/src/ai/logger.ts similarity index 100% rename from packages/server/src/ai/logger.ts rename to apps/cli/src/ai/logger.ts diff --git a/packages/server/src/ai/manager-factory.ts b/apps/cli/src/ai/manager-factory.ts similarity index 100% rename from packages/server/src/ai/manager-factory.ts rename to apps/cli/src/ai/manager-factory.ts diff --git a/packages/server/src/ai/remote-api.ts b/apps/cli/src/ai/remote-api.ts similarity index 100% rename from packages/server/src/ai/remote-api.ts rename to apps/cli/src/ai/remote-api.ts diff --git a/packages/server/src/ai/tool-adapter.ts b/apps/cli/src/ai/tool-adapter.ts similarity index 100% rename from packages/server/src/ai/tool-adapter.ts rename to apps/cli/src/ai/tool-adapter.ts diff --git a/packages/server/src/cli.ts b/apps/cli/src/cli.ts similarity index 100% rename from packages/server/src/cli.ts rename to apps/cli/src/cli.ts diff --git a/packages/server/src/http/auth.ts b/apps/cli/src/http/auth.ts similarity index 100% rename from packages/server/src/http/auth.ts rename to apps/cli/src/http/auth.ts diff --git a/packages/server/src/http/errors.ts b/apps/cli/src/http/errors.ts similarity index 100% rename from packages/server/src/http/errors.ts rename to apps/cli/src/http/errors.ts diff --git a/packages/server/src/http/index.ts b/apps/cli/src/http/index.ts similarity index 88% rename from packages/server/src/http/index.ts rename to apps/cli/src/http/index.ts index 794f716d..b9565bfa 100644 --- a/packages/server/src/http/index.ts +++ b/apps/cli/src/http/index.ts @@ -9,7 +9,7 @@ import * as fs from 'fs' import * as path from 'path' import * as crypto from 'crypto' import type { FastifyInstance } from 'fastify' -import { loadConfig, getConfigDir, MigrationRunner, ALL_MIGRATIONS } from '@openchatlab/config' +import { loadConfig, writeConfigField, MigrationRunner, ALL_MIGRATIONS } from '@openchatlab/config' import type { ChatLabConfig } from '@openchatlab/config' import { NodePathProvider, DatabaseManager, AIConversationManager } from '@openchatlab/node-runtime' import { createServer } from './server' @@ -45,22 +45,10 @@ function ensureToken(config: ChatLabConfig): string { if (config.api.token) return config.api.token const token = `clb_${crypto.randomBytes(32).toString('hex')}` - const configDir = getConfigDir() - const configPath = path.join(configDir, 'config.toml') try { - let content = '' - if (fs.existsSync(configPath)) { - content = fs.readFileSync(configPath, 'utf-8') - } - if (!content.includes('[api]')) { - content += `\n[api]\ntoken = "${token}"\n` - } else { - content = content.replace(/\[api\]/, `[api]\ntoken = "${token}"`) - } - fs.mkdirSync(configDir, { recursive: true }) - fs.writeFileSync(configPath, content, 'utf-8') + writeConfigField('api', 'token', token) } catch { - // 写入失败时仍使用生成的 token 运行本次会话 + // best-effort: token still usable for this session } return token } diff --git a/packages/server/src/http/routes/ai.ts b/apps/cli/src/http/routes/ai.ts similarity index 100% rename from packages/server/src/http/routes/ai.ts rename to apps/cli/src/http/routes/ai.ts diff --git a/packages/server/src/http/routes/nlp.ts b/apps/cli/src/http/routes/nlp.ts similarity index 100% rename from packages/server/src/http/routes/nlp.ts rename to apps/cli/src/http/routes/nlp.ts diff --git a/packages/server/src/http/routes/sessions.ts b/apps/cli/src/http/routes/sessions.ts similarity index 100% rename from packages/server/src/http/routes/sessions.ts rename to apps/cli/src/http/routes/sessions.ts diff --git a/packages/server/src/http/routes/system.ts b/apps/cli/src/http/routes/system.ts similarity index 100% rename from packages/server/src/http/routes/system.ts rename to apps/cli/src/http/routes/system.ts diff --git a/packages/server/src/http/routes/web.ts b/apps/cli/src/http/routes/web.ts similarity index 100% rename from packages/server/src/http/routes/web.ts rename to apps/cli/src/http/routes/web.ts diff --git a/packages/server/src/http/server.ts b/apps/cli/src/http/server.ts similarity index 100% rename from packages/server/src/http/server.ts rename to apps/cli/src/http/server.ts diff --git a/packages/server/src/import/chatlab-reader.ts b/apps/cli/src/import/chatlab-reader.ts similarity index 100% rename from packages/server/src/import/chatlab-reader.ts rename to apps/cli/src/import/chatlab-reader.ts diff --git a/packages/server/src/import/importer.ts b/apps/cli/src/import/importer.ts similarity index 100% rename from packages/server/src/import/importer.ts rename to apps/cli/src/import/importer.ts diff --git a/packages/server/src/import/index.ts b/apps/cli/src/import/index.ts similarity index 100% rename from packages/server/src/import/index.ts rename to apps/cli/src/import/index.ts diff --git a/packages/server/src/import/stream-import.ts b/apps/cli/src/import/stream-import.ts similarity index 100% rename from packages/server/src/import/stream-import.ts rename to apps/cli/src/import/stream-import.ts diff --git a/packages/server/src/index.ts b/apps/cli/src/index.ts similarity index 100% rename from packages/server/src/index.ts rename to apps/cli/src/index.ts diff --git a/packages/server/src/mcp.ts b/apps/cli/src/mcp.ts similarity index 100% rename from packages/server/src/mcp.ts rename to apps/cli/src/mcp.ts diff --git a/packages/server/src/merger/merge-cache.ts b/apps/cli/src/merger/merge-cache.ts similarity index 100% rename from packages/server/src/merger/merge-cache.ts rename to apps/cli/src/merger/merge-cache.ts diff --git a/packages/server/src/sync/adapters.ts b/apps/cli/src/sync/adapters.ts similarity index 100% rename from packages/server/src/sync/adapters.ts rename to apps/cli/src/sync/adapters.ts diff --git a/packages/server/src/sync/index.ts b/apps/cli/src/sync/index.ts similarity index 100% rename from packages/server/src/sync/index.ts rename to apps/cli/src/sync/index.ts diff --git a/packages/server/src/sync/routes.ts b/apps/cli/src/sync/routes.ts similarity index 100% rename from packages/server/src/sync/routes.ts rename to apps/cli/src/sync/routes.ts diff --git a/apps/cli/tsconfig.json b/apps/cli/tsconfig.json new file mode 100644 index 00000000..748959f8 --- /dev/null +++ b/apps/cli/tsconfig.json @@ -0,0 +1,17 @@ +{ + "extends": "../../tsconfig.node.json", + "compilerOptions": { + "composite": true, + "noEmit": true + }, + "include": [ + "src/**/*.ts", + "../../packages/shared-types/**/*", + "../../packages/core/**/*", + "../../packages/node-runtime/**/*", + "../../packages/config/**/*", + "../../packages/parser/**/*", + "../../packages/tools/**/*", + "../../packages/sync/**/*" + ] +} diff --git a/apps/desktop/tsconfig.node.json b/apps/desktop/tsconfig.node.json index 2a692067..28984e5d 100644 --- a/apps/desktop/tsconfig.node.json +++ b/apps/desktop/tsconfig.node.json @@ -11,7 +11,7 @@ "../../packages/node-runtime/**/*", "../../packages/config/**/*", "../../packages/parser/**/*", - "../../packages/server/**/*", + "../../apps/cli/**/*", "../../packages/tools/**/*", "../../packages/sync/**/*" ], diff --git a/package.json b/package.json index 18803a4d..3efaa44a 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "dev:app": "vite --config vite.web.config.mts", "dev:serve": "bash scripts/dev-serve.sh", "dev:web": "pnpm run ensure:server-native && CHATLAB_AUTO_SERVE=1 vite --config vite.web.config.mts", - "ensure:server-native": "pnpm --filter chatlab run ensure-native", + "ensure:server-native": "pnpm --filter @openchatlab/chatlab run ensure-native", "build:web": "vite build --config vite.web.config.mts", "format": "prettier --write .", "lint": "eslint . --ext .js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index afaaa58e..066f7b5a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -88,6 +88,49 @@ importers: specifier: ^3.1.1 version: 3.2.6(typescript@5.9.3) + apps/cli: + dependencies: + '@fastify/multipart': + specifier: ^10.0.0 + version: 10.0.0 + '@fastify/static': + specifier: ^9.1.3 + version: 9.1.3 + '@modelcontextprotocol/sdk': + specifier: ^1.12.1 + version: 1.29.0(zod@3.25.76) + '@openchatlab/config': + specifier: workspace:* + version: link:../../packages/config + '@openchatlab/core': + specifier: workspace:* + version: link:../../packages/core + '@openchatlab/node-runtime': + specifier: workspace:* + version: link:../../packages/node-runtime + '@openchatlab/parser': + specifier: workspace:* + version: link:../../packages/parser + '@openchatlab/shared-types': + specifier: workspace:* + version: link:../../packages/shared-types + '@openchatlab/sync': + specifier: workspace:* + version: link:../../packages/sync + '@openchatlab/tools': + specifier: workspace:* + version: link:../../packages/tools + commander: + specifier: ^13.1.0 + version: 13.1.0 + fastify: + specifier: ^5.8.4 + version: 5.8.4 + devDependencies: + tsx: + specifier: ^4.21.0 + version: 4.21.0 + apps/desktop: dependencies: '@aptabase/electron': @@ -181,49 +224,6 @@ importers: specifier: ^1.7.8 version: 1.7.8 - packages/server: - dependencies: - '@fastify/multipart': - specifier: ^10.0.0 - version: 10.0.0 - '@fastify/static': - specifier: ^9.1.3 - version: 9.1.3 - '@modelcontextprotocol/sdk': - specifier: ^1.12.1 - version: 1.29.0(zod@3.25.76) - '@openchatlab/config': - specifier: workspace:* - version: link:../config - '@openchatlab/core': - specifier: workspace:* - version: link:../core - '@openchatlab/node-runtime': - specifier: workspace:* - version: link:../node-runtime - '@openchatlab/parser': - specifier: workspace:* - version: link:../parser - '@openchatlab/shared-types': - specifier: workspace:* - version: link:../shared-types - '@openchatlab/sync': - specifier: workspace:* - version: link:../sync - '@openchatlab/tools': - specifier: workspace:* - version: link:../tools - commander: - specifier: ^13.1.0 - version: 13.1.0 - fastify: - specifier: ^5.8.4 - version: 5.8.4 - devDependencies: - tsx: - specifier: ^4.21.0 - version: 4.21.0 - packages/shared-types: {} packages/sync: {} diff --git a/scripts/dev-serve.sh b/scripts/dev-serve.sh index e0140a64..8eb5f973 100755 --- a/scripts/dev-serve.sh +++ b/scripts/dev-serve.sh @@ -7,4 +7,4 @@ pnpm run ensure:server-native exec tsx watch \ --include 'packages/core/src/**' \ --include 'packages/node-runtime/src/**' \ - packages/server/src/cli.ts serve "$@" + apps/cli/src/cli.ts serve "$@" diff --git a/vite.web.config.mts b/vite.web.config.mts index e916d4c7..6bc40af2 100644 --- a/vite.web.config.mts +++ b/vite.web.config.mts @@ -50,7 +50,7 @@ function chatlabServePlugin(): Plugin { return } - const serverDir = resolve(__dirname, 'packages/server') + const serverDir = resolve(__dirname, 'apps/cli') const coreDir = resolve(__dirname, 'packages/core/src') const runtimeDir = resolve(__dirname, 'packages/node-runtime/src') serverProcess = spawn(