@yorha2b-lab/autodev 7.3.6 → 7.4.1
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/example/example.json +13 -13
- package/package.json +3 -3
- package/src/constitution/council.js +1 -1
- package/src/labs/council.js +20 -34
- package/src/units/raider.js +6 -1
- package/src/workshop/react/blueprint/molds/handleBlock.hbs +10 -8
- package/src/workshop/react/blueprint/molds/hookBlock.hbs +1 -1
- package/src/workshop/react/briefings/raider.js +1 -0
- package/src/workshop/react/briefings/striker.js +3 -2
- package/src/workshop/react/builder/index.js +1 -4
- package/src/workshop/react/protocols/striker.json +6 -6
package/example/example.json
CHANGED
|
@@ -77,19 +77,19 @@
|
|
|
77
77
|
],
|
|
78
78
|
"operation": [
|
|
79
79
|
{
|
|
80
|
-
"
|
|
80
|
+
"request": "BUNKER_API_ANCHOR_viewJob",
|
|
81
81
|
"label": "查看",
|
|
82
|
-
"action": "
|
|
82
|
+
"action": "viewJob"
|
|
83
83
|
},
|
|
84
84
|
{
|
|
85
|
-
"
|
|
85
|
+
"request": "BUNKER_API_ANCHOR_editJob",
|
|
86
86
|
"label": "编辑",
|
|
87
|
-
"action": "
|
|
87
|
+
"action": "editJob"
|
|
88
88
|
},
|
|
89
89
|
{
|
|
90
|
-
"
|
|
90
|
+
"request": "BUNKER_API_ANCHOR_deleteJob",
|
|
91
91
|
"label": "删除",
|
|
92
|
-
"action": "
|
|
92
|
+
"action": "deleteJob"
|
|
93
93
|
}
|
|
94
94
|
],
|
|
95
95
|
"pagination": true,
|
|
@@ -97,8 +97,8 @@
|
|
|
97
97
|
"rowSelection": true
|
|
98
98
|
},
|
|
99
99
|
"title": {
|
|
100
|
-
"chinese": "
|
|
101
|
-
"english": "
|
|
100
|
+
"chinese": "鬼剑士职业管理",
|
|
101
|
+
"english": "GhostSwordsmanManagement"
|
|
102
102
|
},
|
|
103
103
|
"formItems": [
|
|
104
104
|
{
|
|
@@ -140,7 +140,7 @@
|
|
|
140
140
|
},
|
|
141
141
|
{
|
|
142
142
|
"label": "太刀",
|
|
143
|
-
"value": "
|
|
143
|
+
"value": "katana"
|
|
144
144
|
},
|
|
145
145
|
{
|
|
146
146
|
"label": "巨剑",
|
|
@@ -170,13 +170,13 @@
|
|
|
170
170
|
"functionButton": [
|
|
171
171
|
{
|
|
172
172
|
"btn": "批量删除",
|
|
173
|
-
"
|
|
174
|
-
"action": "
|
|
173
|
+
"request": "BUNKER_API_ANCHOR_batchDeleteJobs",
|
|
174
|
+
"action": "batchDeleteJobs"
|
|
175
175
|
},
|
|
176
176
|
{
|
|
177
177
|
"btn": "批量导出",
|
|
178
|
-
"
|
|
179
|
-
"action": "
|
|
178
|
+
"request": "BUNKER_API_ANCHOR_exportJobs",
|
|
179
|
+
"action": "exportJobs"
|
|
180
180
|
}
|
|
181
181
|
]
|
|
182
182
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yorha2b-lab/autodev",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.4.1",
|
|
4
4
|
"description": "基于 AI 视觉与语义协议的前端 (React+Antd) 代码构筑与旧系统重构引擎",
|
|
5
5
|
"bin": {
|
|
6
6
|
"bunker": "bin/bunker.js"
|
|
@@ -49,8 +49,8 @@
|
|
|
49
49
|
"json-stringify-pretty-compact": "^4.0.0"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
|
-
"
|
|
52
|
+
"http-proxy": "^1.18.1",
|
|
53
53
|
"puppeteer": "^25.4.0",
|
|
54
|
-
"
|
|
54
|
+
"segmentit": "^2.0.3"
|
|
55
55
|
}
|
|
56
56
|
}
|
|
@@ -12,7 +12,7 @@ ${realApis}
|
|
|
12
12
|
- 识别后缀(如 edit, delete, add)。
|
|
13
13
|
- 结合 UI 语义,在 API 库中寻找对应路径。
|
|
14
14
|
- **输出格式**:请只输出一个 JSON 映射表。
|
|
15
|
-
- **例如**:{"BUNKER_API_ANCHOR_editByRecord": "
|
|
15
|
+
- **例如**:{"BUNKER_API_ANCHOR_editByRecord": {"uri": "/api/records/{recordId}", "method": "POST"}}
|
|
16
16
|
|
|
17
17
|
⚠️ 严禁解释,严禁输出 JSON 之外的内容。
|
|
18
18
|
`.trim()
|
package/src/labs/council.js
CHANGED
|
@@ -14,18 +14,15 @@ module.exports = async ({ llm, yorha, dialog, logistics }) => {
|
|
|
14
14
|
pod153.report(dialog.pod153.autonomousAddressing, 'magenta')
|
|
15
15
|
|
|
16
16
|
try {
|
|
17
|
-
// 1. 抓取情报
|
|
18
17
|
const apiData = await fetch(apiDoc).then(res => res.json())
|
|
19
18
|
const refinedApis = Object.entries(apiData.paths).flatMap(([apiUrl, methods]) => {
|
|
20
|
-
// 💡 适配多方法接口:有的路径下可能既有 GET 也有 POST
|
|
21
19
|
return Object.entries(methods).map(([method, info]) => ({
|
|
22
20
|
path: apiUrl,
|
|
23
|
-
method: method
|
|
24
|
-
desc: info.summary || info.description || 'N/A'
|
|
21
|
+
method: method?.toUpperCase() || '',
|
|
22
|
+
desc: info.summary || info.description || 'N/A',
|
|
25
23
|
}))
|
|
26
24
|
})
|
|
27
25
|
|
|
28
|
-
// 2. 战场侦察
|
|
29
26
|
const pages = path.join(process.cwd(), pagesDir)
|
|
30
27
|
const files = fs.readdirSync(pages)
|
|
31
28
|
const enumParamsMap = {}
|
|
@@ -37,18 +34,15 @@ module.exports = async ({ llm, yorha, dialog, logistics }) => {
|
|
|
37
34
|
if (fs.existsSync(indexPath) && fs.existsSync(resourcePath)) {
|
|
38
35
|
let indexCode = fs.readFileSync(indexPath, 'utf-8')
|
|
39
36
|
|
|
40
|
-
// 💡 锁定待通电锚点
|
|
41
37
|
if (indexCode.includes('BUNKER_API_ANCHOR')) {
|
|
42
38
|
const resourceCode = fs.readFileSync(resourcePath, 'utf-8')
|
|
43
39
|
const bunkerAnchors = indexCode.match(/BUNKER_API_ANCHOR_\w+/g)?.join('\n') ?? ''
|
|
44
40
|
|
|
45
|
-
// 💡 执行语义提取流程
|
|
46
41
|
const returnMatch = indexCode.match(/return\s*\(([\s\S]*?)\)\s*}/)
|
|
47
42
|
const returnStatement = returnMatch ? returnMatch[0] : ''
|
|
48
43
|
|
|
49
44
|
const moduleSemantics = `${returnStatement}${resourceCode}`.match(/[\u4e00-\u9fa5][\u4e00-\u9fa5A-Za-z0-9?。,、:;!() ]*/g) || []
|
|
50
45
|
const pageKeywords = getSemanticKeywords(moduleSemantics)
|
|
51
|
-
// 💡 物理扫描:执行“语义雷达”过滤
|
|
52
46
|
const candidates = refinedApis
|
|
53
47
|
.map(api => ({
|
|
54
48
|
...api,
|
|
@@ -56,40 +50,32 @@ module.exports = async ({ llm, yorha, dialog, logistics }) => {
|
|
|
56
50
|
}))
|
|
57
51
|
.filter(item => item.score > 0)
|
|
58
52
|
.sort((a, b) => b.score - a.score)
|
|
59
|
-
.slice(0, 20)
|
|
53
|
+
.slice(0, 20)
|
|
60
54
|
|
|
61
55
|
const finalCandidates = candidates.map(item => `${item.method} ${item.path} ${item.desc}`).join('\n')
|
|
62
56
|
const spinner = pod153.start(dialog.pod153.inactiveModule(fileName), 'yellow')
|
|
63
|
-
// 3. 驱动 9S 最终裁决
|
|
64
57
|
const result = await apiParser({ bunkerAnchors, realApis: finalCandidates })
|
|
65
58
|
|
|
66
59
|
if (result) {
|
|
67
|
-
|
|
68
|
-
Object.entries(result).forEach(([anchor,
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
// 💡 4. 执行“全频道通电”
|
|
84
|
-
// $1 现在包含了 request('/api 这一串
|
|
85
|
-
indexCode = indexCode.replace(requestRegex, `$1${cleanPath}$2${realMethod.toUpperCase()}$4`)
|
|
86
|
-
// 💡 5. 兜底替换(针对没有 method 配置的简易请求)
|
|
87
|
-
// 同样保留 /api/ 前缀
|
|
88
|
-
indexCode = indexCode.replaceAll(`/api/${anchor}`, `/api${cleanPath}`)
|
|
60
|
+
let hasQsImport = indexCode.includes(`import qs from 'qs'`)
|
|
61
|
+
Object.entries(result).forEach(([anchor, { uri, method }]) => {
|
|
62
|
+
const cleanPath = uri.startsWith('/') ? uri : `/${uri}`
|
|
63
|
+
let finalUri = cleanPath.startsWith('/api') ? cleanPath : `/api${cleanPath}`
|
|
64
|
+
finalUri = finalUri.replace(/\{(\w+)\}/g, (_, key) => '${params.' + key + '}')
|
|
65
|
+
const quotationMark = finalUri.includes('${params.') ? '\`' : "'"
|
|
66
|
+
if (method?.toUpperCase() === 'GET') {
|
|
67
|
+
indexCode = indexCode.replaceAll(anchor, `request(\`${finalUri}?\${qs.stringify(params)}\`)`)
|
|
68
|
+
if (!hasQsImport) {
|
|
69
|
+
indexCode = `import qs from 'qs'\n${indexCode}`
|
|
70
|
+
hasQsImport = true
|
|
71
|
+
}
|
|
72
|
+
} else {
|
|
73
|
+
indexCode = indexCode.replaceAll(anchor, `request(${quotationMark}${finalUri}${quotationMark}, { method: '${method?.toUpperCase()}', body: params })`)
|
|
74
|
+
}
|
|
89
75
|
})
|
|
90
76
|
|
|
91
|
-
const
|
|
92
|
-
const definitions = (apiData.paths[pagesApi]?.[pagesMethod] ?? apiData.paths[pagesApi]?.[pagesMethod
|
|
77
|
+
const { uri: pagesApi, method: pagesMethod } = result?.['BUNKER_API_ANCHOR_pages']
|
|
78
|
+
const definitions = (apiData.paths[pagesApi]?.[pagesMethod] ?? apiData.paths[pagesApi]?.[pagesMethod?.toLowerCase()])?.parameters?.flatMap(item => Object.values(item.schema ?? {})?.flatMap(def => def?.split('/')?.at(-1))) || []
|
|
93
79
|
const parameters = apiData.definitions?.[definitions[0]]?.properties ?? {}
|
|
94
80
|
const enumParams = Object.entries(parameters)?.filter(([_, value]) => value.hasOwnProperty('enum')) || []
|
|
95
81
|
enumParamsMap[fileName] = contextStringify({
|
package/src/units/raider.js
CHANGED
|
@@ -37,7 +37,12 @@ module.exports = {
|
|
|
37
37
|
|
|
38
38
|
const pageConfig = await recognizePage({ prompt: raider, filePath: mission.input })
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
let { formItems, dictBlocks, processedColumns } = formatFormItemAndColumns({ pageConfig })
|
|
41
|
+
|
|
42
|
+
processedColumns = processedColumns.map(col => {
|
|
43
|
+
delete col.type
|
|
44
|
+
return col
|
|
45
|
+
})
|
|
41
46
|
|
|
42
47
|
const result = Object.fromEntries(Object.entries({ formItems, processedColumns }).filter(([key, value]) => value?.length > 0))
|
|
43
48
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
{{#each operations}}
|
|
3
|
-
const {{this.action}} = async
|
|
4
|
-
const response = await
|
|
3
|
+
const {{this.action}} = async params => {
|
|
4
|
+
const response = await {{{this.request}}}
|
|
5
5
|
if({{{../responseSuccess}}}){
|
|
6
6
|
refresh()
|
|
7
7
|
}
|
|
@@ -11,12 +11,13 @@ const {{this.action}} = async record => {
|
|
|
11
11
|
|
|
12
12
|
{{#each functionButtons}}
|
|
13
13
|
const {{this.action}} = () => {
|
|
14
|
+
const params = {}
|
|
14
15
|
Modal.confirm({
|
|
15
16
|
title: '确认',
|
|
16
17
|
centered: true,
|
|
17
18
|
content: '确认{{this.btn}}吗?',
|
|
18
19
|
onOk: async () => {
|
|
19
|
-
const response = await
|
|
20
|
+
const response = await {{{this.request}}}
|
|
20
21
|
if({{{../responseSuccess}}}){
|
|
21
22
|
refresh()
|
|
22
23
|
}
|
|
@@ -62,12 +63,13 @@ const showImg = (record, dataIndex) => {
|
|
|
62
63
|
|
|
63
64
|
{{/if}}
|
|
64
65
|
|
|
65
|
-
const modalSubmit = async
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
66
|
+
const modalSubmit = async params => {
|
|
67
|
+
const requestMap={
|
|
68
|
+
{{#each operations}}
|
|
69
|
+
{{this.action}}:()=> {{this.request}},
|
|
70
|
+
{{/each}}
|
|
70
71
|
}
|
|
72
|
+
const response = await requestMap[modal.type]
|
|
71
73
|
if({{{responseSuccess}}}){
|
|
72
74
|
setModal({ visible: false })
|
|
73
75
|
refresh()
|
|
@@ -6,7 +6,7 @@ const query = formatQuery(Object.fromEntries(new URLSearchParams(location.search
|
|
|
6
6
|
const { total, columns, loading, dataSource, search, setSearch, setDataSource, refresh } = useTableQuery({
|
|
7
7
|
cols:tableColumns,
|
|
8
8
|
initialParams: { ...initialParams, ...query },
|
|
9
|
-
api: async params => await
|
|
9
|
+
api: async params => await {{{this.uri}}},
|
|
10
10
|
formatResponse: response => {
|
|
11
11
|
return {
|
|
12
12
|
data: response?.data?.datas ?? [],
|
|
@@ -36,7 +36,7 @@ module.exports = `
|
|
|
36
36
|
## 表格主体 (table)
|
|
37
37
|
- **基础格式(columns)**: [{ title: '文本', dataIndex: 'englishName' }]。
|
|
38
38
|
- **配置项**: [pagination, expandable, rowSelection] 均为布尔值。
|
|
39
|
-
- **行操作 (operation)**: [{ label: '操作名', action: '操作动词+[模块名单数]',
|
|
39
|
+
- **行操作 (operation)**: [{ label: '操作名', action: '操作动词+[模块名单数]', request: 'BUNKER_API_ANCHOR_动词+[模块名单数]'}]
|
|
40
40
|
- **类型定义 (type)**:
|
|
41
41
|
- enum: 枚举列
|
|
42
42
|
- money: 金额列
|
|
@@ -45,10 +45,11 @@ module.exports = `
|
|
|
45
45
|
- date: 时间/日期列
|
|
46
46
|
- text: 普通文本(默认)
|
|
47
47
|
- tag: 标签列(有背景色的文本)
|
|
48
|
+
- link: 链接列(蓝色下划线的文本)
|
|
48
49
|
- badge: 徽标列(文本前有颜色小圆点)
|
|
49
50
|
|
|
50
51
|
## 全局功能按钮 (functionButton)
|
|
51
|
-
- **基础格式**: [{ btn: '按钮', action: '操作动词+[模块名复数]',
|
|
52
|
+
- **基础格式**: [{ btn: '按钮', action: '操作动词+[模块名复数]', request: 'BUNKER_API_ANCHOR_动词+[模块名复数]'}]。
|
|
52
53
|
- **导出数据**: action 设为 'export[模块名]'。
|
|
53
54
|
- **逻辑锁定**: 只要页面中出现了非查询、非重置的独立操作按钮,必须识别并存入 [functionButton] 数组。
|
|
54
55
|
- **构筑联动**: 若 [functionButton] 数组不为空,则在下文的 [RenderTree] 中必须包含 "FunctionButtons"。
|
|
@@ -33,9 +33,6 @@ module.exports = ({ template, logistics, headquarters }) => {
|
|
|
33
33
|
})
|
|
34
34
|
|
|
35
35
|
const processedColumns = columns?.map(col => {
|
|
36
|
-
if (col.type === 'text') {
|
|
37
|
-
delete col.type
|
|
38
|
-
}
|
|
39
36
|
if (['image'].includes(col.type)) {
|
|
40
37
|
return { ...col, renderAction: true }
|
|
41
38
|
}
|
|
@@ -147,10 +144,10 @@ module.exports = ({ template, logistics, headquarters }) => {
|
|
|
147
144
|
hasExpandable: pageConfig.table.expandable,
|
|
148
145
|
staticInfoText: pageConfig.staticInfo?.text,
|
|
149
146
|
hasRowSelection: pageConfig.table.rowSelection,
|
|
150
|
-
uri: needMock ? fileName : 'BUNKER_API_ANCHOR_pages',
|
|
151
147
|
formItems: hasFormItems ? (hasTabs ? 'formItems[activeKey]' : 'formItems') : '[]',
|
|
152
148
|
operations: pageConfig.table.operation?.sort((a, b) => a.action.length - b.action.length) || [],
|
|
153
149
|
initParams: `{ ${hasTabs ? 'type: tabs[0].key ,' : ''}${hasPagination ? 'pageNo: 1 , pageSize: 10' : ''}}`,
|
|
150
|
+
uri: needMock ? `request('/api/${fileName}', { method: 'POST', body: params })` : 'BUNKER_API_ANCHOR_pages',
|
|
154
151
|
}
|
|
155
152
|
|
|
156
153
|
const bodyCode = indexTpl(viewData)
|
|
@@ -83,13 +83,13 @@
|
|
|
83
83
|
"items": {
|
|
84
84
|
"type": "object",
|
|
85
85
|
"required": [
|
|
86
|
-
"uri",
|
|
87
86
|
"label",
|
|
88
|
-
"action"
|
|
87
|
+
"action",
|
|
88
|
+
"request"
|
|
89
89
|
],
|
|
90
90
|
"additionalProperties": false,
|
|
91
91
|
"properties": {
|
|
92
|
-
"
|
|
92
|
+
"request": {
|
|
93
93
|
"type": "string"
|
|
94
94
|
},
|
|
95
95
|
"label": {
|
|
@@ -230,15 +230,15 @@
|
|
|
230
230
|
"type": "object",
|
|
231
231
|
"required": [
|
|
232
232
|
"btn",
|
|
233
|
-
"
|
|
234
|
-
"
|
|
233
|
+
"action",
|
|
234
|
+
"request"
|
|
235
235
|
],
|
|
236
236
|
"additionalProperties": false,
|
|
237
237
|
"properties": {
|
|
238
238
|
"btn": {
|
|
239
239
|
"type": "string"
|
|
240
240
|
},
|
|
241
|
-
"
|
|
241
|
+
"request": {
|
|
242
242
|
"type": "string"
|
|
243
243
|
},
|
|
244
244
|
"action": {
|