@coze-arch/cli 0.0.37 → 0.1.3-alpha.8d71d5

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 (154) hide show
  1. package/README.md +69 -104
  2. package/docs/deploy.md +181 -0
  3. package/lib/__templates__/expo/.cozeproj/scripts/dev_run.sh +108 -19
  4. package/lib/__templates__/expo/.cozeproj/scripts/prod_run.sh +1 -1
  5. package/lib/__templates__/expo/.cozeproj/scripts/server_dev_run.sh +1 -1
  6. package/lib/__templates__/expo/client/metro.config.js +3 -1
  7. package/lib/__templates__/expo/pnpm-lock.yaml +5 -5
  8. package/lib/__templates__/expo/server/package.json +2 -2
  9. package/lib/__templates__/expo/server/src/index.ts +1 -1
  10. package/lib/__templates__/expo/template.config.js +11 -2
  11. package/lib/__templates__/native-static/.coze +4 -2
  12. package/lib/__templates__/native-static/scripts/serve.ps1 +7 -0
  13. package/lib/__templates__/nextjs/.coze +5 -0
  14. package/lib/__templates__/nextjs/package.json +2 -2
  15. package/lib/__templates__/nextjs/pnpm-lock.yaml +5 -5
  16. package/lib/__templates__/nextjs/scripts/build.ps1 +16 -0
  17. package/lib/__templates__/nextjs/scripts/dev.ps1 +63 -0
  18. package/lib/__templates__/nextjs/scripts/dev.sh +234 -7
  19. package/lib/__templates__/nextjs/scripts/prepare.ps1 +18 -0
  20. package/lib/__templates__/nextjs/scripts/start.ps1 +11 -0
  21. package/lib/__templates__/nextjs/scripts/validate.ps1 +8 -0
  22. package/lib/__templates__/nextjs/template.config.js +4 -2
  23. package/lib/__templates__/nuxt-vue/.coze +5 -0
  24. package/lib/__templates__/nuxt-vue/package.json +1 -1
  25. package/lib/__templates__/nuxt-vue/pnpm-lock.yaml +5 -5
  26. package/lib/__templates__/nuxt-vue/scripts/build.ps1 +12 -0
  27. package/lib/__templates__/nuxt-vue/scripts/dev.ps1 +63 -0
  28. package/lib/__templates__/nuxt-vue/scripts/dev.sh +232 -3
  29. package/lib/__templates__/nuxt-vue/scripts/prepare.ps1 +12 -0
  30. package/lib/__templates__/nuxt-vue/scripts/start.ps1 +11 -0
  31. package/lib/__templates__/nuxt-vue/scripts/validate.ps1 +8 -0
  32. package/lib/__templates__/phaser/.coze +18 -0
  33. package/lib/__templates__/phaser/README.md +45 -0
  34. package/lib/__templates__/phaser/_gitignore +23 -0
  35. package/lib/__templates__/phaser/_npmrc +14 -0
  36. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0001.png +0 -0
  37. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0002.png +0 -0
  38. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0003.png +0 -0
  39. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0004.png +0 -0
  40. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0005.png +0 -0
  41. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0006.png +0 -0
  42. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0007.png +0 -0
  43. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0008.png +0 -0
  44. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0009.png +0 -0
  45. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0010.png +0 -0
  46. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0011.png +0 -0
  47. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0012.png +0 -0
  48. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0013.png +0 -0
  49. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0014.png +0 -0
  50. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0015.png +0 -0
  51. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0016.png +0 -0
  52. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0017.png +0 -0
  53. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0018.png +0 -0
  54. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0019.png +0 -0
  55. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0020.png +0 -0
  56. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0021.png +0 -0
  57. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0022.png +0 -0
  58. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0023.png +0 -0
  59. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/frame_0024.png +0 -0
  60. package/lib/__templates__/phaser/assets/image_sequence/coze-game-loading/manifest.json +11 -0
  61. package/lib/__templates__/phaser/debug-runtime/flow-graph.json +20 -0
  62. package/lib/__templates__/phaser/index.html +12 -0
  63. package/lib/__templates__/phaser/package.json +31 -0
  64. package/lib/__templates__/phaser/pnpm-lock.yaml +661 -0
  65. package/lib/__templates__/phaser/scripts/build.ps1 +12 -0
  66. package/lib/__templates__/phaser/scripts/build.sh +8 -0
  67. package/lib/__templates__/phaser/scripts/dev.ps1 +49 -0
  68. package/lib/__templates__/phaser/scripts/dev.sh +82 -0
  69. package/lib/__templates__/phaser/scripts/prepare.ps1 +8 -0
  70. package/lib/__templates__/phaser/scripts/prepare.sh +7 -0
  71. package/lib/__templates__/phaser/scripts/spawn-detached.cjs +29 -0
  72. package/lib/__templates__/phaser/scripts/start.ps1 +49 -0
  73. package/lib/__templates__/phaser/scripts/start.sh +82 -0
  74. package/lib/__templates__/phaser/scripts/validate.ps1 +7 -0
  75. package/lib/__templates__/phaser/scripts/validate.sh +7 -0
  76. package/lib/__templates__/phaser/src/assets.ts +15 -0
  77. package/lib/__templates__/phaser/src/global.d.ts +39 -0
  78. package/lib/__templates__/phaser/src/main.ts +28 -0
  79. package/lib/__templates__/phaser/src/scene/BootScene.ts +213 -0
  80. package/lib/__templates__/phaser/src/scene/DevLoadingScene.ts +69 -0
  81. package/lib/__templates__/phaser/src/style.css +28 -0
  82. package/lib/__templates__/phaser/src/types.ts +32 -0
  83. package/lib/__templates__/phaser/src/utils/asset-loader.ts +319 -0
  84. package/lib/__templates__/phaser/src/utils/index.ts +2 -0
  85. package/lib/__templates__/phaser/src/utils/mark-editable.ts +13 -0
  86. package/lib/__templates__/phaser/template.config.js +43 -0
  87. package/lib/__templates__/phaser/tsconfig.json +23 -0
  88. package/lib/__templates__/phaser/vite.config.ts +96 -0
  89. package/lib/__templates__/phaser-static/.coze +15 -0
  90. package/lib/__templates__/phaser-static/README.md +40 -0
  91. package/lib/__templates__/phaser-static/_gitignore +6 -0
  92. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0001.png +0 -0
  93. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0002.png +0 -0
  94. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0003.png +0 -0
  95. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0004.png +0 -0
  96. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0005.png +0 -0
  97. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0006.png +0 -0
  98. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0007.png +0 -0
  99. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0008.png +0 -0
  100. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0009.png +0 -0
  101. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0010.png +0 -0
  102. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0011.png +0 -0
  103. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0012.png +0 -0
  104. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0013.png +0 -0
  105. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0014.png +0 -0
  106. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0015.png +0 -0
  107. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0016.png +0 -0
  108. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0017.png +0 -0
  109. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0018.png +0 -0
  110. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0019.png +0 -0
  111. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0020.png +0 -0
  112. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0021.png +0 -0
  113. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0022.png +0 -0
  114. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0023.png +0 -0
  115. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/frame_0024.png +0 -0
  116. package/lib/__templates__/phaser-static/assets/image_sequence/coze-game-loading/manifest.json +11 -0
  117. package/lib/__templates__/phaser-static/debug-runtime/flow-graph.json +20 -0
  118. package/lib/__templates__/phaser-static/index.html +17 -0
  119. package/lib/__templates__/phaser-static/scripts/serve.ps1 +7 -0
  120. package/lib/__templates__/phaser-static/src/assets.js +15 -0
  121. package/lib/__templates__/phaser-static/src/main.js +26 -0
  122. package/lib/__templates__/phaser-static/src/phaser.js +7 -0
  123. package/lib/__templates__/phaser-static/src/scene/BootScene.js +205 -0
  124. package/lib/__templates__/phaser-static/src/scene/DevLoadingScene.js +67 -0
  125. package/lib/__templates__/phaser-static/src/style.css +28 -0
  126. package/lib/__templates__/phaser-static/src/utils/asset-loader.js +267 -0
  127. package/lib/__templates__/phaser-static/src/utils/index.js +2 -0
  128. package/lib/__templates__/phaser-static/src/utils/mark-editable.js +3 -0
  129. package/lib/__templates__/phaser-static/template.config.js +35 -0
  130. package/lib/__templates__/pi-agent/package.json +1 -1
  131. package/lib/__templates__/pi-agent/pnpm-lock.yaml +5 -5
  132. package/lib/__templates__/taro/.cozeproj/scripts/deploy_run.sh +1 -1
  133. package/lib/__templates__/taro/.cozeproj/scripts/dev_run.sh +178 -68
  134. package/lib/__templates__/taro/AGENTS.md +11 -7
  135. package/lib/__templates__/taro/README.md +4 -4
  136. package/lib/__templates__/taro/config/index.ts +10 -2
  137. package/lib/__templates__/taro/pnpm-lock.yaml +5 -5
  138. package/lib/__templates__/taro/server/package.json +1 -1
  139. package/lib/__templates__/taro/server/src/main.ts +8 -2
  140. package/lib/__templates__/templates.json +51 -1
  141. package/lib/__templates__/vite/.coze +5 -0
  142. package/lib/__templates__/vite/package.json +1 -1
  143. package/lib/__templates__/vite/pnpm-lock.yaml +5 -5
  144. package/lib/__templates__/vite/scripts/build.ps1 +16 -0
  145. package/lib/__templates__/vite/scripts/dev.ps1 +63 -0
  146. package/lib/__templates__/vite/scripts/dev.sh +110 -1
  147. package/lib/__templates__/vite/scripts/prepare.ps1 +18 -0
  148. package/lib/__templates__/vite/scripts/start.ps1 +11 -0
  149. package/lib/__templates__/vite/scripts/validate.ps1 +8 -0
  150. package/lib/__templates__/vite/template.config.js +4 -2
  151. package/lib/cli.js +3718 -211
  152. package/lib/deploy/package-project.js +244 -0
  153. package/lib/deploy/package-project.py +183 -0
  154. package/package.json +5 -2
