@yorha2b-lab/autodev 4.2.0 → 5.0.0

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 (50) hide show
  1. package/.github/scripts/deploy/publish.py +2 -2
  2. package/.github/scripts/render/dashboard.py +13 -9
  3. package/CONTRIBUTING.md +0 -18
  4. package/bin/autodev.js +4 -4
  5. package/config.js +3 -3
  6. package/package.json +1 -3
  7. package/src/bootstrap/handlebars.js +26 -0
  8. package/src/bootstrap/handlers.js +10 -0
  9. package/src/bootstrap/index.js +49 -0
  10. package/src/bootstrap/infrastructure.js +15 -0
  11. package/src/bootstrap/openai.js +13 -0
  12. package/src/bootstrap/prompt.js +10 -0
  13. package/src/commands/watch.js +14 -29
  14. package/src/{core/react-compiler.js → framework/react/generator/index.js} +1 -1
  15. package/src/{prompts/react/watch-part.js → framework/react/prompts/part.js} +1 -1
  16. package/{templates → src/framework}/react/utils/utils.js +1 -1
  17. package/src/{commands/handlers/api-handler.js → handlers/apiHandler.js} +6 -6
  18. package/src/{commands/handlers/page-handler.js → handlers/pageHandler.js} +8 -9
  19. package/src/{commands/handlers/part-handler.js → handlers/partHandler.js} +7 -7
  20. package/src/{services/api-linker.js → labs/linker.js} +5 -6
  21. package/src/{services/proxy-tower.js → labs/tower.js} +5 -6
  22. package/src/services/llm.js +3 -3
  23. package/src/utils/infrastructure.js +5 -2
  24. package/src/core/context.js +0 -93
  25. /package/{templates → src/framework}/react/components/EditableCell.js +0 -0
  26. /package/{templates → src/framework}/react/components/MyBaseForm.js +0 -0
  27. /package/{templates → src/framework}/react/components/MyImage.js +0 -0
  28. /package/{templates → src/framework}/react/components/MyModalForm.js +0 -0
  29. /package/{templates → src/framework}/react/components/MyModalTable.js +0 -0
  30. /package/{templates → src/framework}/react/components/MySearchForm.js +0 -0
  31. /package/{templates → src/framework}/react/components/MyTable.js +0 -0
  32. /package/{templates → src/framework}/react/components/index.js +0 -0
  33. /package/{templates/react → src/framework/react/handlebars}/index.hbs +0 -0
  34. /package/{templates/react/handlebars → src/framework/react/handlebars/partials}/AlertInfo.hbs +0 -0
  35. /package/{templates/react/handlebars → src/framework/react/handlebars/partials}/FunctionButtons.hbs +0 -0
  36. /package/{templates/react/handlebars → src/framework/react/handlebars/partials}/MySearchForm.hbs +0 -0
  37. /package/{templates/react/handlebars → src/framework/react/handlebars/partials}/MyTable.hbs +0 -0
  38. /package/{templates/react/handlebars → src/framework/react/handlebars/partials}/handleBlock.hbs +0 -0
  39. /package/{templates/react/handlebars → src/framework/react/handlebars/partials}/hookBlock.hbs +0 -0
  40. /package/{templates/react/handlebars → src/framework/react/handlebars/partials}/operateBlock.hbs +0 -0
  41. /package/{templates/react/handlebars → src/framework/react/handlebars/partials}/renderBlock.hbs +0 -0
  42. /package/{templates/react/handlebars → src/framework/react/handlebars/partials}/stateBlock.hbs +0 -0
  43. /package/{templates/react → src/framework/react/handlebars}/resource.hbs +0 -0
  44. /package/{templates → src/framework}/react/hooks/useTableQuery.js +0 -0
  45. /package/src/{prompts/react/watch-api.js → framework/react/prompts/api.js} +0 -0
  46. /package/src/{prompts/react/api-linker.js → framework/react/prompts/linker.js} +0 -0
  47. /package/src/{prompts → framework/react/prompts}/mock.js +0 -0
  48. /package/src/{prompts/react/watch-page.js → framework/react/prompts/page.js} +0 -0
  49. /package/src/{prompts → framework/react/prompts}/system.js +0 -0
  50. /package/src/{schema/react → framework/react/schema}/page.json +0 -0
@@ -13,7 +13,7 @@ def assemble_readme():
13
13
  ref_table = '| Referrer | Views | Uniques |\n| :--- | :--- | :--- |\n'
14
14
  if referrers:
15
15
  for r in referrers:
