@coze-arch/cli 0.0.1-alpha.a1ca15 → 0.0.1-alpha.c49cb2

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.
@@ -2,6 +2,7 @@
2
2
  if [ -z "${BASH_VERSION:-}" ]; then exec /usr/bin/env bash "$0" "$@"; fi
3
3
  set -euo pipefail
4
4
  ROOT_DIR="$(pwd)"
5
+ PREVIEW_DIR="${COZE_PREVIEW_DIR:-$ROOT_DIR}"
5
6
  LOG_DIR="${COZE_LOG_DIR:-$ROOT_DIR/logs}"
6
7
  LOG_FILE="$LOG_DIR/app.log"
7
8
  mkdir -p "$LOG_DIR"
@@ -61,9 +62,9 @@ fs.closeSync(fd);
61
62
  write_log "INFO" "==================== 开始构建 ===================="
62
63
 
63
64
  write_log "INFO" "检查根目录 pre_install.py"
64
- if [ -f "$ROOT_DIR/pre_install.py" ]; then
65
- write_log "INFO" "执行:python $ROOT_DIR/pre_install.py"
66
- python "$ROOT_DIR/pre_install.py" || write_log "ERROR" "pre_install.py 执行失败"
65
+ if [ -f "$PREVIEW_DIR/pre_install.py" ]; then
66
+ write_log "INFO" "执行:python $PREVIEW_DIR/pre_install.py"
67
+ python "$PREVIEW_DIR/pre_install.py" || write_log "ERROR" "pre_install.py 执行失败"
67
68
  fi
68
69
 
69
70
  write_log "INFO" "开始执行构建脚本(build_dev.sh)..."
@@ -4,7 +4,7 @@ LOG_FILE="$LOG_DIR/app.log"
4
4
  mkdir -p "$LOG_DIR"
5
5
 
6
6
  # ==================== 配置项 ====================
7
- # Python 服务配置
7
+ # Server 服务配置
8
8
  SERVER_HOST="0.0.0.0"
9
9
  SERVER_PORT="9091"
10
10
  # Expo 项目配置
@@ -175,39 +175,15 @@ mkdir -p logs
175
175
  ensure_port SERVER_PORT "$SERVER_PORT"
176
176
  ensure_port EXPO_PORT "$EXPO_PORT"
177
177
 
178
- # ==================== 步骤 1:启动 Python 服务 ====================
179
-
180
- # ------------环境变量----------------------
181
- export storage_type="s3"
182
- export project_platform="app"
183
-
184
- if [ -n "${COZE_WORKLOAD_IDENTITY_API_KEY:-}" ]; then
185
- export OPENAI_API_KEY="$COZE_WORKLOAD_IDENTITY_API_KEY"
186
- fi
187
- if [ -n "${OPENAI_API_KEY:-}" ]; then
188
- export ARK_API_KEY="$OPENAI_API_KEY"
189
- fi
190
-
191
- if [ -n "${COZE_INTEGRATION_BASE_URL:-}" ]; then
192
- _base="${COZE_INTEGRATION_BASE_URL%/}"
193
- export default_llm_base_url="${_base}/api/v3"
178
+ # ==================== 启动 Server 服务 ====================
179
+ write_log "INFO" "检查 Nginx 端口 (5000)..."
180
+ if is_port_free 5000; then
181
+ write_log "INFO" "端口 5000 未被占用,正在启动 Nginx..."
182
+ service nginx start
194
183
  else
195
- export default_llm_base_url="https://ark.cn-beijing.volces.com/api/v3"
196
- fi
197
-
198
- if [ -n "${PGDATABASE_URL:-}" ]; then
199
- _pg="${PGDATABASE_URL}"
200
- case "${_pg}" in
201
- postgresql://*)
202
- _pg="postgresql+asyncpg://${_pg#postgresql://}"
203
- ;;
204
- esac
205
- _pg="${_pg%%\?*}"
206
- export DATABASE_URL="${_pg}"
184
+ write_log "INFO" "端口 5000 已被占用,跳过 Nginx 启动"
207
185
  fi
208
186
 
209
- # ------------环境变量----------------------
210
-
211
187
  write_log "INFO" "==================== 启动 server 服务 ===================="
212
188
  write_log "INFO" "正在执行:npm run server"
213
189
  PORT="$SERVER_PORT" nohup npm run server > logs/app.log 2>&1 &
@@ -227,7 +203,7 @@ if detect_expo_fetch_failed 8; then
227
203
  : > logs/expo.log
228
204
  EXPO_PID=$(start_expo 1)
229
205
  fi
230
- # 输出以下环境变量,确保 Expo 项目能正确连接到 Python 服务
206
+ # 输出以下环境变量,确保 Expo 项目能正确连接到 Server 服务
231
207
  write_log "INFO" "Expo 环境变量配置:"
232
208
  write_log "INFO" "EXPO_PUBLIC_BACKEND_BASE_URL=${EXPO_PUBLIC_BACKEND_BASE_URL}"
233
209
  write_log "INFO" "EXPO_PACKAGER_PROXY_URL=${EXPO_PACKAGER_PROXY_URL}"
@@ -260,12 +236,4 @@ if [ -f "$ROOT_DIR/post_run.py" ]; then
260
236
  write_log "INFO" "启动检查结束"
261
237
  fi
262
238
 
263
- write_log "INFO" "检查 Nginx 端口 (5000)..."
264
- if is_port_free 5000; then
265
- write_log "INFO" "端口 5000 未被占用,正在启动 Nginx..."
266
- service nginx start
267
- else
268
- write_log "INFO" "端口 5000 已被占用,跳过 Nginx 启动"
269
- fi
270
-
271
239
  write_log "INFO" "==================== 服务启动完成 ===================="
