create-pardx-scaffold 0.1.8 → 0.1.9

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-pardx-scaffold",
3
- "version": "0.1.8",
3
+ "version": "0.1.9",
4
4
  "description": "Scaffold a new project from PardxAI monorepo (git-tracked files)",
5
5
  "license": "MIT",
6
6
  "bin": "./cli.js",
@@ -1,6 +1,5 @@
1
1
  app:
2
2
  name: 'pardx'
3
- ChineseName: 'Pardx'
4
3
  version: '2.1.0'
5
4
  apiVersion: '1' # API 版本号
6
5
  minClientVersion: '0.0.1' # 最低兼容前端版本
@@ -11,17 +10,9 @@ app:
11
10
  MaxPageSize: 500
12
11
  defaultPageSize: 100
13
12
  defaultMiniPageSize: 30
14
- canCreateTrail: true
15
13
  defaultVendor: 'tos'
16
14
  defaultBucketPublic: false
17
- enableRetryMechanism: true
18
- enableEnhancedLogging: true
19
- maxRetries: 3
20
- baseRetryDelay: 1000
21
15
  nestLogOutput: 'both'
22
- audioTranscribe:
23
- statusUpdateMode: 'polling'
24
- pollingInterval: 30
25
16
  zones:
26
17
  - zone: 'cn'
27
18
  locale: 'zh-CN'
@@ -29,9 +20,6 @@ app:
29
20
  defaultPublicBucket: 'tos-pardx-files'
30
21
  transcodeBucket: 'tos-pardx-files'
31
22
 
32
- uploadConfig:
33
- chrunkSize: 8388608 #1024 * 1024 * 8
34
-
35
23
  ipinfo:
36
24
  url: 'https://ipinfo.io'
37
25
  token: 'f23c2d43721815'
@@ -107,9 +95,6 @@ rateLimit:
107
95
  userIds: [] # 管理员用户 ID
108
96
  apiKeys: [] # 内部服务 API Key
109
97
 
110
- pinecone:
111
- apiKey: 'cd14c373-cf91-4857-bdba-8384386193d5'
112
-
113
98
  # jwt 配置
114
99
  jwt:
115
100
  secret: '0EHAmnd9i82n'
@@ -150,18 +135,9 @@ redis:
150
135
  - name: 'shortCode'
151
136
  key: 'pardx:shortCode:'
152
137
  expireIn: -1
153
- - name: 'dailyQuestion'
154
- key: 'pardx:daily-question:'
155
- expireIn: 86400 # 24小时 (每天过期)
156
- - name: 'checkInStatus'
157
- key: 'pardx:check-in-status:'
158
- expireIn: 86400 # 24小时 (每天过期)
159
138
  - name: 'emailCodeDevice'
160
139
  key: 'pardx:emailCode:device:'
161
140
  expireIn: 180 # 3分钟
162
- - name: 'emailCodeEmail'
163
- key: 'pardx:emailCode:Email:'
164
- expireIn: 180 # 3分钟
165
141
  - name: 'emailCodePerDay'
166
142
  key: 'pardx:emailCode:EmailNumPerDay:'
167
143
  expireIn: 86400
@@ -179,93 +155,29 @@ redis:
179
155
  - name: 'subscription'
180
156
  key: 'pardx:subscription:'
181
157
  expireIn: 600 # 10分钟
182
- - name: 'subscriptionList'
183
- key: 'pardx:subscription:list:'
184
- expireIn: 300 # 5分钟(列表缓存时间较短,保证数据新鲜度)
185
- - name: 'notificationList'
186
- key: 'pardx:notification:list:'
187
- expireIn: 300 # 5分钟(通知列表缓存时间较短,保证数据新鲜度)
188
- - name: 'notificationStats'
189
- key: 'pardx:notification:stats:'
190
- expireIn: 60 # 1分钟(统计数据更新频繁,缓存时间更短)
191
158
  - name: 'privateDownloadUrl'
192
159
  key: 'pardx:file:fileurl:'
193
160
  expireIn: 30 #1小时
194
161
  - name: 'ipinfo'
195
162
  key: 'pardx:ipinfo:ip:'
196
163
  expireIn: 2592000 #30天
