@sanqianx/project-knowledge 5.0.17 → 5.0.18-rc.2
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/.claude-plugin/marketplace.json +1 -1
- package/_site/_test/agent-capture-ui-test.js +100 -87
- package/_site/_test/desktop-browser-compat-test.js +1 -1
- package/_site/_test/glm-ui-refresh-review-test.js +404 -385
- package/_site/_test/integration-auto-repair-test.js +92 -0
- package/_site/_test/integration-intent-test.js +81 -0
- package/_site/_test/module-bridge-eventbridge-test.js +3 -1
- package/_site/_test/module-dynamic-port-test.js +118 -0
- package/_site/_test/non-release-ci-test.js +1 -1
- package/_site/_test/product-progress-status-test.js +73 -70
- package/_site/_test/vector-storage-root-test.js +75 -68
- package/_site/lib/integration-auto-repair.js +75 -0
- package/_site/lib/integration-intent.js +88 -0
- package/_site/lib/module-bridge.js +114 -16
- package/_site/lib/module-port-resolver.js +57 -0
- package/_site/lib/server-app.js +43 -1
- package/docs/release-5.0.17-acceptance.md +20 -2
- package/module-runtime-manifest.json +19 -19
- package/package.json +108 -108
- package/plugins/project-knowledge/.claude-plugin/plugin.json +1 -1
- package/plugins/project-knowledge/.codex-plugin/plugin.json +1 -1
- package/plugins/project-knowledge/.mcp.json +1 -1
- package/ui/index.html +1 -1
- package/ui/product.css +1 -0
- package/ui/product.js +41 -26
package/package.json
CHANGED
|
@@ -1,108 +1,108 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@sanqianx/project-knowledge",
|
|
3
|
-
"version": "5.0.
|
|
4
|
-
"description": "Knowledge base manager with Git integration, AI-driven analysis, and bilingual (zh-CN/en-US) knowledge output",
|
|
5
|
-
"main": "_site/server.js",
|
|
6
|
-
"scripts": {
|
|
7
|
-
"start": "node _site/server.js",
|
|
8
|
-
"test": "node _site/_test/run-all-tests.js",
|
|
9
|
-
"release:sync": "node _site/scripts/sync-release-version.js --web-only",
|
|
10
|
-
"vendor:modules": "node _site/scripts/vendor-modules.js",
|
|
11
|
-
"runtime:verify": "node _site/scripts/verify-module-runtime.js --working-tree",
|
|
12
|
-
"release:verify": "node _site/scripts/sync-release-version.js --check --web-only && node _site/scripts/verify-module-runtime.js && node _site/scripts/verify-product-runtime.js && node _site/_test/integration-adapters-test.js",
|
|
13
|
-
"preversion": "npm run release:verify",
|
|
14
|
-
"version": "node _site/scripts/sync-release-version.js --stage --web-only",
|
|
15
|
-
"postversion": "npm run release:verify"
|
|
16
|
-
},
|
|
17
|
-
"bin": {
|
|
18
|
-
"project-knowledge": "bin/project-knowledge.js",
|
|
19
|
-
"project-knowledge-kb": "bin/project-knowledge-kb.js",
|
|
20
|
-
"project-knowledge-mcp": "bin/project-knowledge-mcp.js",
|
|
21
|
-
"project-knowledge-integrations": "bin/project-knowledge-integrations.js"
|
|
22
|
-
},
|
|
23
|
-
"engines": {
|
|
24
|
-
"node": ">=22"
|
|
25
|
-
},
|
|
26
|
-
"files": [
|
|
27
|
-
"_site/server.js",
|
|
28
|
-
"ui/index.html",
|
|
29
|
-
"ui/product.css",
|
|
30
|
-
"ui/product.js",
|
|
31
|
-
"ui/live-client.js",
|
|
32
|
-
"ui/favicon.svg",
|
|
33
|
-
"_site/lib/",
|
|
34
|
-
"_modules/knowledge-engine/",
|
|
35
|
-
"vendor-manifest.json",
|
|
36
|
-
"module-runtime-manifest.json",
|
|
37
|
-
"_site/scripts/",
|
|
38
|
-
"_site/_test/*.js",
|
|
39
|
-
"_site/_test/fixtures/",
|
|
40
|
-
"_site/start.bat",
|
|
41
|
-
"_site/stop.bat",
|
|
42
|
-
"claude-prompts.json",
|
|
43
|
-
"bin/",
|
|
44
|
-
"plugins/",
|
|
45
|
-
".claude-plugin/",
|
|
46
|
-
".agents/plugins/",
|
|
47
|
-
"templates/",
|
|
48
|
-
"docs/assets/",
|
|
49
|
-
"docs/README.zh-CN.md",
|
|
50
|
-
"docs/project-registry-schema.md",
|
|
51
|
-
"docs/team-knowledge-mode-a-plan.md",
|
|
52
|
-
"docs/testing-strategy.md",
|
|
53
|
-
"docs/leader-glm-workbench-playbook.md",
|
|
54
|
-
"docs/release-5.0.16-acceptance.md",
|
|
55
|
-
"docs/release-5.0.17-acceptance.md",
|
|
56
|
-
"docs/fresh-v5-start.md",
|
|
57
|
-
"README.md",
|
|
58
|
-
"NOTICE",
|
|
59
|
-
"CHANGELOG.md"
|
|
60
|
-
],
|
|
61
|
-
"repository": {
|
|
62
|
-
"type": "git",
|
|
63
|
-
"url": "git+https://github.com/SanQianX/project-knowledge-base.git"
|
|
64
|
-
},
|
|
65
|
-
"keywords": [
|
|
66
|
-
"knowledge-base",
|
|
67
|
-
"git",
|
|
68
|
-
"ai",
|
|
69
|
-
"claude",
|
|
70
|
-
"codex",
|
|
71
|
-
"opencode",
|
|
72
|
-
"mcp",
|
|
73
|
-
"documentation",
|
|
74
|
-
"scanner",
|
|
75
|
-
"context-pack",
|
|
76
|
-
"post-commit-hook"
|
|
77
|
-
],
|
|
78
|
-
"author": "SanQianX",
|
|
79
|
-
"license": "Apache-2.0",
|
|
80
|
-
"dependencies": {
|
|
81
|
-
"@anthropic-ai/claude-agent-sdk": "^0.2.141",
|
|
82
|
-
"@grpc/grpc-js": "^1.14.5",
|
|
83
|
-
"@grpc/proto-loader": "^0.8.1",
|
|
84
|
-
"@huggingface/transformers": "3.8.1",
|
|
85
|
-
"@lancedb/lancedb": "0.31.0",
|
|
86
|
-
"@modelcontextprotocol/sdk": "1.29.0",
|
|
87
|
-
"@sanqianx/ai-coding-event-bridge-console": "0.7.2",
|
|
88
|
-
"@sanqianx/vector-hub": "1.0.8-rc.8",
|
|
89
|
-
"buffer": "^6.0.3",
|
|
90
|
-
"cheerio": "^1.2.0",
|
|
91
|
-
"claude-ai-workbench": "npm:@sanqianx/claude-ai-workbench@0.13.2-rc.
|
|
92
|
-
"cross-spawn": "7.0.6",
|
|
93
|
-
"dotenv": "^17.4.2",
|
|
94
|
-
"gpt-tokenizer": "^3.4.0",
|
|
95
|
-
"http-proxy-agent": "7.0.2",
|
|
96
|
-
"https-proxy-agent": "7.0.6",
|
|
97
|
-
"json-colorizer": "^3.0.1",
|
|
98
|
-
"jsonc-parser": "3.3.1",
|
|
99
|
-
"openai": "^6.49.0",
|
|
100
|
-
"socks-proxy-agent": "8.0.5",
|
|
101
|
-
"turndown": "^7.2.4",
|
|
102
|
-
"uuid": "^13.0.2",
|
|
103
|
-
"wink-bm25-text-search": "^3.1.2",
|
|
104
|
-
"wink-nlp": "^2.4.0",
|
|
105
|
-
"ws": "^8.21.0",
|
|
106
|
-
"yargs": "^18.1.0"
|
|
107
|
-
}
|
|
108
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@sanqianx/project-knowledge",
|
|
3
|
+
"version": "5.0.18-rc.2",
|
|
4
|
+
"description": "Knowledge base manager with Git integration, AI-driven analysis, and bilingual (zh-CN/en-US) knowledge output",
|
|
5
|
+
"main": "_site/server.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"start": "node _site/server.js",
|
|
8
|
+
"test": "node _site/_test/run-all-tests.js",
|
|
9
|
+
"release:sync": "node _site/scripts/sync-release-version.js --web-only",
|
|
10
|
+
"vendor:modules": "node _site/scripts/vendor-modules.js",
|
|
11
|
+
"runtime:verify": "node _site/scripts/verify-module-runtime.js --working-tree",
|
|
12
|
+
"release:verify": "node _site/scripts/sync-release-version.js --check --web-only && node _site/scripts/verify-module-runtime.js && node _site/scripts/verify-product-runtime.js && node _site/_test/integration-adapters-test.js",
|
|
13
|
+
"preversion": "npm run release:verify",
|
|
14
|
+
"version": "node _site/scripts/sync-release-version.js --stage --web-only",
|
|
15
|
+
"postversion": "npm run release:verify"
|
|
16
|
+
},
|
|
17
|
+
"bin": {
|
|
18
|
+
"project-knowledge": "bin/project-knowledge.js",
|
|
19
|
+
"project-knowledge-kb": "bin/project-knowledge-kb.js",
|
|
20
|
+
"project-knowledge-mcp": "bin/project-knowledge-mcp.js",
|
|
21
|
+
"project-knowledge-integrations": "bin/project-knowledge-integrations.js"
|
|
22
|
+
},
|
|
23
|
+
"engines": {
|
|
24
|
+
"node": ">=22"
|
|
25
|
+
},
|
|
26
|
+
"files": [
|
|
27
|
+
"_site/server.js",
|
|
28
|
+
"ui/index.html",
|
|
29
|
+
"ui/product.css",
|
|
30
|
+
"ui/product.js",
|
|
31
|
+
"ui/live-client.js",
|
|
32
|
+
"ui/favicon.svg",
|
|
33
|
+
"_site/lib/",
|
|
34
|
+
"_modules/knowledge-engine/",
|
|
35
|
+
"vendor-manifest.json",
|
|
36
|
+
"module-runtime-manifest.json",
|
|
37
|
+
"_site/scripts/",
|
|
38
|
+
"_site/_test/*.js",
|
|
39
|
+
"_site/_test/fixtures/",
|
|
40
|
+
"_site/start.bat",
|
|
41
|
+
"_site/stop.bat",
|
|
42
|
+
"claude-prompts.json",
|
|
43
|
+
"bin/",
|
|
44
|
+
"plugins/",
|
|
45
|
+
".claude-plugin/",
|
|
46
|
+
".agents/plugins/",
|
|
47
|
+
"templates/",
|
|
48
|
+
"docs/assets/",
|
|
49
|
+
"docs/README.zh-CN.md",
|
|
50
|
+
"docs/project-registry-schema.md",
|
|
51
|
+
"docs/team-knowledge-mode-a-plan.md",
|
|
52
|
+
"docs/testing-strategy.md",
|
|
53
|
+
"docs/leader-glm-workbench-playbook.md",
|
|
54
|
+
"docs/release-5.0.16-acceptance.md",
|
|
55
|
+
"docs/release-5.0.17-acceptance.md",
|
|
56
|
+
"docs/fresh-v5-start.md",
|
|
57
|
+
"README.md",
|
|
58
|
+
"NOTICE",
|
|
59
|
+
"CHANGELOG.md"
|
|
60
|
+
],
|
|
61
|
+
"repository": {
|
|
62
|
+
"type": "git",
|
|
63
|
+
"url": "git+https://github.com/SanQianX/project-knowledge-base.git"
|
|
64
|
+
},
|
|
65
|
+
"keywords": [
|
|
66
|
+
"knowledge-base",
|
|
67
|
+
"git",
|
|
68
|
+
"ai",
|
|
69
|
+
"claude",
|
|
70
|
+
"codex",
|
|
71
|
+
"opencode",
|
|
72
|
+
"mcp",
|
|
73
|
+
"documentation",
|
|
74
|
+
"scanner",
|
|
75
|
+
"context-pack",
|
|
76
|
+
"post-commit-hook"
|
|
77
|
+
],
|
|
78
|
+
"author": "SanQianX",
|
|
79
|
+
"license": "Apache-2.0",
|
|
80
|
+
"dependencies": {
|
|
81
|
+
"@anthropic-ai/claude-agent-sdk": "^0.2.141",
|
|
82
|
+
"@grpc/grpc-js": "^1.14.5",
|
|
83
|
+
"@grpc/proto-loader": "^0.8.1",
|
|
84
|
+
"@huggingface/transformers": "3.8.1",
|
|
85
|
+
"@lancedb/lancedb": "0.31.0",
|
|
86
|
+
"@modelcontextprotocol/sdk": "1.29.0",
|
|
87
|
+
"@sanqianx/ai-coding-event-bridge-console": "0.7.2",
|
|
88
|
+
"@sanqianx/vector-hub": "1.0.8-rc.8",
|
|
89
|
+
"buffer": "^6.0.3",
|
|
90
|
+
"cheerio": "^1.2.0",
|
|
91
|
+
"claude-ai-workbench": "npm:@sanqianx/claude-ai-workbench@0.13.2-rc.18",
|
|
92
|
+
"cross-spawn": "7.0.6",
|
|
93
|
+
"dotenv": "^17.4.2",
|
|
94
|
+
"gpt-tokenizer": "^3.4.0",
|
|
95
|
+
"http-proxy-agent": "7.0.2",
|
|
96
|
+
"https-proxy-agent": "7.0.6",
|
|
97
|
+
"json-colorizer": "^3.0.1",
|
|
98
|
+
"jsonc-parser": "3.3.1",
|
|
99
|
+
"openai": "^6.49.0",
|
|
100
|
+
"socks-proxy-agent": "8.0.5",
|
|
101
|
+
"turndown": "^7.2.4",
|
|
102
|
+
"uuid": "^13.0.2",
|
|
103
|
+
"wink-bm25-text-search": "^3.1.2",
|
|
104
|
+
"wink-nlp": "^2.4.0",
|
|
105
|
+
"ws": "^8.21.0",
|
|
106
|
+
"yargs": "^18.1.0"
|
|
107
|
+
}
|
|
108
|
+
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
|
|
3
3
|
"name": "project-knowledge",
|
|
4
4
|
"hooks": "./hooks/claude.json",
|
|
5
|
-
"version": "5.0.
|
|
5
|
+
"version": "5.0.18-rc.2",
|
|
6
6
|
"description": "Read durable project decisions and implementation history from Project Knowledge.",
|
|
7
7
|
"author": {
|
|
8
8
|
"name": "SanQianX",
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"const fs=require('fs'),path=require('path'),os=require('os');const PKG='@sanqianx/project-knowledge',SC='project-knowledge/integration-runtime/v1';let f='';const root=process.env.CLAUDE_PLUGIN_ROOT||process.env.PLUGIN_ROOT;if(root){f=path.join(root,'scripts','mcp-launcher.cjs');if(!fs.existsSync(f))f=''}if(!f){const dd=process.env.KB_DATA_DIR||path.join(os.homedir(),'.project-knowledge-v5');try{const bp=path.join(dd,'integration-runtime.json');const st=fs.statSync(bp);if(st.isFile()&&st.size<=32768){const b=JSON.parse(fs.readFileSync(bp,'utf8'));if(b&&b.schema===SC&&b.packageName===PKG&&typeof b.packageRoot==='string'&&path.isAbsolute(b.packageRoot)){const c=path.join(b.packageRoot,'plugins','project-knowledge','scripts','mcp-launcher.cjs');const rr=fs.realpathSync(b.packageRoot),cr=fs.realpathSync(c);const rel=path.relative(rr,cr);if(rel&&rel!=='..'&&!rel.startsWith('..'+path.sep)&&!path.isAbsolute(rel)&&fs.statSync(cr).isFile())f=cr}}}catch(e){}}if(!f){console.error('[project-knowledge-mcp] 未能通过受信任插件根或已验证的安装绑定定位启动器,已停止;不访问网络,也不加载工作目录源码。');process.exit(127)}require(f);"
|
|
9
9
|
],
|
|
10
10
|
"env": {
|
|
11
|
-
"KB_PLUGIN_VERSION": "5.0.
|
|
11
|
+
"KB_PLUGIN_VERSION": "5.0.18-rc.2"
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
14
|
}
|
package/ui/index.html
CHANGED
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
<header><h2>系统状态</h2><button id="closeSystem" class="icon-button" aria-label="关闭系统状态">×</button></header>
|
|
38
38
|
<div class="drawer-content">
|
|
39
39
|
<section><h3>模块连接</h3><div id="moduleHealth"></div><button id="repairWiring">修复当前项目接线</button><p class="muted" id="wiringFeedback"></p><p class="muted" id="captureStatus"></p></section>
|
|
40
|
-
<section id="agentCaptureSection"><div class="actions"><h3>外部 Agent 接入</h3
|
|
40
|
+
<section id="agentCaptureSection"><div class="actions"><h3>外部 Agent 接入</h3></div><p class="muted">接入过的 Agent 配置损坏时会在启动时自动修复;只接入你使用的工具,不重装 Agent、不覆盖第三方配置。</p><div id="agentCaptureList"></div><p id="agentCaptureFeedback" class="feedback" role="status"></p></section>
|
|
41
41
|
<section><h3>后台维护模型</h3><p class="muted">使用持久化默认模型,不跟随聊天中的临时切换。</p><select id="maintenanceModel" aria-label="后台维护默认模型"></select><div class="actions"><button id="saveMaintenance">保存默认模型</button><button id="configureProviders">管理模型供应商</button></div><p id="configurationStatus" class="muted"></p></section>
|
|
42
42
|
<section><h3>向量检索模型</h3><p id="embeddingStatus" class="muted">正在读取配置。</p><button id="openEmbedding">配置向量模型</button><p class="muted">凭据由工作台统一保存。未配置时仍可使用文本检索。</p></section>
|
|
43
43
|
<section><h3>智脑设置</h3><label>名称<input id="brainName" maxlength="100"></label><label>知识根目录<div class="input-with-action"><input id="knowledgeRoot"><button id="pickRoot">选择</button></div></label><label>向量索引目录<output id="indexStoragePath" class="detail-path"></output></label><p id="indexStorageStatus" class="muted"></p><p class="muted">索引跟随知识根目录,可重新构建;切换时原索引保留,已有项目知识与共享知识不移动。</p><button id="saveBrainSettings">保存设置</button></section>
|
package/ui/product.css
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
label>.detail-path{display:block;width:100%;margin:8px 0 0;color:var(--text)}
|
|
3
3
|
.memory-toolbar{display:flex;justify-content:space-between;align-items:center;gap:24px}.memory-meta{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:16px}.memory-evidence{margin-top:24px;border-top:1px solid var(--line);padding-top:16px}.memory-evidence summary{cursor:pointer;color:var(--muted)}.memory-evidence p,.memory-evidence blockquote{white-space:pre-wrap;overflow-wrap:anywhere}.memory-evidence blockquote{margin:16px 0;border-left:2px solid var(--line);padding-left:16px;color:var(--muted)}
|
|
4
4
|
.agent-capture-row{display:flex;align-items:center;gap:16px;padding:16px 0;border-bottom:1px solid var(--line)}.agent-capture-row>div:first-child{flex:1;min-width:0}.agent-capture-row small{display:block;color:var(--muted);margin-top:8px;overflow-wrap:anywhere}.agent-capture-row .actions{flex-shrink:0}#agentCaptureFeedback{white-space:pre-wrap}
|
|
5
|
+
.agent-detail{margin-top:8px}.agent-detail summary{cursor:pointer;color:var(--muted);font-size:12px;user-select:none}.agent-detail[open] summary{margin-bottom:2px}.agent-detail .actions{margin-top:8px}
|
|
5
6
|
#logsDialog{display:flex;flex-direction:column;overflow:hidden}#logsDialog:not([open]){display:none}#logsContent{overflow:auto;min-height:0;flex:1;margin-top:16px}#logsContent .row{align-items:flex-start;cursor:pointer}#logsContent pre{flex:1;min-width:0;margin:0}#logsContent .log-entry{border-bottom:1px solid var(--line)}#logsContent .log-detail{padding:16px;background:var(--surface2);max-height:320px;overflow:auto}#logsContent [data-level=warn],#logsContent [data-level=error],#logsContent [data-level=fatal]{color:var(--bad)}#logsContent .row time,#logsContent .row pre{color:inherit}
|
|
6
7
|
@media(prefers-reduced-motion:reduce){*,*::before,*::after{scroll-behavior:auto!important;animation:none!important;transition:none!important}}
|
|
7
8
|
.knowledge-context{overflow-x:hidden}.reference{overflow-wrap:anywhere}.reference small{min-width:0;max-width:100%}
|
package/ui/product.js
CHANGED
|
@@ -289,7 +289,10 @@
|
|
|
289
289
|
$('systemDrawer').hidden = false; $('drawerBackdrop').hidden = false;
|
|
290
290
|
$('brainName').value = state.brain.name; $('knowledgeRoot').value = state.root;
|
|
291
291
|
renderStorageInfo();
|
|
292
|
-
|
|
292
|
+
// Opening the drawer is the explicit refresh point (the manual status
|
|
293
|
+
// button is gone): force a fresh scan so externally changed client
|
|
294
|
+
// configs are reflected instead of serving the 30s cache.
|
|
295
|
+
await Promise.all([loadMaintenance(), loadAgentCapture(true)]);
|
|
293
296
|
}
|
|
294
297
|
function renderStorageInfo() {
|
|
295
298
|
$('indexStoragePath').textContent = state.indexStorage?.actualPath || state.indexStorage?.path || '设置知识根目录后自动确定';
|
|
@@ -307,45 +310,58 @@
|
|
|
307
310
|
const result = await api('/api/integrations/status?' + params);
|
|
308
311
|
if (projectId !== state.projectId) return;
|
|
309
312
|
if (epoch !== captureEpoch) return;
|
|
313
|
+
const badgeState = { connected: 'up', error: 'issue' };
|
|
314
|
+
const badgeText = { checking: '检测中', connected: '已接入', disconnected: '未接入', error: '异常', 'not-detected': '未检测到' };
|
|
310
315
|
$('agentCaptureList').innerHTML = result.clients.map(agent => {
|
|
311
316
|
const capture = agent.developmentCapture;
|
|
312
317
|
const found = agent.available || agent.configFound;
|
|
313
318
|
const software = agent.available ? '检测到命令' : agent.configFound ? '检测到配置' : capture.state === 'checking' ? '正在检测客户端' : '未检测到';
|
|
314
|
-
const status = capture.state === 'checking' ? '检查中' : !capture.ok ? '检查或接线异常' : capture.installed ? '已配置采集' : '未接入';
|
|
315
319
|
const auto = agent.automaticContext;
|
|
316
320
|
const mcp = agent.mcpStartup;
|
|
317
|
-
const mcpLine = mcp ?
|
|
318
|
-
|
|
321
|
+
const mcpLine = mcp ? `MCP ${mcp.state === 'ready' ? '已通过' : '未通过'}${mcp.code ? `(${esc(mcp.code)})` : ''}${mcp.detail ? ` · ${esc(mcp.detail)}` : ''}` : '';
|
|
322
|
+
const repairLine = agent.repair ? `启动自动修复:${agent.repair.state === 'repaired' ? '成功' : `失败${agent.repair.error ? ` · ${esc(agent.repair.error)}` : ''}`}` : '';
|
|
323
|
+
const summary = agent.summary || 'checking';
|
|
324
|
+
const switchOn = summary === 'connected';
|
|
325
|
+
const details = [
|
|
326
|
+
`<small>${esc(software)} · ${esc(capture.detail || '')}</small>`,
|
|
327
|
+
auto ? `<small>开发前知识:${esc(auto.detail)}</small>` : '',
|
|
328
|
+
mcpLine ? `<small>${mcpLine}</small>` : '',
|
|
329
|
+
repairLine ? `<small>${repairLine}</small>` : '',
|
|
330
|
+
summary === 'error' ? `<div class="actions"><button data-agent-retry="1" data-agent-client="${esc(agent.client)}" ${captureBusy ? 'disabled' : ''}>重试修复</button></div>` : '',
|
|
331
|
+
].filter(Boolean).join('');
|
|
332
|
+
return `<div class="agent-capture-row"><div><b>${esc(agent.label)}</b> ${badge(badgeText[summary] || summary, badgeState[summary] || '')}<details class="agent-detail"><summary>详情</summary>${details}</details></div><div class="actions"><button data-agent-switch="${switchOn ? 'uninstall' : 'install'}" data-agent-client="${esc(agent.client)}" ${!found || captureBusy ? 'disabled' : ''}>${switchOn ? '移除' : '接入'}</button></div></div>`;
|
|
319
333
|
}).join('');
|
|
320
|
-
|
|
334
|
+
const pendingScan = ['checking', 'refreshing'].includes(result.scan?.state)
|
|
335
|
+
|| (result.clients || []).some(client => client.developmentCapture?.state === 'checking' || client.knowledgeIntegration?.state === 'checking' || client.summary === 'checking');
|
|
336
|
+
if (pendingScan) captureScanTimer = setTimeout(() => {
|
|
321
337
|
if (epoch === captureEpoch && !$('systemDrawer').hidden) loadAgentCapture().catch(error => toast(error.message));
|
|
322
338
|
}, 1500);
|
|
323
339
|
} catch (error) { if (epoch === captureEpoch) $('agentCaptureList').textContent = `无法检查采集状态:${error.message}`; }
|
|
324
340
|
}
|
|
325
|
-
async function
|
|
341
|
+
async function changeAgentAccess(client, operation) {
|
|
326
342
|
if (captureBusy) return;
|
|
327
343
|
captureBusy = true; captureEpoch++;
|
|
328
|
-
|
|
344
|
+
all('[data-agent-switch]').forEach(button => { button.disabled = true; });
|
|
345
|
+
$('agentCaptureFeedback').textContent = operation === 'install' ? '正在接入,保留第三方配置…' : '正在移除,已有记录保留…';
|
|
329
346
|
try {
|
|
330
|
-
const result = await api(
|
|
331
|
-
const
|
|
332
|
-
$('agentCaptureFeedback').textContent =
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
347
|
+
const result = await api(`/api/integrations/${operation}`, { method: 'POST', body: { clients: [client] } });
|
|
348
|
+
const success = result.complete === true;
|
|
349
|
+
$('agentCaptureFeedback').textContent = success
|
|
350
|
+
? operation === 'install' ? '已接入。重新打开客户端后生效,实际记录可在活动页面查看。' : '已移除,第三方配置与已有记录保留。'
|
|
351
|
+
: `操作未完成,展开详情查看原因;更多请查系统诊断记录(操作 ID:${result.operationId || '—'})。`;
|
|
352
|
+
$('agentCaptureFeedback').classList.toggle('issue', !success);
|
|
353
|
+
} catch (error) { $('agentCaptureFeedback').textContent = `操作失败:${error.message}`; $('agentCaptureFeedback').classList.add('issue'); }
|
|
354
|
+
finally { captureBusy = false; await loadAgentCapture(); post('eventBridge', { type: 'kb:refresh-agents' }); }
|
|
355
|
+
}
|
|
356
|
+
async function retryAgentRepair(client) {
|
|
338
357
|
if (captureBusy) return;
|
|
339
358
|
captureBusy = true; captureEpoch++;
|
|
340
|
-
|
|
341
|
-
$('agentCaptureFeedback').textContent = operation === 'install' ? '正在配置采集 Hook…' : '正在移除托管采集,已有记录保留…';
|
|
359
|
+
$('agentCaptureFeedback').textContent = '正在重试修复…';
|
|
342
360
|
try {
|
|
343
|
-
const result = await api(
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
$('agentCaptureFeedback').classList.toggle('issue', !success);
|
|
348
|
-
} catch (error) { $('agentCaptureFeedback').textContent = `操作失败:${error.message}`; $('agentCaptureFeedback').classList.add('issue'); }
|
|
361
|
+
const result = await api('/api/integrations/install', { method: 'POST', body: { clients: [client] } });
|
|
362
|
+
$('agentCaptureFeedback').textContent = result.complete === true ? '修复成功,重新打开客户端后生效。' : `修复未完成,详情见系统诊断记录(操作 ID:${result.operationId || '—'})。`;
|
|
363
|
+
$('agentCaptureFeedback').classList.toggle('issue', result.complete !== true);
|
|
364
|
+
} catch (error) { $('agentCaptureFeedback').textContent = `修复失败:${error.message}`; $('agentCaptureFeedback').classList.add('issue'); }
|
|
349
365
|
finally { captureBusy = false; await loadAgentCapture(); post('eventBridge', { type: 'kb:refresh-agents' }); }
|
|
350
366
|
}
|
|
351
367
|
async function loadLogs() {
|
|
@@ -473,8 +489,8 @@
|
|
|
473
489
|
if (button.dataset.action === 'refresh') await refreshRegistry(true);
|
|
474
490
|
if (button.dataset.action === 'repair') await repair();
|
|
475
491
|
if (button.dataset.action === 'system') await openSystem();
|
|
476
|
-
if (button.dataset.
|
|
477
|
-
if (button.dataset.
|
|
492
|
+
if (button.dataset.agentSwitch) await changeAgentAccess(button.dataset.agentClient, button.dataset.agentSwitch);
|
|
493
|
+
if (button.dataset.agentRetry) await retryAgentRepair(button.dataset.agentClient);
|
|
478
494
|
if (button.dataset.action === 'unbind') { const p = activeProject(); if (p && !unbinding) { unbindProjectId = p.projectId; $('unbindProjectName').textContent = `解绑「${p.name}」?`; $('unbindFeedback').textContent = ''; $('unbindDialog').showModal(); } }
|
|
479
495
|
if (button.dataset.retryRun) { await api(`/api/engine/runs/${encodeURIComponent(button.dataset.retryRun)}/retry`, { method: 'POST', body: {} }); await refreshSnapshot(); }
|
|
480
496
|
if (button.dataset.runPage !== undefined) await loadActivityPage(button.dataset.runPage || null);
|
|
@@ -506,7 +522,6 @@
|
|
|
506
522
|
on('themeToggle', 'click', () => { document.documentElement.dataset.theme = document.documentElement.dataset.theme === 'dark' ? 'light' : 'dark'; localStorage.setItem('kb.theme', document.documentElement.dataset.theme); Object.keys(frames).forEach(key => post(key, { type: 'kb:theme', theme: document.documentElement.dataset.theme })); });
|
|
507
523
|
on('openSystem', 'click', openSystem); on('closeSystem', 'click', closeSystem); on('drawerBackdrop', 'click', closeSystem);
|
|
508
524
|
on('repairWiring', 'click', repair);
|
|
509
|
-
on('refreshAgentCapture', 'click', () => captureBusy ? undefined : loadAgentCapture(true));
|
|
510
525
|
on('configureProviders', 'click', () => { closeSystem(); setView('work'); initializeFrame('terminal'); if (frames.terminal.ready) post('terminal', { type: 'kb:open-settings' }); else frames.terminal.openSettings = true; });
|
|
511
526
|
on('saveMaintenance', 'click', async () => { await api('/api/terminal/maintenance-default', { method: 'PUT', body: { profileId: $('maintenanceModel').value || null } }); const result = await api('/api/modules/configure', { method: 'POST', body: {} }); $('configurationStatus').textContent = result.configuration.model ? '后台默认模型已保存并同步。' : '配置已保存,后台运行配置尚未同步,请检查模块连接。'; });
|
|
512
527
|
on('openEmbedding', 'click', openEmbedding);
|