@coze-arch/cli 0.0.36-alpha.2c0689 → 0.0.36-alpha.4e6503

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.
Files changed (151) hide show
  1. package/README.md +104 -66
  2. package/lib/__templates__/expo/.cozeproj/scripts/dev_run.sh +18 -74
  3. package/lib/__templates__/expo/.cozeproj/scripts/prod_run.sh +1 -1
  4. package/lib/__templates__/expo/.cozeproj/scripts/server_dev_run.sh +1 -1
  5. package/lib/__templates__/expo/client/metro.config.js +1 -3
  6. package/lib/__templates__/expo/pnpm-lock.yaml +5 -5
  7. package/lib/__templates__/expo/server/package.json +2 -2
  8. package/lib/__templates__/expo/server/src/index.ts +1 -1
  9. package/lib/__templates__/expo/template.config.js +2 -11
  10. package/lib/__templates__/native-static/.coze +0 -2
  11. package/lib/__templates__/nextjs/.coze +0 -5
  12. package/lib/__templates__/nextjs/package.json +1 -1
  13. package/lib/__templates__/nextjs/pnpm-lock.yaml +5 -5
  14. package/lib/__templates__/nextjs/scripts/dev.sh +2 -83
  15. package/lib/__templates__/nextjs/template.config.js +2 -4
  16. package/lib/__templates__/nuxt-vue/.coze +0 -5
  17. package/lib/__templates__/nuxt-vue/package.json +1 -1
  18. package/lib/__templates__/nuxt-vue/pnpm-lock.yaml +5 -5
  19. package/lib/__templates__/nuxt-vue/scripts/dev.sh +1 -82
  20. package/lib/__templates__/pi-agent/package.json +1 -1
  21. package/lib/__templates__/pi-agent/pnpm-lock.yaml +5 -5
  22. package/lib/__templates__/taro/.cozeproj/scripts/deploy_run.sh +1 -1
  23. package/lib/__templates__/taro/.cozeproj/scripts/dev_run.sh +68 -150
  24. package/lib/__templates__/taro/AGENTS.md +7 -11
  25. package/lib/__templates__/taro/README.md +4 -4
  26. package/lib/__templates__/taro/config/index.ts +2 -10
  27. package/lib/__templates__/taro/pnpm-lock.yaml +5 -5
  28. package/lib/__templates__/taro/server/package.json +1 -1
  29. package/lib/__templates__/taro/server/src/main.ts +2 -8
  30. package/lib/__templates__/templates.json +1 -51
  31. package/lib/__templates__/vite/package.json +1 -1
  32. package/lib/__templates__/vite/pnpm-lock.yaml +5 -5
  33. package/lib/__templates__/vite/scripts/build.ps1 +1 -1
  34. package/lib/__templates__/vite/scripts/dev.ps1 +65 -9
  35. package/lib/__templates__/vite/scripts/dev.sh +1 -82
  36. package/lib/__templates__/vite/scripts/start.ps1 +8 -2
  37. package/lib/__templates__/vite/template.config.js +2 -4
  38. package/lib/cli.js +205 -3426
  39. package/package.json +3 -5
  40. package/docs/deploy.md +0 -172
  41. package/lib/__templates__/native-static/scripts/serve.ps1 +0 -7
  42. package/lib/__templates__/nextjs/scripts/build.ps1 +0 -16
  43. package/lib/__templates__/nextjs/scripts/dev.ps1 +0 -63
  44. package/lib/__templates__/nextjs/scripts/prepare.ps1 +0 -18
  45. package/lib/__templates__/nextjs/scripts/start.ps1 +0 -11
  46. package/lib/__templates__/nextjs/scripts/validate.ps1 +0 -8
  47. package/lib/__templates__/nuxt-vue/scripts/build.ps1 +0 -12
  48. package/lib/__templates__/nuxt-vue/scripts/dev.ps1 +0 -63
  49. package/lib/__templates__/nuxt-vue/scripts/prepare.ps1 +0 -12
  50. package/lib/__templates__/nuxt-vue/scripts/start.ps1 +0 -11
  51. package/lib/__templates__/nuxt-vue/scripts/validate.ps1 +0 -8
  52. package/lib/__templates__/phaser/.coze +0 -18
  53. package/lib/__templates__/phaser/README.md +0 -45
  54. package/lib/__templates__/phaser/_gitignore +0 -23
  55. package/lib/__templates__/phaser/_npmrc +0 -14
  56. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0001.png +0 -0
  57. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0002.png +0 -0
  58. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0003.png +0 -0
  59. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0004.png +0 -0
  60. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0005.png +0 -0
  61. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0006.png +0 -0
  62. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0007.png +0 -0
  63. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0008.png +0 -0
  64. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0009.png +0 -0
  65. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0010.png +0 -0
  66. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0011.png +0 -0
  67. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0012.png +0 -0
  68. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0013.png +0 -0
  69. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0014.png +0 -0
  70. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0015.png +0 -0
  71. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0016.png +0 -0
  72. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0017.png +0 -0
  73. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0018.png +0 -0
  74. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0019.png +0 -0
  75. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0020.png +0 -0
  76. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0021.png +0 -0
  77. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0022.png +0 -0
  78. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0023.png +0 -0
  79. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0024.png +0 -0
  80. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/manifest.json +0 -11
  81. package/lib/__templates__/phaser/debug-runtime/flow-graph.json +0 -20
  82. package/lib/__templates__/phaser/index.html +0 -12
  83. package/lib/__templates__/phaser/package.json +0 -31
  84. package/lib/__templates__/phaser/pnpm-lock.yaml +0 -661
  85. package/lib/__templates__/phaser/scripts/build.ps1 +0 -12
  86. package/lib/__templates__/phaser/scripts/build.sh +0 -8
  87. package/lib/__templates__/phaser/scripts/dev.ps1 +0 -49
  88. package/lib/__templates__/phaser/scripts/dev.sh +0 -82
  89. package/lib/__templates__/phaser/scripts/prepare.ps1 +0 -8
  90. package/lib/__templates__/phaser/scripts/prepare.sh +0 -7
  91. package/lib/__templates__/phaser/scripts/spawn-detached.cjs +0 -29
  92. package/lib/__templates__/phaser/scripts/start.ps1 +0 -49
  93. package/lib/__templates__/phaser/scripts/start.sh +0 -82
  94. package/lib/__templates__/phaser/scripts/validate.ps1 +0 -7
  95. package/lib/__templates__/phaser/scripts/validate.sh +0 -7
  96. package/lib/__templates__/phaser/src/assets.ts +0 -15
  97. package/lib/__templates__/phaser/src/global.d.ts +0 -39
  98. package/lib/__templates__/phaser/src/main.ts +0 -28
  99. package/lib/__templates__/phaser/src/scene/BootScene.ts +0 -213
  100. package/lib/__templates__/phaser/src/scene/DevLoadingScene.ts +0 -69
  101. package/lib/__templates__/phaser/src/style.css +0 -28
  102. package/lib/__templates__/phaser/src/types.ts +0 -32
  103. package/lib/__templates__/phaser/src/utils/asset-loader.ts +0 -319
  104. package/lib/__templates__/phaser/src/utils/index.ts +0 -2
  105. package/lib/__templates__/phaser/src/utils/mark-editable.ts +0 -13
  106. package/lib/__templates__/phaser/template.config.js +0 -43
  107. package/lib/__templates__/phaser/tsconfig.json +0 -23
  108. package/lib/__templates__/phaser/vite.config.ts +0 -96
  109. package/lib/__templates__/phaser-static/.coze +0 -15
  110. package/lib/__templates__/phaser-static/README.md +0 -40
  111. package/lib/__templates__/phaser-static/_gitignore +0 -6
  112. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0001.png +0 -0
  113. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0002.png +0 -0
  114. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0003.png +0 -0
  115. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0004.png +0 -0
  116. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0005.png +0 -0
  117. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0006.png +0 -0
  118. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0007.png +0 -0
  119. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0008.png +0 -0
  120. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0009.png +0 -0
  121. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0010.png +0 -0
  122. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0011.png +0 -0
  123. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0012.png +0 -0
  124. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0013.png +0 -0
  125. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0014.png +0 -0
  126. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0015.png +0 -0
  127. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0016.png +0 -0
  128. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0017.png +0 -0
  129. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0018.png +0 -0
  130. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0019.png +0 -0
  131. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0020.png +0 -0
  132. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0021.png +0 -0
  133. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0022.png +0 -0
  134. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0023.png +0 -0
  135. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0024.png +0 -0
  136. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/manifest.json +0 -11
  137. package/lib/__templates__/phaser-static/debug-runtime/flow-graph.json +0 -20
  138. package/lib/__templates__/phaser-static/index.html +0 -17
  139. package/lib/__templates__/phaser-static/scripts/serve.ps1 +0 -7
  140. package/lib/__templates__/phaser-static/src/assets.js +0 -15
  141. package/lib/__templates__/phaser-static/src/main.js +0 -26
  142. package/lib/__templates__/phaser-static/src/phaser.js +0 -7
  143. package/lib/__templates__/phaser-static/src/scene/BootScene.js +0 -205
  144. package/lib/__templates__/phaser-static/src/scene/DevLoadingScene.js +0 -67
  145. package/lib/__templates__/phaser-static/src/style.css +0 -28
  146. package/lib/__templates__/phaser-static/src/utils/asset-loader.js +0 -267
  147. package/lib/__templates__/phaser-static/src/utils/index.js +0 -2
  148. package/lib/__templates__/phaser-static/src/utils/mark-editable.js +0 -3
  149. package/lib/__templates__/phaser-static/template.config.js +0 -35
  150. package/lib/deploy/package-project.js +0 -244
  151. package/lib/deploy/package-project.py +0 -183
