@yorha2b-lab/autodev 5.7.3 → 6.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.
Files changed (42) hide show
  1. package/CONTRIBUTING.md +2 -2
  2. package/README.md +87 -80
  3. package/README_EN.md +93 -89
  4. package/bin/{autodev.js → bunker.js} +10 -10
  5. package/package.json +26 -23
  6. package/src/{bootstrap → awakening}/index.js +9 -10
  7. package/src/dialogs/DE-DE.js +1 -1
  8. package/src/dialogs/EN-US.js +1 -1
  9. package/src/dialogs/ES-ES.js +1 -1
  10. package/src/dialogs/FR-FR.js +1 -1
  11. package/src/dialogs/ID-ID.js +1 -1
  12. package/src/dialogs/IT-IT.js +1 -1
  13. package/src/dialogs/JA-JP.js +1 -1
  14. package/src/dialogs/KO-KR.js +1 -1
  15. package/src/dialogs/PT-BR.js +1 -1
  16. package/src/dialogs/RU-RU.js +1 -1
  17. package/src/dialogs/TR-TR.js +1 -1
  18. package/src/dialogs/ZH-CN.js +1 -1
  19. package/src/dialogs/ZH-TW.js +1 -1
  20. package/src/framework/react/components/MyBaseForm.js +1 -1
  21. package/src/framework/react/components/MyModalForm.js +14 -2
  22. package/src/framework/react/generator/index.js +4 -4
  23. package/src/{ai/openai.js → gateway/client.js} +2 -2
  24. package/src/{ai → gateway}/index.js +5 -35
  25. package/src/gateway/protocol.js +36 -0
  26. package/src/{core/engine.js → headquarters/builder.js} +3 -3
  27. package/src/{core/queue.js → headquarters/dispatcher.js} +1 -1
  28. package/src/{core/deployment.js → headquarters/engineer.js} +4 -4
  29. package/src/headquarters/observer.js +36 -0
  30. package/src/labs/council.js +4 -4
  31. package/src/labs/index.js +1 -1
  32. package/src/labs/tower.js +4 -9
  33. package/src/{utils → logistics}/foundation.js +3 -3
  34. package/src/{utils → logistics}/ux.js +3 -2
  35. package/src/{handlers → units}/page.js +10 -7
  36. package/src/{handlers → units}/part.js +3 -3
  37. package/src/{handlers → units}/response.js +5 -5
  38. package/src/commands/watch.js +0 -38
  39. /package/src/{utils/installer.js → headquarters/quartermaster.js} +0 -0
  40. /package/src/{core → headquarters}/recruiter.js +0 -0
  41. /package/src/{utils → logistics}/generator.js +0 -0
  42. /package/src/{utils → logistics}/semantic.js +0 -0
package/package.json CHANGED
@@ -1,53 +1,56 @@
1
1
  {
2
2
  "name": "@yorha2b-lab/autodev",
3
- "version": "5.7.3",
4
- "description": "基于视觉大模型的前端(react+Antd)全自动 CRUD 代码生成器",
3
+ "version": "6.0.0",
4
+ "description": "基于 AI 视觉与语义协议的前端 (React+Antd) 代码构筑与旧系统重构引擎",
5
5
  "bin": {
6
- "autodev": "bin/autodev.js"
6
+ "bunker": "bin/bunker.js"
7
7
  },
8
8
  "scripts": {
9
9
  "test": "echo \"Error: no test specified\" && exit 1"
10
10
  },
11
11
  "keywords": [
12
- "crud",
13
- "generator",
14
12
  "ai",
15
- "vision",
16
- "react",
17
- "antd",
18
13
  "umi",
19
- "code-generation",
20
- "automation",
14
+ "antd",
15
+ "crud",
16
+ "react",
17
+ "vision",
18
+ "copilot",
21
19
  "frontend",
22
- "scaffold"
20
+ "scaffold",
21
+ "generator",
22
+ "automation",
23
+ "refactoring",
24
+ "legacy-code",
25
+ "code-generation"
23
26
  ],
24
27
  "author": "yorha2b-Lab",
25
28
  "license": "AGPL-3.0",
26
29
  "type": "commonjs",
27
30
  "repository": {
28
31
  "type": "git",
29
- "url": "https://github.com/yorha2b-lab/auto-crud-copilot.git"
32
+ "url": "https://github.com/yorha2b-lab/autodev.git"
30
33
  },
31
34
  "bugs": {
32
- "url": "https://github.com/yorha2b-lab/auto-crud-copilot/issues"
35
+ "url": "https://github.com/yorha2b-lab/autodev/issues"
33
36
  },
34
- "homepage": "https://github.com/yorha2b-lab/auto-crud-copilot#readme",
37
+ "homepage": "https://github.com/yorha2b-lab/autodev#readme",
35
38
  "dependencies": {
39
+ "ora": "^5.4.1",
36
40
  "chalk": "^4.1.2",
37
- "chokidar": "^5.0.0",
38
- "commander": "^14.0.3",
41
+ "json5": "^2.2.3",
42
+ "sharp": "^0.34.5",
39
43
  "dotenv": "^17.3.1",
40
44
  "figlet": "^1.10.0",
41
- "handlebars": "^4.7.8",
42
- "json-stringify-pretty-compact": "^4.0.0",
43
- "json5": "^2.2.3",
44
45
  "openai": "^6.24.0",
45
- "ora": "^5.4.1",
46
- "sharp": "^0.34.5"
46
+ "chokidar": "^5.0.0",
47
+ "commander": "^14.0.3",
48
+ "handlebars": "^4.7.8",
49
+ "json-stringify-pretty-compact": "^4.0.0"
47
50
  },
48
51
  "devDependencies": {
49
- "http-proxy": "^1.18.1",
52
+ "segmentit": "^2.0.3",
50
53
  "puppeteer": "^25.4.0",
51
- "segmentit": "^2.0.3"
54
+ "http-proxy": "^1.18.1"
52
55
  }
53
56
  }
