@yorha2b-lab/autodev 1.0.44 → 1.0.46
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/README.md +2 -1
- package/README_EN.md +1 -1
- package/bin/autodev.js +1 -1
- package/package.json +1 -1
- package/src/commands/watch-api.js +2 -2
- package/src/commands/watch-page.js +10 -5
- package/src/commands/watch-part.js +8 -4
- package/src/prompts/{watch-api.js → react/watch-api.js} +1 -1
- package/src/prompts/{watch-part.js → react/watch-part.js} +1 -0
- package/src/services/llm.js +11 -10
- package/src/utils/utils.js +17 -1
- package/templates/react/components/MyModalTable.js +3 -2
- /package/src/prompts/{watch-page.js → react/watch-page.js} +0 -0
package/README.md
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
[English](./README_EN.md) | 简体中文
|
|
4
4
|
|
|
5
|
-

|
|
6
|
+
|
|
6
7
|
|
|
7
8
|
[](https://www.npmjs.com/package/@yorha2b-lab/autodev)
|
|
8
9
|
[](https://www.npmjs.com/package/@yorha2b-lab/autodev)
|
package/README_EN.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
English | [简体中文](./README.md)
|
|
4
4
|
|
|
5
|
-

|
|
6
6
|
|
|
7
7
|
[](https://www.npmjs.com/package/@yorha2b-lab/autodev)
|
|
8
8
|
[](https://www.npmjs.com/package/@yorha2b-lab/autodev)
|
package/bin/autodev.js
CHANGED
|
@@ -91,7 +91,7 @@ program
|
|
|
91
91
|
.description(language('监听 Response,自动对齐真实接口字段', 'Watch responses and auto-align real API fields'))
|
|
92
92
|
.action(() => {
|
|
93
93
|
const watchApi = require('../src/commands/watch-api')
|
|
94
|
-
watchApi()
|
|
94
|
+
watchApi(program.opts())
|
|
95
95
|
})
|
|
96
96
|
|
|
97
97
|
program.parse(process.argv)
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@ const path = require('path')
|
|
|
4
4
|
const chalk = require('chalk')
|
|
5
5
|
const chokidar = require('chokidar')
|
|
6
6
|
|
|
7
|
-
const watchApi =
|
|
7
|
+
const watchApi = options => {
|
|
8
8
|
// 导入配置文件和多语言函数
|
|
9
9
|
const { getConfig, language } = require('../utils/utils.js')
|
|
10
10
|
const { alignResponseFields } = require('../services/llm.js')
|
|
@@ -36,7 +36,7 @@ const watchApi = () => {
|
|
|
36
36
|
let resourceStr = fs.readFileSync(`./${config.pagesDir}/${fileName}/resource.js`, 'utf8')
|
|
37
37
|
|
|
38
38
|
// 调用 AI 服务进行字段对齐
|
|
39
|
-
const result = await alignResponseFields(responseStr, resourceStr)
|
|
39
|
+
const result = await alignResponseFields(options, responseStr, resourceStr)
|
|
40
40
|
|
|
41
41
|
Object.entries(result).forEach(([oldField, newField]) => {
|
|
42
42
|
if (oldField === newField) return
|
|
@@ -9,15 +9,20 @@ const chalk = require('chalk')
|
|
|
9
9
|
* @param {string} options.template - 前端框架模板
|
|
10
10
|
*/
|
|
11
11
|
const watchPage = options => {
|
|
12
|
+
|
|
13
|
+
const { language, getConfig, copyTemplateDir, checkPromptPath, getExistingMenus } = require('../utils/utils.js')
|
|
14
|
+
|
|
15
|
+
const promptPath = `../prompts/${options.template}/watch-page.js`
|
|
16
|
+
|
|
17
|
+
checkPromptPath(promptPath)
|
|
18
|
+
|
|
12
19
|
const chokidar = require('chokidar')
|
|
20
|
+
const pagePrompt = require(promptPath)
|
|
13
21
|
const Handlebars = require('handlebars')
|
|
14
|
-
const pagePrompt = require('../prompts/watch-page.js')
|
|
15
22
|
const { createTaskQueue } = require('../core/task-queue')
|
|
16
23
|
const stringify = require('json-stringify-pretty-compact')
|
|
17
24
|
const { recognizePage, generateMock } = require('../services/llm.js')
|
|
18
25
|
|
|
19
|
-
const { language, getConfig, copyTemplateDir, getExistingMenus } = require('../utils/utils.js')
|
|
20
|
-
|
|
21
26
|
const config = getConfig()
|
|
22
27
|
|
|
23
28
|
const compilerPath = path.join(__dirname, `../core/${options.template}-compiler.js`)
|
|
@@ -118,8 +123,8 @@ const watchPage = options => {
|
|
|
118
123
|
// 4. 生成 Mock 数据
|
|
119
124
|
if (config.needMock) {
|
|
120
125
|
console.log(chalk.yellow(language(
|
|
121
|
-
|
|
122
|
-
|
|
126
|
+
`\n🧑💻 9S: 交给我吧 2B!正在骇入并伪造 [${fileName}] 的 Mock 数据...`,
|
|
127
|
+
`\n🧑💻 9S: Leave it to me, 2B! Hacking and forging Mock data for [${fileName}]...`
|
|
123
128
|
)))
|
|
124
129
|
const rawContent = await generateMock(pageConfig.table.columns, fileName)
|
|
125
130
|
fs.writeFileSync(path.join(mockDir, `${fileName}.js`), `export default ${stringify.default(rawContent, { indent: 4, maxLength: 200 })}`)
|
|
@@ -4,10 +4,15 @@ const chalk = require('chalk')
|
|
|
4
4
|
const chokidar = require('chokidar')
|
|
5
5
|
const stringify = require('json-stringify-pretty-compact')
|
|
6
6
|
|
|
7
|
-
const watchPart =
|
|
8
|
-
|
|
7
|
+
const watchPart = options => {
|
|
8
|
+
|
|
9
|
+
const { language, checkPromptPath } = require('../utils/utils.js')
|
|
10
|
+
|
|
11
|
+
const promptPath = `../prompts/${options.template}/watch-part.js`
|
|
12
|
+
|
|
13
|
+
checkPromptPath(promptPath)
|
|
14
|
+
const partPrompt = require(promptPath)
|
|
9
15
|
const { recognizePage } = require('../services/llm.js')
|
|
10
|
-
const { language } = require('../utils/utils.js')
|
|
11
16
|
|
|
12
17
|
const watcher = chokidar.watch('./screenPart', {
|
|
13
18
|
persistent: true,
|
|
@@ -28,7 +33,6 @@ const watchPart = () => {
|
|
|
28
33
|
|
|
29
34
|
try {
|
|
30
35
|
const startTime = Date.now()
|
|
31
|
-
const partPrompt = require('../prompts/watch-part.js')
|
|
32
36
|
const pageConfig = await recognizePage(partPrompt, filePath)
|
|
33
37
|
|
|
34
38
|
const optionDict = pageConfig.optionDict || {}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module.exports = (responseStr, resourceStr) => `
|
|
2
2
|
responseStr: ${responseStr}
|
|
3
3
|
resourceStr: ${resourceStr}
|
|
4
|
-
resourceStr
|
|
4
|
+
resourceStr是前端目前猜测的字段名(请从resourceStr中提取dataIndex和name),
|
|
5
5
|
responseStr是后端的真实响应。
|
|
6
6
|
请比对两者,找出现有前端字段名应该被替换为哪个真实的后端字段名。
|
|
7
7
|
匹配规则: 1.完全相同 2.下划线/驼峰转换 3.语义相似。
|
|
@@ -22,5 +22,6 @@ module.exports = `
|
|
|
22
22
|
⚠️⚠️⚠️注意:
|
|
23
23
|
type:text/date/daterange/radio/checkbox/select/auto/textarea,如果是text可以省略
|
|
24
24
|
如果type是auto/radio/select/checkbox,请加入options:_CODE_对应的英文名词Options_CODE_
|
|
25
|
+
如果表单项末尾有文字描述,请将文字描述放在unit属性中
|
|
25
26
|
** 只输出modalItems就可以,不需要对应的formItems和columns **
|
|
26
27
|
`
|
package/src/services/llm.js
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
const fs = require('fs')
|
|
2
2
|
const path = require('path')
|
|
3
|
-
const JSON5 = require('json5')
|
|
4
|
-
const sharp = require('sharp')
|
|
5
3
|
const chalk = require('chalk')
|
|
6
|
-
const
|
|
7
|
-
const { getConfig, language } = require('../utils/utils.js') // 导入语言助手
|
|
4
|
+
const { language, getConfig, checkPromptPath } = require('../utils/utils.js') // 导入语言助手
|
|
8
5
|
|
|
9
6
|
let client = null
|
|
10
7
|
|
|
@@ -13,6 +10,7 @@ let client = null
|
|
|
13
10
|
*/
|
|
14
11
|
const getOpenAI = () => {
|
|
15
12
|
if (!client) {
|
|
13
|
+
const OpenAI = require('openai')
|
|
16
14
|
const localEnv = path.resolve(process.cwd(), '.env')
|
|
17
15
|
const pkgEnv = path.resolve(__dirname, '../.env')
|
|
18
16
|
require("dotenv").config({
|
|
@@ -42,20 +40,21 @@ const askAI = async (model, messages, retryCount = 0) => {
|
|
|
42
40
|
messages,
|
|
43
41
|
response_format: { type: 'json_object' }
|
|
44
42
|
})
|
|
45
|
-
|
|
46
43
|
let raw = response.choices[0].message.content.trim()
|
|
47
44
|
raw = raw.replace(/^```json\n?/, '').replace(/\n?```$/, '')
|
|
48
45
|
const match = raw.match(/[\{\[][\s\S]*[\}\]]/)
|
|
46
|
+
const JSON5 = require('json5')
|
|
49
47
|
return JSON5.parse(match ? match[0] : raw)
|
|
50
48
|
|
|
51
49
|
} catch (err) {
|
|
52
|
-
const
|
|
50
|
+
const statusCode = err.status || err.response?.status
|
|
51
|
+
const isAuthError = err.message.includes('401') || err.message.includes('402') || [401, 402].includes(statusCode)
|
|
53
52
|
if (isAuthError) {
|
|
54
53
|
// 权限错误:司令部拒绝访问
|
|
55
54
|
throw new Error(language(
|
|
56
55
|
'[系统警告] YoRHa 司令部拒绝访问:API Key 无效或额度耗尽,请检查!',
|
|
57
56
|
'[SYSTEM ALERT] YoRHa Command Center Access Denied: Invalid API Key or quota exhausted!'
|
|
58
|
-
))
|
|
57
|
+
))
|
|
59
58
|
}
|
|
60
59
|
|
|
61
60
|
// 重试警告:神经云网络连接不稳
|
|
@@ -91,7 +90,7 @@ module.exports = {
|
|
|
91
90
|
recognizePage: async (prompt, filePath) => {
|
|
92
91
|
const config = getConfig()
|
|
93
92
|
const { UI_DESIGNER } = require('../prompts/system.js')
|
|
94
|
-
|
|
93
|
+
const sharp = require('sharp')
|
|
95
94
|
const compressedBuffer = await sharp(filePath)
|
|
96
95
|
.resize(1280, null, { withoutEnlargement: true })
|
|
97
96
|
.jpeg({ quality: 80 })
|
|
@@ -116,10 +115,12 @@ module.exports = {
|
|
|
116
115
|
/**
|
|
117
116
|
* 对齐 Response 接口字段
|
|
118
117
|
*/
|
|
119
|
-
alignResponseFields: async (responseStr, resourceStr) => {
|
|
118
|
+
alignResponseFields: async (options, responseStr, resourceStr) => {
|
|
120
119
|
const config = getConfig()
|
|
121
|
-
const apiPrompt = require('../prompts/watch-api.js')
|
|
122
120
|
const { API_DESIGNER } = require('../prompts/system.js')
|
|
121
|
+
const promptPath = `../prompts/${options.template}/watch-api.js`
|
|
122
|
+
checkPromptPath(promptPath)
|
|
123
|
+
const apiPrompt = require(promptPath)
|
|
123
124
|
return askAI(
|
|
124
125
|
config.textModel,
|
|
125
126
|
[
|
package/src/utils/utils.js
CHANGED
|
@@ -41,6 +41,22 @@ const cleanCode = str => {
|
|
|
41
41
|
.trim() + '\n'
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
+
/**
|
|
45
|
+
* 检查 Prompt 文件是否存在
|
|
46
|
+
* @param {string} promptPath - Prompt 文件路径
|
|
47
|
+
* @returns {void}
|
|
48
|
+
*/
|
|
49
|
+
const checkPromptPath = promptPath => {
|
|
50
|
+
const promptAbsPath = path.resolve(__dirname, promptPath)
|
|
51
|
+
if (!fs.existsSync(promptAbsPath)) {
|
|
52
|
+
const displayPath = promptPath.slice(3)
|
|
53
|
+
throw new Error(language(
|
|
54
|
+
`🤖 Pod 042: [警告] 侦测到未知的构筑协议 ${displayPath},地堡数据库暂无此类资料。`,
|
|
55
|
+
`🤖 Pod 042: [Warning] Unknown construction protocol ${displayPath}. No such protocol found in the bunker database.`
|
|
56
|
+
))
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
44
60
|
/**
|
|
45
61
|
* 获取已有的页面菜单配置
|
|
46
62
|
* @param {string} dir - 页面目录路径(默认 'src/pages')
|
|
@@ -109,4 +125,4 @@ const copyTemplateDir = (options, templateSubDir, targetSubDir) => {
|
|
|
109
125
|
}
|
|
110
126
|
|
|
111
127
|
// 导出工具函数
|
|
112
|
-
module.exports = { language, getConfig, cleanCode, getExistingMenus, copyTemplateDir, generateSmartImports }
|
|
128
|
+
module.exports = { language, getConfig, cleanCode, getExistingMenus, copyTemplateDir, checkPromptPath, generateSmartImports }
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { Modal } from 'antd'
|
|
2
1
|
import { MyTable } from './MyTable'
|
|
2
|
+
import { Modal, Button } from 'antd'
|
|
3
3
|
import { MySearchForm } from './MySearchForm'
|
|
4
4
|
import { useTableQuery } from '../hooks/useTableQuery'
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
export const MyModalTable = ({ api, onOk, title, width, footer, visible, columns, setModal, formItems, rowSelection, formatResponse, extraParams = {} }) => {
|
|
7
|
+
export const MyModalTable = ({ api, onOk, title, width, footer, visible, columns, setModal, formItems, rowSelection, formatResponse, functionButtons, extraParams = {} }) => {
|
|
8
8
|
|
|
9
9
|
const { total, loading, dataSource, search, setSearch } = useTableQuery(api, formatResponse, extraParams)
|
|
10
10
|
|
|
@@ -22,6 +22,7 @@ export const MyModalTable = ({ api, onOk, title, width, footer, visible, columns
|
|
|
22
22
|
return (
|
|
23
23
|
<Modal centered destroyOnClose title={title} width={width} open={visible} onOk={handleOk} footer={footer} onCancel={() => setModal({ visible: false })}>
|
|
24
24
|
{formItems?.length > 0 && <MySearchForm search={search} formItems={formItems} setSearch={handleSearch} syncUrlParams={false} />}
|
|
25
|
+
{functionButtons?.length > 0 && functionButtons.map(item => <Button key={item.name} type={item.type} onClick={item.onClick}>{item.name}</Button>)}
|
|
25
26
|
<MyTable
|
|
26
27
|
loading={loading}
|
|
27
28
|
columns={columns}
|
|
File without changes
|