@yorha2b-lab/autodev 4.1.0 → 4.2.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/analyze/bot_detect.py +5 -5
- package/.github/scripts/analyze/cluster.py +5 -5
- package/.github/scripts/collect/traffic.py +11 -11
- package/.github/scripts/deploy/publish.py +15 -15
- package/.github/scripts/render/dashboard.py +9 -9
- package/.github/workflows/bunker-intelligence.yml +4 -4
- package/bin/autodev.js +6 -5
- package/config.js +1 -1
- package/package.json +1 -1
- package/src/commands/handlers/api-handler.js +15 -10
- package/src/commands/handlers/page-handler.js +21 -19
- package/src/commands/handlers/part-handler.js +14 -11
- package/src/commands/watch.js +20 -18
- package/src/core/context.js +39 -52
- package/src/core/react-compiler.js +69 -85
- package/src/prompts/mock.js +1 -1
- package/src/prompts/react/api-linker.js +1 -1
- package/src/prompts/react/watch-api.js +1 -1
- package/src/prompts/react/watch-page.js +1 -0
- package/src/prompts/react/watch-part.js +1 -0
- package/src/services/api-linker.js +21 -59
- package/src/services/llm.js +64 -81
- package/src/services/proxy-tower.js +17 -12
- package/src/utils/{utils.js → core.js} +41 -165
- package/src/utils/infrastructure.js +102 -0
- package/src/utils/ux.js +115 -0
- package/templates/react/components/MyModalForm.js +1 -1
- package/templates/react/components/MyModalTable.js +1 -1
- package/templates/react/components/index.js +2 -2
- package/templates/react/handlebars/handleBlock.hbs +3 -2
- package/templates/react/handlebars/hookBlock.hbs +1 -0
- package/src/core/task-queue.js +0 -38
- /package/src/schema/{page.json → react/page.json} +0 -0
|
@@ -4,7 +4,7 @@ import matplotlib.pyplot as plt
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
def plot_bot_composition():
|
|
7
|
-
print(
|
|
7
|
+
print('🤖 Pod 042: 正在绘制‘肉机成分分析图’...')
|
|
8
8
|
df_c = pd.read_csv('ghrs-data/clones_ledger.csv')
|
|
9
9
|
df_v = pd.read_csv('ghrs-data/views_ledger.csv')
|
|
10
10
|
df = pd.merge(df_c, df_v, on='date', how='inner')
|
|
@@ -25,19 +25,19 @@ def plot_bot_composition():
|
|
|
25
25
|
|
|
26
26
|
wedges, texts, autotexts = ax.pie(data, labels=labels, autopct='%1.1f%%',
|
|
27
27
|
startangle=90, colors=colors, pctdistance=0.85,
|
|
28
|
-
explode=(0.05, 0), textprops={'color':
|
|
28
|
+
explode=(0.05, 0), textprops={'color': 'w'})
|
|
29
29
|
|
|
30
30
|
# 画个中间的黑洞,变成甜甜圈
|
|
31
31
|
centre_circle = plt.Circle((0, 0), 0.70, fc='#0d1117')
|
|
32
32
|
fig.gca().add_artist(centre_circle)
|
|
33
33
|
|
|
34
|
-
ax.set_title(
|
|
34
|
+
ax.set_title('Operational Composition: Meat vs Machine',
|
|
35
35
|
color='#33cc33', fontsize=14)
|
|
36
36
|
plt.tight_layout()
|
|
37
37
|
os.makedirs('plots', exist_ok=True)
|
|
38
38
|
plt.savefig('plots/bot_composition.png', dpi=100)
|
|
39
|
-
print(
|
|
39
|
+
print('✅ 甜甜圈图封存成功。')
|
|
40
40
|
|
|
41
41
|
|
|
42
|
-
if __name__ ==
|
|
42
|
+
if __name__ == '__main__':
|
|
43
43
|
plot_bot_composition()
|
|
@@ -4,7 +4,7 @@ import matplotlib.pyplot as plt
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
def plot_commander_profiles():
|
|
7
|
-
print(
|
|
7
|
+
print('🤖 Pod 042: 正在绘制‘指挥官军衔分布图’...')
|
|
8
8
|
df_c = pd.read_csv('ghrs-data/clones_ledger.csv')
|
|
9
9
|
df_c['intensity'] = df_c['clones'] / df_c['uniques'].replace(0, 1)
|
|
10
10
|
|
|
@@ -27,14 +27,14 @@ def plot_commander_profiles():
|
|
|
27
27
|
ax = sns.barplot(x=rank_counts.index,
|
|
28
28
|
y=rank_counts.values, palette='viridis')
|
|
29
29
|
|
|
30
|
-
plt.title(
|
|
31
|
-
plt.ylabel(
|
|
30
|
+
plt.title('Commander Hierarchy Distribution', color='#0066ff', fontsize=14)
|
|
31
|
+
plt.ylabel('Node Count', color='#888')
|
|
32
32
|
plt.grid(axis='y', color='#333', linestyle='--', alpha=0.5)
|
|
33
33
|
|
|
34
34
|
plt.tight_layout()
|
|
35
35
|
plt.savefig('plots/commander_profiles.png', dpi=100)
|
|
36
|
-
print(
|
|
36
|
+
print('✅ 军衔分布图封存成功。')
|
|
37
37
|
|
|
38
38
|
|
|
39
|
-
if __name__ ==
|
|
39
|
+
if __name__ == '__main__':
|
|
40
40
|
plot_commander_profiles()
|
|
@@ -7,7 +7,7 @@ REPO = os.getenv('REPO')
|
|
|
7
7
|
TOKEN = os.getenv('STATS_TOKEN')
|
|
8
8
|
HEADERS = {'Authorization': f'token {TOKEN}',
|
|
9
9
|
'Accept': 'application/vnd.github.v3+json'}
|
|
10
|
-
API_BASE = f
|
|
10
|
+
API_BASE = f'https://api.github.com/repos/{REPO}'
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
def fetch_api(url, fallback):
|
|
@@ -36,14 +36,14 @@ def merge_ledger(data, ledger_path, col_name):
|
|
|
36
36
|
ledger_path, index=False)
|
|
37
37
|
|
|
38
38
|
|
|
39
|
-
if __name__ ==
|
|
40
|
-
print(
|
|
39
|
+
if __name__ == '__main__':
|
|
40
|
+
print('🤖 Pod 042: Executing Data Mining Protocol...')
|
|
41
41
|
|
|
42
42
|
# 抓取原始数据
|
|
43
|
-
clones = fetch_api(f
|
|
44
|
-
views = fetch_api(f
|
|
45
|
-
repo_info = fetch_api(API_BASE, {
|
|
46
|
-
referrers = fetch_api(f
|
|
43
|
+
clones = fetch_api(f'{API_BASE}/traffic/clones', {'clones': []})
|
|
44
|
+
views = fetch_api(f'{API_BASE}/traffic/views', {'views': []})
|
|
45
|
+
repo_info = fetch_api(API_BASE, {'stargazers_count': 0, 'forks_count': 0})
|
|
46
|
+
referrers = fetch_api(f'{API_BASE}/traffic/popular/referrers', [])
|
|
47
47
|
|
|
48
48
|
# 物理焊接账本
|
|
49
49
|
merge_ledger(clones['clones'], 'ghrs-data/clones_ledger.csv', 'clones')
|
|
@@ -57,10 +57,10 @@ if __name__ == "__main__":
|
|
|
57
57
|
c_df = pd.read_csv('ghrs-data/clones_ledger.csv')
|
|
58
58
|
total_clones = int(c_df['clones'].sum())
|
|
59
59
|
stats = {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
60
|
+
'total_clones': total_clones,
|
|
61
|
+
'stars': repo_info['stargazers_count'],
|
|
62
|
+
'forks': repo_info['forks_count']
|
|
63
63
|
}
|
|
64
64
|
with open('bunker-stats.json', 'w') as f:
|
|
65
65
|
json.dump(stats, f)
|
|
66
|
-
print(f
|
|
66
|
+
print(f'✅ Ledger synced. Total Clones: {total_clones}')
|
|
@@ -10,14 +10,14 @@ def assemble_readme():
|
|
|
10
10
|
with open('raw_referrers.json', 'r') as f:
|
|
11
11
|
referrers = json.load(f)
|
|
12
12
|
|
|
13
|
-
ref_table =
|
|
13
|
+
ref_table = '| Referrer | Views | Uniques |\n| :--- | :--- | :--- |\n'
|
|
14
14
|
if referrers:
|
|
15
15
|
for r in referrers:
|
|
16
|
-
ref_table += f
|
|
16
|
+
ref_table += f'| {r['referrer']} | {r['count']} | {r['uniques']} |\n'
|
|
17
17
|
else:
|
|
18
|
-
ref_table +=
|
|
18
|
+
ref_table += '| No Signal | - | - |\n'
|
|
19
19
|
|
|
20
|
-
report = f
|
|
20
|
+
report = f'''# 🛰️ 地堡终极运行报告 (Sovereign Dashboard v8.5)
|
|
21
21
|
## 📊 核心战力指标
|
|
22
22
|
- **累计物理克隆**: `{stats['total_clones']}` 次
|
|
23
23
|
- **社群声望**: ⭐ `{stats['stars']}` / 🍴 `{stats['forks']}`
|
|
@@ -41,7 +41,7 @@ def assemble_readme():
|
|
|
41
41
|
{ref_table}
|
|
42
42
|
|
|
43
43
|
> 📡 物理封存点: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')} CST | Glory to Mankind.
|
|
44
|
-
|
|
44
|
+
'''
|
|
45
45
|
with open('README.md', 'w') as f:
|
|
46
46
|
f.write(report)
|
|
47
47
|
|
|
@@ -51,20 +51,20 @@ def git_push():
|
|
|
51
51
|
stats = json.load(f)
|
|
52
52
|
# 执行物理封存 Git 指令
|
|
53
53
|
try:
|
|
54
|
-
subprocess.run([
|
|
55
|
-
|
|
56
|
-
subprocess.run([
|
|
57
|
-
|
|
58
|
-
subprocess.run([
|
|
54
|
+
subprocess.run(['git', 'config', 'user.name',
|
|
55
|
+
'github-actions'], check=True)
|
|
56
|
+
subprocess.run(['git', 'config', 'user.email',
|
|
57
|
+
'github-actions@github.com'], check=True)
|
|
58
|
+
subprocess.run(['git', 'add', '-A'], check=True)
|
|
59
59
|
subprocess.run(
|
|
60
|
-
[
|
|
60
|
+
['git', 'commit', '-m', f'chore: sovereign modular update [total {stats['total_clones']}]'], check=True)
|
|
61
61
|
subprocess.run(
|
|
62
|
-
[
|
|
63
|
-
print(
|
|
62
|
+
['git', 'push', 'origin', 'github-repo-stats', '--force'], check=True)
|
|
63
|
+
print('✅ Data sealed and pushed to cloud.')
|
|
64
64
|
except Exception as e:
|
|
65
|
-
print(f
|
|
65
|
+
print(f'⚠️ Git push skipped: {e}')
|
|
66
66
|
|
|
67
67
|
|
|
68
|
-
if __name__ ==
|
|
68
|
+
if __name__ == '__main__':
|
|
69
69
|
assemble_readme()
|
|
70
70
|
git_push()
|
|
@@ -26,7 +26,7 @@ def peak_recon():
|
|
|
26
26
|
fontsize=14, fontweight='bold')
|
|
27
27
|
|
|
28
28
|
peak_clone_idx = df['clones'].idxmax()
|
|
29
|
-
axA.annotate(f'LEGEND PEAK: {df[
|
|
29
|
+
axA.annotate(f'LEGEND PEAK: {df['clones'].max()}',
|
|
30
30
|
xy=(df.loc[peak_clone_idx, 'date'],
|
|
31
31
|
df.loc[peak_clone_idx, 'clones']),
|
|
32
32
|
xytext=(10, 20), textcoords='offset points',
|
|
@@ -48,7 +48,7 @@ def peak_recon():
|
|
|
48
48
|
5 else '#e74c3c' for r in df['ratio']]
|
|
49
49
|
axC.bar(df['date'], df['ratio'], color=colors3, alpha=0.7)
|
|
50
50
|
axC.axhline(y=df['ratio'].mean(), color='#9b59b6',
|
|
51
|
-
ls='--', label=f'Avg: {df[
|
|
51
|
+
ls='--', label=f'Avg: {df['ratio'].mean():.2f}')
|
|
52
52
|
axC.set_title('Clones/Visitor Ratio (High Ratio = CI/Automation)',
|
|
53
53
|
fontsize=14, fontweight='bold')
|
|
54
54
|
axC.legend()
|
|
@@ -84,7 +84,7 @@ def intelligence_grid():
|
|
|
84
84
|
ax1.fill_between(df['date'], df['clones'],
|
|
85
85
|
alpha=0.3, color='#2E86AB')
|
|
86
86
|
ax1.axhline(y=df['clones'].mean(), color='red', linestyle='--',
|
|
87
|
-
alpha=0.7, label=f'Avg: {df[
|
|
87
|
+
alpha=0.7, label=f'Avg: {df['clones'].mean():.0f}')
|
|
88
88
|
ax1.set_title('Daily Clone Trend', fontsize=12, fontweight='bold')
|
|
89
89
|
ax1.set_ylabel('Clones')
|
|
90
90
|
ax1.legend()
|
|
@@ -100,7 +100,7 @@ def intelligence_grid():
|
|
|
100
100
|
ax2.fill_between(df['date'], df['uniques'],
|
|
101
101
|
alpha=0.3, color='#A23B72')
|
|
102
102
|
ax2.axhline(y=df['uniques'].mean(), color='red', linestyle='--',
|
|
103
|
-
alpha=0.7, label=f'Avg: {df[
|
|
103
|
+
alpha=0.7, label=f'Avg: {df['uniques'].mean():.0f}')
|
|
104
104
|
ax2.set_title('Daily Unique Commanders',
|
|
105
105
|
fontsize=12, fontweight='bold')
|
|
106
106
|
ax2.set_ylabel('Unique Visitors')
|
|
@@ -121,7 +121,7 @@ def intelligence_grid():
|
|
|
121
121
|
z = np.polyfit(df['uniques'], df['clones'], 1)
|
|
122
122
|
p = np.poly1d(z)
|
|
123
123
|
ax3.plot(df['uniques'].sort_values(), p(df['uniques'].sort_values(
|
|
124
|
-
)),
|
|
124
|
+
)), 'r--', alpha=0.7, label=f'Trend: y={z[0]:.1f}x+{z[1]:.1f}')
|
|
125
125
|
ax3.legend()
|
|
126
126
|
ax3.grid(True, alpha=0.3)
|
|
127
127
|
|
|
@@ -131,7 +131,7 @@ def intelligence_grid():
|
|
|
131
131
|
ax4.hist(df['clones_per_unique'], bins=25,
|
|
132
132
|
color='#F18F01', alpha=0.7, edgecolor='white')
|
|
133
133
|
ax4.axvline(x=df['clones_per_unique'].mean(
|
|
134
|
-
), color='red', linestyle='--', label=f'Avg: {df[
|
|
134
|
+
), color='red', linestyle='--', label=f'Avg: {df['clones_per_unique'].mean():.2f}')
|
|
135
135
|
ax4.set_xlabel('Clones Per Unit')
|
|
136
136
|
ax4.set_ylabel('Days')
|
|
137
137
|
ax4.set_title('Clones Per User Distribution',
|
|
@@ -218,8 +218,8 @@ def main_dashboard(df_c, df_v):
|
|
|
218
218
|
plt.tight_layout()
|
|
219
219
|
plt.savefig('plots/bunker_main_v7.png', dpi=120)
|
|
220
220
|
|
|
221
|
-
if __name__ ==
|
|
222
|
-
print(
|
|
221
|
+
if __name__ == '__main__':
|
|
222
|
+
print('🤖 Pod 042: Rendering Strategic Dashboards...')
|
|
223
223
|
plt.style.use('dark_background')
|
|
224
224
|
os.makedirs('plots', exist_ok=True)
|
|
225
225
|
|
|
@@ -232,4 +232,4 @@ if __name__ == "__main__":
|
|
|
232
232
|
intelligence_grid()
|
|
233
233
|
main_dashboard(df_c, df_v)
|
|
234
234
|
|
|
235
|
-
print(
|
|
235
|
+
print('✅ Dashboards rendered.')
|
|
@@ -39,25 +39,25 @@ jobs:
|
|
|
39
39
|
|
|
40
40
|
# 💡 步骤 3:运行脚本,注意现在的相对路径!
|
|
41
41
|
# 我们在当前根目录运行,调用 scripts_repo 里的脚本,去处理 data_repo 里的数据
|
|
42
|
-
- name:
|
|
42
|
+
- name: '🛰️ Step 1: Data Collection'
|
|
43
43
|
run: |
|
|
44
44
|
cd data_repo
|
|
45
45
|
python ../scripts_repo/.github/scripts/collect/traffic.py
|
|
46
46
|
|
|
47
|
-
- name:
|
|
47
|
+
- name: '🧠 Step 2: Intelligence Analysis'
|
|
48
48
|
run: |
|
|
49
49
|
cd data_repo
|
|
50
50
|
# 执行“肉机比”扫描与“军衔”聚类分析
|
|
51
51
|
python ../scripts_repo/.github/scripts/analyze/bot_detect.py
|
|
52
52
|
python ../scripts_repo/.github/scripts/analyze/cluster.py
|
|
53
53
|
|
|
54
|
-
- name:
|
|
54
|
+
- name: '📈 Step 3: Visualization Rendering'
|
|
55
55
|
run: |
|
|
56
56
|
cd data_repo
|
|
57
57
|
# 渲染核心看板
|
|
58
58
|
python ../scripts_repo/.github/scripts/render/dashboard.py
|
|
59
59
|
|
|
60
|
-
- name:
|
|
60
|
+
- name: '💾 Step 4: Deployment & Sealing'
|
|
61
61
|
run: |
|
|
62
62
|
cd data_repo
|
|
63
63
|
# 物理封存至 README
|
package/bin/autodev.js
CHANGED
|
@@ -4,8 +4,7 @@ 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
|
|
8
|
-
const { language, matrixEffect, bootSequence } = require('../src/utils/utils.js')
|
|
7
|
+
const { language, matrixEffect, bootSequence } = require('../src/utils/ux')
|
|
9
8
|
|
|
10
9
|
program
|
|
11
10
|
.version(pkg.version)
|
|
@@ -40,7 +39,7 @@ program
|
|
|
40
39
|
console.log(chalk.green(language('🤖 Pod 042: [报告] config.js 存储完毕。', '🤖 Pod 042: [Report] config.js storage complete.')))
|
|
41
40
|
}
|
|
42
41
|
|
|
43
|
-
const bunkerCmd = chalk.yellow('
|
|
42
|
+
const bunkerCmd = chalk.yellow(`'bunker': 'autodev watch'`)
|
|
44
43
|
console.log(chalk.cyan(language(
|
|
45
44
|
`📡 Operator 6O: 呼叫 2B, 地堡部署完毕, 为了更快捷地进入战场,建议手动执行 [物理装配]: 将 ${bunkerCmd} 加入您的 package.json scripts 中`,
|
|
46
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.`
|
|
@@ -52,6 +51,7 @@ program
|
|
|
52
51
|
.alias('start')
|
|
53
52
|
.description(language('开启全频道联动监控:支持 Page/Part/API 协同构筑', 'Start full-channel linked monitoring: Coordinated Page/Part/API construction'))
|
|
54
53
|
.action(() => {
|
|
54
|
+
const bunker = require('../src/core/context')
|
|
55
55
|
const result = bunker.init(program.opts())
|
|
56
56
|
if (!result) {
|
|
57
57
|
return
|
|
@@ -59,10 +59,11 @@ program
|
|
|
59
59
|
bootSequence(pkg.version)
|
|
60
60
|
require('../src/commands/watch')()
|
|
61
61
|
const { config } = bunker.get()
|
|
62
|
-
|
|
62
|
+
const { apiDoc, needMock, proxyTarget, enableAutoAlignment } = config
|
|
63
|
+
if (apiDoc && enableAutoAlignment) {
|
|
63
64
|
require('../src/services/api-linker')()
|
|
64
65
|
}
|
|
65
|
-
if (
|
|
66
|
+
if (proxyTarget && !needMock && enableAutoAlignment) {
|
|
66
67
|
require('../src/services/proxy-tower')()
|
|
67
68
|
}
|
|
68
69
|
process.on('SIGINT', () => {
|
package/config.js
CHANGED
package/package.json
CHANGED
|
@@ -1,16 +1,21 @@
|
|
|
1
|
-
const fs = require('fs')
|
|
2
|
-
const ora = require('ora')
|
|
3
|
-
const path = require('path')
|
|
4
|
-
const chalk = require('chalk')
|
|
5
|
-
|
|
6
1
|
module.exports = async (filePath, liveResponse = null) => {
|
|
7
2
|
|
|
8
|
-
const
|
|
9
|
-
const
|
|
3
|
+
const fs = require('fs')
|
|
4
|
+
const ora = require('ora')
|
|
5
|
+
const path = require('path')
|
|
6
|
+
const chalk = require('chalk')
|
|
7
|
+
|
|
8
|
+
const {
|
|
9
|
+
unwrapSignal,
|
|
10
|
+
config, language,
|
|
11
|
+
alignResponseFields
|
|
12
|
+
} = require('../../core/context').get()
|
|
13
|
+
|
|
14
|
+
const { pagesDir } = config
|
|
10
15
|
|
|
11
16
|
const startTime = Date.now()
|
|
12
17
|
const fileName = liveResponse?.fileName ?? path.basename(filePath, path.extname(filePath))
|
|
13
|
-
const resourcePath = path.join(process.cwd(),
|
|
18
|
+
const resourcePath = path.join(process.cwd(), pagesDir, fileName, 'resource.js')
|
|
14
19
|
|
|
15
20
|
const spinner = ora({
|
|
16
21
|
text: chalk.yellow(language(
|
|
@@ -57,7 +62,7 @@ module.exports = async (filePath, liveResponse = null) => {
|
|
|
57
62
|
return Array.from(new Set(keys))
|
|
58
63
|
}
|
|
59
64
|
|
|
60
|
-
const result = await alignResponseFields(
|
|
65
|
+
const result = await alignResponseFields({ responseStr: JSON.stringify(sampleData), resourceStr: extractKeys(resourceStr).join(',') })
|
|
61
66
|
let changeCount = 0
|
|
62
67
|
const resultMapping = {}
|
|
63
68
|
Object.entries(result).forEach(([oldField, newField]) => {
|
|
@@ -81,7 +86,7 @@ module.exports = async (filePath, liveResponse = null) => {
|
|
|
81
86
|
Object.entries(resultMapping).forEach(([oldField, newField]) => {
|
|
82
87
|
// 💡 物理校准:计算空格数量,让箭头对齐在第 15 个字符位
|
|
83
88
|
// 中文字符长度 * 2 是为了抵消它在终端占的双倍宽度
|
|
84
|
-
const padding =
|
|
89
|
+
const padding = ' '.repeat(Math.max(1, 15 - oldField.length * 2))
|
|
85
90
|
console.log(
|
|
86
91
|
chalk.gray(` │ `) +
|
|
87
92
|
chalk.yellow(oldField) +
|
|
@@ -1,23 +1,25 @@
|
|
|
1
|
-
const fs = require('fs')
|
|
2
|
-
const ora = require('ora')
|
|
3
|
-
const path = require('path')
|
|
4
|
-
const chalk = require('chalk')
|
|
5
|
-
const stringify = require('json-stringify-pretty-compact')
|
|
6
|
-
|
|
7
1
|
module.exports = async filePath => {
|
|
8
2
|
|
|
9
|
-
const
|
|
3
|
+
const fs = require('fs')
|
|
4
|
+
const ora = require('ora')
|
|
5
|
+
const path = require('path')
|
|
6
|
+
const chalk = require('chalk')
|
|
10
7
|
|
|
11
8
|
const {
|
|
12
|
-
|
|
13
|
-
pagePrompt,
|
|
14
|
-
|
|
15
|
-
|
|
9
|
+
language,
|
|
10
|
+
pagePrompt,
|
|
11
|
+
menus, config,
|
|
12
|
+
index, resource,
|
|
13
|
+
contextStringify,
|
|
14
|
+
generateMock, recognizePage,
|
|
15
|
+
} = require('../../core/context').get()
|
|
16
|
+
|
|
17
|
+
const { useDemo, pagesDir, needMock } = config
|
|
16
18
|
|
|
17
19
|
const startTime = Date.now()
|
|
18
20
|
const fileName = path.basename(filePath, path.extname(filePath))
|
|
19
21
|
const mockDir = path.join(process.cwd(), 'mock')
|
|
20
|
-
const targetDir = path.join(process.cwd(),
|
|
22
|
+
const targetDir = path.join(process.cwd(), pagesDir, fileName)
|
|
21
23
|
|
|
22
24
|
const spinner = ora({
|
|
23
25
|
text: chalk.cyan(language(
|
|
@@ -41,7 +43,7 @@ module.exports = async filePath => {
|
|
|
41
43
|
if (!fs.existsSync(targetDir)) fs.mkdirSync(targetDir, { recursive: true })
|
|
42
44
|
|
|
43
45
|
let pageConfig
|
|
44
|
-
if (
|
|
46
|
+
if (useDemo) {
|
|
45
47
|
console.log(chalk.yellow(language(
|
|
46
48
|
`\n🤖 Pod 042: [报告] 拦截到实弹请求。正在空投标准模拟包: example.json\n`,
|
|
47
49
|
`\n🤖 Pod 042: [Report] Real-fire request intercepted. Dropping simulation package: example.json\n`
|
|
@@ -52,23 +54,23 @@ module.exports = async filePath => {
|
|
|
52
54
|
`🤖 Pod 042: 正在上传视觉元数据至司令部进行语义分析...\n`,
|
|
53
55
|
`🤖 Pod 042: Uploading visual metadata to Command for semantic analysis...\n`
|
|
54
56
|
))
|
|
55
|
-
pageConfig = await recognizePage(pagePrompt, filePath)
|
|
57
|
+
pageConfig = await recognizePage({ prompt: pagePrompt, filePath })
|
|
56
58
|
}
|
|
57
59
|
|
|
58
|
-
fs.writeFileSync(path.join(targetDir, 'resource.js'), resource({ pageConfig
|
|
59
|
-
fs.writeFileSync(path.join(targetDir, 'index.js'), index({
|
|
60
|
+
fs.writeFileSync(path.join(targetDir, 'resource.js'), resource({ pageConfig }))
|
|
61
|
+
fs.writeFileSync(path.join(targetDir, 'index.js'), index({ fileName, pageConfig }))
|
|
60
62
|
|
|
61
63
|
if (!menus.find(m => m.key === fileName)) {
|
|
62
64
|
menus.push({ label: fileName, key: fileName })
|
|
63
65
|
}
|
|
64
66
|
|
|
65
|
-
if (
|
|
67
|
+
if (needMock) {
|
|
66
68
|
spinner.text = chalk.yellow(language(
|
|
67
69
|
`🧑💻 9S: 正在突破目标防火墙... 执行数据伪装程序 [${fileName}]`,
|
|
68
70
|
`🧑💻 9S: Piercing target firewall... Executing data camouflage [${fileName}]`
|
|
69
71
|
))
|
|
70
|
-
const rawContent = await generateMock(pageConfig.table.columns, fileName)
|
|
71
|
-
fs.writeFileSync(path.join(mockDir, `${fileName}.js`), `export default ${
|
|
72
|
+
const rawContent = await generateMock({ columns: pageConfig.table.columns, fileName })
|
|
73
|
+
fs.writeFileSync(path.join(mockDir, `${fileName}.js`), `export default ${contextStringify({ context: rawContent })}`)
|
|
72
74
|
console.log(chalk.green(language(
|
|
73
75
|
`\n[Success] 9S 报告: Mock 数据生成成功`,
|
|
74
76
|
`\n[Success] 9S Report: Mock data generation successful.`
|
|
@@ -1,20 +1,23 @@
|
|
|
1
|
-
const fs = require('fs')
|
|
2
|
-
const ora = require('ora')
|
|
3
|
-
const chalk = require('chalk')
|
|
4
|
-
const stringify = require('json-stringify-pretty-compact')
|
|
5
|
-
|
|
6
1
|
module.exports = async filePath => {
|
|
7
2
|
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
const
|
|
3
|
+
const fs = require('fs')
|
|
4
|
+
const ora = require('ora')
|
|
5
|
+
const chalk = require('chalk')
|
|
6
|
+
|
|
7
|
+
const {
|
|
8
|
+
language,
|
|
9
|
+
partPrompt,
|
|
10
|
+
recognizePage,
|
|
11
|
+
contextStringify,
|
|
12
|
+
cleanCode, formatFormItemAndColumns,
|
|
13
|
+
} = require('../../core/context').get()
|
|
11
14
|
|
|
12
15
|
const startTime = Date.now()
|
|
13
16
|
|
|
14
17
|
const spinner = ora({
|
|
15
18
|
text: chalk.cyan(language(
|
|
16
19
|
`[System] 侦测到局部视觉样本。正在执行“碎片构筑协议”...`,
|
|
17
|
-
`[System] Partial visual sample detected. Executing
|
|
20
|
+
`[System] Partial visual sample detected. Executing 'Fragment Construction Protocol'...`
|
|
18
21
|
)),
|
|
19
22
|
color: 'cyan'
|
|
20
23
|
}).start()
|
|
@@ -25,13 +28,13 @@ module.exports = async filePath => {
|
|
|
25
28
|
`🤖 Pod 042: Extracting UI metadata from neural cloud network...\n`
|
|
26
29
|
))
|
|
27
30
|
|
|
28
|
-
const pageConfig = await recognizePage(partPrompt, filePath, 'part')
|
|
31
|
+
const pageConfig = await recognizePage({ prompt: partPrompt, filePath, taskType: 'part' })
|
|
29
32
|
|
|
30
33
|
const { formItems, dictBlocks, processedColumns } = formatFormItemAndColumns({ pageConfig })
|
|
31
34
|
|
|
32
35
|
const result = Object.fromEntries(Object.entries({ formItems, processedColumns }).filter(([key, value]) => value?.length > 0))
|
|
33
36
|
|
|
34
|
-
let mainConfigStr = cleanCode(
|
|
37
|
+
let mainConfigStr = cleanCode(contextStringify({ context: result }))
|
|
35
38
|
|
|
36
39
|
let optionsCodeStr = ''
|
|
37
40
|
dictBlocks.forEach(key => {
|
package/src/commands/watch.js
CHANGED
|
@@ -1,22 +1,26 @@
|
|
|
1
|
-
|
|
2
|
-
const path = require('path')
|
|
3
|
-
const chalk = require('chalk')
|
|
4
|
-
const chokidar = require('chokidar')
|
|
5
|
-
const stringify = require('json-stringify-pretty-compact')
|
|
1
|
+
module.exports = () => {
|
|
6
2
|
|
|
7
|
-
const
|
|
3
|
+
const fs = require('fs')
|
|
4
|
+
const path = require('path')
|
|
5
|
+
const chalk = require('chalk')
|
|
6
|
+
const chokidar = require('chokidar')
|
|
8
7
|
|
|
9
|
-
const {
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
const {
|
|
9
|
+
options,
|
|
10
|
+
language,
|
|
11
|
+
createTaskQueue,
|
|
12
|
+
contextStringify,
|
|
13
|
+
menus, config, copyTemplateDir,
|
|
14
|
+
apiHandler, pageHandler, partHandler,
|
|
15
|
+
} = require('../core/context').get()
|
|
12
16
|
|
|
13
|
-
const {
|
|
17
|
+
const { hbsDir, hooksDir, utilsDir, componentsDir } = config
|
|
14
18
|
|
|
15
19
|
try {
|
|
16
|
-
if (
|
|
17
|
-
copyTemplateDir(options, 'hooks',
|
|
18
|
-
copyTemplateDir(options, 'utils',
|
|
19
|
-
copyTemplateDir(options, 'components',
|
|
20
|
+
if (hbsDir === '') {
|
|
21
|
+
copyTemplateDir(options, 'hooks', hooksDir)
|
|
22
|
+
copyTemplateDir(options, 'utils', utilsDir)
|
|
23
|
+
copyTemplateDir(options, 'components', componentsDir)
|
|
20
24
|
}
|
|
21
25
|
} catch (error) {
|
|
22
26
|
console.error(language('❌ 模板构筑失败:', '❌ Template construction failed:'), error)
|
|
@@ -31,7 +35,7 @@ const watch = () => {
|
|
|
31
35
|
)))
|
|
32
36
|
const utilsDir = path.join(process.cwd(), config.utilsDir)
|
|
33
37
|
if (!fs.existsSync(utilsDir)) fs.mkdirSync(utilsDir, { recursive: true })
|
|
34
|
-
fs.writeFileSync(path.join(utilsDir, 'menus.js'), `export const menus = ${
|
|
38
|
+
fs.writeFileSync(path.join(utilsDir, 'menus.js'), `export const menus = ${contextStringify({ context: menus, maxLength: 50 })}`)
|
|
35
39
|
console.log(chalk.gray(language(
|
|
36
40
|
'\n🤖 [System] 未检测到运行中的任务,系统待机中...\n',
|
|
37
41
|
'\n🤖 [System] System is STANDBY.\n'
|
|
@@ -64,6 +68,4 @@ const watch = () => {
|
|
|
64
68
|
queue.add(() => apiHandler(filePath))
|
|
65
69
|
}
|
|
66
70
|
})
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
module.exports = watch
|
|
71
|
+
}
|