16
- ref_table += f'| {r['referrer']} | {r['count']} | {r['uniques']} |\n'
16
+ ref_table += f'| {r["referrer"]} | {r["count"]} | {r["uniques"]} |\n'
17
17
  else:
18
18
  ref_table += '| No Signal | - | - |\n'
19
19
 
@@ -57,7 +57,7 @@ def git_push():
57
57
  'github-actions@github.com'], check=True)
58
58
  subprocess.run(['git', 'add', '-A'], check=True)
59
59
  subprocess.run(
60
- ['git', 'commit', '-m', f'chore: sovereign modular update [total {stats['total_clones']}]'], check=True)
60
+ ['git', 'commit', '-m', f'chore: sovereign modular update [total {stats["total_clones"]}]'], check=True)
61
61
  subprocess.run(
62
62
  ['git', 'push', 'origin', 'github-repo-stats', '--force'], check=True)
63
63
  print('✅ Data sealed and pushed to cloud.')
@@ -5,6 +5,7 @@ import seaborn as sns
5
5
  import matplotlib.pyplot as plt
6
6
  import matplotlib.dates as mdates
7
7
 
8
+
8
9
  def peak_recon():
9
10
  df = pd.read_csv('ghrs-data/clones_ledger.csv')
10
11
  df['date'] = pd.to_datetime(df['date'])
@@ -26,7 +27,7 @@ def peak_recon():
26
27
  fontsize=14, fontweight='bold')
27
28
 
28
29
  peak_clone_idx = df['clones'].idxmax()
29
- axA.annotate(f'LEGEND PEAK: {df['clones'].max()}',
30
+ axA.annotate(f'LEGEND PEAK: {df["clones"].max()}',
30
31
  xy=(df.loc[peak_clone_idx, 'date'],
31
32
  df.loc[peak_clone_idx, 'clones']),
32
33
  xytext=(10, 20), textcoords='offset points',
@@ -48,7 +49,7 @@ def peak_recon():
48
49
  5 else '#e74c3c' for r in df['ratio']]
49
50
  axC.bar(df['date'], df['ratio'], color=colors3, alpha=0.7)
50
51
  axC.axhline(y=df['ratio'].mean(), color='#9b59b6',
51
- ls='--', label=f'Avg: {df['ratio'].mean():.2f}')
52
+ ls='--', label=f'Avg: {df["ratio"].mean():.2f}')
52
53
  axC.set_title('Clones/Visitor Ratio (High Ratio = CI/Automation)',
53
54
  fontsize=14, fontweight='bold')
54
55
  axC.legend()
@@ -56,6 +57,7 @@ def peak_recon():
56
57
  plt.tight_layout()
57
58
  plt.savefig('plots/bunker_peak_recon.png', dpi=100)
58
59
 
60
+
59
61
  def intelligence_grid():
60
62
  df = pd.read_csv('ghrs-data/clones_ledger.csv')
61
63
  df['date'] = pd.to_datetime(df['date'])
@@ -84,7 +86,7 @@ def intelligence_grid():
84
86
  ax1.fill_between(df['date'], df['clones'],
85
87
  alpha=0.3, color='#2E86AB')
86
88
  ax1.axhline(y=df['clones'].mean(), color='red', linestyle='--',
87
- alpha=0.7, label=f'Avg: {df['clones'].mean():.0f}')
89
+ alpha=0.7, label=f'Avg: {df["clones"].mean():.0f}')
88
90
  ax1.set_title('Daily Clone Trend', fontsize=12, fontweight='bold')
89
91
  ax1.set_ylabel('Clones')
90
92
  ax1.legend()
@@ -100,7 +102,7 @@ def intelligence_grid():
100
102
  ax2.fill_between(df['date'], df['uniques'],
101
103
  alpha=0.3, color='#A23B72')
102
104
  ax2.axhline(y=df['uniques'].mean(), color='red', linestyle='--',
103
- alpha=0.7, label=f'Avg: {df['uniques'].mean():.0f}')
105
+ alpha=0.7, label=f'Avg: {df["uniques"].mean():.0f}')
104
106
  ax2.set_title('Daily Unique Commanders',
105
107
  fontsize=12, fontweight='bold')
106
108
  ax2.set_ylabel('Unique Visitors')
@@ -121,7 +123,7 @@ def intelligence_grid():
121
123
  z = np.polyfit(df['uniques'], df['clones'], 1)
122
124
  p = np.poly1d(z)
123
125
  ax3.plot(df['uniques'].sort_values(), p(df['uniques'].sort_values(
124
- )), 'r--', alpha=0.7, label=f'Trend: y={z[0]:.1f}x+{z[1]:.1f}')
126
+ )), "r--", alpha=0.7, label=f'Trend: y={z[0]:.1f}x+{z[1]:.1f}')
125
127
  ax3.legend()
