@coze-arch/cli 0.0.36-alpha.b293fc → 0.0.36-alpha.fd6b86

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,10 +2,81 @@
2
2
  set -Eeuo pipefail
3
3
 
4
4
  COZE_WORKSPACE_PATH="${COZE_WORKSPACE_PATH:-$(pwd)}"
5
- PORT="${DEPLOY_RUN_PORT:-${PORT:-<%= port %>}}"
5
+ PORT="${PORT:-<%= port %>}"
6
+ DEPLOY_RUN_PORT="${DEPLOY_RUN_PORT:-${PORT}}"
6
7
  cd "${COZE_WORKSPACE_PATH}"
7
8
 
8
- COZE_PHASER_GAME_ENV=DEV pnpm vite \
9
- --port "${PORT}" \
9
+ get_listening_pids() {
10
+ local port="$1"
11
+
12
+ if command -v lsof >/dev/null 2>&1; then
13
+ lsof -tiTCP:"${port}" -sTCP:LISTEN 2>/dev/null || true
14
+ elif command -v ss >/dev/null 2>&1; then
15
+ ss -H -lntp 2>/dev/null \
16
+ | awk -v port="${port}" '$4 ~ ":"port"$"' \
17
+ | grep -o 'pid=[0-9]*' \
18
+ | cut -d= -f2 \
19
+ | sort -u || true
20
+ else
21
+ echo "Warning: neither lsof nor ss found, cannot check port ${port}." >&2
22
+ fi
23
+ }
24
+
25
+ kill_port_if_listening() {
26
+ local port="$1"
27
+ local pids
28
+
29
+ pids="$(get_listening_pids "${port}")"
30
+ if [[ -z "${pids}" ]]; then
31
+ echo "Port ${port} is free."
32
+ return
33
+ fi
34
+
35
+ echo "Port ${port} is in use by PIDs: ${pids//$'\n'/ } (SIGKILL)"
36
+ echo "${pids}" | xargs kill -9 2>/dev/null || true
37
+ sleep 1
38
+
39
+ pids="$(get_listening_pids "${port}")"
40
+ if [[ -n "${pids}" ]]; then
41
+ echo "Failed to clear port ${port}; remaining PIDs: ${pids//$'\n'/ }." >&2
42
+ return 1
43
+ fi
44
+
45
+ echo "Port ${port} cleared."
46
+ }
47
+
48
+ echo "Clearing port ${DEPLOY_RUN_PORT} before start."
49
+ kill_port_if_listening "${DEPLOY_RUN_PORT}"
50
+
51
+ <% if (process.env.NODE_ENV === 'test') { %>
52
+ # Keep the process attached in tests so the test runner can collect logs and stop it.
53
+ exec env COZE_PHASER_GAME_ENV=DEV pnpm vite \
54
+ --port "${DEPLOY_RUN_PORT}" \
10
55
  --host 127.0.0.1 \
11
56
  --strictPort
57
+ <% } else { %>
58
+ LOG_DIR="${COZE_WORKSPACE_PATH}/logs"
59
+ LOG_FILE="${LOG_DIR}/phaser-dev.log"
60
+ PID_FILE="${LOG_DIR}/phaser-dev.pid"
61
+ mkdir -p "${LOG_DIR}"
62
+
63
+ echo "Starting Phaser dev server on port ${DEPLOY_RUN_PORT}..."
64
+ server_pid="$(COZE_PHASER_GAME_ENV=DEV node scripts/spawn-detached.cjs \
65
+ "${LOG_FILE}" pnpm vite \
66
+ --port "${DEPLOY_RUN_PORT}" \
67
+ --host 127.0.0.1 \
68
+ --strictPort)"
69
+ echo "${server_pid}" > "${PID_FILE}"
70
+
71
+ sleep 1
72
+ if ! kill -0 "${server_pid}" 2>/dev/null; then
73
+ echo "Phaser dev server failed to start. See ${LOG_FILE}." >&2
74
+ tail -n 20 "${LOG_FILE}" >&2 || true
75
+ rm -f "${PID_FILE}"
76
+ exit 1
77
+ fi
78
+
79
+ echo "Phaser dev server started (PID: ${server_pid})."
80
+ echo "Log file: ${LOG_FILE}"
81
+ echo "PID file: ${PID_FILE}"
82
+ <% } %>
@@ -0,0 +1,29 @@
1
+ const fs = require('node:fs');
2
+ const { spawn } = require('node:child_process');
3
+
4
+ const [logFile, command, ...args] = process.argv.slice(2);
5
+
6
+ if (!logFile || !command) {
7
+ process.stderr.write(
8
+ 'Usage: node scripts/spawn-detached.cjs <log-file> <command> [...args]\n',
9
+ );
10
+ process.exit(1);
11
+ }
12
+
13
+ const logFd = fs.openSync(logFile, 'a');
14
+ const child = spawn(command, args, {
15
+ cwd: process.cwd(),
16
+ detached: process.platform !== 'win32',
17
+ env: process.env,
18
+ stdio: ['ignore', logFd, logFd],
19
+ });
20
+
21
+ fs.closeSync(logFd);
22
+ child.unref();
23
+
24
+ if (!child.pid) {
25
+ process.stderr.write('Failed to start detached process.\n');
26
+ process.exit(1);
27
+ }
28
+
29
+ process.stdout.write(String(child.pid));
@@ -2,10 +2,81 @@
2
2
  set -Eeuo pipefail