@@ -361,20 +361,24 @@ if (isExternalUrl) {
361
361
 
362
362
  **工作原理**:
363
363
 
364
- 1. **开发环境(H5)**:使用 `/api/xxx` 相对路径,Vite 的 proxy 会自动将其代理到 `http://localhost:3000/api/xxx`
364
+ 1. **开发环境(H5)**:使用 `/api/xxx` 相对路径,Vite 的 proxy 会自动将其代理到后端;后端端口读取 `SERVER_PORT`,未设置时使用模板默认端口 `<%= serverPort %>`
365
365
  2. **生产环境**:如果配置了 `PROJECT_DOMAIN` 环境变量,Network 会自动拼接为 `${PROJECT_DOMAIN}/api/xxx`
366
366
  3. **小程序端**:同样会根据 `PROJECT_DOMAIN` 配置使用正确的域名
367
367
 
368
368
  **Vite 代理配置**(已在项目中配置,无需修改):
369
369
 
370
370
  ```typescript
371
- // vite.config.ts
371
+ // config/index.ts
372
+ const serverPort = Number(process.env.SERVER_PORT) || <%= serverPort %>
373
+
372
374
  export default {
373
- server: {
374
- proxy: {
375
- '/api': {
376
- target: 'http://localhost:3000',
377
- changeOrigin: true
375
+ h5: {
376
+ devServer: {
377
+ proxy: {
378
+ '/api': {
379
+ target: `http://localhost:${serverPort}`,
380
+ changeOrigin: true
381
+ }
378
382
  }