126
128
  ax3.grid(True, alpha=0.3)
127
129
 
@@ -131,7 +133,7 @@ def intelligence_grid():
131
133
  ax4.hist(df['clones_per_unique'], bins=25,
132
134
  color='#F18F01', alpha=0.7, edgecolor='white')
133
135
  ax4.axvline(x=df['clones_per_unique'].mean(
134
- ), color='red', linestyle='--', label=f'Avg: {df['clones_per_unique'].mean():.2f}')
136
+ ), color='red', linestyle='--', label=f'Avg: {df["clones_per_unique"].mean():.2f}')
135
137
  ax4.set_xlabel('Clones Per Unit')
136
138
  ax4.set_ylabel('Days')
137
139
  ax4.set_title('Clones Per User Distribution',
@@ -178,6 +180,7 @@ def intelligence_grid():
178
180
  plt.tight_layout(rect=[0, 0.03, 1, 0.95])
179
181
  plt.savefig('plots/bunker_intelligence_grid.png', dpi=100)
180
182
 
183
+
181
184
  def load_clean(path, col):
182
185
  df = pd.read_csv(path)
183
186
  df['date'] = pd.to_datetime(df['date'], errors='coerce')
@@ -218,8 +221,9 @@ def main_dashboard(df_c, df_v):
218
221
  plt.tight_layout()
219
222
  plt.savefig('plots/bunker_main_v7.png', dpi=120)
220
223
 
221
- if __name__ == '__main__':
222
- print('🤖 Pod 042: Rendering Strategic Dashboards...')
224
+
225
+ if __name__ == "__main__":
226
+ print("🤖 Pod 042: Rendering Strategic Dashboards...")
223
227
  plt.style.use('dark_background')
224
228
  os.makedirs('plots', exist_ok=True)
225
229
 
@@ -232,4 +236,4 @@ if __name__ == '__main__':
232
236
  intelligence_grid()
233
237
  main_dashboard(df_c, df_v)
234
238
 
235
- print('✅ Dashboards rendered.')
239
+ print("✅ Dashboards rendered.")
package/CONTRIBUTING.md CHANGED
@@ -75,24 +75,6 @@ cp .env.example .env
75
75
  # 编辑 .env 文件,填入您的API密钥
76
76
  ```
77
77
 
78
- ### 项目结构
79
-
80
- ```
81
- auto-crud-copilot/
82
- ├── bin/ # 可执行文件
83
- ├── src/
84
- │ ├── commands/ # 命令实现
85
- │ ├── core/ # 核心逻辑
86
- │ ├── prompts/ # AI提示词
87
- │ ├── services/ # 服务层
88
- │ └── utils/ # 工具函数
89
- ├── templates/ # 代码模板
90
- │ ├── react/
91
- │ ├── vue/
92
- │ └── angular/
93
- └── config.js # 配置文件
94
- ```
95
-
96
78
  - 提交信息遵循[Conventional Commits](https://www.conventionalcommits.org/zh-hans/v1.0.0/)规范
97
79
 
98
80
  ### 测试
package/bin/autodev.js CHANGED
@@ -51,20 +51,20 @@ program
51
51
  .alias('start')
52
52
  .description(language('开启全频道联动监控:支持 Page/Part/API 协同构筑', 'Start full-channel linked monitoring: Coordinated Page/Part/API construction'))
53
53
  .action(() => {
54
- const bunker = require('../src/core/context')
54
+ const bunker = require('../src/bootstrap')
55
55
  const result = bunker.init(program.opts())
56
56
  if (!result) {
57
57
  return
58
58
  }
59
59
  bootSequence(pkg.version)
60
60
  require('../src/commands/watch')()
61
- const { config } = bunker.get()
61
+ const { config } = result.infrastructure
62
62
  const { apiDoc, needMock, proxyTarget, enableAutoAlignment } = config
63
63
  if (apiDoc && enableAutoAlignment) {
64
- require('../src/services/api-linker')()
64
+ require('../src/labs/linker')()
65
65
  }
66
66
  if (proxyTarget && !needMock && enableAutoAlignment) {
67
- require('../src/services/proxy-tower')()
67
+ require('../src/labs/tower')()
68
68
  }
69
69
  process.on('SIGINT', () => {
70
70
  console.log('\n')
package/config.js CHANGED
@@ -18,10 +18,10 @@ module.exports = {
18
18
  utilsDir: 'src/utils',
19
19
  componentsDir: 'src/components',
20
20
 
21
- // 代理目标
22
- proxyTarget: 'http://id:port',
23
- responseSuccess: `response?.code === 200`,
24
21
  // 指向公司的 Swagger JSON 地址
25
22
  apiDoc: '',
23
+ // 代理目标
24
+ proxyTarget: '',
25
+ responseSuccess: `response?.code === 200`,
26
26
 
27
27
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yorha2b-lab/autodev",
3
- "version": "4.2.0",
3
+ "version": "5.0.0",
4
4
  "description": "基于视觉大模型的前端(react+Antd)全自动 CRUD 代码生成器",
5
5
  "bin": {
6
6
  "autodev": "bin/autodev.js"
@@ -14,8 +14,6 @@
14
14
  "ai",
15
15
  "vision",
16
16
  "react",
17
- "vue",
18
- "angular",
19
17
  "antd",
20
18
  "umi",
21
19
  "code-generation",
@@ -0,0 +1,26 @@
1
+ module.exports = ({ config, template, contextStringify }) => {
2
+
3
+ const fs = require('fs')
4
+ const path = require('path')
5
+ const Handlebars = require('handlebars')
6
+
7
+ Handlebars.registerHelper('raw', opt => opt.fn())
8
+ Handlebars.registerHelper('stringify', (context, maxLength = 200) => context ? new Handlebars.SafeString(contextStringify({ context, maxLength })) : '[]')
9
+
10
+ const { hbsDir } = config
11
+ const tplDir = hbsDir !== '' ? path.join(process.cwd(), hbsDir) : path.join(__dirname, `../framework/${template}/handlebars`)
12
+ const partialsDir = hbsDir !== '' ? path.join(process.cwd(), hbsDir) : path.join(__dirname, `../framework/${template}/handlebars/partials`)
13
+
14
+ fs.readdirSync(partialsDir).forEach(file => {
15
+ if (file.endsWith('.hbs')) {
16
+ const name = path.basename(file, '.hbs') // 去掉后缀拿名字
17
+ const content = fs.readFileSync(path.join(partialsDir, file), 'utf-8')
18
+ Handlebars.registerPartial(name, `${content}\n`)
19
+ }
20
+ })
21
+
22
+ return {
23
+ indexTpl: Handlebars.compile(fs.readFileSync(path.join(tplDir, 'index.hbs'), 'utf-8')),
24
+ resourceTpl: Handlebars.compile(fs.readFileSync(path.join(tplDir, 'resource.hbs'), 'utf-8')),
25
+ }
26
+ }
@@ -0,0 +1,10 @@
1
+ module.exports = () => {
2
+
3
+ const fs = require('fs')
4
+ const path = require('path')
5
+
6
+ const handlersPath = path.join(__dirname, `../handlers`)
7
+ const handlers = fs.readdirSync(handlersPath).map(handler => [path.basename(handler, '.js'), require(path.join(handlersPath, handler))])
8
+
9
+ return Object.fromEntries(handlers)
10
+ }
@@ -0,0 +1,49 @@
1
+ const fs = require('fs')
2
+ const path = require('path')
3
+ const chalk = require('chalk')
4
+
5
+ let instance = null
6
+
7
+ module.exports = {
8
+
9
+ init: options => {
10
+
11
+ const template = options.template
12
+ const ux = require('../utils/ux')
13
+
14
+ const generatorPath = path.join(__dirname, `../framework/${template}/generator`)
15
+ if (!fs.existsSync(generatorPath)) {
16
+ console.error(chalk.red(ux.language(`❌ 暂不支持 [${template}] 框架。欢迎提交 Pull Request 贡献。`, `❌ [${template}] framework not supported. Welcome to contribute a Pull Request to help.`)))
17
+ return
18
+ }
19
+
20
+ const infrastructure = require('../utils/infrastructure')
21
+
22
+ const openAI = require('./openai')()
23
+ const core = require('../utils/core')
24
+ const handlers = require('./handlers')()
25
+ const config = infrastructure.getConfig()
26
+ const menus = infrastructure.getExistingMenus()
27
+ const prompts = require('./prompt')({ template })
28
+ require('./infrastructure')({ ux, config, options, ...infrastructure })
29
+ const llm = require('../services/llm')({ config, openAI, template, ...prompts })
30
+ const handlebars = require('./handlebars')({ config, template, ...infrastructure })
31
+ const generator = require(generatorPath)({ config, ...core, ...handlebars, ...infrastructure })
32
+
33
+ instance = {
34
+ ux,
35
+ llm,
36
+ core,
37
+ openAI,
38
+ prompts,
39
+ handlers,
40
+ generator,
41
+ handlebars,
42
+ cli: options,
43
+ infrastructure: { menus, config, ...infrastructure },
44
+ }
45
+ return instance
46
+ },
47
+
48
+ get: () => instance
49
+ }
@@ -0,0 +1,15 @@
1
+ module.exports = ({ ux, config, options, copyTemplateDir }) => {
2
+
3
+ const { language } = ux
4
+ const { hbsDir, hooksDir, utilsDir, componentsDir } = config
5
+
6
+ try {
7
+ if (hbsDir === '') {
8
+ copyTemplateDir(options, 'hooks', hooksDir)
9
+ copyTemplateDir(options, 'utils', utilsDir)
10
+ copyTemplateDir(options, 'components', componentsDir)
11
+ }
12
+ } catch (error) {
13
+ console.error(language('❌ 模板构筑失败:', '❌ Template construction failed:'), error)
14
+ }
15
+ }
@@ -0,0 +1,13 @@
1
+ module.exports = () => {
2
+
3
+ const fs = require('fs')
4
+ const path = require('path')
5
+ const OpenAI = require('openai')
6
+
7
+ const pkgEnv = path.resolve(__dirname, '../.env')
8
+ const localEnv = path.resolve(process.cwd(), '.env')
9
+ require('dotenv').config({ path: fs.existsSync(localEnv) ? localEnv : pkgEnv })
10
+ const openAI = new OpenAI({ apiKey: process.env.API_KEY, baseURL: process.env.BASE_URL })
11
+
12
+ return openAI
13
+ }
@@ -0,0 +1,10 @@
1
+ module.exports = ({ template }) => {
2
+
3
+ const fs = require('fs')
4
+ const path = require('path')
5
+
6
+ const promptsPath = path.join(__dirname, `../framework/${template}/prompts`)
7
+ const prompts = fs.readdirSync(promptsPath).map(prompt => [`${path.basename(prompt, '.js')}Prompt`, require(path.join(promptsPath, prompt))])
8
+
9
+ return Object.fromEntries(prompts)
10
+ }
@@ -5,26 +5,12 @@ module.exports = () => {
5
5
  const chalk = require('chalk')
6
6
  const chokidar = require('chokidar')
7
7
 
8
- const {
9
- options,
10
- language,
11
- createTaskQueue,
12
- contextStringify,
13
- menus, config, copyTemplateDir,
14
- apiHandler, pageHandler, partHandler,
15
- } = require('../core/context').get()
8
+ const { ux, core, handlers, infrastructure } = require('../bootstrap').get()
16
9
 
17
- const { hbsDir, hooksDir, utilsDir, componentsDir } = config
18
-
19
- try {
20
- if (hbsDir === '') {
21
- copyTemplateDir(options, 'hooks', hooksDir)
22
- copyTemplateDir(options, 'utils', utilsDir)
23
- copyTemplateDir(options, 'components', componentsDir)
24
- }
25
- } catch (error) {
26
- console.error(language('❌ 模板构筑失败:', '❌ Template construction failed:'), error)
27
- }
10
+ const { language } = ux
11
+ const { createTaskQueue } = core
12
+ const { apiHandler, pageHandler, partHandler } = handlers
13
+ const { menus, config, contextStringify } = infrastructure
28
14
 
29
15
  const queue = createTaskQueue(2)
30
16
 
@@ -54,18 +40,17 @@ module.exports = () => {
54
40
  '📡 Operator 6O: Calling 2B, all-channel linked monitoring is ready!'
55
41
  )))
56
42
 
57
- watcher.on('add', filePath => {
43
+ const routes = [
44
+ { match: 'response', handler: apiHandler },
45
+ { match: 'screenShot', handler: pageHandler },
46
+ { match: 'screenPart', handler: partHandler },
47
+ ]
58
48
 
49
+ watcher.on('add', filePath => {
59
50
  const absolutePath = path.resolve(filePath)
60
-
61
- if (absolutePath.includes('screenShot')) {
62
- queue.add(() => pageHandler(filePath))
63
- }
64
- else if (absolutePath.includes('screenPart')) {
65
- queue.add(() => partHandler(filePath))
66
- }
67
- else if (absolutePath.includes('response')) {
68
- queue.add(() => apiHandler(filePath))
51
+ const route = routes.find(r => absolutePath.includes(r.match))
52
+ if (route) {
53
+ queue.add(() => route.handler(filePath))
69
54
  }
70
55
  })
71
56
  }
@@ -1,4 +1,4 @@
1
- module.exports = ({ config, contextStringify, indexTpl, resourceTpl, formatFormItemAndColumns, cleanCode, generateSmartImports }) => {
1
+ module.exports = ({ config, indexTpl, cleanCode, resourceTpl, contextStringify, generateSmartImports, formatFormItemAndColumns, }) => {
2
2
 
3
3
  const { needMock, responseSuccess } = config
4
4
 
@@ -8,7 +8,7 @@ module.exports = `
8
8
  3. 必须严格遵守以下字段规范。
9
9
 
10
10
  ## 1. 表格 (Table)
11
- - 结构: { columns: [{ title: '列名', dataIndex: '列名英文名词', type: '' }] }
11
+ - 结构: { columns: [{ title: '列名', dataIndex: '***englishName***', type: '' }] }
12
12
  - ⚠️ 字段白名单: [title, dataIndex, sorter, render, filters, onFilter]
13
13
  - **注意**: type为text时必须省略type属性。
14
14
  - 禁止输出:
@@ -100,7 +100,7 @@ export const timeRender = ({ time, date, minute }) => {
100
100
  * @param {Function} [formatter] - 数据预处理回调
101
101
  * @param {Array} columns - 表格列配置,支持 exportRender 优先级
102
102
  */
103
- export const exportDataToExcel = async (url, options, columns, fileName, formatter) => {
103
+ export const exportDataToExcel = async ({ url, options, columns, fileName, formatter }) => {
104
104
  /* const response = await request(url, options)
105
105
  const result = formatter ? formatter(response) : (response?.data ?? [])
106
106
  if (result?.length > 0) {
@@ -5,14 +5,14 @@ module.exports = async (filePath, liveResponse = null) => {
5
5
  const path = require('path')
6
6
  const chalk = require('chalk')
7
7
 
8
- const {
9
- unwrapSignal,
10
- config, language,
11
- alignResponseFields
12
- } = require('../../core/context').get()
8
+ const { ux, llm, core, infrastructure } = require('../bootstrap').get()
13
9
 
14
- const { pagesDir } = config
10
+ const { language } = ux
11
+ const { unwrapSignal } = core
12
+ const { config } = infrastructure
13
+ const { alignResponseFields } = llm
15
14
 
15
+ const { pagesDir } = config
16
16
  const startTime = Date.now()
17
17
  const fileName = liveResponse?.fileName ?? path.basename(filePath, path.extname(filePath))
18
18
  const resourcePath = path.join(process.cwd(), pagesDir, fileName, 'resource.js')
@@ -5,14 +5,13 @@ module.exports = async filePath => {
5
5
  const path = require('path')
6
6
  const chalk = require('chalk')
7
7
 
8
- const {
9
- language,
10
- pagePrompt,
11
- menus, config,
12
- index, resource,
13
- contextStringify,
14
- generateMock, recognizePage,
15
- } = require('../../core/context').get()
8
+ const { ux, llm, prompts, generator, infrastructure } = require('../bootstrap').get()
9
+
10
+ const { language } = ux
11
+ const { pagePrompt } = prompts
12
+ const { index, resource } = generator
13
+ const { generateMock, recognizePage } = llm
14
+ const { menus, config, contextStringify } = infrastructure
16
15
 
17
16
  const { useDemo, pagesDir, needMock } = config
18
17
 
@@ -48,7 +47,7 @@ module.exports = async filePath => {
48
47
  `\n🤖 Pod 042: [报告] 拦截到实弹请求。正在空投标准模拟包: example.json\n`,
49
48
  `\n🤖 Pod 042: [Report] Real-fire request intercepted. Dropping simulation package: example.json\n`
50
49
  )))
51
- pageConfig = require('../../../example/example.json')
50
+ pageConfig = require('../../example/example.json')
52
51
  } else {
53
52
  spinner.text = chalk.cyan(language(
54
53
  `🤖 Pod 042: 正在上传视觉元数据至司令部进行语义分析...\n`,
@@ -4,13 +4,13 @@ module.exports = async filePath => {
4
4
  const ora = require('ora')
5
5
  const chalk = require('chalk')
6
6
 
7
- const {
8
- language,
9
- partPrompt,
10
- recognizePage,
11
- contextStringify,
12
- cleanCode, formatFormItemAndColumns,
13
- } = require('../../core/context').get()
7
+ const { ux, llm, core, prompts, infrastructure } = require('../bootstrap').get()
8
+
9
+ const { language } = ux
10
+ const { partPrompt } = prompts
11
+ const { recognizePage } = llm
12
+ const { contextStringify } = infrastructure
13
+ const { cleanCode, formatFormItemAndColumns } = core
14
14
 
15
15
  const startTime = Date.now()
16
16
 
@@ -4,12 +4,11 @@ module.exports = async () => {
4
4
  const path = require('path')
5
5
  const chalk = require('chalk')
6
6
 
7
- const {
8
- config,
9
- language,
10
- apiLinker,
11
- getLocalScore, getSemanticKeywords,
12
- } = require('../core/context').get()
7
+ const { ux, llm, infrastructure } = require('../bootstrap').get()
8
+
9
+ const { language } = ux
10
+ const { apiLinker } = llm
11
+ const { config, getLocalScore, getSemanticKeywords, } = infrastructure
13
12
 
14
13
  const { apiDoc, pagesDir } = config
15
14
  if (!apiDoc) return
@@ -10,13 +10,12 @@ module.exports = () => {
10
10
  const chalk = require('chalk')
11
11
  const httpProxy = require('http-proxy')
12
12
 
13
- const {
14
- config,
15
- language,
16
- apiHandler,
17
- unwrapSignal, isQuerySignal
18
- } = require('../core/context').get()
13
+ const { ux, core, handlers, infrastructure } = require('../bootstrap').get()
19
14
 
15
+ const { language } = ux
16
+ const { apiHandler } = handlers
17
+ const { config } = infrastructure
18
+ const { unwrapSignal, isQuerySignal } = core
20
19
  const { routeMap = {}, proxyTarget } = config
21
20
 
22
21
  const TOWER_PORT = 42153
@@ -43,12 +43,12 @@ const askAI = async ({ model, openAI, messages, response_format = { type: 'json_
43
43
  }
44
44
  }
45
45
 
46
- module.exports = ({ config, openAI, template, sysPrompt, apiPrompt, mockPrompt, linkerPrompt }) => {
46
+ module.exports = ({ config, openAI, template, systemPrompt, apiPrompt, mockPrompt, linkerPrompt }) => {
47
47
 
48
48
  const sharp = require('sharp')
49
49
 
50
50
  const { textModel, visionModel } = config
51
- const { UI_DESIGNER, API_DESIGNER, MOCK_DESIGNER } = sysPrompt
51
+ const { UI_DESIGNER, API_DESIGNER, MOCK_DESIGNER } = systemPrompt
52
52
 
53
53
  return {
54
54
  generateMock: async ({ columns, fileName }) => {
@@ -101,7 +101,7 @@ module.exports = ({ config, openAI, template, sysPrompt, apiPrompt, mockPrompt,
101
101
  ]
102
102
  }
103
103
  ],
104
- response_format: taskType === 'page' ? { type: 'json_schema', strict: true, json_schema: require(`../schema/${template}/page.json`) } : { type: 'json_object' }
104
+ response_format: taskType === 'page' ? { type: 'json_schema', strict: true, json_schema: require(`../framework/${template}/schema/page.json`) } : { type: 'json_object' }
105
105
  })
106
106
  },
107
107
  }
@@ -10,6 +10,7 @@
10
10
  const fs = require('fs')
11
11
  const path = require('path')
12
12
  const { Segment, useDefault } = require('segmentit')
13
+ const stringify = require('json-stringify-pretty-compact')
13
14
  const segmentit = useDefault(new Segment())
14
15
 
15
16
  /**
@@ -87,7 +88,7 @@ const getLocalScore = (api, pageKeywords, moduleName) => {
87
88
  */
88
89
  const copyTemplateDir = (options, templateSubDir, targetSubDir) => {
89
90
  const targetDir = path.join(process.cwd(), targetSubDir)
90
- const sourceDir = path.join(__dirname, `../../templates/${options.template}/${templateSubDir}`)
91
+ const sourceDir = path.join(__dirname, `../framework/${options.template}/${templateSubDir}`)
91
92
  if (!fs.existsSync(sourceDir)) return
92
93
  fs.mkdirSync(targetDir, { recursive: true })
93
94
  fs.readdirSync(sourceDir).forEach(file => {
@@ -99,4 +100,6 @@ const copyTemplateDir = (options, templateSubDir, targetSubDir) => {
99
100
  })
100
101
  }
101
102
 
102
- module.exports = { getConfig, getLocalScore, getExistingMenus, copyTemplateDir, getSemanticKeywords }
103
+ const contextStringify = ({ context, indent = 4, maxLength = 200 }) => stringify.default(context, { indent, maxLength })
104
+
105
+ module.exports = { getConfig, getLocalScore, getExistingMenus, copyTemplateDir, contextStringify, getSemanticKeywords }
@@ -1,93 +0,0 @@
1
- const fs = require('fs')
2
- const path = require('path')
3
- const chalk = require('chalk')
4
- const OpenAI = require('openai')
5
- const Handlebars = require('handlebars')
6
- const stringify = require('json-stringify-pretty-compact')
7
-
8
- const contextStringify = ({ context, indent = 4, maxLength = 200 }) => stringify.default(context, { indent, maxLength })
9
-
10
- Handlebars.registerHelper('raw', opt => opt.fn())
11
- Handlebars.registerHelper('stringify', (context, maxLength = 200) => context ? new Handlebars.SafeString(contextStringify({ context, maxLength })) : '[]')
12
-
13
- let instance = null
14
-
15
- module.exports = {
16
-
17
- init: options => {
18
-
19
- const template = options.template
20
- const uxCtx = require('../utils/ux')
21
- const coreCtx = require('../utils/core')
22
- const infrastructureCtx = require('../utils/infrastructure')
23
-
24
- const { language } = uxCtx
25
- const { getConfig, getExistingMenus } = infrastructureCtx
26
-
27
- const config = getConfig()
28
- const { hbsDir } = config
29
-
30
- const menus = getExistingMenus()
31
- const apiHandler = require('../commands/handlers/api-handler')
32
- const pageHandler = require('../commands/handlers/page-handler')
33
- const partHandler = require('../commands/handlers/part-handler')
34
- const tplDir = hbsDir !== '' ? path.join(process.cwd(), hbsDir) : path.join(__dirname, `../../templates/${template}`)
35
-
36
- const compilerPath = path.join(__dirname, `./${template}-compiler.js`)
37
- if (!fs.existsSync(compilerPath)) {
38
- console.error(chalk.red(language(`❌ 暂不支持 [${template}] 框架。欢迎提交 Pull Request 贡献。`, `❌ [${template}] framework not supported. Welcome to contribute a Pull Request to help.`)))
39
- return
40
- }
41
-
42
- const partialsDir = hbsDir !== '' ? path.join(process.cwd(), hbsDir, 'handlebars') : path.join(__dirname, `../../templates/${template}/handlebars`)
43
- fs.readdirSync(partialsDir).forEach(file => {
44
- if (file.endsWith('.hbs')) {
45
- const name = path.basename(file, '.hbs') // 去掉后缀拿名字
46
- const content = fs.readFileSync(path.join(partialsDir, file), 'utf-8')
47
- Handlebars.registerPartial(name, `${content}\n`)
48
- }
49
- })
50
-
51
- const promptCtx = {
52
- mockPrompt: require(`../prompts/mock.js`),
53
- sysPrompt: require(`../prompts/system.js`),
54
- apiPrompt: require(`../prompts/${template}/watch-api.js`),
55
- pagePrompt: require(`../prompts/${template}/watch-page.js`),
56
- partPrompt: require(`../prompts/${template}/watch-part.js`),
57
- linkerPrompt: require(`../prompts/${template}/api-linker.js`),
58
- }
59
-
60
- const hbsTplCtx = {
61
- indexTpl: Handlebars.compile(fs.readFileSync(path.join(tplDir, 'index.hbs'), 'utf-8')),
62
- resourceTpl: Handlebars.compile(fs.readFileSync(path.join(tplDir, 'resource.hbs'), 'utf-8')),
63
- }
64
-
65
- const pkgEnv = path.resolve(__dirname, '../.env')
66
- const localEnv = path.resolve(process.cwd(), '.env')
67
- require('dotenv').config({ path: fs.existsSync(localEnv) ? localEnv : pkgEnv })
68
- const openAI = new OpenAI({ apiKey: process.env.API_KEY, baseURL: process.env.BASE_URL })
69
-
70
- const cliCtx = { options }
71
- const handlerCtx = { apiHandler, pageHandler, partHandler }
72
- const finalInfrastructureCtx = { menus, config, ...infrastructureCtx }
73
- const llmCtx = require('../services/llm')({ config, openAI, template, ...promptCtx })
74
- const compileCtx = require(compilerPath)({ config, contextStringify, ...coreCtx, ...hbsTplCtx })
75
-
76
- instance = {
77
- openAI,
78
- ...uxCtx,
79
- ...cliCtx,
80
- ...llmCtx,
81
- ...coreCtx,
82
- ...promptCtx,
83
- ...hbsTplCtx,
84
- ...handlerCtx,
85
- ...compileCtx,
86
- contextStringify,
87
- ...finalInfrastructureCtx,
88
- }
89
- return instance
90
- },
91
-
92
- get: () => instance
93
- }