@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.
- package/.github/scripts/deploy/publish.py +2 -2
- package/.github/scripts/render/dashboard.py +13 -9
- package/CONTRIBUTING.md +0 -18
- package/bin/autodev.js +28 -26
- package/config.js +3 -3
- package/package.json +1 -3
- package/src/bootstrap/dialogs.js +10 -0
- package/src/bootstrap/handlebars.js +26 -0
- package/src/bootstrap/handlers.js +10 -0
- package/src/bootstrap/index.js +56 -0
- package/src/bootstrap/infrastructure.js +16 -0
- package/src/bootstrap/openai.js +13 -0
- package/src/bootstrap/prompts.js +10 -0
- package/src/bootstrap/yorha.js +39 -0
- package/src/commands/watch.js +15 -42
- package/src/dialogs/EN-US.js +55 -0
- package/src/dialogs/ZH-CN.js +55 -0
- package/src/{core/react-compiler.js → framework/react/generator/index.js} +1 -1
- package/src/{prompts/react/watch-part.js → framework/react/prompts/part.js} +1 -1
- package/{templates → src/framework}/react/utils/utils.js +1 -1
- package/src/handlers/api.js +92 -0
- package/src/handlers/page.js +70 -0
- package/src/handlers/part.js +59 -0
- package/src/{services/api-linker.js → labs/linker.js} +14 -31
- package/src/{services/proxy-tower.js → labs/tower.js} +10 -23
- package/src/services/llm.js +21 -20
- package/src/utils/infrastructure.js +5 -2
- package/src/utils/ux.js +21 -18
- package/src/commands/handlers/api-handler.js +0 -111
- package/src/commands/handlers/page-handler.js +0 -96
- package/src/commands/handlers/part-handler.js +0 -77
- package/src/core/context.js +0 -93
- /package/{templates → src/framework}/react/components/EditableCell.js +0 -0
- /package/{templates → src/framework}/react/components/MyBaseForm.js +0 -0
- /package/{templates → src/framework}/react/components/MyImage.js +0 -0
- /package/{templates → src/framework}/react/components/MyModalForm.js +0 -0
- /package/{templates → src/framework}/react/components/MyModalTable.js +0 -0
- /package/{templates → src/framework}/react/components/MySearchForm.js +0 -0
- /package/{templates → src/framework}/react/components/MyTable.js +0 -0
- /package/{templates → src/framework}/react/components/index.js +0 -0
- /package/{templates/react → src/framework/react/handlebars}/index.hbs +0 -0
- /package/{templates/react/handlebars → src/framework/react/handlebars/partials}/AlertInfo.hbs +0 -0
- /package/{templates/react/handlebars → src/framework/react/handlebars/partials}/FunctionButtons.hbs +0 -0
- /package/{templates/react/handlebars → src/framework/react/handlebars/partials}/MySearchForm.hbs +0 -0
- /package/{templates/react/handlebars → src/framework/react/handlebars/partials}/MyTable.hbs +0 -0
- /package/{templates/react/handlebars → src/framework/react/handlebars/partials}/handleBlock.hbs +0 -0
- /package/{templates/react/handlebars → src/framework/react/handlebars/partials}/hookBlock.hbs +0 -0
- /package/{templates/react/handlebars → src/framework/react/handlebars/partials}/operateBlock.hbs +0 -0
- /package/{templates/react/handlebars → src/framework/react/handlebars/partials}/renderBlock.hbs +0 -0
- /package/{templates/react/handlebars → src/framework/react/handlebars/partials}/stateBlock.hbs +0 -0
- /package/{templates/react → src/framework/react/handlebars}/resource.hbs +0 -0
- /package/{templates → src/framework}/react/hooks/useTableQuery.js +0 -0
- /package/src/{prompts/react/watch-api.js → framework/react/prompts/api.js} +0 -0
- /package/src/{prompts/react/api-linker.js → framework/react/prompts/linker.js} +0 -0
- /package/src/{prompts → framework/react/prompts}/mock.js +0 -0
- /package/src/{prompts/react/watch-page.js → framework/react/prompts/page.js} +0 -0
- /package/src/{prompts → framework/react/prompts}/system.js +0 -0
- /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[
|
|
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[
|
|
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[
|
|
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[
|
|
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[
|
|
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[
|
|
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
|
-
)),
|
|
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[
|
|
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
|
-
|
|
222
|
-
|
|
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(
|
|
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 {
|
|
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(
|
|
14
|
+
.description(dialog.bunker.desc)
|
|
12
15
|
|
|
13
|
-
program.option('-t, --template <type>',
|
|
16
|
+
program.option('-t, --template <type>', dialog.bunker.argDesc, 'react')
|
|
14
17
|
|
|
15
18
|
program
|
|
16
19
|
.command('init')
|
|
17
|
-
.description(
|
|
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(
|
|
32
|
+
console.log(chalk.yellow(dialog.bunker.envCheck))
|
|
30
33
|
} else {
|
|
31
34
|
fs.copyFileSync(tplEnv, targetEnv)
|
|
32
|
-
console.log(chalk.green(
|
|
35
|
+
console.log(chalk.green(dialog.bunker.envCopy))
|
|
33
36
|
}
|
|
34
37
|
|
|
35
38
|
if (fs.existsSync(targetConfig)) {
|
|
36
|
-
console.log(chalk.yellow(
|
|
39
|
+
console.log(chalk.yellow(dialog.bunker.configCheck))
|
|
37
40
|
} else {
|
|
38
41
|
fs.copyFileSync(tplConfig, targetConfig)
|
|
39
|
-
console.log(chalk.green(
|
|
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(
|
|
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(
|
|
53
|
-
.action(() => {
|
|
54
|
-
const bunker = require('../src/
|
|
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
|
-
|
|
60
|
-
|
|
61
|
-
const { config } = bunker.get()
|
|
59
|
+
const { commander } = result.yorha
|
|
60
|
+
const { config } = result.infrastructure
|
|
62
61
|
const { apiDoc, needMock, proxyTarget, enableAutoAlignment } = config
|
|
63
|
-
|
|
64
|
-
|
|
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 (
|
|
67
|
-
require('../src/
|
|
70
|
+
if (apiDoc && enableAutoAlignment) {
|
|
71
|
+
require('../src/labs/linker')()
|
|
68
72
|
}
|
|
69
73
|
process.on('SIGINT', () => {
|
|
70
|
-
|
|
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": "
|
|
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
|
+
}
|
package/src/commands/watch.js
CHANGED
|
@@ -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 {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
34
|
+
const routes = Object.values(handlers)
|
|
58
35
|
|
|
36
|
+
watcher.on('add', filePath => {
|
|
59
37
|
const absolutePath = path.resolve(filePath)
|
|
60
|
-
|
|
61
|
-
if (
|
|
62
|
-
queue.add(() =>
|
|
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
|
+
}
|