197
- - name: 'transferSaveForlder'
198
- key: 'pardx:transferSave:folderIds:'
199
- expireIn: 86400
200
- - name: 'recycleBinTask'
201
- key: 'pardx:recycleTask:fileSystemIds:'
202
- expireIn: 86400
203
- - name: 'moveFolder'
204
- key: 'pardx:moveFolder:folderIds:'
205
- expireIn: 86400
206
- # Long-term Memory System Cache (长期记忆系统缓存)
207
- - name: 'userPreferences'
208
- key: 'pardx:memory:preferences:'
209
- expireIn: 300 # 5分钟 (参考 Python 最佳实践)
210
- - name: 'memoryStats'
211
- key: 'pardx:memory:stats:'
212
- expireIn: 300 # 5分钟
213
- - name: 'preferenceStats'
214
- key: 'pardx:memory:preferenceStats:'
215
- expireIn: 300 # 5分钟
216
- - name: 'processTaskIdList' # 正在处理的taskId
217
- key: 'pardx:processTaskList:taskId:'
218
- expireIn: 86400
219
- - name: 'taskFileList' # 正在处理的task里面剩余处理的fsIds
220
- key: 'pardx:taskFileList:fsIds:'
221
- expireIn: 86400
222
164
  # ========== 业务实体缓存 (用于 @Cacheable 装饰器) ==========
223
165
  - name: 'userInfo' # 用户信息缓存
224
166
  key: 'pardx:cache:user:'
225
167
  expireIn: 1800 # 30分钟,提升登录响应速度
226
- - name: 'spaceInfo' # 空间信息缓存
227
- key: 'pardx:cache:space:'
228
- expireIn: 1800 # 30分钟
229
- - name: 'planInfo' # 套餐信息缓存
230
- key: 'pardx:cache:plan:'
231
- expireIn: 300 # 5分钟,变更频率低,查询频繁
232
168
  - name: 'permissions' # 权限配置缓存
233
169
  key: 'pardx:cache:perm:'
234
170
  expireIn: 600 # 10分钟,基础配置,变更少
235
171
  - name: 'modulePermission' # 模块级权限缓存
236
172
  key: 'pardx:cache:modulePerm:'
237
173
  expireIn: 300 # 5分钟
238
- - name: 'userRole' # 用户角色缓存 (包含 baseRole)
239
- key: 'pardx:cache:userRole:'
240
- expireIn: 3600 # 1小时
241
- - name: 'userInfoCache' # 旧的用户缓存 (保持兼容)
242
- key: 'pardx:user:'
243
- expireIn: -1
244
174
  - name: 'systemTask'
245
175
  key: 'pardx:task:'
246
176
  expireIn: -1
247
- - name: 'stockTask'
248
- key: 'pardx:stockTask:'
249
- expireIn: 86400
250
- - name: 'systemTaskListenerLock'
251
- key: 'pardx:taskListener:'
252
- expireIn: 15
253
- - name: 'taskLock'
254
- key: 'pardx:tasks:'
255
- expireIn: 10
256
- - name: 'tradeCache'
257
- key: 'pardx:file:fileurl:'
258
- expireIn: 30 #30s
259
177
  - name: 'sseChannel'
260
178
  key: 'pardx:sseChannel:'
261
179
  expireIn: 86400
262
- - name: 'wxAccessToken'
263
- key: 'pardx:wx:accessToken:'
264
- expireIn: 7200
265
- - name: 'wxmpQrcode'
266
- key: 'pardx:wxmp:qrcode:'
267
- expireIn: 300
268
- # ⚠️ P2: 流式识别会话数据持久化(Redis)
180
+ # 流式识别会话数据持久化(Redis)
269
181
  - name: 'streamingAsrSession'
270
182
  key: 'pardx:streaming-asr:session:'
271
183
  expireIn: 7200 # 2小时(与会话最大时长一致)