379
383
  }
380
384
  }
@@ -63,8 +63,8 @@ pnpm install
63
63
  pnpm dev
64
64
  ```
65
65
 
66
- - 前端地址:http://localhost:5000
67
- - 后端地址:http://localhost:3000
66
+ - 前端地址:http://localhost:<%= port %>
67
+ - 后端地址:http://localhost:<%= serverPort %>
68
68
 
69
69
  单独启动:
70
70
 
@@ -560,7 +560,7 @@ async function getLocation(): Promise<Taro.getLocation.SuccessCallbackResult> {
560
560
  ### 开发命令
561
561
 
562
562
  ```sh
563
- pnpm dev:server // 启动开发服务 (热重载, 默认端口 3000)
563
+ pnpm dev:server // 启动开发服务 (热重载, 默认端口 <%= serverPort %>,可用 SERVER_PORT 环境变量覆盖)
564
564
  pnpm build:server // 构建生产版本
565
565
  ```
566
566
 
@@ -586,7 +586,7 @@ npx nest g service modules/order
586
586
 
587
587
  ```sh
588
588
  ## 服务端口
589
- PORT=3000
589
+ SERVER_PORT=<%= serverPort %>
590
590
 
591
591
  ## 微信小程序配置
592
592
  WX_APP_ID=你的AppID