@@ -12,12 +12,6 @@ function parsePort(): number {
12
12
  return port;
13
13
  }
14
14
  }
15
-
16
- const envPort = parseInt(process.env.SERVER_PORT || '', 10);
17
- if (!isNaN(envPort) && envPort > 0 && envPort < 65536) {
18
- return envPort;
19
- }
20
-
21
15
  return <%= serverPort %>;
22
16
  }
23
17
 
@@ -44,12 +38,12 @@ async function bootstrap() {
44
38
  console.log(`Server running on http://localhost:${port}`);
45
39
  } catch (err) {
46
40
  if (err.code === 'EADDRINUSE') {
47
- console.error(`❌ 端口 ${port} 被占用,请设置其他 SERVER_PORT 后重试。`);
41
+ console.error(`❌ 端口 \({port} 被占用! 请运行 'npx kill-port \){port}' 然后重试。`);
48
42
  process.exit(1);
49
43
  } else {
50
44
  throw err;
51
45
  }
52
46
  }
53
- console.log(`Application is running on: http://localhost:${port}`);
47
+ console.log(`Application is running on: http://localhost:<%= serverPort %>`);
54
48
  }
55
49
  bootstrap();
@@ -16,17 +16,10 @@
16
16
  },
17
17
  "port": {
18
18
  "type": "number",
19
- "default": 5000,
19
+ "default": 8081,
20
20
  "minimum": 1024,
21
21
  "maximum": 65535,
22
22
  "description": "Metro bundler port"
23
- },
24
- "serverPort": {
25
- "type": "number",
26
- "default": 9091,
27
- "minimum": 1024,
28
- "maximum": 65535,
29
- "description": "Express backend server port"
30
23
  }
