@yorha2b-lab/autodev 4.2.0 → 5.1.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 (58) 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 +28 -26
  5. package/config.js +3 -3
  6. package/package.json +1 -3
  7. package/src/bootstrap/dialogs.js +10 -0
  8. package/src/bootstrap/handlebars.js +26 -0
  9. package/src/bootstrap/handlers.js +10 -0
  10. package/src/bootstrap/index.js +56 -0
  11. package/src/bootstrap/infrastructure.js +16 -0
  12. package/src/bootstrap/openai.js +13 -0
  13. package/src/bootstrap/prompts.js +10 -0
  14. package/src/bootstrap/yorha.js +39 -0
  15. package/src/commands/watch.js +15 -42
  16. package/src/dialogs/EN-US.js +55 -0
  17. package/src/dialogs/ZH-CN.js +55 -0
  18. package/src/{core/react-compiler.js → framework/react/generator/index.js} +1 -1
  19. package/src/{prompts/react/watch-part.js → framework/react/prompts/part.js} +1 -1
  20. package/{templates → src/framework}/react/utils/utils.js +1 -1
  21. package/src/handlers/api.js +92 -0
  22. package/src/handlers/page.js +70 -0
  23. package/src/handlers/part.js +59 -0
  24. package/src/{services/api-linker.js → labs/linker.js} +14 -31
  25. package/src/{services/proxy-tower.js → labs/tower.js} +10 -23
  26. package/src/services/llm.js +21 -20
  27. package/src/utils/infrastructure.js +5 -2
  28. package/src/utils/ux.js +21 -18
  29. package/src/commands/handlers/api-handler.js +0 -111
  30. package/src/commands/handlers/page-handler.js +0 -96
  31. package/src/commands/handlers/part-handler.js +0 -77
  32. package/src/core/context.js +0 -93
  33. /package/{templates → src/framework}/react/components/EditableCell.js +0 -0
  34. /package/{templates → src/framework}/react/components/MyBaseForm.js +0 -0
  35. /package/{templates → src/framework}/react/components/MyImage.js +0 -0
  36. /package/{templates → src/framework}/react/components/MyModalForm.js +0 -0
  37. /package/{templates → src/framework}/react/components/MyModalTable.js +0 -0
  38. /package/{templates → src/framework}/react/components/MySearchForm.js +0 -0
  39. /package/{templates → src/framework}/react/components/MyTable.js +0 -0
  40. /package/{templates → src/framework}/react/components/index.js +0 -0
  41. /package/{templates/react → src/framework/react/handlebars}/index.hbs +0 -0
  42. /package/{templates/react/handlebars → src/framework/react/handlebars/partials}/AlertInfo.hbs +0 -0
  43. /package/{templates/react/handlebars → src/framework/react/handlebars/partials}/FunctionButtons.hbs +0 -0
  44. /package/{templates/react/handlebars → src/framework/react/handlebars/partials}/MySearchForm.hbs +0 -0
  45. /package/{templates/react/handlebars → src/framework/react/handlebars/partials}/MyTable.hbs +0 -0
  46. /package/{templates/react/handlebars → src/framework/react/handlebars/partials}/handleBlock.hbs +0 -0
  47. /package/{templates/react/handlebars → src/framework/react/handlebars/partials}/hookBlock.hbs +0 -0
  48. /package/{templates/react/handlebars → src/framework/react/handlebars/partials}/operateBlock.hbs +0 -0
  49. /package/{templates/react/handlebars → src/framework/react/handlebars/partials}/renderBlock.hbs +0 -0
  50. /package/{templates/react/handlebars → src/framework/react/handlebars/partials}/stateBlock.hbs +0 -0
  51. /package/{templates/react → src/framework/react/handlebars}/resource.hbs +0 -0
  52. /package/{templates → src/framework}/react/hooks/useTableQuery.js +0 -0
  53. /package/src/{prompts/react/watch-api.js → framework/react/prompts/api.js} +0 -0
  54. /package/src/{prompts/react/api-linker.js → framework/react/prompts/linker.js} +0 -0
  55. /package/src/{prompts → framework/react/prompts}/mock.js +0 -0
  56. /package/src/{prompts/react/watch-page.js → framework/react/prompts/page.js} +0 -0
  57. /package/src/{prompts → framework/react/prompts}/system.js +0 -0
  58. /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