3
3
 
4
4
  COZE_WORKSPACE_PATH="${COZE_WORKSPACE_PATH:-$(pwd)}"
5
- PORT="${DEPLOY_RUN_PORT:-${PORT:-<%= port %>}}"
5
+ PORT="${PORT:-<%= port %>}"
6
+ DEPLOY_RUN_PORT="${DEPLOY_RUN_PORT:-${PORT}}"
6
7
  cd "${COZE_WORKSPACE_PATH}"
7
8
 
8
- COZE_PHASER_GAME_ENV=PROD pnpm vite preview \
9
- --port "${PORT}" \
9
+ get_listening_pids() {
10
+ local port="$1"
11
+
12
+ if command -v lsof >/dev/null 2>&1; then
13
+ lsof -tiTCP:"${port}" -sTCP:LISTEN 2>/dev/null || true
14
+ elif command -v ss >/dev/null 2>&1; then
15
+ ss -H -lntp 2>/dev/null \
16
+ | awk -v port="${port}" '$4 ~ ":"port"$"' \
17
+ | grep -o 'pid=[0-9]*' \
18
+ | cut -d= -f2 \
19
+ | sort -u || true
20
+ else
21
+ echo "Warning: neither lsof nor ss found, cannot check port ${port}." >&2
22
+ fi
23
+ }
24
+
25
+ kill_port_if_listening() {
26
+ local port="$1"
27
+ local pids
28
+
29
+ pids="$(get_listening_pids "${port}")"
30
+ if [[ -z "${pids}" ]]; then
31
+ echo "Port ${port} is free."
32
+ return
33
+ fi
34
+
35
+ echo "Port ${port} is in use by PIDs: ${pids//$'\n'/ } (SIGKILL)"
36
+ echo "${pids}" | xargs kill -9 2>/dev/null || true
37
+ sleep 1
38
+
39
+ pids="$(get_listening_pids "${port}")"
40
+ if [[ -n "${pids}" ]]; then
41
+ echo "Failed to clear port ${port}; remaining PIDs: ${pids//$'\n'/ }." >&2
42
+ return 1
43
+ fi
44
+
45
+ echo "Port ${port} cleared."
46
+ }
47
+
48
+ echo "Clearing port ${DEPLOY_RUN_PORT} before start."
49
+ kill_port_if_listening "${DEPLOY_RUN_PORT}"
50
+
51
+ <% if (process.env.NODE_ENV === 'test') { %>
52
+ # Keep the process attached in tests so the test runner can collect logs and stop it.
53
+ exec env COZE_PHASER_GAME_ENV=PROD pnpm vite preview \
54
+ --port "${DEPLOY_RUN_PORT}" \
10
55
  --host 127.0.0.1 \
11
56
  --strictPort
57
+ <% } else { %>
58
+ LOG_DIR="${COZE_WORKSPACE_PATH}/logs"
59
+ LOG_FILE="${LOG_DIR}/phaser-start.log"
60
+ PID_FILE="${LOG_DIR}/phaser-start.pid"
61
+ mkdir -p "${LOG_DIR}"
62
+
63
+ echo "Starting Phaser production server on port ${DEPLOY_RUN_PORT}..."
64
+ server_pid="$(COZE_PHASER_GAME_ENV=PROD node scripts/spawn-detached.cjs \
65
+ "${LOG_FILE}" pnpm vite preview \
66
+ --port "${DEPLOY_RUN_PORT}" \
67
+ --host 127.0.0.1 \
68
+ --strictPort)"
69
+ echo "${server_pid}" > "${PID_FILE}"
70
+
71
+ sleep 1
72
+ if ! kill -0 "${server_pid}" 2>/dev/null; then
73
+ echo "Phaser production server failed to start. See ${LOG_FILE}." >&2
74
+ tail -n 20 "${LOG_FILE}" >&2 || true
75
+ rm -f "${PID_FILE}"
76
+ exit 1
77
+ fi
78
+
79
+ echo "Phaser production server started (PID: ${server_pid})."
80
+ echo "Log file: ${LOG_FILE}"
81
+ echo "PID file: ${PID_FILE}"
82
+ <% } %>
@@ -4,7 +4,7 @@ import { defineConfig, type Plugin } from "vite";
4
4
  import serveStatic from "serve-static";