@@ -4,19 +4,15 @@
4
4
  *
5
5
  * 基于固定的 API 接口实现,可复用到其他项目
6
6
  * 其他项目使用时,只需修改 @api 的导入路径指向项目的 api 模块
7
+ *
8
+ * 注意:
9
+ * - 如果需要登录/鉴权场景,请扩展本文件,完善 login/logout、token 管理、用户信息获取与刷新等逻辑
10
+ * - 将示例中的占位实现替换为项目实际的接口调用与状态管理
7
11
  */
8
- import React, {
9
- createContext,
10
- useContext,
11
- useState,
12
- useEffect,
13
- ReactNode,
14
- } from "react";
15
- import AsyncStorage from "@react-native-async-storage/async-storage";
16
- //import { UserOut, UsersService, AuthenticationService } from "@api";
12
+ import React, { createContext, useContext, ReactNode } from "react";
17
13
 
18
14
  interface UserOut {
19
-
15
+
20
16
  }
21
17
 
22
18
  interface AuthContextType {
@@ -31,105 +27,16 @@ interface AuthContextType {
31
27
 
32
28
  const AuthContext = createContext<AuthContextType | undefined>(undefined);
33
29
 
34
- export const AuthProvider: React.FC<{ children: ReactNode }> = ({
35
- children,
36
- }) => {
37
- const [user, setUser] = useState<UserOut | null>(null);
38
- const [token, setToken] = useState<string | null>(null);
39
- const [isLoading, setIsLoading] = useState(true);
40
-
41
- useEffect(() => {
42
- loadAuthData();
43
- }, []);
44
-
45
- const loadAuthData = async () => {
46
- try {
47
- const results = await AsyncStorage.multiGet(["access_token", "user_data"]);
48
- const storedToken = results?.[0]?.[1] ?? null;
49
- const storedUser = results?.[1]?.[1] ?? null;
50
-
51
- if (!storedToken) {
52
- setToken(null);
53
- setUser(null);
54
- await AsyncStorage.multiRemove(["access_token", "user_data"]);
55
- return;
56
- }
57
-
58
- if (storedToken && storedUser) {
59
- setToken(storedToken);
60
- setUser(JSON.parse(storedUser));
61
- } else if (storedToken && !storedUser) {
62
- // 若仅有 token,主动拉取当前用户信息
63
- setToken(storedToken);
64
- try {
65
- // const me = await UsersService.getCurrentUserApiV1UsersMeGet();
66
- //if (me?.success && me.data) {
67
- // setUser(me.data);
68
- // await AsyncStorage.setItem("user_data", JSON.stringify(me.data));
69
- //}
70
- } catch (e) {
71
- // 拉取失败则保持未登录状态
72
- console.error("Failed to fetch current user with stored token:", e);
73
- }
74
- }
75
- } catch (error) {
76
- console.error("Failed to load auth data:", error);
77
- } finally {
78
- setIsLoading(false);
79
- }
80
- };
81
-
82
- const login = async (newToken: string) => {
83
- try {
84
- setToken(newToken);
85
- // 统一写入 access_token,供 OpenAPI 读取并自动携带
86
- await AsyncStorage.setItem("access_token", newToken);
87
- // 登录后拉取当前用户并缓存
88
- try {
89
- const me = await UsersService.getCurrentUserApiV1UsersMeGet();
90
- if (me?.success && me.data) {
91
- setUser(me.data);
92
- await AsyncStorage.setItem("user_data", JSON.stringify(me.data));
93
- }
94
- } catch (e) {
95
- console.error("Fetch current user after login failed:", e);
96
- }
97
- } catch (error) {
98
- console.error("Login failed:", error);
99
- throw error;
100
- }
101
- };
102
-
103
- const logout = async () => {
104
- try {
105
- // await AuthenticationService.logoutApiV1AuthLogoutPost(true);
106
- } catch(error) {
107
- console.warn('Logout failed:', error);
108
- }
109
- // remove token
110
- setToken(null);
111
- setUser(null);
112
- await AsyncStorage.multiRemove(["auth_token", "access_token", "user_data"]);
113
- };
114
-
115
- const updateUser = (userData: Partial<UserOut>) => {
116
- if (user) {
117
- const updatedUser = { ...user, ...userData };
118
- setUser(updatedUser);
119
- AsyncStorage.setItem("user_data", JSON.stringify(updatedUser));
120
- }
121
- };
122
-
30
+ export const AuthProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
123
31
  const value: AuthContextType = {
124
- user,
125
- token,
126
- isAuthenticated: !!token && !!user,
127
- isLoading,
128
- login,
129
- logout,
130
- updateUser,
32
+ user: null,
33
+ token: null,
34
+ isAuthenticated: false,
35
+ isLoading: false,
36
+ login: async (token: string) => {},
37
+ logout: async () => {},
38
+ updateUser: () => {},
131
39
  };
132
-
133
40
  return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
134
41
  };
135
42
 
@@ -3,10 +3,7 @@ import {
3
3
  View,
4
4
  Text,
5
5
  ScrollView,
6
- TouchableOpacity,
7
6
  RefreshControl,
8
- Image,
9
- ActivityIndicator,
10
7
  } from 'react-native';
11
8
  import { useRouter, useFocusEffect } from 'expo-router';
12
9
  import { FontAwesome6 } from '@expo/vector-icons';
@@ -15,7 +12,7 @@ import { useTheme } from "@/hooks/useTheme";
15
12
 
16
13
  import { Screen } from '@/components/Screen';
17
14
 
18
- import styles from './styles';
15
+ import { styles } from './styles';
19
16
 
20
17
 
21
18
  export default function HomeScreen() {
@@ -1,6 +1,6 @@
1
1
  import { StyleSheet, Platform } from 'react-native';
2
2
 
3
- const styles = StyleSheet.create({
3
+ export const styles = StyleSheet.create({
4
4
  loadingContainer: {
5
5
  flex: 1,
6
6
  justifyContent: 'center',
@@ -22,18 +22,6 @@ const styles = StyleSheet.create({
22
22
  fontSize: 16,
23
23
  color: '#64748B',
24
24
  },
25
- retryButton: {
26
- marginTop: 20,
27
- paddingHorizontal: 24,
28
- paddingVertical: 12,
29
- backgroundColor: '#2563EB',
30
- borderRadius: 8,
31
- },
32
- retryButtonText: {
33
- color: '#FFFFFF',
34
- fontSize: 14,
35
- fontWeight: '600',
36
- },
37
25
  header: {
38
26
  flexDirection: 'row',
39
27
  justifyContent: 'space-between',
@@ -44,11 +32,6 @@ const styles = StyleSheet.create({
44
32
  // borderBottomWidth: 1,
45
33
  borderBottomColor: '#E2E8F0',
46
34
  },
47
- headerLeft: {
48
- flexDirection: 'row',
49
- alignItems: 'center',
50
- gap: 10,
51
- },
52
35
  logoContainer: {
53
36
  width: 32,
54
37
  height: 32,
@@ -74,259 +57,4 @@ const styles = StyleSheet.create({
74
57
  color: '#1E293B',
75
58
  letterSpacing: -0.5,
76
59
  },
77
- userMenuContainer: {
78
- flexDirection: 'row',
79
- alignItems: 'center',
80
- gap: 10,
81
- paddingLeft: 16,
82
- borderLeftWidth: 1,
83
- borderLeftColor: '#E2E8F0',
84
- },
85
- userInfo: {
86
- alignItems: 'flex-end',
87
- },
88
- userName: {
89
- fontSize: 14,
90
- fontWeight: '500',
91
- color: '#1E293B',
92
- },
93
- userRole: {
94
- fontSize: 12,
95
- color: '#64748B',
96
- },
97
- avatar: {
98
- width: 36,
99
- height: 36,
100
- borderRadius: 18,
101
- borderWidth: 2,
102
- borderColor: '#FFFFFF',
103
- ...Platform.select({
104
- ios: {
105
- shadowColor: '#000',
106
- shadowOffset: { width: 0, height: 1 },
107
- shadowOpacity: 0.1,
108
- shadowRadius: 2,
109
- },
110
- android: {
111
- elevation: 2,
112
- },
113
- }),
114
- },
115
- avatarPlaceholder: {
116
- width: 36,
117
- height: 36,
118
- borderRadius: 18,
119
- justifyContent: 'center',
120
- alignItems: 'center',
121
- borderWidth: 2,
122
- borderColor: '#FFFFFF',
123
- backgroundColor: '#3B82F6',
124
- ...Platform.select({
125
- ios: {
126
- shadowColor: '#000',
127
- shadowOffset: { width: 0, height: 1 },
128
- shadowOpacity: 0.1,
129
- shadowRadius: 2,
130
- },
131
- android: {
132
- elevation: 2,
133
- },
134
- }),
135
- },
136
- avatarInitial: {
137
- fontSize: 14,
138
- fontWeight: '700',
139
- color: '#FFFFFF',
140
- },
141
- content: {
142
- paddingHorizontal: 16,
143
- paddingTop: 24,
144
- },
145
- welcomeSection: {
146
- marginBottom: 24,
147
- },
148
- welcomeTitle: {
149
- fontSize: 22,
150
- fontWeight: '700',
151
- color: '#1E293B',
152
- marginBottom: 4,
153
- },
154
- welcomeSubtitle: {
155
- fontSize: 14,
156
- color: '#64748B',
157
- },
158
- statsGrid: {
159
- flexDirection: 'row',
160
- gap: 12,
161
- marginBottom: 24,
162
- },
163
- statCard: {
164
- flex: 1,
165
- backgroundColor: '#FFFFFF',
166
- borderRadius: 12,
167
- padding: 16,
168
- ...Platform.select({
169
- ios: {
170
- shadowColor: '#000',
171
- shadowOffset: { width: 0, height: 1 },
172
- shadowOpacity: 0.05,
173
- shadowRadius: 3,
174
- },
175
- android: {
176
- elevation: 2,
177
- },
178
- }),
179
- },
180
- statCardHeader: {
181
- flexDirection: 'row',
182
- justifyContent: 'space-between',
183
- alignItems: 'flex-start',
184
- marginBottom: 12,
185
- },
186
- statIconContainer: {
187
- width: 40,
188
- height: 40,
189
- borderRadius: 10,
190
- justifyContent: 'center',
191
- alignItems: 'center',
192
- },
193
- statIconBlue: {
194
- backgroundColor: '#EFF6FF',
195
- },
196
- statIconRed: {
197
- backgroundColor: '#FEF2F2',
198
- },
199
- statIconGreen: {
200
- backgroundColor: '#ECFDF5',
201
- },
202
- attentionBadge: {
203
- backgroundColor: '#FEF2F2',
204
- paddingHorizontal: 6,
205
- paddingVertical: 2,
206
- borderRadius: 10,
207
- },
208
- attentionBadgeText: {
209
- fontSize: 10,
210
- fontWeight: '500',
211
- color: '#EF4444',
212
- },
213
- rateBadge: {
214
- backgroundColor: '#ECFDF5',
215
- paddingHorizontal: 6,
216
- paddingVertical: 2,
217
- borderRadius: 10,
218
- },
219
- rateBadgeText: {
220
- fontSize: 10,
221
- fontWeight: '500',
222
- color: '#10B981',
223
- },
224
- statValue: {
225
- fontSize: 28,
226
- fontWeight: '700',
227
- color: '#1E293B',
228
- marginBottom: 2,
229
- },
230
- statLabel: {
231
- fontSize: 13,
232
- color: '#64748B',
233
- },
234
- shortcutsSection: {
235
- gap: 12,
236
- marginBottom: 24,
237
- },
238
- shortcutCard: {
239
- flexDirection: 'row',
240
- justifyContent: 'space-between',
241
- alignItems: 'center',
242
- backgroundColor: '#FFFFFF',
243
- borderRadius: 12,
244
- padding: 16,
245
- ...Platform.select({
246
- ios: {
247
- shadowColor: '#000',
248
- shadowOffset: { width: 0, height: 1 },
249
- shadowOpacity: 0.05,
250
- shadowRadius: 3,
251
- },
252
- android: {
253
- elevation: 2,
254
- },
255
- }),
256
- },
257
- shortcutContent: {
258
- flex: 1,
259
- marginRight: 16,
260
- },
261
- shortcutTitle: {
262
- fontSize: 16,
263
- fontWeight: '600',
264
- color: '#1E293B',
265
- marginBottom: 6,
266
- },
267
- shortcutDescription: {
268
- fontSize: 13,
269
- color: '#64748B',
270
- marginBottom: 10,
271
- lineHeight: 18,
272
- },
273
- shortcutAction: {
274
- flexDirection: 'row',
275
- alignItems: 'center',
276
- gap: 6,
277
- },
278
- shortcutActionText: {
279
- fontSize: 13,
280
- fontWeight: '500',
281
- color: '#2563EB',
282
- },
283
- shortcutIconContainer: {
284
- width: 56,
285
- height: 56,
286
- borderRadius: 28,
287
- justifyContent: 'center',
288
- alignItems: 'center',
289
- },
290
- shortcutIconBlue: {
291
- backgroundColor: '#EFF6FF',
292
- },
293
- shortcutIconGreen: {
294
- backgroundColor: '#ECFDF5',
295
- },
296
- bannerContainer: {
297
- height: 160,
298
- borderRadius: 12,
299
- overflow: 'hidden',
300
- backgroundColor: '#1E3A8A',
301
- },
302
- bannerOverlay: {
303
- flex: 1,
304
- justifyContent: 'center',
305
- paddingHorizontal: 20,
306
- },
307
- bannerTitle: {
308
- fontSize: 18,
309
- fontWeight: '700',
310
- color: '#FFFFFF',
311
- marginBottom: 6,
312
- },
313
- bannerSubtitle: {
314
- fontSize: 13,
315
- color: '#BFDBFE',
316
- marginBottom: 16,
317
- },
318
- bannerButton: {
319
- alignSelf: 'flex-start',
320
- backgroundColor: '#FFFFFF',
321
- paddingHorizontal: 20,
322
- paddingVertical: 10,
323
- borderRadius: 8,
324
- },
325
- bannerButtonText: {
326
- fontSize: 13,
327
- fontWeight: '500',
328
- color: '#2563EB',
329
- },
330
60
  });
331
-
332
- export default styles;
@@ -1,4 +1,3 @@
1
- // import { OpenAPI } from '@api'; // 如果使用 openapi 客户端,请取消注释并确保安装
2
1
  import dayjs from 'dayjs';
3
2
  import utc from 'dayjs/plugin/utc';
4
3
  dayjs.extend(utc);
@@ -26,7 +25,7 @@ export const buildAssetUrl = (url?: string | null, w?: number, h?: number): stri
26
25
  // 3. 构造参数,保留原有 Query (如有)
27
26
  const separator = abs.includes('?') ? '&' : '?';
28
27
  const query = [
29
- w ? `w=${Math.floor(w)}` : '',
28
+ w ? `w=${Math.floor(w)}` : '',
30
29
  h ? `h=${Math.floor(h)}` : ''
31
30
  ].filter(Boolean).join('&');
32
31
  return `${abs}${separator}${query}`;
@@ -33,7 +33,7 @@
33
33
  "ajv": "^8.17.1",
34
34
  "ajv-formats": "^3.0.1",
35
35
  "connect": "^3.7.0",
36
- "coze-coding-dev-sdk": "0.5.0",
36
+ "coze-coding-dev-sdk": "^0.5.2",
37
37
  "dayjs": "^1.11.19",
38
38
  "drizzle-kit": "^0.31.8",
39
39
  "drizzle-orm": "^0.45.1",
@@ -51,8 +51,8 @@ importers:
51
51
  specifier: ^3.7.0
52
52
  version: 3.7.0
53
53
  coze-coding-dev-sdk:
54
- specifier: 0.5.0
55
- version: 0.5.0(@types/pg@8.16.0)(openai@6.15.0(ws@8.18.3)(zod@4.3.2))(ws@8.18.3)
54
+ specifier: ^0.5.2
55
+ version: 0.5.4(@types/pg@8.16.0)(openai@6.15.0(ws@8.18.3)(zod@4.3.2))(ws@8.18.3)
56
56
  dayjs:
57
57
  specifier: ^1.11.19
58
58
  version: 1.11.19
@@ -3137,8 +3137,8 @@ packages:
3137
3137
  resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==}
3138
3138
  engines: {node: '>=10'}
3139
3139
 
3140
- coze-coding-dev-sdk@0.5.0:
3141
- resolution: {integrity: sha512-fmJypE4jgExKOOFSz26ZNRUyKmAh3FENKORXMfvP7JIbXmk092ntrnll9DCJ+HpNOcpdvlE5lTmGSvyGh9nwrw==}
3140
+ coze-coding-dev-sdk@0.5.4:
3141
+ resolution: {integrity: sha512-nIH2hMFlO2PSnqdslFzOITK+2FhR64caoYFuzy2ma+ceu0o2Spe7tLYLIsyUc42Prr5gXqk4MZESQqpXD34ZwQ==}
3142
3142
  engines: {node: '>=18.0.0'}
3143
3143
  hasBin: true
3144
3144
 
@@ -10312,7 +10312,7 @@ snapshots:
10312
10312
  path-type: 4.0.0
10313
10313
  yaml: 1.10.2
10314
10314
 
10315
- coze-coding-dev-sdk@0.5.0(@types/pg@8.16.0)(openai@6.15.0(ws@8.18.3)(zod@4.3.2))(ws@8.18.3):
10315
+ coze-coding-dev-sdk@0.5.4(@types/pg@8.16.0)(openai@6.15.0(ws@8.18.3)(zod@4.3.2))(ws@8.18.3):
10316
10316
  dependencies:
10317
10317
  '@aws-sdk/client-s3': 3.958.0
10318
10318
  '@aws-sdk/lib-storage': 3.958.0(@aws-sdk/client-s3@3.958.0)
@@ -3,8 +3,8 @@ import express from "express";
3
3
  const app = express();
4
4
  const port = process.env.PORT || 9091;
5
5
 
6
- app.get('/api/hello', (req, res) => {
7
- res.status(200).json({ message: 'hello world' });
6
+ app.get('/api/v1/ping', (req, res) => {
7
+ res.status(200).json({ message: 'connected' });
8
8
  });
9
9
 
10
10
  app.listen(port, () => {
@@ -31,7 +31,7 @@ export const paramsSchema = {
31
31
  const config = {
32
32
  paramsSchema,
33
33
  defaultParams: {
34
- port: 8081,
34
+ port: 9090,
35
35
  appName: 'my-expo-app',
36
36
  },
37
37
  onBeforeRender: async context => {
@@ -42,7 +42,7 @@
42
42
  "class-variance-authority": "^0.7.1",
43
43
  "clsx": "^2.1.1",
44
44
  "cmdk": "^1.1.1",
45
- "coze-coding-dev-sdk": "0.5.0",
45
+ "coze-coding-dev-sdk": "^0.5.2",
46
46
  "date-fns": "^4.1.0",
47
47
  "drizzle-kit": "^0.31.8",
48
48
  "drizzle-orm": "^0.45.1",
@@ -105,8 +105,8 @@ importers:
105
105
  specifier: ^1.1.1
106
106
  version: 1.1.1(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
107
107
  coze-coding-dev-sdk:
108
- specifier: 0.5.0
109
- version: 0.5.0(@types/pg@8.16.0)(openai@6.15.0(zod@4.3.5))
108
+ specifier: ^0.5.2
109
+ version: 0.5.4(@types/pg@8.16.0)(openai@6.15.0(zod@4.3.5))
110
110
  date-fns:
111
111
  specifier: ^4.1.0
112
112
  version: 4.1.0
@@ -2747,8 +2747,8 @@ packages:
2747
2747
  typescript:
2748
2748
  optional: true
2749
2749
 
2750
- coze-coding-dev-sdk@0.5.0:
2751
- resolution: {integrity: sha512-fmJypE4jgExKOOFSz26ZNRUyKmAh3FENKORXMfvP7JIbXmk092ntrnll9DCJ+HpNOcpdvlE5lTmGSvyGh9nwrw==}
2750
+ coze-coding-dev-sdk@0.5.4:
2751
+ resolution: {integrity: sha512-nIH2hMFlO2PSnqdslFzOITK+2FhR64caoYFuzy2ma+ceu0o2Spe7tLYLIsyUc42Prr5gXqk4MZESQqpXD34ZwQ==}
2752
2752
  engines: {node: '>=18.0.0'}
2753
2753
  hasBin: true
2754
2754
 
@@ -7931,7 +7931,7 @@ snapshots:
7931
7931
  optionalDependencies:
7932
7932
  typescript: 5.9.3
7933
7933
 
7934
- coze-coding-dev-sdk@0.5.0(@types/pg@8.16.0)(openai@6.15.0(zod@4.3.5)):
7934
+ coze-coding-dev-sdk@0.5.4(@types/pg@8.16.0)(openai@6.15.0(zod@4.3.5)):
7935
7935
  dependencies:
7936
7936
  '@aws-sdk/client-s3': 3.962.0
7937
7937
  '@aws-sdk/lib-storage': 3.962.0(@aws-sdk/client-s3@3.962.0)
@@ -33,9 +33,9 @@ export const metadata: Metadata = {
33
33
  ],
34
34
  authors: [{ name: 'Coze Code Team', url: 'https://code.coze.cn' }],
35
35
  generator: 'Coze Code',
36
- icons: {
37
- icon: '',
38
- },
36
+ // icons: {
37
+ // icon: '',
38
+ // },
39
39
  openGraph: {
40
40
  title: '扣子编程 | 你的 AI 工程师已就位',
41
41
  description:
@@ -44,22 +44,22 @@ export const metadata: Metadata = {
44
44
  siteName: '扣子编程',
45
45
  locale: 'zh_CN',
46
46
  type: 'website',
47
- images: [
48
- {
49
- url: '',
50
- width: 1200,
51
- height: 630,
52
- alt: '扣子编程 - 你的 AI 工程师',
53
- },
54
- ],
55
- },
56
- twitter: {
57
- card: 'summary_large_image',
58
- title: 'Coze Code | Your AI Engineer is Here',
59
- description:
60
- 'Build and deploy full-stack applications through AI conversation. No env setup, just flow.',
61
- images: [''],
47
+ // images: [
48
+ // {
49
+ // url: '',
50
+ // width: 1200,
51
+ // height: 630,
52
+ // alt: '扣子编程 - 你的 AI 工程师',
53
+ // },
54
+ // ],
62
55
  },
56
+ // twitter: {
57
+ // card: 'summary_large_image',
58
+ // title: 'Coze Code | Your AI Engineer is Here',
59
+ // description:
60
+ // 'Build and deploy full-stack applications through AI conversation. No env setup, just flow.',
61
+ // // images: [''],
62
+ // },
63
63
  robots: {
64
64
  index: true,
65
65
  follow: true,
@@ -52,6 +52,13 @@
52
52
  "port": {
53
53
  "type": "number",
54
54
  "description": "Development server port",
55
+ "default": 5000,
56
+ "minimum": 1024,
57
+ "maximum": 65535
58
+ },
59
+ "hmrPort": {
60
+ "type": "number",
61
+ "description": "Development HMR server port",
55
62
  "default": 6000,
56
63
  "minimum": 1024,
57
64
  "maximum": 65535
@@ -7,6 +7,7 @@
7
7
 
8
8
 
9
9
 
10
+
10
11
  export const paramsSchema = {
11
12
  type: 'object',
12
13
  properties: {
@@ -19,11 +20,18 @@ export const paramsSchema = {
19
20
  },
20
21
  port: {
21
22
  type: 'number',
22
- default: 6000,
23
+ default: 5000,
23
24
  minimum: 1024,
24
25
  maximum: 65535,
25
26
  description: 'Development server port',
26
27
  },
28
+ hmrPort: {
29
+ type: 'number',
30
+ default: 6000,
31
+ minimum: 1024,
32
+ maximum: 65535,
33
+ description: 'Development HMR server port',
34
+ },
27
35
  },
28
36
  required: [],
29
37
  additionalProperties: false,
@@ -33,7 +41,8 @@ const config = {
33
41
  paramsSchema,
34
42
 
35
43
  defaultParams: {
36
- port: 6000,
44
+ port: 5000,
45
+ hmrPort: 6000,
37
46
  appName: 'projects',
38
47
  },
39
48
 
@@ -1,13 +1,13 @@
1
1
  import { defineConfig } from 'vite';
2
2
 
3
3
  export default defineConfig({
4
- port: '<%= port %>',
5
- host: '0.0.0.0',
6
4
  server: {
5
+ port: <%= port %>,
6
+ host: '0.0.0.0',
7
7
  hmr: {
8
8
  overlay: true,
9
9
  path: '/hot/vite-hmr',
10
- port: '<%= port %>',
10
+ port: <%= hmrPort %>,
11
11
  clientPort: 443,
12
12
  timeout: 30000,
13
13
  },
package/lib/cli.js CHANGED
@@ -9,6 +9,8 @@ var perf_hooks = require('perf_hooks');
9
9
  var fs$1 = require('fs/promises');
10
10
  var toml = require('@iarna/toml');
11
11
  var jsYaml = require('js-yaml');
12
+ var child_process = require('child_process');
13
+ var os = require('os');
12
14
  var addFormats = require('ajv-formats');
13
15
  var Ajv = require('ajv');
14
16
  var minimist = require('minimist');
@@ -125,7 +127,7 @@ const generateTemplatesHelpText = () => {
125
127
  return lines.join('\n');
126
128
  };
127
129
 
128
- function _nullishCoalesce$2(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain$4(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }var LogLevel; (function (LogLevel) {
130
+ function _nullishCoalesce$2(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain$3(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }var LogLevel; (function (LogLevel) {
129
131
  const ERROR = 0; LogLevel[LogLevel["ERROR"] = ERROR] = "ERROR";
130
132
  const WARN = 1; LogLevel[LogLevel["WARN"] = WARN] = "WARN";
131
133
  const SUCCESS = 2; LogLevel[LogLevel["SUCCESS"] = SUCCESS] = "SUCCESS";
@@ -172,7 +174,7 @@ class Logger {
172
174
  return level;
173
175
  }
174
176
 
175
- const envLevel = _optionalChain$4([process, 'access', _ => _.env, 'access', _2 => _2.LOG_LEVEL, 'optionalAccess', _3 => _3.toLowerCase, 'call', _4 => _4()]);
177
+ const envLevel = _optionalChain$3([process, 'access', _ => _.env, 'access', _2 => _2.LOG_LEVEL, 'optionalAccess', _3 => _3.toLowerCase, 'call', _4 => _4()]);
176
178
  if (envLevel && envLevel in LOG_LEVEL_MAP) {
177
179
  return LOG_LEVEL_MAP[envLevel];
178
180
  }
@@ -184,7 +186,7 @@ class Logger {
184
186
  // 简单检测:Node.js 环境且支持 TTY
185
187
  return (
186
188
  typeof process !== 'undefined' &&
187
- _optionalChain$4([process, 'access', _5 => _5.stdout, 'optionalAccess', _6 => _6.isTTY]) === true &&
189
+ _optionalChain$3([process, 'access', _5 => _5.stdout, 'optionalAccess', _6 => _6.isTTY]) === true &&
188
190
  process.env.NO_COLOR === undefined
189
191
  );
190
192
  }
@@ -593,7 +595,7 @@ const registerCommand$2 = program => {
593
595
  });
594
596
  };
595
597
 
596
- function _optionalChain$3(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }/* eslint-disable @typescript-eslint/no-explicit-any */
598
+ function _optionalChain$2(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }/* eslint-disable @typescript-eslint/no-explicit-any */
597
599
  // Safe JSON parsing utilities with type safety and error handling
598
600
  // Provides fallback values, validation, and error monitoring capabilities
599
601
 
@@ -684,12 +686,12 @@ function safeJsonParse(
684
686
  const parsed = JSON.parse(String(input));
685
687
 
686
688
  // Optional validation
687
- if (_optionalChain$3([options, 'optionalAccess', _ => _.validate])) {
689
+ if (_optionalChain$2([options, 'optionalAccess', _ => _.validate])) {
688
690
  if (options.validate(parsed)) {
689
691
  return parsed;
690
692
  } else {
691
693
  const validationError = new Error('JSON validation failed');
692
- _optionalChain$3([options, 'access', _2 => _2.onError, 'optionalCall', _3 => _3(validationError, input)]);
694
+ _optionalChain$2([options, 'access', _2 => _2.onError, 'optionalCall', _3 => _3(validationError, input)]);
693
695
 
694
696
  if (options.throwOnValidationError) {
695
697
  throw validationError;
@@ -701,15 +703,15 @@ function safeJsonParse(
701
703
  return parsed;
702
704
  } catch (error) {
703
705
  // Re-throw validation errors when throwOnValidationError is true
704
- if (error instanceof Error && error.message === 'JSON validation failed' && _optionalChain$3([options, 'optionalAccess', _4 => _4.throwOnValidationError])) {
706
+ if (error instanceof Error && error.message === 'JSON validation failed' && _optionalChain$2([options, 'optionalAccess', _4 => _4.throwOnValidationError])) {
705
707
  throw error;
706
708
  }
707
- _optionalChain$3([options, 'optionalAccess', _5 => _5.onError, 'optionalCall', _6 => _6(error , input)]);
709
+ _optionalChain$2([options, 'optionalAccess', _5 => _5.onError, 'optionalCall', _6 => _6(error , input)]);
708
710
  return defaultValue;
709
711
  }
710
712
  }
711
713
 
712
- function _optionalChain$2(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
714
+ function _optionalChain$1(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
713
715
 
714
716
 
715
717
  /**
@@ -799,13 +801,13 @@ const getCommandConfig = (
799
801
  // 根据命令名称映射到配置路径
800
802
  switch (commandName) {
801
803
  case 'dev':
802
- commandConfig = _optionalChain$2([config, 'access', _ => _.dev, 'optionalAccess', _2 => _2.run]);
804
+ commandConfig = _optionalChain$1([config, 'access', _ => _.dev, 'optionalAccess', _2 => _2.run]);
803
805
  break;
804
806
  case 'build':
805
- commandConfig = _optionalChain$2([config, 'access', _3 => _3.deploy, 'optionalAccess', _4 => _4.build]);
807
+ commandConfig = _optionalChain$1([config, 'access', _3 => _3.deploy, 'optionalAccess', _4 => _4.build]);
806
808
  break;
807
809
  case 'start':
808
- commandConfig = _optionalChain$2([config, 'access', _5 => _5.deploy, 'optionalAccess', _6 => _6.run]);
810
+ commandConfig = _optionalChain$1([config, 'access', _5 => _5.deploy, 'optionalAccess', _6 => _6.run]);
809
811
  break;
810
812
  default:
811
813
  throw new Error(`Unknown command: ${commandName}`);
@@ -821,7 +823,7 @@ const getCommandConfig = (
821
823
  return commandConfig;
822
824
  };
823
825
 
824
- function _nullishCoalesce$1(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain$1(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
826
+ function _nullishCoalesce$1(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
825
827
 
826
828
  /**
827
829
  * 创建日志管理器
@@ -879,12 +881,12 @@ const executeRun = async (
879
881
  }
880
882
 
881
883
  // 将输出同时写入控制台和日志文件
882
- _optionalChain$1([childProcess, 'access', _ => _.stdout, 'optionalAccess', _2 => _2.on, 'call', _3 => _3('data', (data) => {
884
+ _optionalChain([childProcess, 'access', _ => _.stdout, 'optionalAccess', _2 => _2.on, 'call', _3 => _3('data', (data) => {
883
885
  process.stdout.write(data);
884
886
  logStream.write(data);
885
887
  })]);
886
888
 
887
- _optionalChain$1([childProcess, 'access', _4 => _4.stderr, 'optionalAccess', _5 => _5.on, 'call', _6 => _6('data', (data) => {
889
+ _optionalChain([childProcess, 'access', _4 => _4.stderr, 'optionalAccess', _5 => _5.on, 'call', _6 => _6('data', (data) => {
888
890
  process.stderr.write(data);
889
891
  logStream.write(data);
890
892
  })]);
@@ -952,6 +954,45 @@ const registerCommand$1 = program => {
952
954
  });
953
955
  };
954
956
 
957
+ /**
958
+ * 在后台启动一个独立的子进程
959
+ * 类似于 `setsid command args >/dev/null 2>&1 &`
960
+ *
961
+ * @param command - 要执行的命令 (例如: 'npm', 'node', 'bash')
962
+ * @param args - 命令参数数组 (例如: ['run', 'dev'])
963
+ * @param options - 配置选项
964
+ * @returns 子进程的 PID
965
+ */
966
+ function spawnDetached(
967
+ command,
968
+ args,
969
+ options,
970
+ ) {
971
+ const { cwd, verbose = true } = options;
972
+ const isWindows = os.platform() === 'win32';
973
+
974
+ if (verbose) {
975
+ console.log(`Spawning detached process: ${command} ${args.join(' ')}`);
976
+ console.log(`Working directory: ${cwd}`);
977
+ }
978
+
979
+ // 使用 spawn 创建后台子进程
980
+ const child = child_process.spawn(command, args, {
981
+ cwd,
982
+ detached: !isWindows, // Windows 不完全支持 detached,但仍可以使用
983
+ stdio: 'ignore', // 忽略所有输入输出,让进程完全独立运行
984
+ });
985
+
986
+ // 分离父子进程引用,允许父进程退出而不等待子进程
987
+ child.unref();
988
+
989
+ if (verbose && child.pid) {
990
+ console.log(`Process started with PID: ${child.pid}`);
991
+ }
992
+
993
+ return child.pid;
994
+ }
995
+
955
996
  /**
956
997
  * 创建 AJV 验证器实例
957
998
  */
@@ -1465,7 +1506,7 @@ const execute = async (
1465
1506
  return absoluteOutputPath;
1466
1507
  };
1467
1508
 
1468
- function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
1509
+ function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }
1469
1510
  /**
1470
1511
  * 运行 pnpm install
1471
1512
  */
@@ -1568,45 +1609,26 @@ const runGitInit = (projectPath) => {
1568
1609
  };
1569
1610
 
1570
1611
  /**
1571
- * 运行开发服务器
1612
+ * 运行开发服务器(后台模式)
1613
+ * 启动后台子进程运行开发服务器,父进程可以直接退出
1572
1614
  */
1573
1615
  const runNpmDev = (projectPath) => {
1574
- logger.info('\nStarting development server...');
1616
+ logger.info('\nStarting development server in background...');
1575
1617
  logger.info(`Executing: npm run dev in ${projectPath}`);
1576
- logger.info('Press Ctrl+C to stop the server\n');
1577
1618
 
1578
- // 使用 async: true 异步执行,不阻塞进程
1579
- const child = shelljs.exec('npm run dev', {
1619
+ // 使用通用的后台执行函数启动开发服务器
1620
+ const pid = spawnDetached('npm', ['run', 'dev'], {
1580
1621
  cwd: projectPath,
1581
- async: true,
1582
- silent: true, // 手动处理输出以便显示详细信息
1622
+ verbose: false, // 不输出额外的进程信息,由 logger 统一处理
1583
1623
  });
1584
1624
 
1585
- if (child) {
1586
- // 输出 stdout
1587
- _optionalChain([child, 'access', _ => _.stdout, 'optionalAccess', _2 => _2.on, 'call', _3 => _3('data', (data) => {
1588
- process.stdout.write(data);
1589
- })]);
1590
-
1591
- // 输出 stderr
1592
- _optionalChain([child, 'access', _4 => _4.stderr, 'optionalAccess', _5 => _5.on, 'call', _6 => _6('data', (data) => {
1593
- process.stderr.write(data);
1594
- })]);
1595
-
1596
- // 监听错误
1597
- child.on('error', (error) => {
1598
- logger.error(`Failed to start dev server: ${error.message}`);
1599
- logger.error(`Error stack: ${error.stack}`);
1600
- });
1601
-
1602
- // 监听退出
1603
- child.on('exit', (code, signal) => {
1604
- if (code !== 0 && code !== null) {
1605
- logger.error(
1606
- `Dev server exited with code ${code}${signal ? ` and signal ${signal}` : ''}`,
1607
- );
1608
- }
1609
- });
1625
+ logger.success('Development server started in background!');
1626
+ if (pid) {
1627
+ logger.info(`Process ID: ${pid}`);
1628
+ logger.info(
1629
+ '\nThe dev server is running independently. You can close this terminal.',
1630
+ );
1631
+ logger.info(`To stop the server later, use: kill ${pid}`);
1610
1632
  }
1611
1633
  };
1612
1634
 
@@ -1719,7 +1741,7 @@ const registerCommand = program => {
1719
1741
  });
1720
1742
  };
1721
1743
 
1722
- var version = "0.0.1-alpha.a1ca15";
1744
+ var version = "0.0.1-alpha.c49cb2";
1723
1745
  var packageJson = {
1724
1746
  version: version};
1725
1747
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coze-arch/cli",
3
- "version": "0.0.1-alpha.a1ca15",
3
+ "version": "0.0.1-alpha.c49cb2",
4
4
  "private": false,
5
5
  "description": "coze coding devtools cli",
6
6
  "license": "MIT",
@@ -19,7 +19,6 @@
19
19
  "scripts": {
20
20
  "prebuild": "tsx scripts/prebuild.ts",
21
21
  "build": "tsx scripts/build.ts",
22
- "generate-templates": "tsx scripts/generate-templates-config.ts",
23
22
  "lint": "eslint ./ --cache",
24
23
  "postpublish": "bash scripts/sync-npmmirror.sh",
25
24
  "test": "vitest --run --passWithNoTests",