@@ -4,17 +4,20 @@ const path = require('path')
4
4
  const chalk = require('chalk')
5
5
  const pkg = require('../package.json')
6
6
  const { program } = require('commander')
7
- const { language, matrixEffect, bootSequence } = require('../src/utils/ux')
7
+ const { local, matrixEffect, bootSequence } = require('../src/utils/ux')
8
+
9
+ const dialogs = require('../src/bootstrap/dialogs')()
10
+ const dialog = dialogs[local]
8
11
 
9
12
  program
10
13
  .version(pkg.version)
11
- .description(language('AI驱动的前端CRUD代码生成器', 'AI-powered frontend CRUD code generator'))
14
+ .description(dialog.bunker.desc)
12
15
 
13
- program.option('-t, --template <type>', language('指定前端框架模板', 'Specify frontend framework template'), 'react')
16
+ program.option('-t, --template <type>', dialog.bunker.argDesc, 'react')
14
17
 
15
18
  program
16
19
  .command('init')
17
- .description(language('在当前目录初始化地堡构筑环境', 'Initialize Bunker construction environment'))
20
+ .description(dialog.bunker.initDesc)
18
21
  .action(() => {
19
22
  const tplConfig = path.resolve(__dirname, '../config.js')
20
23
  const tplEnv = path.resolve(__dirname, '../.env.example')
@@ -26,50 +29,49 @@ program
26
29
  fs.mkdirSync(path.join(process.cwd(), 'screenPart'), { recursive: true })
27
30
 
28
31
  if (fs.existsSync(targetEnv)) {
29
- console.log(chalk.yellow(language('🤖 Pod 042: [警告] 终端已存在 .env 文件,跳过生成。', '🤖 Pod 042: [Warning] .env already exists.')))
32
+ console.log(chalk.yellow(dialog.bunker.envCheck))
30
33
  } else {
31
34
  fs.copyFileSync(tplEnv, targetEnv)
32
- console.log(chalk.green(language('🤖 Pod 042: [报告] .env 存储完毕。', '🤖 Pod 042: [Report] .env storage complete.')))
35
+ console.log(chalk.green(dialog.bunker.envCopy))
33
36
  }
34
37
 
35
38
  if (fs.existsSync(targetConfig)) {
36
- console.log(chalk.yellow(language('🤖 Pod 042: [警告] 终端已存在 config.js 文件,跳过生成。', '🤖 Pod 042: [Warning] config.js already exists.')))
39
+ console.log(chalk.yellow(dialog.bunker.configCheck))
37
40
  } else {
38
41
  fs.copyFileSync(tplConfig, targetConfig)
39
- console.log(chalk.green(language('🤖 Pod 042: [报告] config.js 存储完毕。', '🤖 Pod 042: [Report] config.js storage complete.')))
42
+ console.log(chalk.green(dialog.bunker.configCopy))
40
43
  }
41
44
 
42
45
  const bunkerCmd = chalk.yellow(`'bunker': 'autodev watch'`)
43
- console.log(chalk.cyan(language(
44
- `📡 Operator 6O: 呼叫 2B, 地堡部署完毕, 为了更快捷地进入战场,建议手动执行 [物理装配]: 将 ${bunkerCmd} 加入您的 package.json scripts 中`,
45
- `📡 Operator 6O: Calling 2B! Bunker deployment is complete. To expedite your entry into the battlefield, I recommend a manual [Physical Assembly]: Add ${bunkerCmd} to your package.json scripts.`
46
- )))
46
+ console.log(chalk.cyan(dialog.bunker.initComplete(bunkerCmd)))
47
47
  })
48
48
 
49
49
  program
50
50
  .command('watch')
51
51
  .alias('start')