@@ -7,9 +7,9 @@ module.exports = {
7
7
 
8
8
  init: async ({ template }, dialog, version, local) => {
9
9
 
10
- const recruiter = require('../core/recruiter')
11
- const utils = recruiter(path.join(__dirname, '../utils'))
12
- const yorha = utils.ux.yorha()
10
+ const recruiter = require('../headquarters/recruiter')
11
+ const logistics = recruiter(path.join(__dirname, '../logistics'))
12
+ const yorha = logistics.ux.yorha()
13
13
 
14
14
  const generatorPath = path.join(__dirname, `../framework/${template}/generator`)
15
15
  if (!fs.existsSync(generatorPath)) {
@@ -18,21 +18,20 @@ module.exports = {
18
18
  }
19
19
 
20
20
  const accessPoint = {
21
- utils,
22
21
  yorha,
23
22
  dialog,
24
23
  template,
25
- openAI: require('../ai/openai')(),
26
- engine: require('../core/engine')({ utils, template }),
27
- handlers: recruiter(path.join(__dirname, '../handlers')),
24
+ logistics,
25
+ units: recruiter(path.join(__dirname, '../units')),
26
+ builder: require('../headquarters/builder')({ logistics, template }),
28
27
  prompts: recruiter(path.join(__dirname, `../framework/${template}/prompts`)),
29
28
  }
30
29
 
31
30
  if (version) {
32
- await utils.ux.bootSequence(version, local)
31
+ await logistics.ux.bootSequence(version, local)
33
32
  }
34
- require('../core/deployment')(accessPoint)
35
- const llm = require('../ai')(accessPoint)
33
+ require('../headquarters/engineer')(accessPoint)
34
+ const llm = require('../gateway')(accessPoint)
36
35
  const generator = require(generatorPath)(accessPoint)
37
36
  const labs = require('../labs')({ llm, ...accessPoint })
38
37
 
@@ -47,7 +47,7 @@ module.exports = {
47
47
  initDesc: 'Bunker-Konstruktionsumgebung im aktuellen Verzeichnis initialisieren',
48
48
  linkSevered: 'Verbindung getrennt: Netzwerkstatus oder Blackbox-Resonanz prüfen',
49
49
  towerConnected: port => `Befehl: Proxy-Ziel auf http://localhost:${port} setzen`,
50
- watchDesc: 'Überwachung aller Kanäle starten: Page/Part/API-Konstruktion unterstützt',
50
+ bootDesc: 'Überwachung aller Kanäle starten: Page/Part/API-Konstruktion unterstützt',
51
51
  accessDenied: 'Zentralzugriff verweigert: API-Key ungültig oder Kontingent erschöpft',
52
52
  dataSynced: 'Alle Konstruktionsdaten wurden mit dem Bunker-Speicherknoten synchronisiert',
53
53
  systemOffline: 'Neuronale Cloud-Verbindung wird getrennt. Daten werden physisch versiegelt...',
@@ -50,7 +50,7 @@ module.exports = {
50
50
  linkSevered: 'Link Severed: Check network status or Black Box resonance',
51
51
  systemOffline: 'Disconnecting Neural Link, Executing Physical Assembly...',
52
52
  accessDenied: 'YoRHa Command Center Access Denied: Invalid API Key or quota exhausted!',
53
- watchDesc: 'Start full-channel linked monitoring: Coordinated Page/Part/API construction',
53
+ bootDesc: 'Start full-channel linked monitoring: Coordinated Page/Part/API construction',
54
54
  copyEnum: `│ Backend Enums detected \n│ Weld the code below into the module's resource center`,
55
55
  towerConnected: port => `Command: Please point your local proxy target to http://localhost:${port}`,
56
56
  disclaimer: 'Match Result Reference Only. Not Final Decision. Each Unit should adjust based on battlefield conditions',
@@ -50,7 +50,7 @@ module.exports = {
50
50
  initDesc: 'Inicializar entorno de construcción Bunker en el directorio actual',
51
51
  dataSynced: 'Todos los datos de construcción sincronizados con el nodo Bunker',
52
52
  towerConnected: port => `Comando: apunta tu proxy hacia http://localhost:${port}`,
53
- watchDesc: 'Iniciar monitorización completa: construcción coordinada Page/Part/API',
53
+ bootDesc: 'Iniciar monitorización completa: construcción coordinada Page/Part/API',
54
54
  towerOnline: port => `Torre de interceptación de señales activa [Frecuencia: ${port}]`,
55
55
  systemOffline: 'Desconectando enlace neural en la nube. Ejecutando sellado físico de datos...',
56
56
  disclaimer: 'Los resultados son referencias. Cada unidad debe ajustar según la situación real',
@@ -45,7 +45,7 @@ module.exports = {
45
45
  copyTemplateError: virus => `Échec de construction du modèle : ${virus}`,
46
46
  accessDenied: 'Accès au quartier général refusé : clé API invalide ou quota épuisé',
47
47
  towerOnline: port => `Tour d’interception des signaux en ligne [Fréquence : ${port}]`,
48
- watchDesc: 'Démarrer la surveillance multi-canaux : construction coordonnée Page/Part/API',
48
+ bootDesc: 'Démarrer la surveillance multi-canaux : construction coordonnée Page/Part/API',
49
49
  initDesc: 'Initialiser l’environnement de construction du Bunker dans le répertoire actuel',
50
50
  towerConnected: port => `Ordre : configurez votre cible proxy vers http://localhost:${port}`,
51
51
  star: 'Si ce système vous fait gagner du temps, pensez à lui donner une étoile sur GitHub ⭐',
@@ -47,7 +47,7 @@ module.exports = {
47
47
  towerOnline: port => `Menara intersepsi sinyal aktif [Frekuensi: ${port}]`,
48
48
  initDesc: 'Menginisialisasi lingkungan konstruksi Bunker di direktori saat ini',
49
49
  accessDenied: 'Akses ditolak pusat komando: API Key tidak valid atau kuota habis',
50
- watchDesc: 'Mengaktifkan pemantauan multi-kanal: konstruksi Page/Part/API terpadu',
50
+ bootDesc: 'Mengaktifkan pemantauan multi-kanal: konstruksi Page/Part/API terpadu',
51
51
  star: 'Jika proyek ini membantu menghemat waktu Anda, berikan bintang di GitHub ⭐',
52
52
  systemOffline: 'Memutus koneksi neural cloud. Menjalankan penyegelan fisik data...',
53
53
  dataSynced: 'Seluruh data konstruksi telah disinkronkan dengan node penyimpanan Bunker',
@@ -44,7 +44,7 @@ module.exports = {
44
44
  configCheck: 'File config.js già presente. Creazione ignorata',
45
45
  dataSynced: 'Tutti i dati di costruzione sincronizzati con il nodo Bunker',
46
46
  copyTemplateError: virus => `Errore nella costruzione del template: ${virus}`,
47
- watchDesc: 'Avvia monitoraggio completo: costruzione coordinata Page/Part/API',
47
+ bootDesc: 'Avvia monitoraggio completo: costruzione coordinata Page/Part/API',
48
48
  initDesc: 'Inizializza ambiente di costruzione Bunker nella directory corrente',
49
49
  star: 'Se questo progetto ti fa risparmiare tempo, lascia una stella su GitHub ⭐',
50
50
  towerOnline: port => `Torre di intercettazione segnali online [Frequenza: ${port}]`,
@@ -47,7 +47,7 @@ module.exports = {
47
47
  copyTemplateError: virus => `テンプレート構築失敗: ${virus}`,
48
48
  star: 'このシステムが役立った場合、GitHubでスターをお願いします ⭐',
49
49
  towerOnline: port => `シグナル迎撃塔オンライン [周波数: ${port}]`,
50
- watchDesc: '全チャンネル連携監視を開始:Page/Part/API協調構築をサポート',
50
+ bootDesc: '全チャンネル連携監視を開始:Page/Part/API協調構築をサポート',
51
51
  systemOffline: 'ニューラルクラウド接続を切断中。データを物理封印します...',
52
52
  accessDenied: '司令部アクセス拒否:API Keyが無効、または利用上限に達しています',
53
53
  linkSevered: '接続断絶:ネットワーク状態またはブラックボックス共鳴を確認してください',
@@ -50,7 +50,7 @@ module.exports = {
50
50
  towerOnline: port => `신호 인터셉트 타워 온라인 [주파수: ${port}]`,
51
51
  linkSevered: '연결 종료: 네트워크 상태 또는 블랙박스 공명을 확인하십시오',
52
52
  star: '이 프로젝트가 시간을 절약해 준다면 GitHub에서 Star를 눌러주세요 ⭐',
53
- watchDesc: '전체 채널 연동 모니터링 시작: Page/Part/API 협동 구축 지원',
53
+ bootDesc: '전체 채널 연동 모니터링 시작: Page/Part/API 협동 구축 지원',
54
54
  disclaimer: '매칭 결과는 참고용이며 최종 판단은 각 기체가 실제 상황에 따라 조정해야 합니다',
55
55
  towerConnected: port => `명령: 프록시 대상을 http://localhost:${port} 로 설정하십시오`,
56
56
  networkInstability: count => `뉴럴 클라우드 연결 불안정. 재연결 시도 중... (${count}번째 시도)`,
@@ -48,7 +48,7 @@ module.exports = {
48
48
  towerOnline: port => `Torre de interceptação de sinais online [Frequência: ${port}]`,
49
49
  accessDenied: 'Acesso ao comando central negado: API Key inválida ou limite excedido',
50
50
  star: 'Se este projeto ajudou você a economizar tempo, deixe uma estrela no GitHub ⭐',
51
- watchDesc: 'Iniciar monitoramento de todos os canais: construção integrada de Page/Part/API',
51
+ bootDesc: 'Iniciar monitoramento de todos os canais: construção integrada de Page/Part/API',
52
52
  linkSevered: 'Conexão interrompida: verifique o estado da rede ou a ressonância do Black Box',
53
53
  systemOffline: 'Desconectando conexão neural em nuvem. Executando selamento físico dos dados...',
54
54
  dataSynced: 'Todos os dados de construção foram sincronizados com o nó de armazenamento do Bunker',
@@ -47,7 +47,7 @@ module.exports = {
47
47
  configCheck: 'Обнаружен существующий файл config.js. Генерация пропущена',
48
48
  towerOnline: port => `Башня перехвата сигналов активна [Частота: ${port}]`,
49
49
  accessDenied: 'Доступ к штабу запрещён: неверный API Key или исчерпан лимит',
50
- watchDesc: 'Запуск мониторинга всех каналов: совместная сборка Page/Part/API',
50
+ bootDesc: 'Запуск мониторинга всех каналов: совместная сборка Page/Part/API',
51
51
  towerConnected: port => `Приказ: направьте прокси-цель на http://localhost:${port}`,
52
52
  star: 'Если эта система помогла вам сэкономить время, поставьте звезду на GitHub ⭐',
53
53
  linkSevered: 'Соединение разорвано: проверьте состояние сети или резонанс чёрного ящика',
@@ -44,7 +44,7 @@ module.exports = {
44
44
  envCheck: '.env dosyası zaten mevcut. Oluşturma atlandı',
45
45
  copyTemplateError: virus => `Şablon inşası başarısız: ${virus}`,
46
46
  configCheck: 'config.js dosyası zaten mevcut. Oluşturma atlandı',
47
- watchDesc: 'Tam kanal izlemeyi başlat: Page/Part/API ortak inşası',
47
+ bootDesc: 'Tam kanal izlemeyi başlat: Page/Part/API ortak inşası',
48
48
  towerOnline: port => `Sinyal yakalama kulesi aktif [Frekans: ${port}]`,
49
49
  star: 'Bu proje size zaman kazandırdıysa GitHub üzerinde yıldız bırakın ⭐',
50
50
  dataSynced: 'Tüm inşa verileri Bunker depolama düğümü ile senkronize edildi',
@@ -49,7 +49,7 @@ module.exports = {
49
49
  copyTemplateError: virus => `模板构筑失败: ${virus}`,
50
50
  star: '如果它能帮您节省时间,请在 GitHub 上给它点个赞 ⭐',
51
51
  towerOnline: port => `信号拦截塔已在线 [波段: ${port}]`,
52
- watchDesc: '开启全频道联动监控:支持 Page/Part/API 协同构筑',
52
+ bootDesc: '开启全频道联动监控:支持 Page/Part/API 协同构筑',
53
53
  accessDenied: '司令部拒绝访问:API Key 无效或额度耗尽,请检查!',
54
54
  disclaimer: '匹配结果仅供参考,不构成最终决策,各机体需根据实际情况进行调整',
55
55
  towerConnected: port => `指令:请将您的代理目标指向 http://localhost:${port}`,
@@ -49,7 +49,7 @@ module.exports = {
49
49
  copyTemplateError: virus => `模板構築失敗: ${virus}`,
50
50
  star: '如果它能幫助您節省時間,請在 GitHub 上給它一顆 Star ⭐',
51
51
  towerOnline: port => `訊號攔截塔已上線 [頻段: ${port}]`,
52
- watchDesc: '開啟全頻道聯動監控:支援 Page/Part/API 協同構築',
52
+ bootDesc: '開啟全頻道聯動監控:支援 Page/Part/API 協同構築',
53
53
  accessDenied: '司令部拒絕存取:API Key 無效或額度耗盡,請檢查!',
54
54
  disclaimer: '匹配結果僅供參考,不構成最終決策,各機體需依照實際情況進行調整',
55
55
  towerConnected: port => `指令:請將您的代理目標指向 http://localhost:${port}`,
@@ -38,7 +38,7 @@ const renderFormContent = ({ item, prefixName = [] }) => {
38
38
  const namePath = Array.isArray(prefixName) ? [...prefixName, ...(Array.isArray(item.name) ? item.name : [item.name])] : item.name
39
39
 
40
40
  const inputNode = (
41
- <Form.Item noStyle name={namePath} rules={item.rules} initialValue={item.value} {...(['upload', 'ossUpload'].includes(item.type) ? { getValueFromEvent, valuePropName: 'fileList' } : { valuePropName: item.valuePropName })}>
41
+ <Form.Item noStyle name={namePath} rules={item.rules} dependencies={item.dependencies} initialValue={item.value} {...(['upload', 'ossUpload'].includes(item.type) ? { getValueFromEvent, valuePropName: 'fileList' } : { valuePropName: item.valuePropName })}>
42
42
  {formNode({ item })}
43
43
  </Form.Item>
44
44
  )
@@ -118,7 +118,7 @@ const FormRenderer = ({ form, formItems, tableConfig, setModalTable, setSelected
118
118
  * formItems={[{ label: '截止日期', name: 'deadline', type: 'date' }]}
119
119
  * />
120
120
  */
121
- export const MyModalForm = ({ width, title, footer, submit, record, visible, setModal, labelCol, formItems, wrapperCol, tableConfig, onValuesChange, handleModalTableOk }) => {
121
+ export const MyModalForm = ({ width, title, footer, submit, record, visible, setModal, labelCol, formItems, wrapperCol, tableConfig, okButtonProps, onValuesChange, handleModalTableOk }) => {
122
122
 
123
123
  const rowKey = tableConfig?.rowKey || 'id'
124
124
 
@@ -220,7 +220,19 @@ export const MyModalForm = ({ width, title, footer, submit, record, visible, set
220
220
  }), [rowKey, modalTable, selectedTableRows])
221
221
 
222
222
  return (
223
- <Modal centered title={title} width={width} open={visible} onOk={handleOk} footer={footer?.({ setModal })} destroyOnClose onCancel={handleCancel} confirmLoading={pending} bodyStyle={{ paddingBottom: 0 }}>
223
+ <Modal
224
+ centered
225
+ title={title}
226
+ width={width}
227
+ open={visible}
228
+ destroyOnClose
229
+ onOk={handleOk}
230
+ onCancel={handleCancel}
231
+ confirmLoading={pending}
232
+ okButtonProps={okButtonProps}
233
+ bodyStyle={{ paddingBottom: 0 }}
234
+ footer={footer?.({ form, record, setModal })}
235
+ >
224
236
  {modalTable.visible && <MyModalTable rowKey={rowKey} {...modalTable} rowSelection={tableRowSelection} onOk={modalTableOk} setModal={setModalTable} />}
225
237
  <Form form={form} preserve={false} labelCol={labelCol} wrapperCol={wrapperCol} onValuesChange={(changed, all) => onValuesChange?.({ changed, all, form, record })}>
226
238
  <Row gutter={[24, 0]}>
@@ -1,8 +1,8 @@
1
- module.exports = ({ utils, engine }) => {
1
+ module.exports = ({ builder, logistics }) => {
2
2
 
3
- const { indexTpl, resourceTpl } = engine
4
- const { wrapCode, cleanCode, contextStringify } = utils.generator
5
- const { needMock, responseSuccess } = utils.foundation.getConfig()
3
+ const { indexTpl, resourceTpl } = builder
4
+ const { wrapCode, cleanCode, contextStringify } = logistics.generator
5
+ const { needMock, responseSuccess } = logistics.foundation.getConfig()
6
6
 
7
7
  const formatFormItemAndColumns = ({ pageConfig }) => {
8
8
 
@@ -7,7 +7,7 @@ module.exports = () => {
7
7
  const pkgEnv = path.resolve(__dirname, '../../.env')
8
8
  const localEnv = path.resolve(process.cwd(), 'bunker', '.env')
9
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 })
10
+ const client = new OpenAI({ apiKey: process.env.API_KEY, baseURL: process.env.BASE_URL })
11
11
 
12
- return openAI
12
+ return client
13
13
  }
@@ -1,44 +1,14 @@
1
- module.exports = ({ utils, yorha, openAI, dialog, prompts }) => {
1
+ module.exports = ({ yorha, dialog, prompts, logistics }) => {
2
2
 
3
3
  const sharp = require('sharp')
4
4
 
5
+ const { sleep } = logistics.ux
5
6
  const { mock, system, council, response, similarity } = prompts
6
7
  const { UI_DESIGNER, API_DESIGNER, MOCK_DESIGNER } = system
7
- const { textModel, visionModel } = utils.foundation.getConfig()
8
+ const { textModel, visionModel } = logistics.foundation.getConfig()
8
9
 
9
- const askAI = async ({ model, messages, response_format = { type: 'json_object' }, retryCount = 0 }) => {
10
-
11
- if (retryCount >= 3) {
12
- yorha.commander.report(dialog.bunker.linkSevered, 'red')
13
- throw new Error(dialog.bunker.linkSevered)
14
- }
15
-
16
- try {
17
- const response = await openAI.chat.completions.create({
18
- model,
19
- messages,
20
- top_p: 0.1,
21
- response_format,
22
- temperature: 0.01,
23
- })
24
- let raw = response.choices[0].message.content.trim()
25
- raw = raw.replace(/^```json\n?/, '').replace(/\n?```$/, '')
26
- const match = raw.match(/[\{\[][\s\S]*[\}\]]/)
27
- const JSON5 = require('json5')
28
- return JSON5.parse(match ? match[0] : raw)
29
- } catch (err) {
30
- const statusCode = err.status || err.response?.status
31
- const isAuthError = [401, 402].includes(statusCode)
32
- if (isAuthError) {
33
- yorha.commander.report(dialog.bunker.accessDenied, 'red')
34
- throw new Error(dialog.bunker.accessDenied)
35
- }
36
-
37
- yorha.commander.report(dialog.bunker.networkInstability(retryCount + 1))
38
-
39
- return askAI({ model, yorha, dialog, openAI, messages, response_format, retryCount: retryCount + 1 })
40
- }
41
- }
10
+ const openAI = require('./client')()
11
+ const askAI = require('./protocol')({ yorha, sleep, dialog, openAI })
42
12
 
43
13
  return {
44
14
  generateMock: async ({ columns, fileName }) => {
@@ -0,0 +1,36 @@
1
+ module.exports = ({ yorha, sleep, dialog, openAI }) => {
2
+
3
+ return async function askAI({ model, messages, response_format = { type: 'json_object' }, retryCount = 0 }) {
4
+
5
+ if (retryCount >= 3) {
6
+ yorha.commander.report(dialog.bunker.linkSevered, 'red')
7
+ throw new Error(dialog.bunker.linkSevered)
8
+ }
9
+
10
+ try {
11
+ const response = await openAI.chat.completions.create({
12
+ model,
13
+ messages,
14
+ top_p: 0.1,
15
+ response_format,
16
+ temperature: 0.01,
17
+ })
18
+ let raw = response.choices[0].message.content.trim()
19
+ raw = raw.replace(/^```json\n?/, '').replace(/\n?```$/, '')
20
+ const match = raw.match(/[\{\[][\s\S]*[\}\]]/)
21
+ const JSON5 = require('json5')
22
+ return JSON5.parse(match ? match[0] : raw)
23
+ } catch (err) {
24
+ const statusCode = err.status || err.response?.status
25
+ const isAuthError = [401, 402].includes(statusCode)
26
+ if (isAuthError) {
27
+ yorha.commander.report(dialog.bunker.accessDenied, 'red')
28
+ throw new Error(dialog.bunker.accessDenied)
29
+ }
30
+
31
+ yorha.commander.report(dialog.bunker.networkInstability(retryCount + 1))
32
+ await sleep(1000)
33
+ return askAI({ model, messages, response_format, retryCount: retryCount + 1 })
34
+ }
35
+ }
36
+ }
@@ -1,13 +1,13 @@
1
- module.exports = ({ utils, template }) => {
1
+ module.exports = ({ template, logistics }) => {
2
2
 
3
3
  const fs = require('fs')
4
4
  const path = require('path')
5
5
  const Handlebars = require('handlebars')
6
6
 
7
7
  Handlebars.registerHelper('raw', opt => opt.fn())
8
- Handlebars.registerHelper('stringify', (context, maxLength = 200) => context ? new Handlebars.SafeString(utils.generator.contextStringify({ context, maxLength })) : '[]')
8
+ Handlebars.registerHelper('stringify', (context, maxLength = 200) => context ? new Handlebars.SafeString(logistics.generator.contextStringify({ context, maxLength })) : '[]')
9
9
 
10
- const { hbsDir } = utils.foundation.getConfig()
10
+ const { hbsDir } = logistics.foundation.getConfig()
11
11
  const tplDir = !!hbsDir ? path.join(process.cwd(), hbsDir) : path.join(__dirname, `../framework/${template}/handlebars`)
12
12
  const partialsDir = !!hbsDir ? path.join(process.cwd(), hbsDir, 'partials') : path.join(__dirname, `../framework/${template}/handlebars/partials`)
13
13
 
@@ -1,4 +1,4 @@
1
- module.exports = (concurrency = 1, { yorha, dialog }) => {
1
+ module.exports = ({ yorha, dialog }, concurrency = 1) => {
2
2
 
3
3
  let running = 0
4
4
  let queue = []
@@ -1,13 +1,13 @@
1
1
  const fs = require('fs')
2
2
  const path = require('path')
3
3
 
4
- module.exports = ({ utils, yorha, dialog, handlers, template }) => {
4
+ module.exports = ({ units, yorha, dialog, template, logistics }) => {
5
5
 
6
- const { copyTemplateDir } = utils.foundation
7
- const { hbsDir, hooksDir, utilsDir, componentsDir } = utils.foundation.getConfig()
6
+ const { copyTemplateDir } = logistics.foundation
7
+ const { hbsDir, hooksDir, utilsDir, componentsDir } = logistics.foundation.getConfig()
8
8
 
9
9
  try {
10
- Object.values(handlers).forEach(handler => fs.mkdirSync(path.join(process.cwd(), 'bunker', handler.watch), { recursive: true }))
10
+ Object.values(units).forEach(unit => fs.mkdirSync(path.join(process.cwd(), 'bunker', unit.station), { recursive: true }))
11
11
  if (!hbsDir) {
12
12
  copyTemplateDir(template, 'hooks', hooksDir)
13
13
  copyTemplateDir(template, 'utils', utilsDir)
@@ -0,0 +1,36 @@
1
+ module.exports = bunker => {
2
+
3
+ const chokidar = require('chokidar')
4
+
5
+ const acp = bunker.get()
6
+ const units = Object.values(acp.units)
7
+ const dispatcher = require('../headquarters/dispatcher')(acp, 2)
8
+
9
+ dispatcher.onIdle(() => acp.yorha.commander.report(acp.dialog.bunker.systemStandby, 'gray'))
10
+
11
+ const options = {
12
+ persistent: true,
13
+ ignoreInitial: true,
14
+ ignored: /(^|[\/\\])\../,
15
+ awaitWriteFinish: { stabilityThreshold: 500, pollInterval: 100 }
16
+ }
17
+
18
+ const settingWatcher = chokidar.watch(['./bunker/config.js'], options)
19
+ const fileWatcher = chokidar.watch(units.map(unit => `./bunker/${unit.station}`), options)
20
+
21
+ acp.yorha.operator6O.report(acp.dialog.operator6O.call2B)
22
+
23
+ fileWatcher.on('add', filePath => {
24
+ const unit = acp.logistics.foundation.findUnit(units, filePath)
25
+ if (unit) {
26
+ dispatcher.add(() => unit.handle(filePath))
27
+ }
28
+ })
29
+
30
+ settingWatcher.on('change', file => {
31
+ if (file.endsWith('config.js')) {
32
+ bunker.reboot()
33
+ }
34
+ })
35
+
36
+ }
@@ -1,13 +1,13 @@
1
1
  const fs = require('fs')
2
2
  const path = require('path')
3
3
 
4
- module.exports = async ({ llm, utils, yorha, dialog }) => {
4
+ module.exports = async ({ llm, yorha, dialog, logistics }) => {
5
5
 
6
6
  const { apiParser } = llm
7
7
  const { pod153, commander } = yorha
8
- const { contextStringify } = utils.generator
9
- const { apiDoc, pagesDir } = utils.foundation.getConfig()
10
- const { getLocalScore, getSemanticKeywords } = utils.semantic
8
+ const { contextStringify } = logistics.generator
9
+ const { apiDoc, pagesDir } = logistics.foundation.getConfig()
10
+ const { getLocalScore, getSemanticKeywords } = logistics.semantic
11
11
 
12
12
  if (!apiDoc) return
13
13
 
package/src/labs/index.js CHANGED
@@ -2,7 +2,7 @@ module.exports = accessPoint => {
2
2
 
3
3
  const labs = {}
4
4
 
5
- const { apiDoc, remains, needMock, proxyTarget, enableAutoAlignment } = accessPoint.utils.foundation.getConfig()
5
+ const { apiDoc, remains, needMock, proxyTarget, enableAutoAlignment } = accessPoint.logistics.foundation.getConfig()
6
6
 
7
7
  if (!needMock && proxyTarget && enableAutoAlignment) {
8
8
  labs.tower = require('../labs/tower')(accessPoint)
package/src/labs/tower.js CHANGED
@@ -1,17 +1,12 @@
1
- /**
2
- * @function startProxyTower
3
- * @description [地堡 42153 联合波段] 启动流量拦截塔。
4
- * 独立运行于后台,监听 42153 端口,物理截获联调过程中的 JSON 信号并触发语义对齐。
5
- */
6
- module.exports = ({ utils, yorha, dialog, handlers }) => {
1
+ module.exports = ({ units, yorha, dialog, logistics }) => {
7
2
 
8
3
  const http = require('http')
9
4
  const zlib = require('zlib')
10
5
  const httpProxy = require('http-proxy')
11
6
 
12
7
  const { pod153, commander } = yorha
13
- const { unwrapSignal, isQuerySignal } = utils.semantic
14
- const { routeMap = {}, proxyTarget } = utils.foundation.getConfig()
8
+ const { unwrapSignal, isQuerySignal } = logistics.semantic
9
+ const { routeMap = {}, proxyTarget } = logistics.foundation.getConfig()
15
10
 
16
11
  const TOWER_PORT = 42153
17
12
  const hackedRegistry = new Map()
@@ -55,7 +50,7 @@ module.exports = ({ utils, yorha, dialog, handlers }) => {
55
50
 
56
51
  pod153.report(dialog.pod153.capturedRuntimeSignal(fileName))
57
52
  // 💡 直接调用 response-handler 物理更新 resource.js
58
- await handlers.response.handle(null, { fileName, data: json })
53
+ await units.response.handle(null, { fileName, data: json })
59
54
  hackedRegistry.set(fileName, fingerprint)
60
55
  } catch (e) {
61
56
  // 非 JSON 信号,保持静默
@@ -12,10 +12,10 @@ const getConfig = () => {
12
12
  return config
13
13
  }
14
14
 
15
- const findRoute = (routes, filePath) => {
15
+ const findUnit = (units, filePath) => {
16
16
  const relative = path.relative(path.resolve('bunker'), path.resolve(filePath))
17
17
  const root = relative.split(path.sep)[0]
18
- return routes.find(route => root === route.watch)
18
+ return units.find(unit => root === unit.station)
19
19
  }
20
20
 
21
21
  const getExistingMenus = (dir = 'src/pages') => {
@@ -41,8 +41,8 @@ const copyTemplateDir = (template, templateSubDir, targetSubDir) => {
41
41
  }
42
42
 
43
43
  module.exports = {
44
+ findUnit,
44
45
  getConfig,
45
- findRoute,
46
46
  copyTemplateDir,
47
47
  getExistingMenus,
48
48
  }
@@ -68,10 +68,10 @@ const bootSequence = async (version, local) => {
68
68
  const matrixEffect = async (duration = 1500, dialog, result) => {
69
69
 
70
70
  let currentTotal = 0
71
- const MIRROR_URL = 'https://cdn.jsdelivr.net/gh/yorha2b-lab/auto-crud-copilot@github-repo-stats/bunker-stats.json'
71
+ const MIRROR_URL = 'https://cdn.jsdelivr.net/gh/yorha2b-lab/autodev@github-repo-stats/bunker-stats.json'
72
72
 
73
73
  try {
74
- if (result.utils.foundation.getConfig().fetchClone) {
74
+ if (result.logistics.foundation.getConfig().fetchClone) {
75
75
  const controller = new AbortController()
76
76
  const timeoutId = setTimeout(() => controller.abort(), 800)
77
77
  const response = await fetch(MIRROR_URL, { signal: controller.signal })
@@ -138,6 +138,7 @@ const matrixEffect = async (duration = 1500, dialog, result) => {
138
138
  }
139
139
 
140
140
  module.exports = {
141
+ sleep,
141
142
  yorha,
142
143
  matchDialog,
143
144
  bootSequence,