feihong-code 7.2.0 → 7.5.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/workflows/ci.yml +180 -140
- package/.github/workflows/release.yml +200 -173
- package/CHANGELOG.md +94 -115
- package/README.md +609 -586
- package/dist/agent/completion-engine.js +76 -45
- package/dist/agent/completion-engine.js.map +1 -1
- package/dist/agent/completion-postprocess.js +109 -0
- package/dist/agent/completion-postprocess.js.map +1 -0
- package/dist/agent/context-budget.js +121 -0
- package/dist/agent/context-budget.js.map +1 -0
- package/dist/agent/context-compactor.js +47 -0
- package/dist/agent/context-compactor.js.map +1 -1
- package/dist/agent/custom-agent.js +52 -52
- package/dist/agent/design-to-code.js +40 -40
- package/dist/agent/lint.js +121 -0
- package/dist/agent/lint.js.map +1 -0
- package/dist/agent/multi-agent.js +44 -44
- package/dist/agent/orchestrator.js +20 -20
- package/dist/agent/prompts.js +54 -54
- package/dist/agent/self-correction.js +24 -24
- package/dist/agent/self-heal.js +27 -27
- package/dist/cli/commands.js +9 -0
- package/dist/cli/commands.js.map +1 -1
- package/dist/cli/index.js +9 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/multi-pane-tui.js +217 -0
- package/dist/cli/multi-pane-tui.js.map +1 -0
- package/dist/cli/run.js +129 -40
- package/dist/cli/run.js.map +1 -1
- package/dist/cli/tui-run.js +79 -0
- package/dist/cli/tui-run.js.map +1 -0
- package/dist/cli/tui.js.map +1 -1
- package/dist/cli/version.js +1 -1
- package/dist/lsp/lsp-client.js +183 -0
- package/dist/lsp/lsp-client.js.map +1 -0
- package/dist/lsp/lsp-service.js +159 -0
- package/dist/lsp/lsp-service.js.map +1 -0
- package/dist/plugins/manager.js +50 -2
- package/dist/plugins/manager.js.map +1 -1
- package/dist/shared/i18n.js +108 -100
- package/dist/shared/i18n.js.map +1 -1
- package/dist/tools/generator/code-generator.js +40 -40
- package/dist/tools/generator/test-generator.js +9 -9
- package/dist/tools/shell/exec.js +23 -1
- package/dist/tools/shell/exec.js.map +1 -1
- package/dist/web/extra-apis.js +440 -0
- package/dist/web/extra-apis.js.map +1 -0
- package/dist/web/public/css/style.css +1715 -1715
- package/dist/web/public/index.html +1242 -1200
- package/dist/web/public/js/api.js +555 -496
- package/dist/web/public/js/app.js +2210 -2210
- package/dist/web/public/js/mock-api.js +234 -234
- package/dist/web/public/js/monaco-editor.js +363 -203
- package/dist/web/public/js/ui.js +2251 -1981
- package/dist/web/public/js/utils.js +214 -214
- package/dist/web/public/manifest.json +59 -59
- package/dist/web/public/service-worker.js +173 -173
- package/dist/web/server.js +97 -45
- package/dist/web/server.js.map +1 -1
- package/docs/BENCHMARK_REPORT_en.md +386 -329
- package/docs/BENCHMARK_REPORT_zh.md +386 -329
- package/docs/DPA.md +63 -0
- package/docs/DPA/346/225/260/346/215/256/345/244/204/347/220/206/345/215/217/350/256/256/346/250/241/346/235/277_v1.0.md +67 -0
- package/docs/SECURITY_WHITEPAPER.md +74 -0
- package/docs/SWE_BENCH_REPORT.md +55 -0
- package/docs/TECHNICAL_SPEC_en.md +292 -292
- package/docs/TECHNICAL_SPEC_zh.md +292 -292
- package/docs/UPDATE_NOTES_en.md +159 -159
- package/docs/UPDATE_NOTES_zh.md +159 -159
- package/docs/UPGRADE_7.2.0.md +309 -0
- package/docs/UPGRADE_GUIDE_7_5.md +86 -0
- package/docs/geo-feihong-code.html +391 -0
- package/docs//345/205/250/351/235/242/345/244/215/347/233/230_50/350/275/256/346/267/261/345/272/246/345/256/241/350/256/241_v7.2.0.md +208 -0
- package/docs//345/205/250/351/235/242/345/244/215/347/233/230_6/351/241/271/351/207/215/347/202/271/346/240/270/346/237/245_v7.2.0.md +152 -0
- package/docs//345/205/250/351/235/242/345/244/215/347/233/230_/350/277/220/350/241/214/346/227/266/345/256/236/346/265/213/347/211/210_v7.2.0.md +271 -0
- package/docs//345/220/210/350/247/204/350/256/244/350/257/201/345/207/206/345/244/207/346/270/205/345/215/225_v7.2.0.md +59 -0
- package/docs//345/256/211/345/205/250/347/231/275/347/232/256/344/271/246_v7.2.0.md +82 -0
- package/electron/main.js +404 -602
- package/package.json +175 -172
- package/templates/skills/api-design/SKILL.md +27 -0
- package/templates/skills/code-review/SKILL.md +35 -0
- package/templates/skills/dependency-upgrade/SKILL.md +29 -0
- package/templates/skills/doc-gen/SKILL.md +29 -0
- package/templates/skills/git-flow/SKILL.md +26 -0
- package/templates/skills/onboarding/SKILL.md +27 -0
- package/templates/skills/performance/SKILL.md +29 -0
- package/templates/skills/refactor/SKILL.md +28 -0
- package/templates/skills/security-audit/SKILL.md +28 -0
- package/templates/skills/test-gen/SKILL.md +30 -0
- package/tool-schema.json +197 -197
- package/dist/hello.js +0 -14
- package/dist/hello.js.map +0 -1
- package/dist/self-evolve/hook.ts +0 -80
- package/dist/self-evolve/manager.d.ts +0 -8
- package/dist/web/public/vendor/monaco/vs/abap-D-t0cyap.js +0 -1
- package/dist/web/public/vendor/monaco/vs/apex-CcIm7xu6.js +0 -1
- package/dist/web/public/vendor/monaco/vs/assets/css.worker-URu8fCFR.js +0 -97
- package/dist/web/public/vendor/monaco/vs/assets/editor.worker-lj3bdIIn.js +0 -30
- package/dist/web/public/vendor/monaco/vs/assets/editorWebWorkerMain-CA_vMoUU.js +0 -30
- package/dist/web/public/vendor/monaco/vs/assets/html.worker-D1SL3iM8.js +0 -474
- package/dist/web/public/vendor/monaco/vs/assets/json.worker-CoJx_OPf.js +0 -62
- package/dist/web/public/vendor/monaco/vs/assets/ts.worker-BWKtMYOk.js +0 -67722
- package/dist/web/public/vendor/monaco/vs/azcli-BA0tQDCg.js +0 -1
- package/dist/web/public/vendor/monaco/vs/basic-languages/monaco.contribution.js +0 -1
- package/dist/web/public/vendor/monaco/vs/bat-C397hTD6.js +0 -1
- package/dist/web/public/vendor/monaco/vs/bicep-DF5aW17k.js +0 -2
- package/dist/web/public/vendor/monaco/vs/cameligo-plsz8qhj.js +0 -1
- package/dist/web/public/vendor/monaco/vs/clojure-Y2auQMzK.js +0 -1
- package/dist/web/public/vendor/monaco/vs/coffee-Bu45yuWE.js +0 -1
- package/dist/web/public/vendor/monaco/vs/cpp-CkKPQIni.js +0 -1
- package/dist/web/public/vendor/monaco/vs/csharp-CX28MZyh.js +0 -1
- package/dist/web/public/vendor/monaco/vs/csp-D8uWnyxW.js +0 -1
- package/dist/web/public/vendor/monaco/vs/css-CaeNmE3S.js +0 -3
- package/dist/web/public/vendor/monaco/vs/css.worker-CyhWkhHo.js +0 -1
- package/dist/web/public/vendor/monaco/vs/cssMode-CV6Ay48H.js +0 -1
- package/dist/web/public/vendor/monaco/vs/cypher-DVThT8BS.js +0 -1
- package/dist/web/public/vendor/monaco/vs/dart-CmGfCvrO.js +0 -1
- package/dist/web/public/vendor/monaco/vs/dockerfile-CZqqYdch.js +0 -1
- package/dist/web/public/vendor/monaco/vs/ecl-30fUercY.js +0 -1
- package/dist/web/public/vendor/monaco/vs/editor/editor.main.css +0 -1
- package/dist/web/public/vendor/monaco/vs/editor/editor.main.js +0 -1
- package/dist/web/public/vendor/monaco/vs/editor/editor.worker.js +0 -1
- package/dist/web/public/vendor/monaco/vs/editor-KLE6jdfb.js +0 -831
- package/dist/web/public/vendor/monaco/vs/editor.js +0 -1
- package/dist/web/public/vendor/monaco/vs/editorWorkerHost-fVE1cjcC.js +0 -35
- package/dist/web/public/vendor/monaco/vs/elixir-xjPaIfzF.js +0 -1
- package/dist/web/public/vendor/monaco/vs/flow9-DqtmStfK.js +0 -1
- package/dist/web/public/vendor/monaco/vs/freemarker2-FWreY7v7.js +0 -3
- package/dist/web/public/vendor/monaco/vs/fsharp-BOMdg4U1.js +0 -1
- package/dist/web/public/vendor/monaco/vs/go-D_hbi-Jt.js +0 -1
- package/dist/web/public/vendor/monaco/vs/graphql-CKUU4kLG.js +0 -1
- package/dist/web/public/vendor/monaco/vs/handlebars-CZi4pHCH.js +0 -1
- package/dist/web/public/vendor/monaco/vs/hcl-DTaboeZW.js +0 -1
- package/dist/web/public/vendor/monaco/vs/html-j_7ZTNRU.js +0 -1
- package/dist/web/public/vendor/monaco/vs/html.worker-CA3iAimZ.js +0 -1
- package/dist/web/public/vendor/monaco/vs/htmlMode-27by_KM4.js +0 -1
- package/dist/web/public/vendor/monaco/vs/index-049xrXrp.js +0 -1
- package/dist/web/public/vendor/monaco/vs/index-CBVt3dzv.js +0 -5
- package/dist/web/public/vendor/monaco/vs/index.js +0 -1
- package/dist/web/public/vendor/monaco/vs/ini-CsNwO04R.js +0 -1
- package/dist/web/public/vendor/monaco/vs/initialize-DL0l1TGY.js +0 -1
- package/dist/web/public/vendor/monaco/vs/java-CI4ZMsH9.js +0 -1
- package/dist/web/public/vendor/monaco/vs/javascript-DTJl4Jn1.js +0 -1
- package/dist/web/public/vendor/monaco/vs/json.worker-BizpAl9O.js +0 -1
- package/dist/web/public/vendor/monaco/vs/jsonMode-DLUiMUrI.js +0 -1
- package/dist/web/public/vendor/monaco/vs/julia-BwzEvaQw.js +0 -1
- package/dist/web/public/vendor/monaco/vs/kotlin-IUYPiTV8.js +0 -1
- package/dist/web/public/vendor/monaco/vs/language/css/css.worker.js +0 -66
- package/dist/web/public/vendor/monaco/vs/language/css/monaco.contribution.js +0 -1
- package/dist/web/public/vendor/monaco/vs/language/html/html.worker.js +0 -443
- package/dist/web/public/vendor/monaco/vs/language/html/monaco.contribution.js +0 -1
- package/dist/web/public/vendor/monaco/vs/language/json/json.worker.js +0 -17
- package/dist/web/public/vendor/monaco/vs/language/json/monaco.contribution.js +0 -1
- package/dist/web/public/vendor/monaco/vs/language/typescript/monaco.contribution.js +0 -1
- package/dist/web/public/vendor/monaco/vs/language/typescript/ts.worker.js +0 -67693
- package/dist/web/public/vendor/monaco/vs/less-C0eDYdqa.js +0 -2
- package/dist/web/public/vendor/monaco/vs/lexon-iON-Kj97.js +0 -1
- package/dist/web/public/vendor/monaco/vs/liquid-CLJYelW6.js +0 -1
- package/dist/web/public/vendor/monaco/vs/loader.js +0 -1368
- package/dist/web/public/vendor/monaco/vs/lspLanguageFeatures-BIkJOWLw.js +0 -2
- package/dist/web/public/vendor/monaco/vs/lua-DtygF91M.js +0 -1
- package/dist/web/public/vendor/monaco/vs/m3-CsR4AuFi.js +0 -1
- package/dist/web/public/vendor/monaco/vs/main-BEx-Fmlo.js +0 -15
- package/dist/web/public/vendor/monaco/vs/main-DsK8pnKg.js +0 -3
- package/dist/web/public/vendor/monaco/vs/markdown-C_rD0bIw.js +0 -1
- package/dist/web/public/vendor/monaco/vs/mdx-CpzZIPHF.js +0 -1
- package/dist/web/public/vendor/monaco/vs/mips-CiYP61RB.js +0 -1
- package/dist/web/public/vendor/monaco/vs/monaco.contribution-9cKT3C7t.js +0 -1
- package/dist/web/public/vendor/monaco/vs/monaco.contribution-BE88ZNGY.js +0 -1
- package/dist/web/public/vendor/monaco/vs/monaco.contribution-BPhsneLd.js +0 -1
- package/dist/web/public/vendor/monaco/vs/monaco.contribution-BgRy6xDf.js +0 -1
- package/dist/web/public/vendor/monaco/vs/msdax-C38-sJlp.js +0 -1
- package/dist/web/public/vendor/monaco/vs/mysql-CdtbpvbG.js +0 -1
- package/dist/web/public/vendor/monaco/vs/nls/lang/cs.d.ts +0 -1
- package/dist/web/public/vendor/monaco/vs/nls/lang/cs.js +0 -9
- package/dist/web/public/vendor/monaco/vs/nls/lang/de.d.ts +0 -1
- package/dist/web/public/vendor/monaco/vs/nls/lang/de.js +0 -9
- package/dist/web/public/vendor/monaco/vs/nls/lang/es.d.ts +0 -1
- package/dist/web/public/vendor/monaco/vs/nls/lang/es.js +0 -9
- package/dist/web/public/vendor/monaco/vs/nls/lang/fr.d.ts +0 -1
- package/dist/web/public/vendor/monaco/vs/nls/lang/fr.js +0 -9
- package/dist/web/public/vendor/monaco/vs/nls/lang/it.d.ts +0 -1
- package/dist/web/public/vendor/monaco/vs/nls/lang/it.js +0 -9
- package/dist/web/public/vendor/monaco/vs/nls/lang/ja.d.ts +0 -1
- package/dist/web/public/vendor/monaco/vs/nls/lang/ja.js +0 -9
- package/dist/web/public/vendor/monaco/vs/nls/lang/ko.d.ts +0 -1
- package/dist/web/public/vendor/monaco/vs/nls/lang/ko.js +0 -9
- package/dist/web/public/vendor/monaco/vs/nls/lang/pl.d.ts +0 -1
- package/dist/web/public/vendor/monaco/vs/nls/lang/pl.js +0 -9
- package/dist/web/public/vendor/monaco/vs/nls/lang/pt-br.d.ts +0 -1
- package/dist/web/public/vendor/monaco/vs/nls/lang/pt-br.js +0 -9
- package/dist/web/public/vendor/monaco/vs/nls/lang/ru.d.ts +0 -1
- package/dist/web/public/vendor/monaco/vs/nls/lang/ru.js +0 -9
- package/dist/web/public/vendor/monaco/vs/nls/lang/tr.d.ts +0 -1
- package/dist/web/public/vendor/monaco/vs/nls/lang/tr.js +0 -9
- package/dist/web/public/vendor/monaco/vs/nls/lang/zh-cn.d.ts +0 -1
- package/dist/web/public/vendor/monaco/vs/nls/lang/zh-cn.js +0 -9
- package/dist/web/public/vendor/monaco/vs/nls/lang/zh-tw.d.ts +0 -1
- package/dist/web/public/vendor/monaco/vs/nls/lang/zh-tw.js +0 -9
- package/dist/web/public/vendor/monaco/vs/nls.messages-loader.js +0 -1
- package/dist/web/public/vendor/monaco/vs/objective-c-CntZFaHX.js +0 -1
- package/dist/web/public/vendor/monaco/vs/pascal-r6kuqfl_.js +0 -1
- package/dist/web/public/vendor/monaco/vs/pascaligo-BiXoTmXh.js +0 -1
- package/dist/web/public/vendor/monaco/vs/perl-DABw_TcH.js +0 -1
- package/dist/web/public/vendor/monaco/vs/pgsql-me_jFXeX.js +0 -1
- package/dist/web/public/vendor/monaco/vs/php-D_kh-9LK.js +0 -1
- package/dist/web/public/vendor/monaco/vs/pla-VfZjczW0.js +0 -1
- package/dist/web/public/vendor/monaco/vs/postiats-BBSzz8Pk.js +0 -1
- package/dist/web/public/vendor/monaco/vs/powerquery-Dt-g_2cc.js +0 -1
- package/dist/web/public/vendor/monaco/vs/powershell-B-7ap1zc.js +0 -1
- package/dist/web/public/vendor/monaco/vs/protobuf-BmtuEB1A.js +0 -2
- package/dist/web/public/vendor/monaco/vs/pug-BRpRNeEb.js +0 -1
- package/dist/web/public/vendor/monaco/vs/python-CqWUUgfu.js +0 -1
- package/dist/web/public/vendor/monaco/vs/qsharp-BzsFaUU9.js +0 -1
- package/dist/web/public/vendor/monaco/vs/r-f8dDdrp4.js +0 -1
- package/dist/web/public/vendor/monaco/vs/razor-hok5y9Km.js +0 -1
- package/dist/web/public/vendor/monaco/vs/redis-fvZQY4PI.js +0 -1
- package/dist/web/public/vendor/monaco/vs/redshift-45Et0LQi.js +0 -1
- package/dist/web/public/vendor/monaco/vs/restructuredtext-C7UUFKFD.js +0 -1
- package/dist/web/public/vendor/monaco/vs/ruby-CZO8zYTz.js +0 -1
- package/dist/web/public/vendor/monaco/vs/rust-Bfetafyc.js +0 -1
- package/dist/web/public/vendor/monaco/vs/sb-3GYllVck.js +0 -1
- package/dist/web/public/vendor/monaco/vs/scala-foMgrKo1.js +0 -1
- package/dist/web/public/vendor/monaco/vs/scheme-CHdMtr7p.js +0 -1
- package/dist/web/public/vendor/monaco/vs/scss-C1cmLt9V.js +0 -3
- package/dist/web/public/vendor/monaco/vs/shell-ClXCKCEW.js +0 -1
- package/dist/web/public/vendor/monaco/vs/solidity-MZ6ExpPy.js +0 -1
- package/dist/web/public/vendor/monaco/vs/sophia-DWkuSsPQ.js +0 -1
- package/dist/web/public/vendor/monaco/vs/sparql-AUGFYSyk.js +0 -1
- package/dist/web/public/vendor/monaco/vs/sql-32GpJSV2.js +0 -1
- package/dist/web/public/vendor/monaco/vs/st-CuDFIVZ_.js +0 -1
- package/dist/web/public/vendor/monaco/vs/swift-t-PfMj7W.js +0 -1
- package/dist/web/public/vendor/monaco/vs/systemverilog-Ch4vA8Yt.js +0 -1
- package/dist/web/public/vendor/monaco/vs/tcl-D74tq1nH.js +0 -1
- package/dist/web/public/vendor/monaco/vs/toggleHighContrast-qGX7E9o7.js +0 -61
- package/dist/web/public/vendor/monaco/vs/ts.worker-2QLmBukE.js +0 -1
- package/dist/web/public/vendor/monaco/vs/tsMode-B0S_kp2q.js +0 -11
- package/dist/web/public/vendor/monaco/vs/twig-C6taOxMV.js +0 -1
- package/dist/web/public/vendor/monaco/vs/typescript-_2t_511t.js +0 -1
- package/dist/web/public/vendor/monaco/vs/typespec-8OfoLt6R.js +0 -1
- package/dist/web/public/vendor/monaco/vs/vb-Dyb2648j.js +0 -1
- package/dist/web/public/vendor/monaco/vs/wgsl-BhLXMOR0.js +0 -298
- package/dist/web/public/vendor/monaco/vs/workers-BBttULjf.js +0 -1
- package/dist/web/public/vendor/monaco/vs/xml-cZjNDqDT.js +0 -1
- package/dist/web/public/vendor/monaco/vs/yaml-A1fOIdH6.js +0 -1
- package/dist/web/web-config.js +0 -143
- package/dist/web/web-config.js.map +0 -1
- package/docs/DEPLOYMENT.md +0 -382
- package/docs/MODEL_FINETUNING.md +0 -405
|
@@ -1,173 +1,173 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 飞虹 Code Service Worker
|
|
3
|
-
* 支持离线缓存、PWA 安装、移动端适配
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
const CACHE_NAME = 'feihong-code-v1';
|
|
7
|
-
const STATIC_CACHE = 'feihong-static-v1';
|
|
8
|
-
const RUNTIME_CACHE = 'feihong-runtime-v1';
|
|
9
|
-
|
|
10
|
-
// 静态资源缓存列表
|
|
11
|
-
const STATIC_ASSETS = [
|
|
12
|
-
'/',
|
|
13
|
-
'/index.html',
|
|
14
|
-
'/manifest.json',
|
|
15
|
-
'/css/style.css',
|
|
16
|
-
'/js/app.js',
|
|
17
|
-
'/js/ui.js',
|
|
18
|
-
'/js/api.js',
|
|
19
|
-
'/js/utils.js',
|
|
20
|
-
'/js/monaco-editor.js',
|
|
21
|
-
];
|
|
22
|
-
|
|
23
|
-
// 安装事件:预缓存静态资源
|
|
24
|
-
self.addEventListener('install', (event) => {
|
|
25
|
-
console.log('[SW] Installing...');
|
|
26
|
-
event.waitUntil(
|
|
27
|
-
caches.open(STATIC_CACHE).then((cache) => {
|
|
28
|
-
console.log('[SW] Pre-caching static assets');
|
|
29
|
-
return cache.addAll(STATIC_ASSETS).catch((err) => {
|
|
30
|
-
console.warn('[SW] Pre-cache failed:', err);
|
|
31
|
-
});
|
|
32
|
-
}).then(() => self.skipWaiting())
|
|
33
|
-
);
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
// 激活事件:清理旧缓存
|
|
37
|
-
self.addEventListener('activate', (event) => {
|
|
38
|
-
console.log('[SW] Activating...');
|
|
39
|
-
event.waitUntil(
|
|
40
|
-
caches.keys().then((cacheNames) => {
|
|
41
|
-
return Promise.all(
|
|
42
|
-
cacheNames
|
|
43
|
-
.filter((name) => name !== STATIC_CACHE && name !== RUNTIME_CACHE)
|
|
44
|
-
.map((name) => {
|
|
45
|
-
console.log('[SW] Deleting old cache:', name);
|
|
46
|
-
return caches.delete(name);
|
|
47
|
-
})
|
|
48
|
-
);
|
|
49
|
-
}).then(() => self.clients.claim())
|
|
50
|
-
);
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
// fetch 事件:缓存策略
|
|
54
|
-
self.addEventListener('fetch', (event) => {
|
|
55
|
-
const { request } = event;
|
|
56
|
-
const url = new URL(request.url);
|
|
57
|
-
|
|
58
|
-
// 只缓存同源请求
|
|
59
|
-
if (url.origin !== self.location.origin) {
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// API 请求:网络优先,失败时回退到缓存
|
|
64
|
-
if (url.pathname.startsWith('/api/')) {
|
|
65
|
-
event.respondWith(
|
|
66
|
-
fetch(request)
|
|
67
|
-
.then((response) => {
|
|
68
|
-
// 缓存成功的 API 响应
|
|
69
|
-
if (response.status === 200) {
|
|
70
|
-
const clone = response.clone();
|
|
71
|
-
caches.open(RUNTIME_CACHE).then((cache) => cache.put(request, clone));
|
|
72
|
-
}
|
|
73
|
-
return response;
|
|
74
|
-
})
|
|
75
|
-
.catch(() => {
|
|
76
|
-
return caches.match(request).then((cached) => {
|
|
77
|
-
if (cached) return cached;
|
|
78
|
-
// 返回离线错误
|
|
79
|
-
return new Response(JSON.stringify({
|
|
80
|
-
ok: false,
|
|
81
|
-
error: '网络连接失败,显示离线数据',
|
|
82
|
-
offline: true,
|
|
83
|
-
}), {
|
|
84
|
-
status: 503,
|
|
85
|
-
headers: { 'Content-Type': 'application/json' },
|
|
86
|
-
});
|
|
87
|
-
});
|
|
88
|
-
})
|
|
89
|
-
);
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// 静态资源:缓存优先,失败时回退到网络
|
|
94
|
-
if (request.method === 'GET') {
|
|
95
|
-
event.respondWith(
|
|
96
|
-
caches.match(request).then((cached) => {
|
|
97
|
-
if (cached) return cached;
|
|
98
|
-
return fetch(request).then((response) => {
|
|
99
|
-
if (response.status === 200) {
|
|
100
|
-
const clone = response.clone();
|
|
101
|
-
caches.open(RUNTIME_CACHE).then((cache) => cache.put(request, clone));
|
|
102
|
-
}
|
|
103
|
-
return response;
|
|
104
|
-
}).catch(() => {
|
|
105
|
-
// 对于 HTML 请求,返回离线页面
|
|
106
|
-
if (request.headers.get('accept')?.includes('text/html')) {
|
|
107
|
-
return caches.match('/index.html');
|
|
108
|
-
}
|
|
109
|
-
return new Response('Offline', { status: 503 });
|
|
110
|
-
});
|
|
111
|
-
})
|
|
112
|
-
);
|
|
113
|
-
}
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
// 消息事件:支持手动更新缓存
|
|
117
|
-
self.addEventListener('message', (event) => {
|
|
118
|
-
const { type } = event.data || {};
|
|
119
|
-
|
|
120
|
-
if (type === 'SKIP_WAITING') {
|
|
121
|
-
self.skipWaiting();
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
if (type === 'CLEAR_CACHE') {
|
|
125
|
-
caches.keys().then((names) => {
|
|
126
|
-
names.forEach((name) => caches.delete(name));
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
if (type === 'GET_VERSION') {
|
|
131
|
-
event.source.postMessage({
|
|
132
|
-
type: 'VERSION',
|
|
133
|
-
version: CACHE_NAME,
|
|
134
|
-
staticCache: STATIC_CACHE,
|
|
135
|
-
runtimeCache: RUNTIME_CACHE,
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
// 推送通知(预留)
|
|
141
|
-
self.addEventListener('push', (event) => {
|
|
142
|
-
if (event.data) {
|
|
143
|
-
const data = event.data.json();
|
|
144
|
-
const title = data.title || '飞虹 Code';
|
|
145
|
-
const options = {
|
|
146
|
-
body: data.body || '',
|
|
147
|
-
icon: '/icons/icon-192.png',
|
|
148
|
-
badge: '/icons/icon-192.png',
|
|
149
|
-
data: data.data || {},
|
|
150
|
-
};
|
|
151
|
-
event.waitUntil(self.registration.showNotification(title, options));
|
|
152
|
-
}
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
// 通知点击
|
|
156
|
-
self.addEventListener('notificationclick', (event) => {
|
|
157
|
-
event.notification.close();
|
|
158
|
-
const url = event.notification.data?.url || '/';
|
|
159
|
-
event.waitUntil(
|
|
160
|
-
clients.openWindow(url).catch(() => {
|
|
161
|
-
return clients.matchAll({ type: 'window' }).then((clientList) => {
|
|
162
|
-
for (const client of clientList) {
|
|
163
|
-
if (client.url === url && 'focus' in client) {
|
|
164
|
-
return client.focus();
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
if (clients.openWindow) return clients.openWindow(url);
|
|
168
|
-
});
|
|
169
|
-
})
|
|
170
|
-
);
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
console.log('[SW] Service Worker loaded');
|
|
1
|
+
/**
|
|
2
|
+
* 飞虹 Code Service Worker
|
|
3
|
+
* 支持离线缓存、PWA 安装、移动端适配
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const CACHE_NAME = 'feihong-code-v1';
|
|
7
|
+
const STATIC_CACHE = 'feihong-static-v1';
|
|
8
|
+
const RUNTIME_CACHE = 'feihong-runtime-v1';
|
|
9
|
+
|
|
10
|
+
// 静态资源缓存列表
|
|
11
|
+
const STATIC_ASSETS = [
|
|
12
|
+
'/',
|
|
13
|
+
'/index.html',
|
|
14
|
+
'/manifest.json',
|
|
15
|
+
'/css/style.css',
|
|
16
|
+
'/js/app.js',
|
|
17
|
+
'/js/ui.js',
|
|
18
|
+
'/js/api.js',
|
|
19
|
+
'/js/utils.js',
|
|
20
|
+
'/js/monaco-editor.js',
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
// 安装事件:预缓存静态资源
|
|
24
|
+
self.addEventListener('install', (event) => {
|
|
25
|
+
console.log('[SW] Installing...');
|
|
26
|
+
event.waitUntil(
|
|
27
|
+
caches.open(STATIC_CACHE).then((cache) => {
|
|
28
|
+
console.log('[SW] Pre-caching static assets');
|
|
29
|
+
return cache.addAll(STATIC_ASSETS).catch((err) => {
|
|
30
|
+
console.warn('[SW] Pre-cache failed:', err);
|
|
31
|
+
});
|
|
32
|
+
}).then(() => self.skipWaiting())
|
|
33
|
+
);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
// 激活事件:清理旧缓存
|
|
37
|
+
self.addEventListener('activate', (event) => {
|
|
38
|
+
console.log('[SW] Activating...');
|
|
39
|
+
event.waitUntil(
|
|
40
|
+
caches.keys().then((cacheNames) => {
|
|
41
|
+
return Promise.all(
|
|
42
|
+
cacheNames
|
|
43
|
+
.filter((name) => name !== STATIC_CACHE && name !== RUNTIME_CACHE)
|
|
44
|
+
.map((name) => {
|
|
45
|
+
console.log('[SW] Deleting old cache:', name);
|
|
46
|
+
return caches.delete(name);
|
|
47
|
+
})
|
|
48
|
+
);
|
|
49
|
+
}).then(() => self.clients.claim())
|
|
50
|
+
);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// fetch 事件:缓存策略
|
|
54
|
+
self.addEventListener('fetch', (event) => {
|
|
55
|
+
const { request } = event;
|
|
56
|
+
const url = new URL(request.url);
|
|
57
|
+
|
|
58
|
+
// 只缓存同源请求
|
|
59
|
+
if (url.origin !== self.location.origin) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// API 请求:网络优先,失败时回退到缓存
|
|
64
|
+
if (url.pathname.startsWith('/api/')) {
|
|
65
|
+
event.respondWith(
|
|
66
|
+
fetch(request)
|
|
67
|
+
.then((response) => {
|
|
68
|
+
// 缓存成功的 API 响应
|
|
69
|
+
if (response.status === 200) {
|
|
70
|
+
const clone = response.clone();
|
|
71
|
+
caches.open(RUNTIME_CACHE).then((cache) => cache.put(request, clone));
|
|
72
|
+
}
|
|
73
|
+
return response;
|
|
74
|
+
})
|
|
75
|
+
.catch(() => {
|
|
76
|
+
return caches.match(request).then((cached) => {
|
|
77
|
+
if (cached) return cached;
|
|
78
|
+
// 返回离线错误
|
|
79
|
+
return new Response(JSON.stringify({
|
|
80
|
+
ok: false,
|
|
81
|
+
error: '网络连接失败,显示离线数据',
|
|
82
|
+
offline: true,
|
|
83
|
+
}), {
|
|
84
|
+
status: 503,
|
|
85
|
+
headers: { 'Content-Type': 'application/json' },
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
})
|
|
89
|
+
);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// 静态资源:缓存优先,失败时回退到网络
|
|
94
|
+
if (request.method === 'GET') {
|
|
95
|
+
event.respondWith(
|
|
96
|
+
caches.match(request).then((cached) => {
|
|
97
|
+
if (cached) return cached;
|
|
98
|
+
return fetch(request).then((response) => {
|
|
99
|
+
if (response.status === 200) {
|
|
100
|
+
const clone = response.clone();
|
|
101
|
+
caches.open(RUNTIME_CACHE).then((cache) => cache.put(request, clone));
|
|
102
|
+
}
|
|
103
|
+
return response;
|
|
104
|
+
}).catch(() => {
|
|
105
|
+
// 对于 HTML 请求,返回离线页面
|
|
106
|
+
if (request.headers.get('accept')?.includes('text/html')) {
|
|
107
|
+
return caches.match('/index.html');
|
|
108
|
+
}
|
|
109
|
+
return new Response('Offline', { status: 503 });
|
|
110
|
+
});
|
|
111
|
+
})
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
// 消息事件:支持手动更新缓存
|
|
117
|
+
self.addEventListener('message', (event) => {
|
|
118
|
+
const { type } = event.data || {};
|
|
119
|
+
|
|
120
|
+
if (type === 'SKIP_WAITING') {
|
|
121
|
+
self.skipWaiting();
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (type === 'CLEAR_CACHE') {
|
|
125
|
+
caches.keys().then((names) => {
|
|
126
|
+
names.forEach((name) => caches.delete(name));
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (type === 'GET_VERSION') {
|
|
131
|
+
event.source.postMessage({
|
|
132
|
+
type: 'VERSION',
|
|
133
|
+
version: CACHE_NAME,
|
|
134
|
+
staticCache: STATIC_CACHE,
|
|
135
|
+
runtimeCache: RUNTIME_CACHE,
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
// 推送通知(预留)
|
|
141
|
+
self.addEventListener('push', (event) => {
|
|
142
|
+
if (event.data) {
|
|
143
|
+
const data = event.data.json();
|
|
144
|
+
const title = data.title || '飞虹 Code';
|
|
145
|
+
const options = {
|
|
146
|
+
body: data.body || '',
|
|
147
|
+
icon: '/icons/icon-192.png',
|
|
148
|
+
badge: '/icons/icon-192.png',
|
|
149
|
+
data: data.data || {},
|
|
150
|
+
};
|
|
151
|
+
event.waitUntil(self.registration.showNotification(title, options));
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
// 通知点击
|
|
156
|
+
self.addEventListener('notificationclick', (event) => {
|
|
157
|
+
event.notification.close();
|
|
158
|
+
const url = event.notification.data?.url || '/';
|
|
159
|
+
event.waitUntil(
|
|
160
|
+
clients.openWindow(url).catch(() => {
|
|
161
|
+
return clients.matchAll({ type: 'window' }).then((clientList) => {
|
|
162
|
+
for (const client of clientList) {
|
|
163
|
+
if (client.url === url && 'focus' in client) {
|
|
164
|
+
return client.focus();
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
if (clients.openWindow) return clients.openWindow(url);
|
|
168
|
+
});
|
|
169
|
+
})
|
|
170
|
+
);
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
console.log('[SW] Service Worker loaded');
|
package/dist/web/server.js
CHANGED
|
@@ -57,6 +57,7 @@ const path_1 = require("path");
|
|
|
57
57
|
const fs_1 = require("fs");
|
|
58
58
|
const child_process_1 = require("child_process");
|
|
59
59
|
const auth_1 = require("./auth");
|
|
60
|
+
const extra_apis_1 = require("./extra-apis");
|
|
60
61
|
const task_queue_1 = require("./task-queue");
|
|
61
62
|
const version_1 = require("../cli/version");
|
|
62
63
|
const i18n_1 = require("../shared/i18n");
|
|
@@ -65,6 +66,7 @@ const config_1 = require("../shared/config");
|
|
|
65
66
|
const model_router_1 = require("../models/model-router");
|
|
66
67
|
const openai_compatible_provider_1 = require("../models/providers/openai-compatible.provider");
|
|
67
68
|
const completion_engine_1 = require("../agent/completion-engine");
|
|
69
|
+
const lint_1 = require("../agent/lint");
|
|
68
70
|
const symbol_index_1 = require("../agent/symbol-index");
|
|
69
71
|
const change_manager_1 = require("../agent/change-manager");
|
|
70
72
|
const design_to_code_1 = require("../agent/design-to-code");
|
|
@@ -271,6 +273,9 @@ function startWebServer(opts = {}) {
|
|
|
271
273
|
res.json({ ok: true, history });
|
|
272
274
|
});
|
|
273
275
|
app.use('/api', (0, auth_1.requireToken)(token, sessions));
|
|
276
|
+
// ===== v7.2.0 能力接线层:voice / knowledge / figma / sso / collaboration / plugins / self-correction =====
|
|
277
|
+
// 将原"孤立代码"模块接入 Web API(修复:从 404 变为可调用)
|
|
278
|
+
(0, extra_apis_1.registerExtraApis)(app, { dataDir: (0, path_1.join)((0, config_1.resolveHomeDir)(), '.feihong-code') });
|
|
274
279
|
app.get('/api/auth/me', (req, res) => {
|
|
275
280
|
const session = req.user;
|
|
276
281
|
res.json({
|
|
@@ -776,6 +781,7 @@ function startWebServer(opts = {}) {
|
|
|
776
781
|
const cursorOffset = typeof body?.cursorOffset === 'number' ? body.cursorOffset : fileContent.length;
|
|
777
782
|
const mode = body?.mode === 'full' ? 'full' : 'quick';
|
|
778
783
|
const language = typeof body?.language === 'string' ? body.language : undefined;
|
|
784
|
+
const crossFileContext = typeof body?.crossFileContext === 'string' ? body.crossFileContext : undefined;
|
|
779
785
|
if (!filePath || !fileContent) {
|
|
780
786
|
res.status(400).json({ ok: false, error: '缺少 filePath 或 fileContent' });
|
|
781
787
|
return;
|
|
@@ -791,6 +797,7 @@ function startWebServer(opts = {}) {
|
|
|
791
797
|
cursorOffset,
|
|
792
798
|
mode,
|
|
793
799
|
language,
|
|
800
|
+
crossFileContext,
|
|
794
801
|
});
|
|
795
802
|
res.json({ ok: true, ...result });
|
|
796
803
|
}
|
|
@@ -798,6 +805,17 @@ function startWebServer(opts = {}) {
|
|
|
798
805
|
res.status(500).json({ ok: false, error: '补全失败: ' + e.message, suggestions: [] });
|
|
799
806
|
}
|
|
800
807
|
});
|
|
808
|
+
app.post('/api/lint', (req, res) => {
|
|
809
|
+
const body = (req.body ?? {});
|
|
810
|
+
const code = typeof body?.code === 'string' ? body.code : '';
|
|
811
|
+
const language = typeof body?.language === 'string' ? body.language : undefined;
|
|
812
|
+
if (!code) {
|
|
813
|
+
res.status(400).json({ ok: false, error: '缺少 code' });
|
|
814
|
+
return;
|
|
815
|
+
}
|
|
816
|
+
const errors = (0, lint_1.lintSnippet)(code, language);
|
|
817
|
+
res.json({ ok: true, errors, clean: errors.length === 0 });
|
|
818
|
+
});
|
|
801
819
|
/* ========== 阶段一-2:补全 Pro API ========== */
|
|
802
820
|
// 记录用户接受的补全(用于连续推荐)
|
|
803
821
|
app.post('/api/completion/accept', (req, res) => {
|
|
@@ -844,6 +862,15 @@ function startWebServer(opts = {}) {
|
|
|
844
862
|
}
|
|
845
863
|
});
|
|
846
864
|
/* ========== P2-1: 设计稿转代码 API(多模态,图片→代码) ========== */
|
|
865
|
+
// P1-3: 设计稿转代码引擎状态查询
|
|
866
|
+
app.get('/api/design-to-code', (_req, res) => {
|
|
867
|
+
res.json({
|
|
868
|
+
ok: true,
|
|
869
|
+
configured: !!designToCodeEngine,
|
|
870
|
+
framework: designToCodeEngine ? 'html' : null,
|
|
871
|
+
note: designToCodeEngine ? '已配置多模态模型' : '未配置多模态模型(POST /api/design-to-code 需 vision 模型)',
|
|
872
|
+
});
|
|
873
|
+
});
|
|
847
874
|
app.post('/api/design-to-code', async (req, res) => {
|
|
848
875
|
const body = (req.body ?? {});
|
|
849
876
|
const image = typeof body?.image === 'string' ? body.image.trim() : '';
|
|
@@ -1337,6 +1364,15 @@ function startWebServer(opts = {}) {
|
|
|
1337
1364
|
.catch((e) => res.status(500).json({ ok: false, error: e.message }));
|
|
1338
1365
|
});
|
|
1339
1366
|
// Cron 任务 CRUD
|
|
1367
|
+
app.get('/api/event-driven/cron', (_req, res) => {
|
|
1368
|
+
try {
|
|
1369
|
+
const cfg = eventDrivenManager.getConfig();
|
|
1370
|
+
res.json({ ok: true, cronTasks: cfg.cronTasks ?? [] });
|
|
1371
|
+
}
|
|
1372
|
+
catch (e) {
|
|
1373
|
+
res.status(500).json({ ok: false, error: e.message });
|
|
1374
|
+
}
|
|
1375
|
+
});
|
|
1340
1376
|
app.post('/api/event-driven/cron', (req, res) => {
|
|
1341
1377
|
const body = (req.body ?? {});
|
|
1342
1378
|
if (!body.name || !body.cron || !body.task) {
|
|
@@ -1609,18 +1645,18 @@ function startWebServer(opts = {}) {
|
|
|
1609
1645
|
res.status(400).json({ ok: false, error: '仅支持 Windows 系统' });
|
|
1610
1646
|
return;
|
|
1611
1647
|
}
|
|
1612
|
-
const script = `
|
|
1613
|
-
Add-Type -AssemblyName System.Windows.Forms
|
|
1614
|
-
Add-Type -AssemblyName System.Drawing
|
|
1615
|
-
$screen = [System.Windows.Forms.Screen]::PrimaryScreen
|
|
1616
|
-
$bounds = $screen.Bounds
|
|
1617
|
-
$bitmap = New-Object System.Drawing.Bitmap $bounds.Width, $bounds.Height
|
|
1618
|
-
$graphics = [System.Drawing.Graphics]::FromImage($bitmap)
|
|
1619
|
-
$graphics.CopyFromScreen($bounds.Location, [System.Drawing.Point]::Empty, $bounds.Size)
|
|
1620
|
-
$ms = New-Object System.IO.MemoryStream
|
|
1621
|
-
$bitmap.Save($ms, [System.Drawing.Imaging.ImageFormat]::Png)
|
|
1622
|
-
$bytes = $ms.ToArray()
|
|
1623
|
-
[Convert]::ToBase64String($bytes)
|
|
1648
|
+
const script = `
|
|
1649
|
+
Add-Type -AssemblyName System.Windows.Forms
|
|
1650
|
+
Add-Type -AssemblyName System.Drawing
|
|
1651
|
+
$screen = [System.Windows.Forms.Screen]::PrimaryScreen
|
|
1652
|
+
$bounds = $screen.Bounds
|
|
1653
|
+
$bitmap = New-Object System.Drawing.Bitmap $bounds.Width, $bounds.Height
|
|
1654
|
+
$graphics = [System.Drawing.Graphics]::FromImage($bitmap)
|
|
1655
|
+
$graphics.CopyFromScreen($bounds.Location, [System.Drawing.Point]::Empty, $bounds.Size)
|
|
1656
|
+
$ms = New-Object System.IO.MemoryStream
|
|
1657
|
+
$bitmap.Save($ms, [System.Drawing.Imaging.ImageFormat]::Png)
|
|
1658
|
+
$bytes = $ms.ToArray()
|
|
1659
|
+
[Convert]::ToBase64String($bytes)
|
|
1624
1660
|
`;
|
|
1625
1661
|
const base64 = await runPowerShell(script);
|
|
1626
1662
|
res.json({ ok: true, image: 'data:image/png;base64,' + base64, width: 1920, height: 1080 });
|
|
@@ -1639,17 +1675,17 @@ function startWebServer(opts = {}) {
|
|
|
1639
1675
|
res.status(400).json({ ok: false, error: '缺少 x 或 y 坐标' });
|
|
1640
1676
|
return;
|
|
1641
1677
|
}
|
|
1642
|
-
const script = `
|
|
1643
|
-
Add-Type @"
|
|
1644
|
-
using System;
|
|
1645
|
-
using System.Runtime.InteropServices;
|
|
1646
|
-
public class MouseHelper {
|
|
1647
|
-
[DllImport("user32.dll")]
|
|
1648
|
-
public static extern bool SetCursorPos(int X, int Y);
|
|
1649
|
-
}
|
|
1650
|
-
"@
|
|
1651
|
-
[MouseHelper]::SetCursorPos(${x}, ${y}) | Out-Null
|
|
1652
|
-
Write-Output "ok"
|
|
1678
|
+
const script = `
|
|
1679
|
+
Add-Type @"
|
|
1680
|
+
using System;
|
|
1681
|
+
using System.Runtime.InteropServices;
|
|
1682
|
+
public class MouseHelper {
|
|
1683
|
+
[DllImport("user32.dll")]
|
|
1684
|
+
public static extern bool SetCursorPos(int X, int Y);
|
|
1685
|
+
}
|
|
1686
|
+
"@
|
|
1687
|
+
[MouseHelper]::SetCursorPos(${x}, ${y}) | Out-Null
|
|
1688
|
+
Write-Output "ok"
|
|
1653
1689
|
`;
|
|
1654
1690
|
await runPowerShell(script);
|
|
1655
1691
|
res.json({ ok: true, x, y });
|
|
@@ -1676,20 +1712,20 @@ function startWebServer(opts = {}) {
|
|
|
1676
1712
|
const clickPart = doubleClick
|
|
1677
1713
|
? `[MouseHelper]::mouse_event(${clickFlag}, 0, 0, 0, 0); [MouseHelper]::mouse_event(${upFlag}, 0, 0, 0, 0); Start-Sleep -Milliseconds 100; [MouseHelper]::mouse_event(${clickFlag}, 0, 0, 0, 0); [MouseHelper]::mouse_event(${upFlag}, 0, 0, 0, 0);`
|
|
1678
1714
|
: `[MouseHelper]::mouse_event(${clickFlag}, 0, 0, 0, 0); [MouseHelper]::mouse_event(${upFlag}, 0, 0, 0, 0);`;
|
|
1679
|
-
const script = `
|
|
1680
|
-
Add-Type @"
|
|
1681
|
-
using System;
|
|
1682
|
-
using System.Runtime.InteropServices;
|
|
1683
|
-
public class MouseHelper {
|
|
1684
|
-
[DllImport("user32.dll")]
|
|
1685
|
-
public static extern bool SetCursorPos(int X, int Y);
|
|
1686
|
-
[DllImport("user32.dll")]
|
|
1687
|
-
public static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint cButtons, uint dwExtraInfo);
|
|
1688
|
-
}
|
|
1689
|
-
"@
|
|
1690
|
-
${movePart}
|
|
1691
|
-
${clickPart}
|
|
1692
|
-
Write-Output "ok"
|
|
1715
|
+
const script = `
|
|
1716
|
+
Add-Type @"
|
|
1717
|
+
using System;
|
|
1718
|
+
using System.Runtime.InteropServices;
|
|
1719
|
+
public class MouseHelper {
|
|
1720
|
+
[DllImport("user32.dll")]
|
|
1721
|
+
public static extern bool SetCursorPos(int X, int Y);
|
|
1722
|
+
[DllImport("user32.dll")]
|
|
1723
|
+
public static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint cButtons, uint dwExtraInfo);
|
|
1724
|
+
}
|
|
1725
|
+
"@
|
|
1726
|
+
${movePart}
|
|
1727
|
+
${clickPart}
|
|
1728
|
+
Write-Output "ok"
|
|
1693
1729
|
`;
|
|
1694
1730
|
await runPowerShell(script);
|
|
1695
1731
|
res.json({ ok: true, button, x, y, double: doubleClick });
|
|
@@ -1709,10 +1745,10 @@ function startWebServer(opts = {}) {
|
|
|
1709
1745
|
}
|
|
1710
1746
|
// SendKeys 需要转义特殊字符
|
|
1711
1747
|
const escaped = text.replace(/([+^%~(){}])/g, '{$1}');
|
|
1712
|
-
const script = `
|
|
1713
|
-
Add-Type -AssemblyName System.Windows.Forms
|
|
1714
|
-
[System.Windows.Forms.SendKeys]::SendWait('${escaped.replace(/'/g, "''")}')
|
|
1715
|
-
Write-Output "ok"
|
|
1748
|
+
const script = `
|
|
1749
|
+
Add-Type -AssemblyName System.Windows.Forms
|
|
1750
|
+
[System.Windows.Forms.SendKeys]::SendWait('${escaped.replace(/'/g, "''")}')
|
|
1751
|
+
Write-Output "ok"
|
|
1716
1752
|
`;
|
|
1717
1753
|
await runPowerShell(script);
|
|
1718
1754
|
res.json({ ok: true, text });
|
|
@@ -1730,10 +1766,10 @@ function startWebServer(opts = {}) {
|
|
|
1730
1766
|
res.status(400).json({ ok: false, error: '缺少 key 字段' });
|
|
1731
1767
|
return;
|
|
1732
1768
|
}
|
|
1733
|
-
const script = `
|
|
1734
|
-
Add-Type -AssemblyName System.Windows.Forms
|
|
1735
|
-
[System.Windows.Forms.SendKeys]::SendWait('${key.replace(/'/g, "''")}')
|
|
1736
|
-
Write-Output "ok"
|
|
1769
|
+
const script = `
|
|
1770
|
+
Add-Type -AssemblyName System.Windows.Forms
|
|
1771
|
+
[System.Windows.Forms.SendKeys]::SendWait('${key.replace(/'/g, "''")}')
|
|
1772
|
+
Write-Output "ok"
|
|
1737
1773
|
`;
|
|
1738
1774
|
await runPowerShell(script);
|
|
1739
1775
|
res.json({ ok: true, key });
|
|
@@ -2738,6 +2774,22 @@ function startWebServer(opts = {}) {
|
|
|
2738
2774
|
const list = loadModels().map(publicModel);
|
|
2739
2775
|
res.json({ ok: true, models: list, defaultId: (list.find((m) => m.default) || {}).id || null });
|
|
2740
2776
|
});
|
|
2777
|
+
// P1-3: 模型提供商聚合视图(按 apiBase 分组)
|
|
2778
|
+
app.get('/api/models/providers', (_req, res) => {
|
|
2779
|
+
const list = loadModels().map(publicModel);
|
|
2780
|
+
const byKey = new Map();
|
|
2781
|
+
for (const m of list) {
|
|
2782
|
+
const key = m.apiBase || 'custom';
|
|
2783
|
+
let entry = byKey.get(key);
|
|
2784
|
+
if (!entry) {
|
|
2785
|
+
entry = { providerId: key, apiBase: key, models: [], count: 0 };
|
|
2786
|
+
byKey.set(key, entry);
|
|
2787
|
+
}
|
|
2788
|
+
entry.models.push(m);
|
|
2789
|
+
entry.count++;
|
|
2790
|
+
}
|
|
2791
|
+
res.json({ ok: true, providers: Array.from(byKey.values()), total: list.length });
|
|
2792
|
+
});
|
|
2741
2793
|
app.post('/api/models', (req, res) => {
|
|
2742
2794
|
const body = req.body;
|
|
2743
2795
|
const name = typeof body?.name === 'string' ? body.name.trim() : '';
|