@@ -12,6 +12,14 @@ import pkg from '../package.json';
12
12
 
13
13
  dotenv.config({ path: path.resolve(__dirname, '../.env.local') });
14
14
 
15
+ const resolvePort = (value: string | undefined, fallback: number): number => {
16
+ const port = Number(value);
17
+ return Number.isInteger(port) && port > 0 && port < 65536 ? port : fallback;
18
+ };
19
+
20
+ const h5Port = resolvePort(process.env.PORT, <%= port %>);
21
+ const serverPort = resolvePort(process.env.SERVER_PORT, <%= serverPort %>);
22
+
15
23
  const generateTTProjectConfig = (outputRoot: string) => {
16
24
  const config = {
17
25
  miniprogramRoot: './',
@@ -182,12 +190,12 @@ export default defineConfig<'vite'>(async (merge, _env) => {
182
190
  mode: 'hash',
183
191
  },
184
192
  devServer: {
185
- port: <%= port %>,
193
+ port: h5Port,
186
194
  host: '0.0.0.0',
187
195
  open: false,
188
196
  proxy: {
189
197
  '/api': {
190
- target: 'http://localhost:<%= serverPort %>',
198
+ target: `http://localhost:${serverPort}`,
191
199
  changeOrigin: true,
192
200
  },
193
201
  },
@@ -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
208
+ version: 0.7.25(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:
5420
+ resolution: {integrity: sha512-5683ngikMdsRW0slGTE2OAZ1Fyj0lhkC4fGNOwsqKc35e68/gtg9KmmtK9CK9SZ+5/oIn/4wLoHXFB0gHJtO2A==}
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(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",
21
21
  "dotenv": "^17.2.3",
22
22
  "drizzle-kit": "^0.31.8",
23
23
  "drizzle-orm": "^0.45.1",
@@ -12,6 +12,12 @@ 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
+
15
21
  return <%= serverPort %>;
16
22
  }
17
23
 
@@ -38,12 +44,12 @@ async function bootstrap() {
38
44
  console.log(`Server running on http://localhost:${port}`);
39
45
  } catch (err) {
40
46
  if (err.code === 'EADDRINUSE') {
41
- console.error(`❌ 端口 \({port} 被占用! 请运行 'npx kill-port \){port}' 然后重试。`);
47
+ console.error(`❌ 端口 ${port} 被占用,请设置其他 SERVER_PORT 后重试。`);
42
48
  process.exit(1);
43
49
  } else {
44
50
  throw err;
45
51
  }
46
52
  }
47
- console.log(`Application is running on: http://localhost:<%= serverPort %>`);
53
+ console.log(`Application is running on: http://localhost:${port}`);
48
54
  }
49
55
  bootstrap();
@@ -16,10 +16,17 @@
16
16
  },
17
17
  "port": {
18
18
  "type": "number",
19
- "default": 8081,
19
+ "default": 5000,
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"
23
30
  }
24
31
  },
25
32
  "required": [],
@@ -94,6 +101,49 @@
94
101
  "additionalProperties": false
95
102
  }
96
103
  },
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
+ },
97
147
  {
98
148
  "name": "pi-agent",
99
149
  "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",
@@ -4,11 +4,16 @@ project_type = "web"
4
4
 
5
5
  [dev]
6
6
  build = ["bash", "./scripts/prepare.sh"]
7
+ build_win = ["powershell.exe", "-NoProfile", "-ExecutionPolicy", "Bypass", "-File", "./scripts/prepare.ps1"]
7
8
  run = ["bash", "./scripts/dev.sh"]
9
+ run_win = ["powershell.exe", "-NoProfile", "-ExecutionPolicy", "Bypass", "-File", "./scripts/dev.ps1"]
8
10
  validate = ["bash", "./scripts/validate.sh"]
11
+ validate_win = ["powershell.exe", "-NoProfile", "-ExecutionPolicy", "Bypass", "-File", "./scripts/validate.ps1"]
9
12
  deps = ["git"] # -> apt install git
10
13
 
11
14
  [deploy]
12
15
  build = ["bash","./scripts/build.sh"]
16
+ build_win = ["powershell.exe", "-NoProfile", "-ExecutionPolicy", "Bypass", "-File", "./scripts/build.ps1"]
13
17
  run = ["bash","./scripts/start.sh"]
18
+ run_win = ["powershell.exe", "-NoProfile", "-ExecutionPolicy", "Bypass", "-File", "./scripts/start.ps1"]
14
19
  deps = ["git"] # -> apt install git
@@ -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.16",
25
+ "coze-coding-dev-sdk": "^0.7.25",
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.16
36
- version: 0.7.16(openai@6.16.0(ws@8.19.0)(zod@4.3.5))(ws@8.19.0)
35
+ specifier: ^0.7.25
36
+ version: 0.7.25(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.16:
914
- resolution: {integrity: sha512-B7gRPBa+sfrZL8ur0+F/92SOgZgFaWD/fOnCN2DjthnHSdmCYhAJWCfqzG2oO2vwTiYCXkKUuTBZ3MJLMj886g==}
913
+ coze-coding-dev-sdk@0.7.25:
914
+ resolution: {integrity: sha512-5683ngikMdsRW0slGTE2OAZ1Fyj0lhkC4fGNOwsqKc35e68/gtg9KmmtK9CK9SZ+5/oIn/4wLoHXFB0gHJtO2A==}
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.16(openai@6.16.0(ws@8.19.0)(zod@4.3.5))(ws@8.19.0):
3284
+ coze-coding-dev-sdk@0.7.25(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)
@@ -0,0 +1,16 @@
1
+ $ErrorActionPreference = "Stop"
2
+
3
+ $workspace = if ($env:COZE_WORKSPACE_PATH) { $env:COZE_WORKSPACE_PATH } else { (Get-Location).Path }
4
+ Set-Location $workspace
5
+
6
+ Write-Host "Installing dependencies..."
7
+ & pnpm install --prefer-frozen-lockfile --prefer-offline --loglevel debug --reporter=append-only
8
+ if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
9
+
10
+ Write-Host "Building frontend with Vite..."
11
+ & pnpm vite build
12
+ if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
13
+
14
+ Write-Host "Bundling server with tsup..."
15
+ & pnpm tsup server/server.ts --format cjs --platform node --target node20 --outDir dist-server --no-splitting --no-minify --external vite
16
+ exit $LASTEXITCODE
@@ -0,0 +1,63 @@
1
+ $ErrorActionPreference = "Stop"
2
+
3
+ function Get-WorkspacePath {
4
+ if ($env:COZE_WORKSPACE_PATH) {
5
+ return $env:COZE_WORKSPACE_PATH
6
+ }
7
+ return (Get-Location).Path
8
+ }
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
13
+ }
14
+ }
15
+
16
+ function Stop-ListeningProcess([int] $port) {
17
+ $connections = Get-NetTCPConnection -LocalPort $port -State Listen -ErrorAction SilentlyContinue
18
+ $connections | Select-Object -ExpandProperty OwningProcess -Unique | ForEach-Object {
19
+ Stop-ProcessTree $_
20
+ }
21
+ }
22
+
23
+ $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 }
26
+ Set-Location $workspace
27
+ Stop-ListeningProcess $port
28
+
29
+ <% if (process.env.NODE_ENV === 'test') { %>
30
+ $env:PORT = "$port"
31
+ & pnpm tsx watch server/server.ts
32
+ exit $LASTEXITCODE
33
+ <% } else { %>
34
+ $logDirectory = if ($env:COZE_LOG_DIR) { $env:COZE_LOG_DIR } else { Join-Path $workspace "logs" }
35
+ $logFile = Join-Path $logDirectory "server.log"
36
+ $errorLogFile = Join-Path $logDirectory "server-error.log"
37
+ $pidFile = Join-Path $logDirectory "server.pid"
38
+ New-Item -ItemType Directory -Force -Path $logDirectory | Out-Null
39
+
40
+ if (Test-Path $pidFile) {
41
+ Stop-ProcessTree ([int] (Get-Content $pidFile -Raw))
42
+ Remove-Item $pidFile -Force
43
+ }
44
+
45
+ $previousPort = $env:PORT
46
+ $env:PORT = "$port"
47
+ try {
48
+ $process = Start-Process -FilePath $env:ComSpec -ArgumentList @("/d", "/s", "/c", "pnpm tsx watch server/server.ts") -WorkingDirectory $workspace -RedirectStandardOutput $logFile -RedirectStandardError $errorLogFile -PassThru
49
+ } finally {
50
+ if ($null -eq $previousPort) { Remove-Item Env:PORT -ErrorAction SilentlyContinue } else { $env:PORT = $previousPort }
51
+ }
52
+
53
+ $process.Id | Set-Content $pidFile
54
+ Start-Sleep -Seconds 1
55
+ if ($process.HasExited) {
56
+ Get-Content $errorLogFile -Tail 20 -ErrorAction SilentlyContinue
57
+ Remove-Item $pidFile -Force -ErrorAction SilentlyContinue
58
+ exit 1
59
+ }
60
+
61
+ Write-Host "Dev server started (PID: $($process.Id))."
62
+ Write-Host "Log file: $logFile"
63
+ <% } %>
@@ -32,8 +32,117 @@ kill_port_if_listening() {
32
32
  fi
33
33
  }
