@yorha2b-lab/autodev 4.1.1 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +4 -0
- package/.github/workflows/bunker-intelligence.yml +4 -4
- package/CONTRIBUTING.md +0 -18
- package/bin/autodev.js +9 -8
- package/config.js +3 -3
- package/package.json +1 -3
- package/src/bootstrap/handlebars.js +26 -0
- package/src/bootstrap/handlers.js +10 -0
- package/src/bootstrap/index.js +49 -0
- package/src/bootstrap/infrastructure.js +15 -0
- package/src/bootstrap/openai.js +13 -0
- package/src/bootstrap/prompt.js +10 -0
- package/src/commands/watch.js +21 -34
- package/{templates → src/framework}/react/components/MyModalForm.js +1 -1
- package/{templates → src/framework}/react/components/MyModalTable.js +1 -1
- package/{templates → src/framework}/react/components/index.js +2 -2
- package/src/framework/react/generator/index.js +82 -0
- package/{templates/react/handlebars → src/framework/react/handlebars/partials}/handleBlock.hbs +2 -2
- package/src/{prompts/react/watch-api.js → framework/react/prompts/api.js} +1 -1
- package/src/{prompts/react/api-linker.js → framework/react/prompts/linker.js} +1 -1
- package/src/{prompts → framework/react/prompts}/mock.js +1 -1
- package/src/{prompts/react/watch-page.js → framework/react/prompts/page.js} +1 -0
- package/src/{prompts/react/watch-part.js → framework/react/prompts/part.js} +2 -1
- package/{templates → src/framework}/react/utils/utils.js +1 -1
- package/src/{commands/handlers/api-handler.js → handlers/apiHandler.js} +15 -10
- package/src/{commands/handlers/page-handler.js → handlers/pageHandler.js} +22 -21
- package/src/{commands/handlers/part-handler.js → handlers/partHandler.js} +14 -11
- package/src/{services/api-linker.js → labs/linker.js} +20 -59
- package/src/{services/proxy-tower.js → labs/tower.js} +16 -12
- package/src/services/llm.js +64 -81
- package/src/utils/{utils.js → core.js} +38 -163
- package/src/utils/infrastructure.js +105 -0
- package/src/utils/ux.js +115 -0
- package/src/core/context.js +0 -106
- package/src/core/react-compiler.js +0 -98
- package/src/core/task-queue.js +0 -38
- /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/MySearchForm.js +0 -0
- /package/{templates → src/framework}/react/components/MyTable.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}/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 → framework/react/prompts}/system.js +0 -0
- /package/src/{schema/react → framework/react/schema}/page.json +0 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
module.exports = ({ config, indexTpl, cleanCode, resourceTpl, contextStringify, generateSmartImports, formatFormItemAndColumns, }) => {
|
|
2
|
+
|
|
3
|
+
const { needMock, responseSuccess } = config
|
|
4
|
+
|
|
5
|
+
return {
|
|
6
|
+
index: ({ fileName, pageConfig }) => {
|
|
7
|
+
const hasTabs = pageConfig.tabs?.length > 0
|
|
8
|
+
const hasPagination = pageConfig.table.pagination
|
|
9
|
+
const hasFormItems = pageConfig.formItems?.length > 0
|
|
10
|
+
const hasOperate = pageConfig.table?.operation?.length > 0
|
|
11
|
+
const hasImageColumn = pageConfig.table?.columns?.some(item => item.type === 'image')
|
|
12
|
+
const functionButtons = pageConfig.functionButton?.filter(item => !['查询', '重置', 'query', 'search', 'reset'].includes(item.btn.toLowerCase().replaceAll(' ', ''))) || []
|
|
13
|
+
const needRenderAction = hasImageColumn
|
|
14
|
+
|
|
15
|
+
const pageStruct = ['stateBlock', 'handleBlock', 'hookBlock', hasOperate ? 'operateBlock' : '', 'renderBlock'].filter(Boolean)
|
|
16
|
+
|
|
17
|
+
let columnsValue = hasTabs ? 'columns[activeKey]' : 'columns'
|
|
18
|
+
if (hasOperate) {
|
|
19
|
+
columnsValue = `${columnsValue}.concat(operate)`
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const imgAction = Object.fromEntries(pageConfig.table?.columns?.filter(item => item.type === 'image')?.map(item => [item.dataIndex, `_CODE_(_, record) => <a onClick={() => showImg(record, '${item.dataIndex}')}>查看图片</a>_CODE_`]))
|
|
23
|
+
const renderAction = `{${contextStringify({ context: imgAction, maxLength: 120 })}}`.replace(/\n/g, '\n ')
|
|
24
|
+
|
|
25
|
+
const viewData = {
|
|
26
|
+
hasTabs,
|
|
27
|
+
pageStruct,
|
|
28
|
+
columnsValue,
|
|
29
|
+
hasFormItems,
|
|
30
|
+
renderAction,
|
|
31
|
+
hasPagination,
|
|
32
|
+
hasImageColumn,
|
|
33
|
+
functionButtons,
|
|
34
|
+
responseSuccess,
|
|
35
|
+
needRenderAction,
|
|
36
|
+
tabs: pageConfig.tabs,
|
|
37
|
+
renderTree: pageConfig.renderTree,
|
|
38
|
+
hasExpandable: pageConfig.table.expandable,
|
|
39
|
+
staticInfoText: pageConfig.staticInfo?.text,
|
|
40
|
+
operations: pageConfig.table.operation || [],
|
|
41
|
+
hasRowSelection: pageConfig.table.rowSelection,
|
|
42
|
+
uri: needMock ? fileName : 'BUNKER_API_ANCHOR_pages',
|
|
43
|
+
formItems: hasFormItems ? (hasTabs ? 'formItems[activeKey]' : 'formItems') : '[]',
|
|
44
|
+
initParams: `{ ${hasTabs ? 'type: tabs[0].key ,' : ''}${hasPagination ? 'pageNo: 1 , pageSize: 10' : ''}}`,
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const bodyCode = indexTpl(viewData)
|
|
48
|
+
const importsStr = generateSmartImports({ module: 'index', hasTabs, bodyCode, hasFormItems })
|
|
49
|
+
return cleanCode(`${importsStr}\n\n${bodyCode}`)
|
|
50
|
+
},
|
|
51
|
+
resource: ({ pageConfig }) => {
|
|
52
|
+
|
|
53
|
+
const { formItems, processedColumns, dictBlocks } = formatFormItemAndColumns({ pageConfig })
|
|
54
|
+
|
|
55
|
+
const hasTabs = pageConfig.tabs?.length > 0
|
|
56
|
+
const hasFormItems = pageConfig.formItems?.length > 0
|
|
57
|
+
const tabKeys = pageConfig.tabs.map(tab => tab.key).sort((a, b) => a.length - b.length)
|
|
58
|
+
const optionDict = pageConfig.optionList?.reduce((acc, item) => ({ ...acc, [item.name]: item.options }), {})
|
|
59
|
+
|
|
60
|
+
const columnsData = processedColumns.map(item => {
|
|
61
|
+
delete item.type
|
|
62
|
+
return item
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
const viewData = {
|
|
66
|
+
hasTabs,
|
|
67
|
+
columnsData,
|
|
68
|
+
hasFormItems,
|
|
69
|
+
tabs: pageConfig.tabs,
|
|
70
|
+
dictBlocks: dictBlocks.map(item => ({ name: item, data: optionDict[item] ?? [] })),
|
|
71
|
+
tabColumns: contextStringify({ context: Object.fromEntries(tabKeys.map(tab => [tab, '_CODE_commonColumns_CODE_'])), maxLength: 100 }),
|
|
72
|
+
formItemsData: !hasTabs ?
|
|
73
|
+
`export const formItems = ${contextStringify({ context: formItems, maxLength: 120 })}` :
|
|
74
|
+
`const searchItems = ${contextStringify({ context: formItems, maxLength: 120 })}\n\nexport const formItems = ${contextStringify({ context: Object.fromEntries(tabKeys.map(tab => [tab, '_CODE_searchItems_CODE_'])), maxLength: 100 })}`,
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const bodyCode = resourceTpl(viewData)
|
|
78
|
+
const importsStr = generateSmartImports({ module: 'resource', hasTabs, bodyCode, hasFormItems })
|
|
79
|
+
return cleanCode(`${importsStr}\n\n${bodyCode}`)
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
package/{templates/react/handlebars → src/framework/react/handlebars/partials}/handleBlock.hbs
RENAMED
|
@@ -38,9 +38,9 @@ const onTabChange = key => {
|
|
|
38
38
|
{{#if hasExpandable}}
|
|
39
39
|
const onExpand = async (expanded, record) => {
|
|
40
40
|
if (expanded) {
|
|
41
|
-
setExpandedRowKeys([...
|
|
41
|
+
setExpandedRowKeys(prev=>[...prev, record.key])
|
|
42
42
|
} else {
|
|
43
|
-
setExpandedRowKeys(
|
|
43
|
+
setExpandedRowKeys(prev=>prev.filter(item => item !== record.key))
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
46
|
|
|
@@ -34,6 +34,7 @@ module.exports = `
|
|
|
34
34
|
### 表格主体 (Table)
|
|
35
35
|
- ⚠️ **操作锁定**: 严禁在 columns 数组中包含“操作”列。
|
|
36
36
|
- **标准项**: {title:'列名', dataIndex:'列名英文名词',type:''}。
|
|
37
|
+
- **注意**: type为text时必须省略type属性。
|
|
37
38
|
- **配置项**: [pagination, expandable, rowSelection] 均为布尔值false,只有页面明确有对应功能时才为true。
|
|
38
39
|
- **标准定义 (Columns)**:
|
|
39
40
|
- enum: 枚举列
|
|
@@ -8,8 +8,9 @@ module.exports = `
|
|
|
8
8
|
3. 必须严格遵守以下字段规范。
|
|
9
9
|
|
|
10
10
|
## 1. 表格 (Table)
|
|
11
|
-
- 结构: { columns: [{ title: '列名', dataIndex: '
|
|
11
|
+
- 结构: { columns: [{ title: '列名', dataIndex: '***englishName***', type: '' }] }
|
|
12
12
|
- ⚠️ 字段白名单: [title, dataIndex, sorter, render, filters, onFilter]
|
|
13
|
+
- **注意**: type为text时必须省略type属性。
|
|
13
14
|
- 禁止输出:
|
|
14
15
|
- 严禁在 columns 中包含“操作”列。
|
|
15
16
|
- ***⚠️⚠️⚠️严禁输出formItems,只允许输出columns⚠️⚠️⚠️***
|
|
@@ -100,7 +100,7 @@ export const timeRender = ({ time, date, minute }) => {
|
|
|
100
100
|
* @param {Function} [formatter] - 数据预处理回调
|
|
101
101
|
* @param {Array} columns - 表格列配置,支持 exportRender 优先级
|
|
102
102
|
*/
|
|
103
|
-
export const exportDataToExcel = async (url, options, columns, fileName, formatter) => {
|
|
103
|
+
export const exportDataToExcel = async ({ url, options, columns, fileName, formatter }) => {
|
|
104
104
|
/* const response = await request(url, options)
|
|
105
105
|
const result = formatter ? formatter(response) : (response?.data ?? [])
|
|
106
106
|
if (result?.length > 0) {
|
|
@@ -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 { ux, llm, core, infrastructure } = require('../bootstrap').get()
|
|
9
|
+
|
|
10
|
+
const { language } = ux
|
|
11
|
+
const { unwrapSignal } = core
|
|
12
|
+
const { config } = infrastructure
|
|
13
|
+
const { alignResponseFields } = llm
|
|
10
14
|
|
|
15
|
+
const { pagesDir } = config
|
|
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,24 @@
|
|
|
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')
|
|
7
|
+
|
|
8
|
+
const { ux, llm, prompts, generator, infrastructure } = require('../bootstrap').get()
|
|
9
|
+
|
|
10
|
+
const { language } = ux
|
|
11
|
+
const { pagePrompt } = prompts
|
|
12
|
+
const { index, resource } = generator
|
|
13
|
+
const { generateMock, recognizePage } = llm
|
|
14
|
+
const { menus, config, contextStringify } = infrastructure
|
|
10
15
|
|
|
11
|
-
const {
|
|
12
|
-
config, language, menus, options,
|
|
13
|
-
pagePrompt, resourceTpl, indexTpl,
|
|
14
|
-
recognizePage, generateMock, resource, index
|
|
15
|
-
} = get()
|
|
16
|
+
const { useDemo, pagesDir, needMock } = config
|
|
16
17
|
|
|
17
18
|
const startTime = Date.now()
|
|
18
19
|
const fileName = path.basename(filePath, path.extname(filePath))
|
|
19
20
|
const mockDir = path.join(process.cwd(), 'mock')
|
|
20
|
-
const targetDir = path.join(process.cwd(),
|
|
21
|
+
const targetDir = path.join(process.cwd(), pagesDir, fileName)
|
|
21
22
|
|
|
22
23
|
const spinner = ora({
|
|
23
24
|
text: chalk.cyan(language(
|
|
@@ -41,34 +42,34 @@ module.exports = async filePath => {
|
|
|
41
42
|
if (!fs.existsSync(targetDir)) fs.mkdirSync(targetDir, { recursive: true })
|
|
42
43
|
|
|
43
44
|
let pageConfig
|
|
44
|
-
if (
|
|
45
|
+
if (useDemo) {
|
|
45
46
|
console.log(chalk.yellow(language(
|
|
46
47
|
`\n🤖 Pod 042: [报告] 拦截到实弹请求。正在空投标准模拟包: example.json\n`,
|
|
47
48
|
`\n🤖 Pod 042: [Report] Real-fire request intercepted. Dropping simulation package: example.json\n`
|
|
48
49
|
)))
|
|
49
|
-
pageConfig = require('
|
|
50
|
+
pageConfig = require('../../example/example.json')
|
|
50
51
|
} else {
|
|
51
52
|
spinner.text = chalk.cyan(language(
|
|
52
53
|
`🤖 Pod 042: 正在上传视觉元数据至司令部进行语义分析...\n`,
|
|
53
54
|
`🤖 Pod 042: Uploading visual metadata to Command for semantic analysis...\n`
|
|
54
55
|
))
|
|
55
|
-
pageConfig = await recognizePage({ prompt: pagePrompt, filePath
|
|
56
|
+
pageConfig = await recognizePage({ prompt: pagePrompt, filePath })
|
|
56
57
|
}
|
|
57
58
|
|
|
58
|
-
fs.writeFileSync(path.join(targetDir, 'resource.js'), resource({ pageConfig
|
|
59
|
-
fs.writeFileSync(path.join(targetDir, 'index.js'), index({
|
|
59
|
+
fs.writeFileSync(path.join(targetDir, 'resource.js'), resource({ pageConfig }))
|
|
60
|
+
fs.writeFileSync(path.join(targetDir, 'index.js'), index({ fileName, pageConfig }))
|
|
60
61
|
|
|
61
62
|
if (!menus.find(m => m.key === fileName)) {
|
|
62
63
|
menus.push({ label: fileName, key: fileName })
|
|
63
64
|
}
|
|
64
65
|
|
|
65
|
-
if (
|
|
66
|
+
if (needMock) {
|
|
66
67
|
spinner.text = chalk.yellow(language(
|
|
67
68
|
`🧑💻 9S: 正在突破目标防火墙... 执行数据伪装程序 [${fileName}]`,
|
|
68
69
|
`🧑💻 9S: Piercing target firewall... Executing data camouflage [${fileName}]`
|
|
69
70
|
))
|
|
70
|
-
const rawContent = await generateMock(pageConfig.table.columns, fileName)
|
|
71
|
-
fs.writeFileSync(path.join(mockDir, `${fileName}.js`), `export default ${
|
|
71
|
+
const rawContent = await generateMock({ columns: pageConfig.table.columns, fileName })
|
|
72
|
+
fs.writeFileSync(path.join(mockDir, `${fileName}.js`), `export default ${contextStringify({ context: rawContent })}`)
|
|
72
73
|
console.log(chalk.green(language(
|
|
73
74
|
`\n[Success] 9S 报告: Mock 数据生成成功`,
|
|
74
75
|
`\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 { ux, llm, core, prompts, infrastructure } = require('../bootstrap').get()
|
|
8
|
+
|
|
9
|
+
const { language } = ux
|
|
10
|
+
const { partPrompt } = prompts
|
|
11
|
+
const { recognizePage } = llm
|
|
12
|
+
const { contextStringify } = infrastructure
|
|
13
|
+
const { cleanCode, formatFormItemAndColumns } = core
|
|
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({ prompt: partPrompt, filePath,
|
|
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 => {
|
|
@@ -1,65 +1,26 @@
|
|
|
1
|
-
const fs = require('fs')
|
|
2
|
-
const path = require('path')
|
|
3
|
-
const chalk = require('chalk')
|
|
4
|
-
const { Segment, useDefault } = require('segmentit')
|
|
5
|
-
const segmentit = useDefault(new Segment())
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* @function getSemanticKeywords
|
|
9
|
-
* @description [语义精炼厂 2.0] 使用 segmentit 引擎进行物理切片。
|
|
10
|
-
*/
|
|
11
|
-
const getSemanticKeywords = text => {
|
|
12
|
-
// 💡 物理脱水:确保输入为纯净字符串
|
|
13
|
-
const content = Array.isArray(text) ? text.join(' ') : (text || '')
|
|
14
|
-
// 💡 执行分词
|
|
15
|
-
const result = segmentit.doSegment(content, {
|
|
16
|
-
simple: true, // 开启简易模式,提升吞吐效率
|
|
17
|
-
stripPunctuation: true // 物理过滤掉所有的标点符号
|
|
18
|
-
})
|
|
19
|
-
// 💡 提取词条并执行“基因筛选”
|
|
20
|
-
return Array.from(new Set(result.filter(word => word.length >= 2 && !/^[0-9]+$/.test(word))))
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* @function getLocalScore
|
|
25
|
-
* @description [战力评估协议] 计算语义重合度。
|
|
26
|
-
*/
|
|
27
|
-
const getLocalScore = (api, pageKeywords, moduleName) => {
|
|
28
|
-
let score = 0
|
|
29
|
-
const path = api.path.toLowerCase()
|
|
30
|
-
const desc = api.desc.toLowerCase()
|
|
31
|
-
const mod = moduleName.toLowerCase()
|
|
32
|
-
|
|
33
|
-
// 💡 权重 A:路径直接包含模块名 (暴击加分 +50)
|
|
34
|
-
if (path.includes(mod)) score += 50
|
|
35
|
-
|
|
36
|
-
// 💡 权重 B:描述包含模块核心词 (中量加分 +10)
|
|
37
|
-
pageKeywords.forEach(word => {
|
|
38
|
-
if (desc.includes(word.toLowerCase())) score += 10
|
|
39
|
-
if (path.includes(word.toLowerCase())) score += 5
|
|
40
|
-
})
|
|
41
|
-
|
|
42
|
-
return score
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* @module apiLinker
|
|
47
|
-
* @description [地堡 4.0 核心] 全频道自动寻址协议。
|
|
48
|
-
*/
|
|
49
1
|
module.exports = async () => {
|
|
50
2
|
|
|
51
|
-
const
|
|
52
|
-
const
|
|
53
|
-
|
|
3
|
+
const fs = require('fs')
|
|
4
|
+
const path = require('path')
|
|
5
|
+
const chalk = require('chalk')
|
|
6
|
+
|
|
7
|
+
const { ux, llm, infrastructure } = require('../bootstrap').get()
|
|
8
|
+
|
|
9
|
+
const { language } = ux
|
|
10
|
+
const { apiLinker } = llm
|
|
11
|
+
const { config, getLocalScore, getSemanticKeywords, } = infrastructure
|
|
12
|
+
|
|
13
|
+
const { apiDoc, pagesDir } = config
|
|
14
|
+
if (!apiDoc) return
|
|
54
15
|
|
|
55
16
|
console.log(chalk.cyan(language(
|
|
56
17
|
`\n🤖 Pod 153: 启动‘全频道自动寻址协议 [语义扫描版]’...`,
|
|
57
|
-
`\n🤖 Pod 153: Initiating
|
|
18
|
+
`\n🤖 Pod 153: Initiating 'Full-Channel Autonomous Addressing Protocol [Semantic Scan]'...`
|
|
58
19
|
)))
|
|
59
20
|
|
|
60
21
|
try {
|
|
61
22
|
// 1. 抓取情报
|
|
62
|
-
const apiData = await fetch(
|
|
23
|
+
const apiData = await fetch(apiDoc).then(res => res.json())
|
|
63
24
|
const refinedApis = Object.entries(apiData.paths).flatMap(([apiUrl, methods]) => {
|
|
64
25
|
// 💡 适配多方法接口:有的路径下可能既有 GET 也有 POST
|
|
65
26
|
return Object.entries(methods).map(([method, info]) => ({
|
|
@@ -70,12 +31,12 @@ module.exports = async () => {
|
|
|
70
31
|
})
|
|
71
32
|
|
|
72
33
|
// 2. 战场侦察
|
|
73
|
-
const
|
|
74
|
-
const files = fs.readdirSync(
|
|
34
|
+
const pages = path.join(process.cwd(), pagesDir)
|
|
35
|
+
const files = fs.readdirSync(pages)
|
|
75
36
|
|
|
76
37
|
for (const fileName of files) {
|
|
77
|
-
const indexPath = path.join(
|
|
78
|
-
const resourcePath = path.join(
|
|
38
|
+
const indexPath = path.join(pages, fileName, 'index.js')
|
|
39
|
+
const resourcePath = path.join(pages, fileName, 'resource.js')
|
|
79
40
|
|
|
80
41
|
if (fs.existsSync(indexPath) && fs.existsSync(resourcePath)) {
|
|
81
42
|
let indexCode = fs.readFileSync(indexPath, 'utf-8')
|
|
@@ -83,7 +44,7 @@ module.exports = async () => {
|
|
|
83
44
|
// 💡 锁定待通电锚点
|
|
84
45
|
if (indexCode.includes('BUNKER_API_ANCHOR')) {
|
|
85
46
|
const resourceCode = fs.readFileSync(resourcePath, 'utf-8')
|
|
86
|
-
const bunkerAnchors = indexCode.match(/BUNKER_API_ANCHOR_\w+/g)
|
|
47
|
+
const bunkerAnchors = indexCode.match(/BUNKER_API_ANCHOR_\w+/g)?.join('\n') ?? ''
|
|
87
48
|
|
|
88
49
|
// 💡 执行语义提取流程
|
|
89
50
|
const returnMatch = indexCode.match(/return\s*\(([\s\S]*?)\)\s*}/)
|
|
@@ -109,7 +70,7 @@ module.exports = async () => {
|
|
|
109
70
|
)))
|
|
110
71
|
|
|
111
72
|
// 3. 驱动 9S 最终裁决
|
|
112
|
-
const result = await apiLinker(
|
|
73
|
+
const result = await apiLinker({ bunkerAnchors, realApis: finalCandidates })
|
|
113
74
|
|
|
114
75
|
if (result) {
|
|
115
76
|
// 💡 执行物理更替
|
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
const http = require('http')
|
|
2
|
-
const zlib = require('zlib')
|
|
3
|
-
const chalk = require('chalk')
|
|
4
|
-
const httpProxy = require('http-proxy')
|
|
5
|
-
|
|
6
1
|
/**
|
|
7
2
|
* @function startProxyTower
|
|
8
3
|
* @description [地堡 42153 联合波段] 启动流量拦截塔。
|
|
@@ -10,14 +5,23 @@ const httpProxy = require('http-proxy')
|
|
|
10
5
|
*/
|
|
11
6
|
module.exports = () => {
|
|
12
7
|
|
|
13
|
-
const
|
|
14
|
-
const
|
|
8
|
+
const http = require('http')
|
|
9
|
+
const zlib = require('zlib')
|
|
10
|
+
const chalk = require('chalk')
|
|
11
|
+
const httpProxy = require('http-proxy')
|
|
12
|
+
|
|
13
|
+
const { ux, core, handlers, infrastructure } = require('../bootstrap').get()
|
|
14
|
+
|
|
15
|
+
const { language } = ux
|
|
16
|
+
const { apiHandler } = handlers
|
|
17
|
+
const { config } = infrastructure
|
|
18
|
+
const { unwrapSignal, isQuerySignal } = core
|
|
19
|
+
const { routeMap = {}, proxyTarget } = config
|
|
15
20
|
|
|
16
21
|
const TOWER_PORT = 42153
|
|
17
22
|
const hackedRegistry = new Map()
|
|
18
23
|
const proxy = httpProxy.createProxyServer({})
|
|
19
24
|
|
|
20
|
-
|
|
21
25
|
// 简单的辅助函数:提取 JSON 的所有 Key 作为“指纹”
|
|
22
26
|
const getJsonFingerprint = obj => {
|
|
23
27
|
if (!obj || typeof obj !== 'object') return ''
|
|
@@ -43,7 +47,8 @@ module.exports = () => {
|
|
|
43
47
|
}
|
|
44
48
|
|
|
45
49
|
const referer = req.headers.referer || ''
|
|
46
|
-
const
|
|
50
|
+
const urlPath = new URL(referer).pathname
|
|
51
|
+
const fileName = routeMap?.[urlPath] ?? urlPath.split('/').filter(Boolean).at(-1)
|
|
47
52
|
|
|
48
53
|
const fingerprint = getJsonFingerprint(unwrapSignal(json)) // 获取数据指纹
|
|
49
54
|
const lastFingerprint = hackedRegistry.get(fileName)
|
|
@@ -68,13 +73,12 @@ module.exports = () => {
|
|
|
68
73
|
})
|
|
69
74
|
|
|
70
75
|
const server = http.createServer((req, res) => {
|
|
71
|
-
|
|
72
|
-
if (!target) {
|
|
76
|
+
if (!proxyTarget) {
|
|
73
77
|
// 静默模式:如果不配置 proxyTarget,拦截塔只转发不处理(或报错提示)
|
|
74
78
|
return
|
|
75
79
|
}
|
|
76
80
|
// 转发至真实后端
|
|
77
|
-
proxy.web(req, res, { target, changeOrigin: true })
|
|
81
|
+
proxy.web(req, res, { target: proxyTarget, changeOrigin: true })
|
|
78
82
|
})
|
|
79
83
|
|
|
80
84
|
server.listen(TOWER_PORT, () => {
|