5
5
 
6
6
  const DEV_PHASER_BRIDGE_URL =
7
- "https://unpkg.byted-static.com/latest/coze-game/phaser-bridge/dist/index.js";
7
+ "https://lf-coze-web-cdn.coze.cn/obj/eden-cn/lm-lgvj/ljhwZthlaukjlkulzlp/coze-game/js/phaser-bridge.min.js";
8
8
 
9
9
  function injectDevPhaserBridge(): Plugin {
10
10
  return {
@@ -8,6 +8,9 @@ cd "${COZE_WORKSPACE_PATH}"
8
8
  # PID 文件,用于追踪上一次启动的进程树
9
9
  # ---------------------------------------------------------
10
10
  PID_FILE="/tmp/coze-dev-run.pid"
11
+ LOG_DIR="/tmp/coze-logs"
12
+ LOG_FILE="${LOG_DIR}/dev.log"
13
+ DEV_PID=""
11
14
 
12
15
  # ---------------------------------------------------------
13
16
  # 工具函数
@@ -25,6 +28,49 @@ kill_process_tree() {
25
28
  fi
26
29
  }
27
30
 
31
+ # coze-daemon 会在 runtime shell 退出时清理原进程组。
32
+ # 通过 Node detached spawn 创建独立 session/进程组,并将 stdio 直接写入日志。
33
+ spawn_detached() {
34
+ local cwd="$1"
35
+ local log_file="$2"
36
+ shift 2
37
+
38
+ node - "$cwd" "$log_file" "$@" <<'NODE'
39
+ const fs = require('node:fs');
40
+ const { spawn } = require('node:child_process');
41
+
42
+ const [cwd, logFile, command, ...args] = process.argv.slice(2);
43
+ if (!cwd || !logFile || !command) {
44
+ throw new Error('spawn_detached 缺少 cwd、log_file 或 command');
45
+ }
46
+
47
+ const logFd = fs.openSync(logFile, 'a');
48
+ try {
49
+ const child = spawn(command, args, {
50
+ cwd,
51
+ detached: true,
52
+ env: process.env,
53
+ stdio: ['ignore', logFd, logFd],
54
+ });
55
+ child.unref();
56
+ process.stdout.write(String(child.pid));
57
+ } finally {
58
+ fs.closeSync(logFd);
59
+ }
60
+ NODE
61
+ }
62
+
63
+ stop_detached() {
64
+ local pid="${1:-}"
65
+ if [[ -z "${pid}" ]]; then
66
+ return
67
+ fi
68
+
69
+ kill -TERM -- "-${pid}" 2>/dev/null || kill -TERM "${pid}" 2>/dev/null || true
70
+ sleep 1
71
+ kill -KILL -- "-${pid}" 2>/dev/null || true
72
+ }
73
+
28
74
  kill_port_if_listening() {
29
75
  local port=$1
30
76
  local pids
@@ -56,7 +102,7 @@ cleanup_previous_run() {
56
102
  old_pid=$(cat "${PID_FILE}" 2>/dev/null || true)
57
103
  if [[ -n "${old_pid}" ]] && kill -0 "${old_pid}" 2>/dev/null; then
58
104
  echo "🧹 Killing previous dev process tree (root PID: ${old_pid})..."
59
- kill_process_tree "${old_pid}"
105
+ stop_detached "${old_pid}"
60
106
  fi
61
107
  rm -f "${PID_FILE}"
62
108
  fi
@@ -89,7 +135,8 @@ cleanup_previous_run() {
89
135
  # 2. 安装依赖
90
136
  # ---------------------------------------------------------
91
137
  echo "📦 Installing dependencies..."
92
- pnpm install
138
+ PNPM_BIN="$(command -v pnpm)"
139
+ "${PNPM_BIN}" install
93
140
  echo "✅ Dependencies installed successfully!"
94
141
 
95
142
  # ---------------------------------------------------------
@@ -105,19 +152,7 @@ echo "Clearing port ${SERVER_PORT} (server) before start."
105
152
  kill_port_if_listening "${SERVER_PORT}"
106
153
 
107
154
  # ---------------------------------------------------------
108
- # 4. 退出时自动清理子进程(信号 trap)
109
- # ---------------------------------------------------------
110
- cleanup_on_exit() {
111
- echo "🛑 dev_run.sh exiting, cleaning up child processes..."
112
- # 杀掉当前脚本的所有子进程
113
- kill -- -$$ 2>/dev/null || true
114
- rm -f "${PID_FILE}"
115
- exit 0
116
- }
117
- trap cleanup_on_exit EXIT INT TERM HUP
118
-
119
- # ---------------------------------------------------------
120
- # 5. 启动服务
155
+ # 4. 启动服务
121
156
  # ---------------------------------------------------------
122
157
  start_service() {
123
158
  cd "${COZE_WORKSPACE_PATH}"
@@ -134,17 +169,19 @@ start_service() {
134
169
  echo "Starting Taro H5 Dev Server and NestJS Server..."
135
170
 
136
171
  export PORT=${DEPLOY_RUN_PORT}
137
- rm -f /tmp/coze-logs/dev.log
138
- mkdir -p /tmp/coze-logs
139
-
140
- # 后台启动并记录 PID
141
- pnpm dev 2>&1 | tee /tmp/coze-logs/dev.log &
142
- local dev_pid=$!
143
- echo "${dev_pid}" > "${PID_FILE}"
144
- echo "📝 Dev process started with PID: ${dev_pid} (saved to ${PID_FILE})"
145
-
146
- # 前台等待,保证 trap 能正常捕获信号
147
- wait "${dev_pid}" || true
172
+ mkdir -p "${LOG_DIR}"
173
+ : > "${LOG_FILE}"
174
+
175
+ DEV_PID="$(spawn_detached \
176
+ "${COZE_WORKSPACE_PATH}" \
177
+ "${LOG_FILE}" \
178
+ "${PNPM_BIN}" dev)"
179
+ if [[ -z "${DEV_PID}" ]]; then
180
+ echo "❌ 无法获取 dev 后台进程 PID"
181
+ return 1
182
+ fi
183
+ echo "${DEV_PID}" > "${PID_FILE}"
184
+ echo "📝 Dev process started with PID: ${DEV_PID} (saved to ${PID_FILE})"
148
185
  }
149
186
 
150
187
  echo "Starting HTTP services on port ${DEPLOY_RUN_PORT} (web) and ${SERVER_PORT} (server)..."
@@ -204,8 +204,8 @@ importers:
204
204
  specifier: 2.95.3
205
205
  version: 2.95.3
206
206
  coze-coding-dev-sdk:
207
- specifier: ^0.7.24
208
- version: 0.7.24(openai@6.16.0(ws@8.19.0)(zod@4.3.5))(ws@8.19.0)
207
+ specifier: ^0.7.25-beta.4
208
+ version: 0.7.25-beta.4(openai@6.16.0(ws@8.19.0)(zod@4.3.5))(ws@8.19.0)
209
209
  dotenv:
210
210
  specifier: ^17.2.3
211
211
  version: 17.2.3
@@ -5416,8 +5416,8 @@ packages:
5416
5416
  typescript:
5417
5417
  optional: true
5418
5418
 
5419
- coze-coding-dev-sdk@0.7.24:
5420
- resolution: {integrity: sha512-oL9Tg5PwxP6iMixonzzMO4aBjOKWcFUMVM+iz5dPyaqQkG84HP1y9DqK5DJVmtdfJuYdAW7pzOatDqLvgvZiXg==}
5419
+ coze-coding-dev-sdk@0.7.25-beta.4:
5420
+ resolution: {integrity: sha512-+PCoJ8yhsAIlx3YT898bCkB2gx5EMBunJMP7/kI/Jq/8dj7SDU9EUBZ2Z8ZJocSaPBT9T6dVvFHBsDLZh4FN/Q==}
5421
5421
  engines: {node: '>=18.0.0'}
5422
5422
  hasBin: true
5423
5423
 
@@ -17159,7 +17159,7 @@ snapshots:
17159
17159
  optionalDependencies:
17160
17160
  typescript: 5.9.3
17161
17161
 
17162
- coze-coding-dev-sdk@0.7.24(openai@6.16.0(ws@8.19.0)(zod@4.3.5))(ws@8.19.0):
17162
+ coze-coding-dev-sdk@0.7.25-beta.4(openai@6.16.0(ws@8.19.0)(zod@4.3.5))(ws@8.19.0):
17163
17163
  dependencies:
17164
17164
  '@langchain/core': 1.1.16(openai@6.16.0(ws@8.19.0)(zod@4.3.5))
17165
17165
  '@langchain/openai': 1.2.3(@langchain/core@1.1.16(openai@6.16.0(ws@8.19.0)(zod@4.3.5)))(ws@8.19.0)
@@ -17,7 +17,7 @@
17
17
  "@nestjs/core": "^10.4.15",
18
18
  "@nestjs/platform-express": "^10.4.15",
19
19
  "@supabase/supabase-js": "2.95.3",
20
- "coze-coding-dev-sdk": "^0.7.24",
20
+ "coze-coding-dev-sdk": "^0.7.25-beta.4",
21
21
  "dotenv": "^17.2.3",
22
22
  "drizzle-kit": "^0.31.8",
23
23
  "drizzle-orm": "^0.45.1",
@@ -32,8 +32,89 @@ kill_port_if_listening() {
32
32
  fi
33
33
  }
34
34
 
35
+ <% if (process.env.NODE_ENV === 'test') { %>
36
+ echo "Clearing port ${DEPLOY_RUN_PORT} before start."
37
+ kill_port_if_listening
38
+ echo "Starting express + Vite dev server on port ${DEPLOY_RUN_PORT}..."
39
+
40
+ # 测试环境保持服务为前台进程,便于 e2e 收集输出并停止进程。
41
+ exec env PORT="${DEPLOY_RUN_PORT}" pnpm tsx watch server/server.ts
42
+ <% } else { %>
43
+ LOG_DIR="${COZE_LOG_DIR:-${COZE_WORKSPACE_PATH}/logs}"
44
+ LOG_FILE="${LOG_DIR}/server.log"
45
+ PID_FILE="${LOG_DIR}/server.pid"
46
+
47
+ # coze-daemon 会在 runtime shell 退出时清理原进程组。
48
+ # 通过 Node detached spawn 创建独立 session/进程组,并将 stdio 直接写入日志。
49
+ spawn_detached() {
50
+ local cwd="$1"
51
+ local log_file="$2"
52
+ shift 2
53
+
54
+ node - "$cwd" "$log_file" "$@" <<'NODE'
55
+ const fs = require('node:fs');
56
+ const { spawn } = require('node:child_process');
57
+
58
+ const [cwd, logFile, command, ...args] = process.argv.slice(2);
59
+ if (!cwd || !logFile || !command) {
60
+ throw new Error('spawn_detached 缺少 cwd、log_file 或 command');
61
+ }
62
+
63
+ const logFd = fs.openSync(logFile, 'a');
64
+ try {
65
+ const child = spawn(command, args, {
66
+ cwd,
67
+ detached: true,
68
+ env: process.env,
69
+ stdio: ['ignore', logFd, logFd],
70
+ });
71
+ child.unref();
72
+ process.stdout.write(String(child.pid));
73
+ } finally {
74
+ fs.closeSync(logFd);
75
+ }
76
+ NODE
77
+ }
78
+
79
+ stop_detached() {
80
+ local pid="${1:-}"
81
+ if [[ -z "${pid}" ]]; then
82
+ return
83
+ fi
84
+
85
+ kill -TERM -- "-${pid}" 2>/dev/null || kill -TERM "${pid}" 2>/dev/null || true
86
+ sleep 1
87
+ kill -KILL -- "-${pid}" 2>/dev/null || true
88
+ }
89
+
90
+ # 监听端口的是孙进程(pnpm -> tsx -> node),只清端口会漏掉上层 pnpm/tsx,
91
+ # 所以先按上次记录的 PID 把整个进程组回收掉。
92
+ if [[ -f "${PID_FILE}" ]]; then
93
+ stop_detached "$(cat "${PID_FILE}" 2>/dev/null || true)"
94
+ rm -f "${PID_FILE}"
95
+ fi
96
+
35
97
  echo "Clearing port ${DEPLOY_RUN_PORT} before start."
36
98
  kill_port_if_listening
37
99
  echo "Starting express + Vite dev server on port ${DEPLOY_RUN_PORT}..."
38
100
 
39
- PORT=${DEPLOY_RUN_PORT} pnpm tsx watch server/server.ts
101
+ mkdir -p "${LOG_DIR}"
102
+ : > "${LOG_FILE}"
103
+
104
+ export PORT="${DEPLOY_RUN_PORT}"
105
+ server_pid="$(spawn_detached "${COZE_WORKSPACE_PATH}" "${LOG_FILE}" \
106
+ "$(command -v pnpm)" tsx watch server/server.ts)"
107
+ echo "${server_pid}" > "${PID_FILE}"
108
+
109
+ sleep 1
110
+ if [[ -z "${server_pid}" ]] || ! kill -0 "${server_pid}" 2>/dev/null; then
111
+ echo "Dev server failed to start. See ${LOG_FILE}." >&2
112
+ tail -n 20 "${LOG_FILE}" >&2 || true
113
+ rm -f "${PID_FILE}"
114
+ exit 1
115
+ fi
116
+
117
+ echo "Dev server started (PID: ${server_pid})."
118
+ echo "Log file: ${LOG_FILE}"
119
+ echo "PID file: ${PID_FILE}"
120
+ <% } %>
@@ -2,6 +2,7 @@
2
2
  import { spawn } from 'child_process';
3
3
  import { resolve, join, basename } from 'path';
4
4
  import { appendFileSync, openSync, closeSync, mkdirSync } from 'fs';
5
+ import { homedir } from 'os';
5
6
 
6
7
 
7
8
 
@@ -81,7 +82,8 @@ const config = {
81
82
  const projectRoot = resolve(outputPath);
82
83
 
83
84
  // Determine log directory
84
- const logDir = process.env.COZE_LOG_DIR || resolve(__dirname, '../.log');
85
+ const cozeHome = process.env.COZE_HOME || join(homedir(), '.coze');
86
+ const logDir = process.env.COZE_LOG_DIR || join(cozeHome, 'logs');
85
87
  mkdirSync(logDir, { recursive: true });
86
88
 
87
89
  // Use project name in log file to avoid conflicts