34
34
 
35
+ <% if (process.env.NODE_ENV === 'test') { %>
35
36
  echo "Clearing port ${DEPLOY_RUN_PORT} before start."
36
37
  kill_port_if_listening
37
38
  echo "Starting express + Vite dev server on port ${DEPLOY_RUN_PORT}..."
38
39
 
39
- PORT=${DEPLOY_RUN_PORT} pnpm tsx watch server/server.ts
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
+ # detached 出去的进程没人负责回收,超过这个时长就自己退出,避免端口与内存长期泄露。
48
+ MAX_RUNTIME_SECONDS=1200
49
+
50
+ # 真正被 detach 的是这层 bash wrapper:它是进程组 leader,组内 watchdog 到点回收整组
51
+ # (wrapper -> pnpm -> tsx -> node);被包的进程自己先退出时也顺手清空进程组,不留残余。
52
+ RUN_WITH_TIMEOUT='
53
+ timeout_seconds=$1
54
+ shift
55
+
56
+ "$@" &
57
+ child_pid=$!
58
+
59
+ # 先忽略 TERM,才能在向整组发 TERM(自己也在组里)之后存活下来补一发 KILL。
60
+ ( trap "" TERM
61
+ sleep "${timeout_seconds}"
62
+ echo "[dev] 后台进程运行超过 ${timeout_seconds}s,回收进程组 $$。"
63
+ kill -TERM -- "-$$" 2>/dev/null || true
64
+ sleep 5
65
+ kill -KILL -- "-$$" 2>/dev/null || true
66
+ ) &
67
+
68
+ wait "${child_pid}"
69
+ kill -KILL -- "-$$" 2>/dev/null || true
70
+ '
71
+
72
+ # coze-daemon 会在 runtime shell 退出时清理原进程组。
73
+ # 通过 Node detached spawn 创建独立 session/进程组,并将 stdio 直接写入日志。
74
+ # 返回的 PID 是 wrapper 的,同时也是整个进程组的 PGID,后续按组回收。
75
+ spawn_detached() {
76
+ local cwd="$1"
77
+ local log_file="$2"
78
+ shift 2
79
+
80
+ node - "$cwd" "$log_file" \
81
+ /bin/bash -c "${RUN_WITH_TIMEOUT}" detached-runner "${MAX_RUNTIME_SECONDS}" "$@" <<'NODE'
82
+ const fs = require('node:fs');
83
+ const { spawn } = require('node:child_process');
84
+
85
+ const [cwd, logFile, command, ...args] = process.argv.slice(2);
86
+ if (!cwd || !logFile || !command) {
87
+ throw new Error('spawn_detached 缺少 cwd、log_file 或 command');
88
+ }
89
+
90
+ const logFd = fs.openSync(logFile, 'a');
91
+ try {
92
+ const child = spawn(command, args, {
93
+ cwd,
94
+ detached: true,
95
+ env: process.env,
96
+ stdio: ['ignore', logFd, logFd],
97
+ });
98
+ child.unref();
99
+ process.stdout.write(String(child.pid));
100
+ } finally {
101
+ fs.closeSync(logFd);
102
+ }
103
+ NODE
104
+ }
105
+
106
+ stop_detached() {
107
+ local pid="${1:-}"
108
+ if [[ -z "${pid}" ]]; then
109
+ return
110
+ fi
111
+
112
+ kill -TERM -- "-${pid}" 2>/dev/null || kill -TERM "${pid}" 2>/dev/null || true
113
+ sleep 1
114
+ kill -KILL -- "-${pid}" 2>/dev/null || true
115
+ }
116
+
117
+ # 监听端口的是孙进程(pnpm -> tsx -> node),只清端口会漏掉上层 pnpm/tsx,
118
+ # 所以先按上次记录的 PID 把整个进程组回收掉。
119
+ if [[ -f "${PID_FILE}" ]]; then
120
+ stop_detached "$(cat "${PID_FILE}" 2>/dev/null || true)"
121
+ rm -f "${PID_FILE}"
122
+ fi
123
+
124
+ echo "Clearing port ${DEPLOY_RUN_PORT} before start."
125
+ kill_port_if_listening
126
+ echo "Starting express + Vite dev server on port ${DEPLOY_RUN_PORT}..."
127
+
128
+ mkdir -p "${LOG_DIR}"
129
+ : > "${LOG_FILE}"
130
+
131
+ export PORT="${DEPLOY_RUN_PORT}"
132
+ server_pid="$(spawn_detached "${COZE_WORKSPACE_PATH}" "${LOG_FILE}" \
133
+ "$(command -v pnpm)" tsx watch server/server.ts)"
134
+ echo "${server_pid}" > "${PID_FILE}"
135
+
136
+ sleep 1
137
+ if [[ -z "${server_pid}" ]] || ! kill -0 "${server_pid}" 2>/dev/null; then
138
+ echo "Dev server failed to start. See ${LOG_FILE}." >&2
139
+ tail -n 20 "${LOG_FILE}" >&2 || true
140
+ rm -f "${PID_FILE}"
141
+ exit 1
142
+ fi
143
+
144
+ echo "Dev server started (PID: ${server_pid})."
145
+ echo "Auto stop after ${MAX_RUNTIME_SECONDS}s."
146
+ echo "Log file: ${LOG_FILE}"
147
+ echo "PID file: ${PID_FILE}"
148
+ <% } %>
@@ -0,0 +1,18 @@
1
+ $ErrorActionPreference = "Stop"
2
+
3
+ $workspace = if ($env:COZE_WORKSPACE_PATH) { $env:COZE_WORKSPACE_PATH } else { (Get-Location).Path }
4
+ Set-Location $workspace
5
+
6
+ Write-Host "Installing dependencies..."
7
+ & pnpm install --prefer-frozen-lockfile --prefer-offline --loglevel debug --reporter=append-only
8
+ if ($LASTEXITCODE -ne 0) {
9
+ exit $LASTEXITCODE
10
+ }
11
+
12
+ if (Get-Command coze-dev -ErrorAction SilentlyContinue) {
13
+ & coze-dev check-bins --help *> $null
14
+ if ($LASTEXITCODE -eq 0) {
15
+ & coze-dev check-bins --fix
16
+ exit $LASTEXITCODE
17
+ }
18
+ }
@@ -0,0 +1,11 @@
1
+ $ErrorActionPreference = "Stop"
2
+
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 }
6
+ Set-Location $workspace
7
+
8
+ Write-Host "Starting express production server on port $port..."
9
+ $env:PORT = "$port"
10
+ & node dist-server/server.js
11
+ exit $LASTEXITCODE
@@ -0,0 +1,8 @@
1
+ $ErrorActionPreference = "Stop"
2
+
3
+ $workspace = if ($env:COZE_WORKSPACE_PATH) { $env:COZE_WORKSPACE_PATH } else { (Get-Location).Path }
4
+ Set-Location $workspace
5
+
6
+ Write-Host "Running validate..."
7
+ & pnpm validate
8
+ exit $LASTEXITCODE
@@ -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
 
@@ -72,7 +73,7 @@ const config = {
72
73
  }
73
74
 
74
75
  const cmd = 'pnpm';
75
- const args = ['update', 'coze-coding-dev-sdk@^0.7.0'];
76
+ const args = ['update', 'coze-coding-dev-sdk@^0.7.25'];
76
77
  console.log(
77
78
  `\nTriggering: ${cmd} ${args.join(' ')} (running in background)`,
78
79
  );
@@ -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