52
- .description(language('开启全频道联动监控:支持 Page/Part/API 协同构筑', 'Start full-channel linked monitoring: Coordinated Page/Part/API construction'))
53
- .action(() => {
54
- const bunker = require('../src/core/context')
55
- const result = bunker.init(program.opts())
52
+ .description(dialog.bunker.watchDesc)
53
+ .action(async () => {
54
+ const bunker = require('../src/bootstrap')
55
+ const result = bunker.init(program.opts(), dialogs)
56
56
  if (!result) {
57
57
  return
58
58
  }
59
- bootSequence(pkg.version)
60
- require('../src/commands/watch')()
61
- const { config } = bunker.get()
59
+ const { commander } = result.yorha
60
+ const { config } = result.infrastructure
62
61
  const { apiDoc, needMock, proxyTarget, enableAutoAlignment } = config
63
- if (apiDoc && enableAutoAlignment) {
64
- require('../src/services/api-linker')()
62
+
63
+ const bootTower = proxyTarget && !needMock && enableAutoAlignment
64
+
65
+ await bootSequence({ dialog, version: pkg.version, bootTower, commander })
66
+ require('../src/commands/watch')()
67
+ if (bootTower) {
68
+ require('../src/labs/tower')()
65
69
  }
66
- if (proxyTarget && !needMock && enableAutoAlignment) {
67
- require('../src/services/proxy-tower')()
70
+ if (apiDoc && enableAutoAlignment) {
71
+ require('../src/labs/linker')()
68
72
  }
69
73
  process.on('SIGINT', () => {
70
- console.log('\n')
71
- console.log(chalk.gray('--------------------------------------------------'))
72
- console.log(chalk.white(' [System] ') + chalk.yellow(language('正在断开神经云链接,执行数据物理封存...', 'Disconnecting Neural Link, Executing Physical Assembly...')))
74
+ commander.log(dialog.bunker.systemOffline)
73
75
  matrixEffect(500)
74
76
  })
75
77
  })
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.1.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,10 @@
1
+ module.exports = () => {
2
+
3
+ const fs = require('fs')
4
+ const path = require('path')
5
+
6
+ const dialogsPath = path.join(__dirname, `../dialogs`)
7
+ const dialogs = fs.readdirSync(dialogsPath).map(dialog => [path.basename(dialog, '.js'), require(path.join(dialogsPath, dialog))])
8
+
9
+ return Object.fromEntries(dialogs)
10
+ }
@@ -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,56 @@
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, dialogs) => {
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.log(chalk.red(ux.local === 'ZH-CN' ? `暂不支持 [${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 yorha = require('./yorha')()
23
+ const openAI = require('./openai')()
24
+ const core = require('../utils/core')
25
+ const handlers = require('./handlers')()
26
+ const config = infrastructure.getConfig()
27
+ const menus = infrastructure.getExistingMenus()
28
+ const prompts = require('./prompts')({ template })
29
+ const handlebars = require('./handlebars')({ config, template, ...infrastructure })
30
+
31
+ const accessPoint = { ux, yorha, openAI, config, dialogs, options, template, ...core, ...prompts, ...handlebars, ...infrastructure }
32
+
33
+ require('./infrastructure')(accessPoint)
34
+ const llm = require('../services/llm')(accessPoint)
35
+ const generator = require(generatorPath)(accessPoint)
36
+
37
+
38
+ instance = {
39
+ ux,
40
+ llm,
41
+ core,
42
+ yorha,
43
+ openAI,
44
+ prompts,
45
+ dialogs,
46
+ handlers,
47
+ generator,
48
+ handlebars,
49
+ cli: options,
50
+ infrastructure: { menus, config, ...infrastructure },
51
+ }
52
+ return instance
53
+ },
54
+
55
+ get: () => instance
56
+ }
@@ -0,0 +1,16 @@
1
+ module.exports = ({ ux, config, yorha, options, copyTemplateDir }) => {
2
+
3
+ const { local } = ux
4
+ const { commander } = yorha
5
+ const { hbsDir, hooksDir, utilsDir, componentsDir } = config
6
+
7
+ try {
8
+ if (hbsDir === '') {
9
+ copyTemplateDir(options, 'hooks', hooksDir)
10
+ copyTemplateDir(options, 'utils', utilsDir)
11
+ copyTemplateDir(options, 'components', componentsDir)
12
+ }
13
+ } catch (error) {
14
+ commander.log(local === 'ZH-CN' ? `模板构筑失败: ${error}` : `Template construction failed: ${error}`, 'red')
15
+ }
16
+ }
@@ -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
+ }
@@ -0,0 +1,39 @@
1
+ module.exports = () => {
2
+
3
+ const ora = require('ora')
4
+ const chalk = require('chalk')
5
+
6
+ const createMember = ({ name }) => ({
7
+ start(text) {
8
+ const spinner = ora({ text: chalk.cyan(`\n${name} ${text}`) }).start()
9
+ return spinner
10
+ },
11
+ fail(spinner, text) {
12
+ spinner.fail(chalk.red(`\n${name} ${text}`))
13
+ },
14
+ log(text, color = 'gray') {
15
+ console.log(chalk[color](`\n${name} ${text}`))
16
+ },
17
+ report(text, color = 'yellow') {
18
+ console.log(chalk[color](`\n${name} ${text}`))
19
+ },
20
+ update(spinner, text) {
21
+ spinner.text = chalk.cyan(`\n${name} ${text}`)
22
+ },
23
+ warning(spinner, text) {
24
+ spinner.warn(chalk.yellow(`\n${name} ${text}`))
25
+ },
26
+ success(spinner, text) {
27
+ spinner.succeed(chalk.green(`\n${name} ${text}`))
28
+ },
29
+ })
30
+
31
+ return {
32
+ nineS: createMember({ name: '[YoRHa::9S]' }),
33
+ commander: createMember({ name: '[BUNKER]' }),
34
+ pod042: createMember({ name: '[YoRHa::Pod042]' }),
35
+ pod153: createMember({ name: '[YoRHa::Pod153]' }),
36
+ operator6O: createMember({ name: '[YoRHa::6O]' }),
37
+ }
38
+
39
+ }
@@ -2,44 +2,24 @@ module.exports = () => {
2
2
 
3
3
  const fs = require('fs')
4
4
  const path = require('path')
5
- const chalk = require('chalk')
6
5
  const chokidar = require('chokidar')
7
6
 
8
- const {
9
- options,
10
- language,
11
- createTaskQueue,
12
- contextStringify,
13
- menus, config, copyTemplateDir,
14
- apiHandler, pageHandler, partHandler,
15
- } = require('../core/context').get()
7
+ const { ux, core, yorha, dialogs, handlers, infrastructure } = require('../bootstrap').get()
16
8
 
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
- }
9
+ const { local } = ux
10
+ const dialog = dialogs[local]
11
+ const { createTaskQueue } = core
12
+ const { pod042, commander, operator6O } = yorha
13
+ const { menus, config, contextStringify } = infrastructure
28
14
 
29
15
  const queue = createTaskQueue(2)
30
16
 
31
17
  queue.onIdle(() => {
32
- console.log(chalk.green(language(
33
- '\n🤖 Pod 042: [报告] 队列已空,正在向 Bunker 同步 Menu 路由配置...',
34
- '\n🤖 Pod 042: [Report] Queue empty. Syncing Menu configuration to Bunker...'
35
- )))
18
+ pod042.report(dialog.pod042.queueEmpty)
36
19
  const utilsDir = path.join(process.cwd(), config.utilsDir)
37
20
  if (!fs.existsSync(utilsDir)) fs.mkdirSync(utilsDir, { recursive: true })
38
21
  fs.writeFileSync(path.join(utilsDir, 'menus.js'), `export const menus = ${contextStringify({ context: menus, maxLength: 50 })}`)
39
- console.log(chalk.gray(language(
40
- '\n🤖 [System] 未检测到运行中的任务,系统待机中...\n',
41
- '\n🤖 [System] System is STANDBY.\n'
42
- )))
22
+ commander.log(dialog.bunker.systemStandby)
43
23
  })
44
24
 
45
25
  const watcher = chokidar.watch(['./screenShot', './screenPart', './response'], {
@@ -49,23 +29,16 @@ module.exports = () => {
49
29
  awaitWriteFinish: { stabilityThreshold: 500, pollInterval: 100 }
50
30
  })
51
31
 
52
- console.log(chalk.magenta(language(
53
- '📡 Operator 6O: 呼叫 2B,地堡全频道联动监控已就绪!',
54
- '📡 Operator 6O: Calling 2B, all-channel linked monitoring is ready!'
55
- )))
32
+ operator6O.report(dialog.operator6O.call2B)
56
33
 
57
- watcher.on('add', filePath => {
34
+ const routes = Object.values(handlers)
58
35
 
36
+ watcher.on('add', filePath => {
59
37
  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))
38
+ const route = routes.find(route => absolutePath.includes(route.watch))
39
+ if (route) {
40
+ queue.add(() => route.handle(filePath))
69
41
  }
70
42
  })
43
+
71
44
  }
@@ -0,0 +1,55 @@
1
+ module.exports = {
2
+ nineS: {
3
+ dataCamouflageComplete: 'Mock data generation successful',
4
+ scanningField: 'Scanning field differences... Bridging semantic gaps',
5
+ dataCamouflage: fileName => `Piercing target firewall... Executing data camouflage [${fileName}]`,
6
+ },
7
+ pod042: {
8
+ queueEmpty: 'Queue empty. Syncing Menu configuration to Bunker...',
9
+ extractingUiMetadata: 'Extracting UI metadata from neural cloud network...',
10
+ simulate: 'Real-fire request intercepted. Dropping simulation package: example.json',
11
+ uploadVisualMetadata: 'Uploading visual metadata to Command for semantic analysis...',
12
+ partialConstruction: time => `Report: Partial construction achieved. Elapsed: ${time}s`,
13
+ constructionAborted: virus => `Construction aborted. Logic virus or timeout detected: ${virus}`,
14
+ visualPartCaptured: `Partial visual sample detected. Executing 'Fragment Construction Protocol'...`,
15
+ intercept: fileName => `Module [${fileName}] already exists. Construction skipped to prevent overwrite.`,
16
+ partialRecommendation: '│ Recommendation: Please manually assemble the above code block into your target file',
17
+ partialConstructionAborted: virus => `[Warning] Fragment construction failed. Logic interference detected: ${virus}`,
18
+ assemblyComplete: (fileName, time) => `Protocol complete. Physical assembly of [${fileName}] achieved. Elapsed: ${time}s`,
19
+ visualCaptured: fileName => `Visual sensor captured: [${fileName}]. Allocating Bunker resources for physical construction...`,
20
+ },
21
+ pod153: {
22
+ signalLinkFault: virus => `Signal Link Fault: ${virus}`,
23
+ signalSynchronized: count => `Signal Synchronized: ${count} nodes energized`,
24
+ formatError: 'Data format is not standard JSON, will try to align by character',
25
+ alignmentFailed: virus => `Alignment failed. Encountered powerful API firewall: ${virus}`,
26
+ autonomousAddressing: `Initiating 'Full-Channel Autonomous Addressing Protocol [Semantic Scan]'...`,
27
+ inactiveModule: fileName => `Inactive module: [${fileName}]. Requesting 9S for precise alignment...`,
28
+ reconEncryptedData: fileName => `Encrypted data source [${fileName}] detected. Initiating semantic alignment...`,
29
+ capturedRuntimeSignal: fileName => `Captured runtime signal [${fileName}]. Executing semantic alignment protocol...`,
30
+ unknownModule: fileName => `Module [${fileName}] resource not found in Bunker database. Please execute visual construction first`,
31
+ bridgeProtocolComplete: (count, time) => `Semantic bridge protocol complete. Corrected ${count} field deviations. Elapsed: ${time}s`,
32
+ },
33
+ bunker: {
34
+ envCopy: '.env storage complete',
35
+ envCheck: '.env already exists',
36
+ systemStandby: 'System is STANDBY',
37
+ configCheck: 'config.js already exists',
38
+ configCopy: 'config.js storage complete',
39
+ argDesc: 'Specify frontend framework template',
40
+ desc: 'AI-powered frontend CRUD code generator',
41
+ initDesc: 'Initialize Bunker construction environment',
42
+ towerOnline: port => `Signal Intercept Tower Online [Band: ${port}]`,
43
+ linkSevered: 'Link Severed: Check network status or Black Box resonance',
44
+ systemOffline: 'Disconnecting Neural Link, Executing Physical Assembly...',
45
+ accessDenied: 'YoRHa Command Center Access Denied: Invalid API Key or quota exhausted!',
46
+ watchDesc: 'Start full-channel linked monitoring: Coordinated Page/Part/API construction',
47
+ towerConnected: port => `Command: Please point your local proxy target to http://localhost:${port}`,
48
+ disclaimer: 'Match Result Reference Only. Not Final Decision. Each Unit should adjust based on battlefield conditions',
49
+ networkInstability: count => `Neural Network instability detected. Attempting to re-establish link... (Retry #${count})`,
50
+ initComplete: cmd => `Bunker deployment is complete. To expedite your entry into the battlefield, I recommend a manual [Physical Assembly]: Add ${cmd} to your package.json scripts.`
51
+ },
52
+ operator6O: {
53
+ call2B: 'Calling 2B, all-channel linked monitoring is ready!'
54
+ }
55
+ }