31
24
  },
32
25
  "required": [],
@@ -101,49 +94,6 @@
101
94
  "additionalProperties": false
102
95
  }
103
96
  },
104
- {
105
- "name": "phaser",
106
- "description": "Phaser(2D 游戏):`coze-dev init ${COZE_WORKSPACE_PATH} --template phaser`\n- 适用:基于 Phaser 3、Vite 和 TypeScript 的 2D Web 游戏。",
107
- "location": "./phaser",
108
- "paramsSchema": {
109
- "type": "object",
110
- "properties": {
111
- "appName": {
112
- "type": "string",
113
- "minLength": 1,
114
- "pattern": "^[a-z0-9-]+$",
115
- "description": "Application name (lowercase, alphanumeric and hyphens only)"
116
- },
117
- "port": {
118
- "type": "number",
119
- "default": 5000,
120
- "minimum": 1024,
121
- "maximum": 65535,
122
- "description": "Development and preview server port"
123
- }
124
- },
125
- "required": [],
126
- "additionalProperties": false
127
- }
128
- },
129
- {
130
- "name": "phaser-static",
131
- "description": "Phaser Static(纯静态 2D 游戏):coze-dev init ${COZE_WORKSPACE_PATH} --template phaser-static\n- 适用:浏览器原生 JavaScript ESM 的 Phaser 3 游戏。\n- Phaser 与 Phaser Bridge 从 CDN 加载;无需 npm、Vite 或 TypeScript。",
132
- "location": "./phaser-static",
133
- "paramsSchema": {
134
- "type": "object",
135
- "properties": {
136
- "appName": {
137
- "type": "string",
138
- "minLength": 1,
139
- "pattern": "^[a-z0-9-]+$",
140
- "description": "Application name (lowercase, alphanumeric and hyphens only)"
141
- }
142
- },
143
- "required": [],
144
- "additionalProperties": false
145
- }
146
- },
147
97
  {
148
98
  "name": "pi-agent",
149
99
  "description": "Pi Agent:`coze-dev init ${COZE_WORKSPACE_PATH} --template pi-agent`\n- 适用:基于 pi-agent-core 的 AI Agent 应用\n- 支持飞书、微信等多渠道接入\n- 内置 Dashboard 管理面板\n- 使用 TypeScript + Express + Vite",
@@ -22,7 +22,7 @@
22
22
  "@types/express": "^5.0.0",
23
23
  "@types/node": "^22.10.5",
24
24
  "autoprefixer": "^10.4.20",
25
- "coze-coding-dev-sdk": "^0.7.25-beta.8",
25
+ "coze-coding-dev-sdk": "^0.7.16",
26
26
  "esbuild": "^0.24.2",
27
27
  "eslint": "^9",
28
28
  "eslint-plugin-import": "^2.32.0",
@@ -32,8 +32,8 @@ importers:
32
32
  specifier: ^10.4.20
33
33
  version: 10.4.23(postcss@8.5.6)
34
34
  coze-coding-dev-sdk:
35
- specifier: ^0.7.25-beta.8
36
- version: 0.7.25-beta.8(openai@6.16.0(ws@8.19.0)(zod@4.3.5))(ws@8.19.0)
35
+ specifier: ^0.7.16
36
+ version: 0.7.16(openai@6.16.0(ws@8.19.0)(zod@4.3.5))(ws@8.19.0)
37
37
  esbuild:
38
38
  specifier: ^0.27.2
39
39
  version: 0.27.2
@@ -910,8 +910,8 @@ packages:
910
910
  typescript:
911
911
  optional: true
912
912
 
913
- coze-coding-dev-sdk@0.7.25-beta.8:
914
- resolution: {integrity: sha512-RSKlXCO0W/OPDjx9D9JICn2cGeOJw3iG+y0Pr1AhAf7YdAjjNbBZoG7qfg0Zg2SqgaVN2qSLQFmKPbhNq9ZWSg==}
913
+ coze-coding-dev-sdk@0.7.16:
914
+ resolution: {integrity: sha512-B7gRPBa+sfrZL8ur0+F/92SOgZgFaWD/fOnCN2DjthnHSdmCYhAJWCfqzG2oO2vwTiYCXkKUuTBZ3MJLMj886g==}
915
915
  engines: {node: '>=18.0.0'}
916
916
  hasBin: true
917
917
 
@@ -3281,7 +3281,7 @@ snapshots:
3281
3281
  optionalDependencies:
3282
3282
  typescript: 5.9.3
3283
3283
 
3284
- coze-coding-dev-sdk@0.7.25-beta.8(openai@6.16.0(ws@8.19.0)(zod@4.3.5))(ws@8.19.0):
3284
+ coze-coding-dev-sdk@0.7.16(openai@6.16.0(ws@8.19.0)(zod@4.3.5))(ws@8.19.0):
3285
3285
  dependencies:
3286
3286
  '@langchain/core': 1.1.16(openai@6.16.0(ws@8.19.0)(zod@4.3.5))
3287
3287
  '@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)
@@ -4,7 +4,7 @@ $workspace = if ($env:COZE_WORKSPACE_PATH) { $env:COZE_WORKSPACE_PATH } else { (
4
4
  Set-Location $workspace
5
5
 
6
6
  Write-Host "Installing dependencies..."
7
- & pnpm install --prefer-frozen-lockfile --prefer-offline --loglevel debug --reporter=append-only
7
+ & pnpm install --frozen-lockfile --prefer-offline --loglevel debug --reporter=append-only
8
8
  if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
9
9
 
10
10
  Write-Host "Building frontend with Vite..."
@@ -7,9 +7,9 @@ function Get-WorkspacePath {
7
7
  return (Get-Location).Path
8
8
  }
9
9
 
10
- function Stop-ProcessTree([int] $processId) {
11
- if ($processId -gt 0 -and (Get-Process -Id $processId -ErrorAction SilentlyContinue)) {
12
- & taskkill.exe /PID $processId /T /F *> $null
10
+ function Stop-ProcessTree([int] $targetProcessId) {
11
+ if ($targetProcessId -gt 0 -and (Get-Process -Id $targetProcessId -ErrorAction SilentlyContinue)) {
12
+ & taskkill.exe /PID $targetProcessId /T /F *> $null
13
13
  }
14
14
  }
15
15
 
@@ -20,11 +20,40 @@ function Stop-ListeningProcess([int] $port) {
20
20
  }
21
21
  }
22
22
 
23
+ function Test-PortListening([int] $port) {
24
+ return $null -ne (Get-NetTCPConnection -LocalPort $port -State Listen -ErrorAction SilentlyContinue | Select-Object -First 1)
25
+ }
26
+
27
+ function Wait-PortState([int] $port, [bool] $listening, [int] $timeoutSeconds) {
28
+ $deadline = (Get-Date).AddSeconds($timeoutSeconds)
29
+ do {
30
+ if ((Test-PortListening $port) -eq $listening) {
31
+ return $true
32
+ }
33
+ Start-Sleep -Milliseconds 250
34
+ } while ((Get-Date) -lt $deadline)
35
+ return $false
36
+ }
37
+
38
+ function Get-Port {
39
+ $rawPort = if ($env:DEPLOY_RUN_PORT) { $env:DEPLOY_RUN_PORT } elseif ($env:PORT) { $env:PORT } else { "<%= port %>" }
40
+ $parsedPort = 0
41
+ if (-not [int]::TryParse($rawPort, [ref] $parsedPort) -or $parsedPort -lt 1 -or $parsedPort -gt 65535) {
42
+ throw "Invalid port '$rawPort'. Expected an integer between 1 and 65535."
43
+ }
44
+ return $parsedPort
45
+ }
46
+
23
47
  $workspace = Get-WorkspacePath
24
- $defaultPort = <%= port %>
25
- $port = if ($env:DEPLOY_RUN_PORT) { [int] $env:DEPLOY_RUN_PORT } elseif ($env:PORT) { [int] $env:PORT } else { $defaultPort }
48
+ if (-not (Test-Path -LiteralPath $workspace -PathType Container)) {
49
+ throw "Workspace directory does not exist: $workspace"
50
+ }
51
+ $port = Get-Port
26
52
  Set-Location $workspace
27
53
  Stop-ListeningProcess $port
54
+ if (-not (Wait-PortState $port $false 10)) {
55
+ throw "Port $port is still in use after stopping the previous process."
56
+ }
28
57
 
29
58
  <% if (process.env.NODE_ENV === 'test') { %>
30
59
  $env:PORT = "$port"
@@ -38,7 +67,10 @@ $pidFile = Join-Path $logDirectory "server.pid"
38
67
  New-Item -ItemType Directory -Force -Path $logDirectory | Out-Null
39
68
 
40
69
  if (Test-Path $pidFile) {
41
- Stop-ProcessTree ([int] (Get-Content $pidFile -Raw))
70
+ $previousPid = 0
71
+ if ([int]::TryParse((Get-Content $pidFile -Raw).Trim(), [ref] $previousPid)) {
72
+ Stop-ProcessTree $previousPid
73
+ }
42
74
  Remove-Item $pidFile -Force
43
75
  }
44
76
 
@@ -51,13 +83,37 @@ try {
51
83
  }
52
84
 
53
85
  $process.Id | Set-Content $pidFile
54
- Start-Sleep -Seconds 1
55
- if ($process.HasExited) {
86
+ $processStartTime = $process.StartTime.ToUniversalTime().Ticks
87
+ if (-not (Wait-PortState $port $true 30)) {
56
88
  Get-Content $errorLogFile -Tail 20 -ErrorAction SilentlyContinue
89
+ Stop-ProcessTree $process.Id
57
90
  Remove-Item $pidFile -Force -ErrorAction SilentlyContinue
58
- exit 1
91
+ throw "Dev server did not listen on port $port within 30 seconds."
92
+ }
93
+
94
+ # 后台服务最长运行 20 分钟。回收前校验启动时间,避免 PID 复用后误杀无关进程。
95
+ $pidFileBase64 = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($pidFile))
96
+ $watchdogScript = @'
97
+ $targetProcessId = __PROCESS_ID__
98
+ $expectedStartTime = __START_TIME__
99
+ $pidFile = [Text.Encoding]::Unicode.GetString([Convert]::FromBase64String('__PID_FILE__'))
100
+ Start-Sleep -Seconds 1200
101
+ $target = Get-Process -Id $targetProcessId -ErrorAction SilentlyContinue
102
+ if ($target -and $target.StartTime.ToUniversalTime().Ticks -eq $expectedStartTime) {
103
+ & taskkill.exe /PID $targetProcessId /T /F *> $null
104
+ }
105
+ $recordedPid = 0
106
+ if ((Test-Path -LiteralPath $pidFile) -and [int]::TryParse((Get-Content -LiteralPath $pidFile -Raw).Trim(), [ref] $recordedPid) -and $recordedPid -eq $targetProcessId) {
107
+ Remove-Item -LiteralPath $pidFile -Force -ErrorAction SilentlyContinue
59
108
  }
109
+ '@
110
+ $watchdogScript = $watchdogScript.Replace('__PROCESS_ID__', "$($process.Id)").Replace('__START_TIME__', "$processStartTime").Replace('__PID_FILE__', $pidFileBase64)
111
+ $encodedWatchdog = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($watchdogScript))
112
+ Start-Process -FilePath "powershell.exe" -WindowStyle Hidden -ArgumentList @(
113
+ "-NoProfile", "-ExecutionPolicy", "Bypass", "-EncodedCommand", $encodedWatchdog
114
+ ) | Out-Null
60
115
 
61
116
  Write-Host "Dev server started (PID: $($process.Id))."
117
+ Write-Host "Auto stop after 1200 seconds."
62
118
  Write-Host "Log file: $logFile"
63
119
  <% } %>
@@ -32,89 +32,8 @@ 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
-
97
35
  echo "Clearing port ${DEPLOY_RUN_PORT} before start."
98
36
  kill_port_if_listening
99
37
  echo "Starting express + Vite dev server on port ${DEPLOY_RUN_PORT}..."
100
38
 
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
- <% } %>
39
+ PORT=${DEPLOY_RUN_PORT} pnpm tsx watch server/server.ts
@@ -1,8 +1,14 @@
1
1
  $ErrorActionPreference = "Stop"
2
2
 
3
3
  $workspace = if ($env:COZE_WORKSPACE_PATH) { $env:COZE_WORKSPACE_PATH } else { (Get-Location).Path }
4
- $defaultPort = <%= port %>
5
- $port = if ($env:DEPLOY_RUN_PORT) { $env:DEPLOY_RUN_PORT } elseif ($env:PORT) { $env:PORT } else { $defaultPort }
4
+ if (-not (Test-Path -LiteralPath $workspace -PathType Container)) {
5
+ throw "Workspace directory does not exist: $workspace"
6
+ }
7
+ $rawPort = if ($env:DEPLOY_RUN_PORT) { $env:DEPLOY_RUN_PORT } elseif ($env:PORT) { $env:PORT } else { "<%= port %>" }
8
+ $port = 0
9
+ if (-not [int]::TryParse($rawPort, [ref] $port) -or $port -lt 1 -or $port -gt 65535) {
10
+ throw "Invalid port '$rawPort'. Expected an integer between 1 and 65535."
11
+ }
6
12
  Set-Location $workspace
7
13
 
8
14
  Write-Host "Starting express production server on port $port..."
@@ -2,7 +2,6 @@
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';
6
5
 
7
6
 
8
7
 
@@ -73,7 +72,7 @@ const config = {
73
72
  }
74
73
 
75
74
  const cmd = 'pnpm';
76
- const args = ['update', 'coze-coding-dev-sdk@^0.7.25-beta.8'];
75
+ const args = ['update', 'coze-coding-dev-sdk@^0.7.0'];
77
76
  console.log(
78
77
  `\nTriggering: ${cmd} ${args.join(' ')} (running in background)`,
79
78
  );
@@ -82,8 +81,7 @@ const config = {
82
81
  const projectRoot = resolve(outputPath);
83
82
 
84
83
  // Determine log directory
85
- const cozeHome = process.env.COZE_HOME || join(homedir(), '.coze');
86
- const logDir = process.env.COZE_LOG_DIR || join(cozeHome, 'logs');
84
+ const logDir = process.env.COZE_LOG_DIR || resolve(__dirname, '../.log');
87
85
  mkdirSync(logDir, { recursive: true });
88
86
 
89
87
  // Use project name in log file to avoid conflicts