@@ -23,7 +23,6 @@ export type {
23
23
  MicroServiceConfig,
24
24
  AppConfig,
25
25
  ZoneConfig,
26
- UploadConfig,
27
26
  IpInfoConfig,
28
27
  JwtConfig,
29
28
  CryptoConfig,
@@ -83,7 +82,6 @@ import type {
83
82
  MicroServiceConfig as MicroServiceConfigType,
84
83
  AppConfig as AppConfigType,
85
84
  ZoneConfig as ZoneConfigType,
86
- UploadConfig as UploadConfigType,
87
85
  IpInfoConfig as IpInfoConfigType,
88
86
  JwtConfig as JwtConfigType,
89
87
  CryptoConfig as CryptoConfigType,
@@ -195,9 +193,6 @@ export namespace PardxApp {
195
193
  /** @deprecated 使用 ZoneConfig from '../validation' */
196
194
  export type Zone = ZoneConfigType;
197
195
 
198
- /** @deprecated 使用 UploadConfig from '../validation' */
199
- export type Upload = UploadConfigType;
200
-
201
196
  /** @deprecated 使用 TranscodeConfig from '../validation' */
202
197
  export type Transcode = TranscodeConfigType;
203
198
 
@@ -35,7 +35,6 @@ export {
35
35
  microServiceSchema,
36
36
  appConfigSchema,
37
37
  zoneSchema,
38
- uploadConfigSchema,
39
38
  ipInfoConfigSchema,
40
39
  videoQualitySchema,
41
40
  jwtConfigSchema,
@@ -77,7 +76,6 @@ export type {
77
76
  MicroServiceConfig,
78
77
  AppConfig,
79
78
  ZoneConfig,
80
- UploadConfig,
81
79
  IpInfoConfig,
82
80
  JwtConfig,
83
81
  CryptoConfig,
@@ -43,46 +43,18 @@ export const appConfigSchema = microServiceSchema.extend({
43
43
  MaxPageSize: z.number().int().positive().default(500),
44
44
  defaultPageSize: z.number().int().positive().default(100),
45
45
  defaultMiniPageSize: z.number().int().positive().default(30),
46
- canCreateTrail: z.boolean().default(true),
47
46
  defaultVendor: z
48
47
  .enum(['tos', 'oss', 'us3', 'qiniu', 'gcs', 's3'])
49
48
  .default('tos'),
50
49
  defaultBucketPublic: z.boolean().default(false),
51
50
 
52
- // S3 重试配置 (从 .env 迁移)
53
- enableRetryMechanism: z.boolean().default(true),
54
- enableEnhancedLogging: z.boolean().default(true),
55
- maxRetries: z.number().int().positive().default(3),
56
- baseRetryDelay: z.number().int().positive().default(1000),
57
-
58
51
  // 日志输出配置 (从 .env 迁移)
59
52
  nestLogOutput: z.enum(['console', 'file', 'both']).default('file'),
60
53
 
61
- // 音频转写状态更新模式配置
62
- audioTranscribe: z
63
- .object({
64
- /** 状态更新模式:webhook(回调)或 polling(轮询) */
65
- statusUpdateMode: z.enum(['webhook', 'polling']).default('webhook'),
66
- /** 轮询间隔(秒),仅在 polling 模式下有效 */
67
- pollingInterval: z.number().int().positive().default(30),
68
- })
69
- .optional()
70
- .default({
71
- statusUpdateMode: 'webhook',
72
- pollingInterval: 30,
73
- }),
74
-
75
54
  admin: microServiceSchema.optional(),
76
55
  zones: z.array(zoneSchema).min(1),
77
56
  });
78
57
 
79
- /**
80
- * Upload configuration schema
81
- */
82
- export const uploadConfigSchema = z.object({
83
- chrunkSize: z.number().int().positive().default(8388608), // 8MB
84
- });
85
-
86
58
  /**
87
59
  * IP info configuration schema
88
60
  */
@@ -411,11 +383,9 @@ export const rateLimitConfigSchema = z.object({
411
383
  */
412
384
  export const yamlConfigSchema = z.object({
413
385
  app: appConfigSchema,
414
- uploadConfig: uploadConfigSchema.optional(),
415
386
  ipinfo: ipInfoConfigSchema.optional(),
416
387
  outOfAnonymityPath: pathConfigSchema.optional(),
417
388
  outOfUserPath: pathConfigSchema.optional(),
418
- pinecone: z.object({ apiKey: z.string() }).optional(),
419
389
  jwt: jwtConfigSchema,
420
390
  crypto: cryptoConfigSchema,
421
391
  cdn: cdnConfigSchema.optional(),
@@ -444,9 +414,6 @@ export type AppConfig = z.infer<typeof appConfigSchema>;
444
414
  /** 区域配置类型 */
445
415
  export type ZoneConfig = z.infer<typeof zoneSchema>;
446
416
 
447
- /** 上传配置类型 */
448
- export type UploadConfig = z.infer<typeof uploadConfigSchema>;
449
-
450
417
  /** IP 信息配置类型 */
451
418
  export type IpInfoConfig = z.infer<typeof ipInfoConfigSchema>;
452
419
 
@@ -1,5 +1,5 @@
1
1
  # API 配置
2
- NEXT_PUBLIC_API_BASE_URL=http://localhost:13100/api
2
+ NEXT_PUBLIC_SERVER_BASE_URL=http://localhost:13100
3
3
 
4
4
  NEXT_PUBLIC_BRAND_NAME='Pardx.ai'
5
5
  NEXT_PUBLIC_BRAND_LOGO='/logo.svg'
@@ -1,17 +1,17 @@
1
1
  // API 配置
2
2
  // API 基础地址从环境变量读取
3
3
  // 在 .env.local 文件中设置以下环境变量:
4
- // - NEXT_PUBLIC_API_BASE_URL: 登录、上传文件、测评等接口的基础地址
4
+ // - NEXT_PUBLIC_SERVER_BASE_URL: 登录、上传文件、测评等接口的基础地址
5
5
 
6
6
  /**
7
- * 获取 API 基础地址(用于登录、上传文件、测评等)
7
+ * 获取 Server 基础地址(用于登录、上传文件、测评等)
8
8
  */
9
- const getApiBaseUrl = (): string => {
10
- const baseUrl = process.env.NEXT_PUBLIC_API_BASE_URL;
9
+ const getServerBaseUrl = (): string => {
10
+ const baseUrl = process.env.NEXT_PUBLIC_SERVER_BASE_URL;
11
11
 
12
12
  if (!baseUrl) {
13
13
  // Use default value during build time or development
14
- const defaultUrl = 'http://localhost:3100/api';
14
+ const defaultUrl = 'http://localhost:3100';
15
15
  if (
16
16
  process.env.NODE_ENV === 'development' ||
17
17
  process.env.NEXT_PHASE === 'phase-production-build'
@@ -19,7 +19,7 @@ const getApiBaseUrl = (): string => {
19
19
  return defaultUrl;
20
20
  }
21
21
  // At runtime in production, use default if not set
22
- console.warn('NEXT_PUBLIC_API_BASE_URL 未设置,使用默认值', defaultUrl);
22
+ console.warn('NEXT_PUBLIC_SERVER_BASE_URL 未设置,使用默认值', defaultUrl);
23
23
  return defaultUrl;
24
24
  }
25
25
 
@@ -78,7 +78,8 @@ const getBrandDescription = (): string => {
78
78
 
79
79
  export const API_CONFIG = {
80
80
  // API 基础地址(用于登录、上传文件、测评等)
81
- baseUrl: getApiBaseUrl(),
81
+ baseUrl: getServerBaseUrl() + '/api',
82
+ apiHealthUrl: getServerBaseUrl() + '/health',
82
83
 
83
84
  // API 端点路径 这些断点是不适用ts-rest-api的,用于登录和校验权限的断点,如果未来需要使用ts-rest-api,则将这些断点迁移到ts-rest-api中
84
85
  endpoints: {
@@ -29,8 +29,9 @@ import { useState, useEffect, useRef, useCallback } from 'react';
29
29
  import { useQueryClient } from '@tanstack/react-query';
30
30
  import { /*getToken,*/ ensureValidToken, isTokenExpired } from '@/lib/api';
31
31
  import { notificationKeys } from '@/lib/api/contracts/hooks/notification';
32
+ import { API_CONFIG } from '@/config';
32
33
 
33
- const API_BASE_URL = process.env.NEXT_PUBLIC_API_BASE_URL || '';
34
+ const API_BASE_URL = API_CONFIG.baseUrl;
34
35
 
35
36
  interface SSEMessage {
36
37
  t: 'm' | 'p'; // 'm' = message, 'p' = ping
@@ -25,6 +25,7 @@
25
25
  */
26
26
 
27
27
  import { useEffect, useRef, useCallback, useState } from 'react';
28
+ import { API_CONFIG } from '@/config';
28
29
 
29
30
  // ============================================================================
30
31
  // Types
@@ -93,7 +94,7 @@ export function useVersionCheck(options: UseVersionCheckOptions = {}) {
93
94
  checkInterval = 60000,
94
95
  autoRefresh = false,
95
96
  onVersionMismatch,
96
- apiBaseUrl = process.env.NEXT_PUBLIC_API_BASE_URL || '/api',
97
+ apiBaseUrl = API_CONFIG.baseUrl,
97
98
  enabled = true,
98
99
  } = options;
99
100
 
@@ -4,6 +4,7 @@
4
4
  */
5
5
 
6
6
  import { useEffect, useState } from 'react';
7
+ import { API_CONFIG } from '@/config';
7
8
 
8
9
  export interface PythonTaskResponse {
9
10
  taskId: string;
@@ -78,7 +79,7 @@ export function usePythonTask({
78
79
  useEffect(() => {
79
80
  if (!taskId) return;
80
81
 
81
- const apiBase = process.env.NEXT_PUBLIC_API_BASE_URL;
82
+ const apiBase = API_CONFIG.baseUrl;
82
83
  const eventSource = new EventSource(
83
84
  `${apiBase}/python-tasks/${taskId}/stream`,
84
85
  );
@@ -25,7 +25,8 @@ const log = {
25
25
  success: (msg) => console.log(`${colors.green}✓${colors.reset} ${msg}`),
26
26
  warning: (msg) => console.log(`${colors.yellow}⚠${colors.reset} ${msg}`),
27
27
  error: (msg) => console.log(`${colors.red}✗${colors.reset} ${msg}`),
28
- header: (msg) => console.log(`\n${colors.bright}${colors.cyan}${msg}${colors.reset}\n`),
28
+ header: (msg) =>
29
+ console.log(`\n${colors.bright}${colors.cyan}${msg}${colors.reset}\n`),
29
30
  };
30
31
 
31
32
  // Create readline interface
@@ -35,7 +36,8 @@ const rl = readline.createInterface({
35
36
  });
36
37
 
37
38
  // Promisify question
38
- const question = (query) => new Promise((resolve) => rl.question(query, resolve));
39
+ const question = (query) =>
40
+ new Promise((resolve) => rl.question(query, resolve));
39
41
 
40
42
  // Project configuration
41
43
  // 注意:API 端口在 apps/api/config.local.yaml 的 app.port 配置;Web 端口由 Next.js 自动配置,此处不配置
@@ -62,49 +64,53 @@ async function main() {
62
64
  try {
63
65
  // Collect project information
64
66
  config.projectName = await question(
65
- `${colors.cyan}Project name${colors.reset} (e.g., my-awesome-app): `
67
+ `${colors.cyan}Project name${colors.reset} (e.g., my-awesome-app): `,
66
68
  );
67
69
  config.projectName = config.projectName.trim() || 'my-project';
68
70
 
69
71
  config.projectDescription = await question(
70
- `${colors.cyan}Project description${colors.reset}: `
72
+ `${colors.cyan}Project description${colors.reset}: `,
71
73
  );
72
- config.projectDescription = config.projectDescription.trim() || 'A PardxAI monorepo project';
74
+ config.projectDescription =
75
+ config.projectDescription.trim() || 'A PardxAI monorepo project';
73
76
 
74
77
  config.authorName = await question(
75
- `${colors.cyan}Author name${colors.reset}: `
78
+ `${colors.cyan}Author name${colors.reset}: `,
76
79
  );
77
80
  config.authorName = config.authorName.trim() || 'Your Name';
78
81
 
79
82
  config.authorEmail = await question(
80
- `${colors.cyan}Author email${colors.reset}: `
83
+ `${colors.cyan}Author email${colors.reset}: `,
81
84
  );
82
85
  config.authorEmail = config.authorEmail.trim() || 'your.email@example.com';
83
86
 
84
87
  log.header('\n📦 Configuration');
85
88
 
86
89
  config.databaseUrl = await question(
87
- `${colors.cyan}Database URL${colors.reset} [postgresql://user:password@localhost:5432/dbname]: `
90
+ `${colors.cyan}Database URL${colors.reset} [postgresql://user:password@localhost:5432/dbname]: `,
88
91
  );
89
- config.databaseUrl = config.databaseUrl.trim() || 'postgresql://user:password@localhost:5432/dbname';
92
+ config.databaseUrl =
93
+ config.databaseUrl.trim() ||
94
+ 'postgresql://user:password@localhost:5432/dbname';
90
95
 
91
96
  config.readDatabaseUrl = await question(
92
- `${colors.cyan}Read Database URL${colors.reset} [same as Database URL]: `
97
+ `${colors.cyan}Read Database URL${colors.reset} [same as Database URL]: `,
93
98
  );
94
- config.readDatabaseUrl = config.readDatabaseUrl.trim() || config.databaseUrl;
99
+ config.readDatabaseUrl =
100
+ config.readDatabaseUrl.trim() || config.databaseUrl;
95
101
 
96
102
  config.redisUrl = await question(
97
- `${colors.cyan}Redis URL${colors.reset} [redis://localhost:6379]: `
103
+ `${colors.cyan}Redis URL${colors.reset} [redis://localhost:6379]: `,
98
104
  );
99
105
  config.redisUrl = config.redisUrl.trim() || 'redis://localhost:6379';
100
106
 
101
107
  config.rabbitmqUrl = await question(
102
- `${colors.cyan}RabbitMQ URL${colors.reset} [amqp://localhost:5672]: `
108
+ `${colors.cyan}RabbitMQ URL${colors.reset} [amqp://localhost:5672]: `,
103
109
  );
104
110
  config.rabbitmqUrl = config.rabbitmqUrl.trim() || 'amqp://localhost:5672';
105
111
 
106
112
  config.baseHost = await question(
107
- `${colors.cyan}Base Host${colors.reset} [127.0.0.1]: `
113
+ `${colors.cyan}Base Host${colors.reset} [127.0.0.1]: `,
108
114
  );
109
115
  config.baseHost = config.baseHost.trim() || '127.0.0.1';
110
116
 
@@ -112,9 +118,13 @@ async function main() {
112
118
 
113
119
  // Display configuration summary
114
120
  log.header('\n📋 Configuration Summary');
115
- console.log(` Project Name: ${colors.green}${config.projectName}${colors.reset}`);
121
+ console.log(
122
+ ` Project Name: ${colors.green}${config.projectName}${colors.reset}`,
123
+ );
116
124
  console.log(` Description: ${config.projectDescription}`);
117
- console.log(` Author: ${config.authorName} <${config.authorEmail}>`);
125
+ console.log(
126
+ ` Author: ${config.authorName} <${config.authorEmail}>`,
127
+ );
118
128
  console.log(` Base Host: ${config.baseHost}`);
119
129
  console.log(` Database: ${config.databaseUrl}`);
120
130
  console.log(` Read DB: ${config.readDatabaseUrl}`);
@@ -128,12 +138,19 @@ async function main() {
128
138
  // Success message
129
139
  log.header('\n✨ Project Initialized Successfully!');
130
140
  log.info('Next steps:');
131
- console.log(` 1. ${colors.cyan}pnpm install${colors.reset} - Install dependencies`);
132
- console.log(` 2. ${colors.cyan}pnpm db:generate${colors.reset} - Generate Prisma client`);
133
- console.log(` 3. ${colors.cyan}pnpm db:migrate:dev${colors.reset} - Run database migrations`);
134
- console.log(` 4. ${colors.cyan}pnpm dev${colors.reset} - Start development servers`);
141
+ console.log(
142
+ ` 1. ${colors.cyan}pnpm install${colors.reset} - Install dependencies`,
143
+ );
144
+ console.log(
145
+ ` 2. ${colors.cyan}pnpm db:generate${colors.reset} - Generate Prisma client`,
146
+ );
147
+ console.log(
148
+ ` 3. ${colors.cyan}pnpm db:migrate:dev${colors.reset} - Run database migrations`,
149
+ );
150
+ console.log(
151
+ ` 4. ${colors.cyan}pnpm dev${colors.reset} - Start development servers`,
152
+ );
135
153
  console.log('');
136
-
137
154
  } catch (error) {
138
155
  log.error(`Initialization failed: ${error.message}`);
139
156
  process.exit(1);
@@ -248,7 +265,8 @@ function createEnvFromExample(rootDir, config) {
248
265
  } else if (val === undefined) {
249
266
  val = null;
250
267
  }
251
- const final = val !== null && val !== undefined ? `${item.key}=${val}` : item.raw;
268
+ const final =
269
+ val !== null && val !== undefined ? `${item.key}=${val}` : item.raw;
252
270
  outLines.push(final);
253
271
  }
254
272
  }
@@ -258,7 +276,10 @@ function createEnvFromExample(rootDir, config) {
258
276
  // 追加 JWT_SECRET(若 .env.example 中无)
259
277
  const apiEnvContent = fs.readFileSync(apiEnvPath, 'utf8');
260
278
  if (!/^JWT_SECRET=/m.test(apiEnvContent)) {
261
- fs.appendFileSync(apiEnvPath, `\n# JWT\nJWT_SECRET=${generateRandomSecret()}\nJWT_EXPIRES_IN=7d\n`);
279
+ fs.appendFileSync(
280
+ apiEnvPath,
281
+ `\n# JWT\nJWT_SECRET=${generateRandomSecret()}\nJWT_EXPIRES_IN=7d\n`,
282
+ );
262
283
  }
263
284
  } else {
264
285
  createEnvFile(path.join(rootDir, 'apps/api/.env'), {
@@ -270,7 +291,6 @@ function createEnvFromExample(rootDir, config) {
270
291
  });
271
292
  }
272
293
 
273
- // apps/web:NEXT_PUBLIC_API_BASE_URL 等由 .env.example 提供,Next.js 端口自动配置,此处不覆盖
274
294
  const webReplacements = {};
275
295
 
276
296
  if (fs.existsSync(webExamplePath)) {
@@ -288,7 +308,7 @@ function createEnvFromExample(rootDir, config) {
288
308
  }
289
309
  fs.writeFileSync(
290
310
  path.join(rootDir, 'apps/web/.env.local'),
291
- outLines.join('\n') + '\n'
311
+ outLines.join('\n') + '\n',
292
312
  );
293
313
  } else {
294
314
  createEnvFile(path.join(rootDir, 'apps/web/.env.local'), {});
@@ -296,9 +316,10 @@ function createEnvFromExample(rootDir, config) {
296
316
  }
297
317
 
298
318
  function createEnvFile(filePath, variables) {
299
- const content = Object.entries(variables)
300
- .map(([key, value]) => `${key}=${value}`)
301
- .join('\n') + '\n';
319
+ const content =
320
+ Object.entries(variables)
321
+ .map(([key, value]) => `${key}=${value}`)
322
+ .join('\n') + '\n';
302
323
  fs.writeFileSync(filePath, content);
303
324
  }
304
325
 
@@ -309,10 +330,13 @@ function updateReadme(filePath) {
309
330
  }
310
331
 
311
332
  let content = fs.readFileSync(filePath, 'utf8');
312
- content = content.replace(/# PardxAI Monorepo Scaffold[^\n]*/, `# ${config.projectName}`);
333
+ content = content.replace(
334
+ /# PardxAI Monorepo Scaffold[^\n]*/,
335
+ `# ${config.projectName}`,
336
+ );
313
337
  content = content.replace(
314
338
  /A comprehensive production-ready monorepo scaffold with complete implementations\./,
315
- config.projectDescription
339
+ config.projectDescription,
316
340
  );
317
341
  fs.writeFileSync(filePath, content);
318
342
  }
@@ -1,163 +0,0 @@
1
- // API 配置
2
- // API 基础地址从环境变量读取
3
- // 在 .env.local 文件中设置以下环境变量:
4
- // - NEXT_PUBLIC_API_BASE_URL: 登录、上传文件、测评等接口的基础地址
5
- // - NEXT_PUBLIC_AGUI_API_BASE_URL: Agno 相关接口的基础地址
6
- // - NEXT_PUBLIC_AGUI_API_BASE_URL: AgUI 相关接口的基础地址
7
-
8
- /**
9
- * 获取 API 基础地址(用于登录、上传文件、测评等)
10
- */
11
- const getApiBaseUrl = (): string => {
12
- const baseUrl = process.env.NEXT_PUBLIC_API_BASE_URL;
13
-
14
- if (!baseUrl) {
15
- // Use default value during build time or development
16
- const defaultUrl = 'http://localhost:3100/api';
17
- if (
18
- process.env.NODE_ENV === 'development' ||
19
- process.env.NEXT_PHASE === 'phase-production-build'
20
- ) {
21
- return defaultUrl;
22
- }
23
- // At runtime in production, use default if not set
24
- console.warn('NEXT_PUBLIC_API_BASE_URL 未设置,使用默认值', defaultUrl);
25
- return defaultUrl;
26
- }
27
-
28
- return baseUrl;
29
- };
30
-
31
- /**
32
- * 获取 Agno API 基础地址
33
- */
34
- const getAgnoApiBaseUrl = (): string => {
35
- const baseUrl = process.env.NEXT_PUBLIC_AGUI_API_BASE_URL;
36
-
37
- if (!baseUrl) {
38
- // Use default value during build time or development
39
- const defaultUrl = 'http://127.0.0.1:8000/api';
40
- // At runtime in production, use default if not set
41
- console.warn(
42
- 'NEXT_PUBLIC_AGUI_API_BASE_URL 未设置,使用默认值',
43
- defaultUrl,
44
- );
45
- return defaultUrl;
46
- }
47
-
48
- return baseUrl;
49
- };
50
-
51
- /**
52
- * 获取 AgUI 基础地址
53
- */
54
- const getAguiBaseUrl = (): string => {
55
- const baseUrl = process.env.NEXT_PUBLIC_AGUI_API_BASE_URL;
56
-
57
- if (!baseUrl) {
58
- // Use default value during build time or development
59
- const defaultUrl = 'http://127.0.0.1:8000/api/agui';
60
- // At runtime in production, use default if not set
61
- console.warn(
62
- 'NEXT_PUBLIC_AGUI_API_BASE_URL 未设置,使用默认值',
63
- defaultUrl,
64
- );
65
- return defaultUrl;
66
- }
67
-
68
- return baseUrl + '/agui';
69
- };
70
-
71
- /**
72
- * 获取品牌名称
73
- */
74
- const getBrandName = (): string => {
75
- const brandName = process.env.NEXT_PUBLIC_BRAND_NAME;
76
- return brandName || 'Pardx.AI';
77
- };
78
-
79
- /**
80
- * 获取品牌 Logo 路径
81
- */
82
- const getBrandLogo = (): string => {
83
- const brandLogo = process.env.NEXT_PUBLIC_BRAND_LOGO;
84
- return brandLogo || '/logo.svg';
85
- };
86
-
87
- /**
88
- * 获取品牌完整标题(用于页面标题)
89
- *
90
- * 产品定位:多智能体驱动的内容创作与运营平台
91
- * 核心能力:
92
- * - AI 内容创作(智能写作、创意生成)
93
- * - 知识库管理(进化型知识库、智能提取、质量评估)
94
- * - 智能推荐(向量检索、协同过滤)
95
- * - 招聘面试(AI 招聘 Agent、简历解析、智能匹配)
96
- * - 会议管理(实时转写、知识提取、纪要生成)
97
- * - 多智能体协作(AG-UI/Agno)
98
- */
99
- const getBrandTitle = (): string => {
100
- const brandTitle = process.env.NEXT_PUBLIC_BRAND_TITLE;
101
- return brandTitle || 'PardxAI - Multi-Agent Content Creation ';
102
- };
103
-
104
- /**
105
- * 获取品牌描述(用于页面描述)
106
- *
107
- * 描述应包含:
108
- * - 产品定位(多智能体平台)
109
- * - 核心功能(内容创作、知识管理、智能推荐、招聘面试)
110
- * - 技术优势(AI 驱动、多智能体协作)
111
- * - 目标用户(企业团队、内容创作者、HR 团队)
112
- */
113
- const getBrandDescription = (): string => {
114
- const brandDescription = process.env.NEXT_PUBLIC_BRAND_DESCRIPTION;
115
- return (
116
- brandDescription ||
117
- 'PardxAI is an AI-powered multi-agent platform for content creation.'
118
- );
119
- };
120
-
121
- export const API_CONFIG = {
122
- // API 基础地址(用于登录、上传文件、测评等)
123
- baseUrl: getApiBaseUrl(),
124
-
125
- // Agno API 基础地址
126
- agnoApiBaseUrl: getAgnoApiBaseUrl(),
127
-
128
- // AgUI 基础地址
129
- aguiBaseUrl: getAguiBaseUrl(),
130
-
131
- // API 端点路径 这些断点是不适用ts-rest-api的,用于登录和校验权限的断点,如果未来需要使用ts-rest-api,则将这些断点迁移到ts-rest-api中
132
- endpoints: {
133
- // 登录端点
134
- login: '/sign/in/mobile/password',
135
-
136
- // Token 刷新端点
137
- refreshToken: '/sign/refresh/token',
138
- },
139
- };
140
-
141
- /**
142
- * 品牌配置
143
- * 可通过环境变量覆盖:
144
- * - NEXT_PUBLIC_BRAND_NAME: 品牌名称(默认: "Pardx.AI")
145
- * - NEXT_PUBLIC_BRAND_LOGO: Logo 路径(默认: "/logo.svg")
146
- * - NEXT_PUBLIC_BRAND_TITLE: 页面标题(默认: "PardxAI - Multi-Agent Content Creation")
147
- * - NEXT_PUBLIC_BRAND_DESCRIPTION: 页面描述(默认: "PardxAI is an AI-powered multi-agent platform for content creation.")
148
- *
149
- * 产品定位说明:
150
- * PardxAI 是一个多智能体驱动的内容创作与运营平台,提供以下核心能力:
151
- * 1. AI 内容创作:智能写作、创意生成、多模态内容创作
152
- * 2. 知识库管理:进化型知识库系统、智能知识提取、质量评估、版本控制、相似度检测与合并
153
- * 3. 智能推荐:基于向量检索和协同过滤的知识推荐系统
154
- * 4. 招聘面试:AI 招聘 Agent、简历解析、JD 分析、人才匹配、智能面试
155
- * 5. 会议管理:实时转写、知识提取、智能纪要生成
156
- * 6. 多智能体协作:AG-UI/Agno 集成,支持多智能体协同工作
157
- */
158
- export const BRAND_CONFIG = {
159
- name: getBrandName(),
160
- logo: getBrandLogo(),
161
- title: getBrandTitle(),
162
- description: getBrandDescription(),
163
- };