dominds 1.17.2 → 1.17.4
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/dist/apps-host/host.js +13 -2
- package/dist/apps-host/ipc-types.js +18 -1
- package/dist/dialog-fork.js +1 -0
- package/dist/dialog.js +5 -0
- package/dist/docs/mcp-support.md +4 -1
- package/dist/docs/team_mgmt-toolset.md +8 -7
- package/dist/docs/team_mgmt-toolset.zh.md +6 -5
- package/dist/mcp/manual-problems.d.ts +33 -0
- package/dist/mcp/manual-problems.js +323 -0
- package/dist/mcp/supervisor.js +23 -1
- package/dist/persistence.js +12 -0
- package/dist/priming.js +7 -0
- package/dist/shared-reminders.js +2 -0
- package/dist/tool.d.ts +5 -0
- package/dist/tool.js +66 -4
- package/dist/tools/app-reminders.js +20 -3
- package/dist/tools/ctrl.js +43 -4
- package/dist/tools/manual/output-limit.d.ts +9 -0
- package/dist/tools/manual/output-limit.js +12 -0
- package/dist/tools/os.js +173 -37
- package/dist/tools/pending-tellask-reminder.d.ts +1 -1
- package/dist/tools/pending-tellask-reminder.js +39 -19
- package/dist/tools/team_mgmt-manual.d.ts +2 -0
- package/dist/tools/team_mgmt-manual.js +160 -0
- package/dist/tools/team_mgmt-mcp-manual.d.ts +27 -0
- package/dist/tools/team_mgmt-mcp-manual.js +643 -0
- package/dist/tools/team_mgmt.d.ts +11 -1
- package/dist/tools/team_mgmt.js +22 -867
- package/dist/tools/toolset-manual.js +5 -5
- package/package.json +4 -4
- package/webapp/dist/assets/{_basePickBy-EK9iGcOl.js → _basePickBy-CgM-M_q8.js} +3 -3
- package/webapp/dist/assets/{_basePickBy-EK9iGcOl.js.map → _basePickBy-CgM-M_q8.js.map} +1 -1
- package/webapp/dist/assets/{_baseUniq-BHtz-XvO.js → _baseUniq-B06twih4.js} +2 -2
- package/webapp/dist/assets/{_baseUniq-BHtz-XvO.js.map → _baseUniq-B06twih4.js.map} +1 -1
- package/webapp/dist/assets/{arc-NqUmMwkS.js → arc-CoXJvjeB.js} +2 -2
- package/webapp/dist/assets/{arc-NqUmMwkS.js.map → arc-CoXJvjeB.js.map} +1 -1
- package/webapp/dist/assets/{architectureDiagram-2XIMDMQ5-CJ7Jb15a.js → architectureDiagram-2XIMDMQ5-BLFRWTKn.js} +7 -7
- package/webapp/dist/assets/{architectureDiagram-2XIMDMQ5-CJ7Jb15a.js.map → architectureDiagram-2XIMDMQ5-BLFRWTKn.js.map} +1 -1
- package/webapp/dist/assets/{blockDiagram-WCTKOSBZ-RNM7ujN4.js → blockDiagram-WCTKOSBZ-CYRE6deu.js} +7 -7
- package/webapp/dist/assets/{blockDiagram-WCTKOSBZ-RNM7ujN4.js.map → blockDiagram-WCTKOSBZ-CYRE6deu.js.map} +1 -1
- package/webapp/dist/assets/{c4Diagram-IC4MRINW-DKra5-za.js → c4Diagram-IC4MRINW-B26QTIJt.js} +3 -3
- package/webapp/dist/assets/{c4Diagram-IC4MRINW-DKra5-za.js.map → c4Diagram-IC4MRINW-B26QTIJt.js.map} +1 -1
- package/webapp/dist/assets/{channel-CxE9sL_E.js → channel-C5U2W0P9.js} +2 -2
- package/webapp/dist/assets/{channel-CxE9sL_E.js.map → channel-C5U2W0P9.js.map} +1 -1
- package/webapp/dist/assets/{chunk-4BX2VUAB-BlyIt9uv.js → chunk-4BX2VUAB-7z2PgnSv.js} +2 -2
- package/webapp/dist/assets/{chunk-4BX2VUAB-BlyIt9uv.js.map → chunk-4BX2VUAB-7z2PgnSv.js.map} +1 -1
- package/webapp/dist/assets/{chunk-55IACEB6-DsPShmjL.js → chunk-55IACEB6-6sRVmXqs.js} +2 -2
- package/webapp/dist/assets/{chunk-55IACEB6-DsPShmjL.js.map → chunk-55IACEB6-6sRVmXqs.js.map} +1 -1
- package/webapp/dist/assets/{chunk-FMBD7UC4-C2i0rEFF.js → chunk-FMBD7UC4-BwYp8OtY.js} +2 -2
- package/webapp/dist/assets/{chunk-FMBD7UC4-C2i0rEFF.js.map → chunk-FMBD7UC4-BwYp8OtY.js.map} +1 -1
- package/webapp/dist/assets/{chunk-JSJVCQXG-CK8inzJx.js → chunk-JSJVCQXG-CRq8LK53.js} +2 -2
- package/webapp/dist/assets/{chunk-JSJVCQXG-CK8inzJx.js.map → chunk-JSJVCQXG-CRq8LK53.js.map} +1 -1
- package/webapp/dist/assets/{chunk-KX2RTZJC-BjEK5_oI.js → chunk-KX2RTZJC-CzFE355P.js} +2 -2
- package/webapp/dist/assets/{chunk-KX2RTZJC-BjEK5_oI.js.map → chunk-KX2RTZJC-CzFE355P.js.map} +1 -1
- package/webapp/dist/assets/{chunk-NQ4KR5QH-Clf489xc.js → chunk-NQ4KR5QH-3cQSOzCt.js} +4 -4
- package/webapp/dist/assets/{chunk-NQ4KR5QH-Clf489xc.js.map → chunk-NQ4KR5QH-3cQSOzCt.js.map} +1 -1
- package/webapp/dist/assets/{chunk-QZHKN3VN-CMikir3s.js → chunk-QZHKN3VN-DWkpxb-w.js} +2 -2
- package/webapp/dist/assets/{chunk-QZHKN3VN-CMikir3s.js.map → chunk-QZHKN3VN-DWkpxb-w.js.map} +1 -1
- package/webapp/dist/assets/{chunk-WL4C6EOR-1gtCLicd.js → chunk-WL4C6EOR-DkpfoQzK.js} +6 -6
- package/webapp/dist/assets/{chunk-WL4C6EOR-1gtCLicd.js.map → chunk-WL4C6EOR-DkpfoQzK.js.map} +1 -1
- package/webapp/dist/assets/{classDiagram-VBA2DB6C-kzzlkQ_D.js → classDiagram-VBA2DB6C-mVfJeuZL.js} +7 -7
- package/webapp/dist/assets/{classDiagram-VBA2DB6C-kzzlkQ_D.js.map → classDiagram-VBA2DB6C-mVfJeuZL.js.map} +1 -1
- package/webapp/dist/assets/{classDiagram-v2-RAHNMMFH-kzzlkQ_D.js → classDiagram-v2-RAHNMMFH-mVfJeuZL.js} +7 -7
- package/webapp/dist/assets/{classDiagram-v2-RAHNMMFH-kzzlkQ_D.js.map → classDiagram-v2-RAHNMMFH-mVfJeuZL.js.map} +1 -1
- package/webapp/dist/assets/{clone-XglJh1R0.js → clone-5uLJc7AC.js} +2 -2
- package/webapp/dist/assets/{clone-XglJh1R0.js.map → clone-5uLJc7AC.js.map} +1 -1
- package/webapp/dist/assets/{cose-bilkent-S5V4N54A--gZrh2tG.js → cose-bilkent-S5V4N54A-CoiJzdQi.js} +2 -2
- package/webapp/dist/assets/{cose-bilkent-S5V4N54A--gZrh2tG.js.map → cose-bilkent-S5V4N54A-CoiJzdQi.js.map} +1 -1
- package/webapp/dist/assets/{dagre-KLK3FWXG-D_JMhNNL.js → dagre-KLK3FWXG-DU_3BSOq.js} +7 -7
- package/webapp/dist/assets/{dagre-KLK3FWXG-D_JMhNNL.js.map → dagre-KLK3FWXG-DU_3BSOq.js.map} +1 -1
- package/webapp/dist/assets/{diagram-E7M64L7V-HkYhqJDL.js → diagram-E7M64L7V-DgqOvF1U.js} +8 -8
- package/webapp/dist/assets/{diagram-E7M64L7V-HkYhqJDL.js.map → diagram-E7M64L7V-DgqOvF1U.js.map} +1 -1
- package/webapp/dist/assets/{diagram-IFDJBPK2-BFv5iU5U.js → diagram-IFDJBPK2-CFWMc1oD.js} +7 -7
- package/webapp/dist/assets/{diagram-IFDJBPK2-BFv5iU5U.js.map → diagram-IFDJBPK2-CFWMc1oD.js.map} +1 -1
- package/webapp/dist/assets/{diagram-P4PSJMXO-Dg46tTnk.js → diagram-P4PSJMXO-lrqvXDXp.js} +7 -7
- package/webapp/dist/assets/{diagram-P4PSJMXO-Dg46tTnk.js.map → diagram-P4PSJMXO-lrqvXDXp.js.map} +1 -1
- package/webapp/dist/assets/{erDiagram-INFDFZHY-BzJClUtq.js → erDiagram-INFDFZHY-C28KjRkA.js} +5 -5
- package/webapp/dist/assets/{erDiagram-INFDFZHY-BzJClUtq.js.map → erDiagram-INFDFZHY-C28KjRkA.js.map} +1 -1
- package/webapp/dist/assets/{flowDiagram-PKNHOUZH-IBGgxeki.js → flowDiagram-PKNHOUZH-DkxGh-JF.js} +7 -7
- package/webapp/dist/assets/{flowDiagram-PKNHOUZH-IBGgxeki.js.map → flowDiagram-PKNHOUZH-DkxGh-JF.js.map} +1 -1
- package/webapp/dist/assets/{ganttDiagram-A5KZAMGK-DdxgzFKe.js → ganttDiagram-A5KZAMGK-BmZnHD96.js} +3 -3
- package/webapp/dist/assets/{ganttDiagram-A5KZAMGK-DdxgzFKe.js.map → ganttDiagram-A5KZAMGK-BmZnHD96.js.map} +1 -1
- package/webapp/dist/assets/{gitGraphDiagram-K3NZZRJ6-C14OpSSI.js → gitGraphDiagram-K3NZZRJ6-xiHqomZC.js} +8 -8
- package/webapp/dist/assets/{gitGraphDiagram-K3NZZRJ6-C14OpSSI.js.map → gitGraphDiagram-K3NZZRJ6-xiHqomZC.js.map} +1 -1
- package/webapp/dist/assets/{graph-BrKKvSVx.js → graph-ozb0amP0.js} +3 -3
- package/webapp/dist/assets/{graph-BrKKvSVx.js.map → graph-ozb0amP0.js.map} +1 -1
- package/webapp/dist/assets/{index-BV_dDe3L.js → index-Cyx7eev_.js} +700 -165
- package/webapp/dist/assets/{index-BV_dDe3L.js.map → index-Cyx7eev_.js.map} +1 -1
- package/webapp/dist/assets/{infoDiagram-LFFYTUFH-k0Yv94VI.js → infoDiagram-LFFYTUFH-fLl_TA1F.js} +6 -6
- package/webapp/dist/assets/{infoDiagram-LFFYTUFH-k0Yv94VI.js.map → infoDiagram-LFFYTUFH-fLl_TA1F.js.map} +1 -1
- package/webapp/dist/assets/{ishikawaDiagram-PHBUUO56-C3EYBxjN.js → ishikawaDiagram-PHBUUO56-ZL9tBKUr.js} +2 -2
- package/webapp/dist/assets/{ishikawaDiagram-PHBUUO56-C3EYBxjN.js.map → ishikawaDiagram-PHBUUO56-ZL9tBKUr.js.map} +1 -1
- package/webapp/dist/assets/{journeyDiagram-4ABVD52K-BnSlOrbq.js → journeyDiagram-4ABVD52K--aRyymZs.js} +5 -5
- package/webapp/dist/assets/{journeyDiagram-4ABVD52K-BnSlOrbq.js.map → journeyDiagram-4ABVD52K--aRyymZs.js.map} +1 -1
- package/webapp/dist/assets/{kanban-definition-K7BYSVSG-CNYH0HDF.js → kanban-definition-K7BYSVSG-BO_QdW_O.js} +3 -3
- package/webapp/dist/assets/{kanban-definition-K7BYSVSG-CNYH0HDF.js.map → kanban-definition-K7BYSVSG-BO_QdW_O.js.map} +1 -1
- package/webapp/dist/assets/{layout-NtmBC9CZ.js → layout-Bu3Xw0z2.js} +5 -5
- package/webapp/dist/assets/{layout-NtmBC9CZ.js.map → layout-Bu3Xw0z2.js.map} +1 -1
- package/webapp/dist/assets/{linear-BrqwApt9.js → linear-Bq77itJm.js} +2 -2
- package/webapp/dist/assets/{linear-BrqwApt9.js.map → linear-Bq77itJm.js.map} +1 -1
- package/webapp/dist/assets/{mindmap-definition-YRQLILUH-DcknQb8H.js → mindmap-definition-YRQLILUH-CHB8qv8L.js} +4 -4
- package/webapp/dist/assets/{mindmap-definition-YRQLILUH-DcknQb8H.js.map → mindmap-definition-YRQLILUH-CHB8qv8L.js.map} +1 -1
- package/webapp/dist/assets/{pieDiagram-SKSYHLDU-wydKHXzN.js → pieDiagram-SKSYHLDU-Cxg_wh4K.js} +8 -8
- package/webapp/dist/assets/{pieDiagram-SKSYHLDU-wydKHXzN.js.map → pieDiagram-SKSYHLDU-Cxg_wh4K.js.map} +1 -1
- package/webapp/dist/assets/{quadrantDiagram-337W2JSQ-D6i3VaFO.js → quadrantDiagram-337W2JSQ-DFguuaS9.js} +3 -3
- package/webapp/dist/assets/{quadrantDiagram-337W2JSQ-D6i3VaFO.js.map → quadrantDiagram-337W2JSQ-DFguuaS9.js.map} +1 -1
- package/webapp/dist/assets/{requirementDiagram-Z7DCOOCP-C0sBwH6H.js → requirementDiagram-Z7DCOOCP--tJ_dfsT.js} +4 -4
- package/webapp/dist/assets/{requirementDiagram-Z7DCOOCP-C0sBwH6H.js.map → requirementDiagram-Z7DCOOCP--tJ_dfsT.js.map} +1 -1
- package/webapp/dist/assets/{sankeyDiagram-WA2Y5GQK-33jPg4PK.js → sankeyDiagram-WA2Y5GQK-f0zWimMc.js} +2 -2
- package/webapp/dist/assets/{sankeyDiagram-WA2Y5GQK-33jPg4PK.js.map → sankeyDiagram-WA2Y5GQK-f0zWimMc.js.map} +1 -1
- package/webapp/dist/assets/{sequenceDiagram-2WXFIKYE-CJsKHnh5.js → sequenceDiagram-2WXFIKYE-dwXRRnyq.js} +4 -4
- package/webapp/dist/assets/{sequenceDiagram-2WXFIKYE-CJsKHnh5.js.map → sequenceDiagram-2WXFIKYE-dwXRRnyq.js.map} +1 -1
- package/webapp/dist/assets/{stateDiagram-RAJIS63D-B6A5jTdU.js → stateDiagram-RAJIS63D-DToxcEC2.js} +9 -9
- package/webapp/dist/assets/{stateDiagram-RAJIS63D-B6A5jTdU.js.map → stateDiagram-RAJIS63D-DToxcEC2.js.map} +1 -1
- package/webapp/dist/assets/{stateDiagram-v2-FVOUBMTO-6YIjpVKr.js → stateDiagram-v2-FVOUBMTO-BY5hDUqz.js} +5 -5
- package/webapp/dist/assets/{stateDiagram-v2-FVOUBMTO-6YIjpVKr.js.map → stateDiagram-v2-FVOUBMTO-BY5hDUqz.js.map} +1 -1
- package/webapp/dist/assets/{timeline-definition-YZTLITO2-BQS5KHfj.js → timeline-definition-YZTLITO2-CT3WRcFt.js} +3 -3
- package/webapp/dist/assets/{timeline-definition-YZTLITO2-BQS5KHfj.js.map → timeline-definition-YZTLITO2-CT3WRcFt.js.map} +1 -1
- package/webapp/dist/assets/{treemap-KZPCXAKY-DB1uUX8l.js → treemap-KZPCXAKY-Lnkh2bpd.js} +5 -5
- package/webapp/dist/assets/{treemap-KZPCXAKY-DB1uUX8l.js.map → treemap-KZPCXAKY-Lnkh2bpd.js.map} +1 -1
- package/webapp/dist/assets/{vennDiagram-LZ73GAT5-BtcfWZJx.js → vennDiagram-LZ73GAT5-CYSLSh1w.js} +2 -2
- package/webapp/dist/assets/{vennDiagram-LZ73GAT5-BtcfWZJx.js.map → vennDiagram-LZ73GAT5-CYSLSh1w.js.map} +1 -1
- package/webapp/dist/assets/{xychartDiagram-JWTSCODW-CfIdcI74.js → xychartDiagram-JWTSCODW-DgvaqrGO.js} +3 -3
- package/webapp/dist/assets/{xychartDiagram-JWTSCODW-CfIdcI74.js.map → xychartDiagram-JWTSCODW-DgvaqrGO.js.map} +1 -1
- package/webapp/dist/index.html +1 -1
package/dist/tools/team_mgmt.js
CHANGED
|
@@ -15,17 +15,27 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
15
15
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
16
|
exports.teamMgmtTools = exports.teamMgmtClearProblemsTool = exports.teamMgmtListProblemsTool = exports.teamMgmtValidateMcpCfgTool = exports.teamMgmtValidateTeamCfgTool = exports.teamMgmtValidatePrimingScriptsTool = exports.teamMgmtRmDirTool = exports.teamMgmtRmFileTool = exports.teamMgmtRipgrepSearchTool = exports.teamMgmtRipgrepFixedTool = exports.teamMgmtRipgrepCountTool = exports.teamMgmtRipgrepSnippetsTool = exports.teamMgmtRipgrepFilesTool = exports.teamMgmtMoveDirTool = exports.teamMgmtMoveFileTool = exports.teamMgmtMkDirTool = exports.teamMgmtApplyFileModificationTool = exports.teamMgmtPrepareFileRangeEditTool = exports.teamMgmtPrepareBlockReplaceTool = exports.teamMgmtPrepareInsertBeforeTool = exports.teamMgmtPrepareInsertAfterTool = exports.teamMgmtPrepareFileAppendTool = exports.teamMgmtOverwriteEntireFileTool = exports.teamMgmtCreateNewFileTool = exports.teamMgmtReadFileTool = exports.teamMgmtListDirTool = exports.teamMgmtListModelsTool = exports.teamMgmtListProvidersTool = exports.teamMgmtCheckProviderTool = void 0;
|
|
17
17
|
exports.splitCommandArgs = splitCommandArgs;
|
|
18
|
-
exports.
|
|
18
|
+
exports.renderMemberProperties = renderMemberProperties;
|
|
19
|
+
exports.renderTeamManual = renderTeamManual;
|
|
20
|
+
exports.renderPermissionsManual = renderPermissionsManual;
|
|
21
|
+
exports.renderMindsManual = renderMindsManual;
|
|
22
|
+
exports.renderSkillsManual = renderSkillsManual;
|
|
23
|
+
exports.renderPrimingManual = renderPrimingManual;
|
|
24
|
+
exports.renderEnvManual = renderEnvManual;
|
|
25
|
+
exports.renderTroubleshooting = renderTroubleshooting;
|
|
26
|
+
exports.renderModelParamsManual = renderModelParamsManual;
|
|
27
|
+
exports.renderToolsets = renderToolsets;
|
|
28
|
+
exports.renderBuiltinDefaults = renderBuiltinDefaults;
|
|
19
29
|
const promises_1 = __importDefault(require("fs/promises"));
|
|
20
30
|
const path_1 = __importDefault(require("path"));
|
|
21
31
|
const yaml_1 = __importDefault(require("yaml"));
|
|
22
|
-
const kernel_1 = require("@longrun-ai/kernel");
|
|
23
32
|
const time_1 = require("@longrun-ai/kernel/utils/time");
|
|
24
33
|
const runtime_1 = require("../apps/runtime");
|
|
25
34
|
const client_1 = require("../llm/client");
|
|
26
35
|
const registry_1 = require("../llm/gen/registry");
|
|
27
36
|
const log_1 = require("../log");
|
|
28
37
|
const config_1 = require("../mcp/config");
|
|
38
|
+
const manual_problems_1 = require("../mcp/manual-problems");
|
|
29
39
|
const supervisor_1 = require("../mcp/supervisor");
|
|
30
40
|
const priming_1 = require("../priming");
|
|
31
41
|
const problems_1 = require("../problems");
|
|
@@ -36,6 +46,7 @@ const fs_1 = require("./fs");
|
|
|
36
46
|
const output_limit_1 = require("./output-limit");
|
|
37
47
|
const registry_2 = require("./registry");
|
|
38
48
|
const ripgrep_1 = require("./ripgrep");
|
|
49
|
+
const team_mgmt_mcp_manual_1 = require("./team_mgmt-mcp-manual");
|
|
39
50
|
const txt_1 = require("./txt");
|
|
40
51
|
const MINDS_ALLOW = ['.minds/**'];
|
|
41
52
|
const MINDS_DIR = '.minds';
|
|
@@ -404,6 +415,7 @@ function listMcpYamlProblems(problems) {
|
|
|
404
415
|
if (p.source !== 'mcp')
|
|
405
416
|
continue;
|
|
406
417
|
if (p.id.startsWith(MCP_WORKSPACE_PROBLEM_PREFIX) ||
|
|
418
|
+
p.id.startsWith((0, manual_problems_1.mcpWorkspaceManualProblemPrefix)()) ||
|
|
407
419
|
p.id.startsWith(MCP_SERVER_PROBLEM_PREFIX)) {
|
|
408
420
|
out.push(p);
|
|
409
421
|
}
|
|
@@ -2875,20 +2887,6 @@ exports.teamMgmtRmDirTool = {
|
|
|
2875
2887
|
}
|
|
2876
2888
|
},
|
|
2877
2889
|
};
|
|
2878
|
-
function parseTeamMgmtGuideTopics(topicsRaw) {
|
|
2879
|
-
const topics = [];
|
|
2880
|
-
for (const token0 of topicsRaw) {
|
|
2881
|
-
const token = token0.trim().startsWith('!') ? token0.trim().slice(1) : token0.trim();
|
|
2882
|
-
if (token === '')
|
|
2883
|
-
continue;
|
|
2884
|
-
if ((0, kernel_1.isTeamMgmtGuideTopicKey)(token)) {
|
|
2885
|
-
topics.push(token);
|
|
2886
|
-
continue;
|
|
2887
|
-
}
|
|
2888
|
-
throw new Error(`Unknown topic: ${token0}`);
|
|
2889
|
-
}
|
|
2890
|
-
return topics;
|
|
2891
|
-
}
|
|
2892
2890
|
function fmtHeader(title) {
|
|
2893
2891
|
return `# ${title}\n`;
|
|
2894
2892
|
}
|
|
@@ -3208,166 +3206,6 @@ function renderTeamManual(language) {
|
|
|
3208
3206
|
(windowsHost ? '' : ' - codex_inspect_and_patch_tools\n') +
|
|
3209
3207
|
'```\n');
|
|
3210
3208
|
}
|
|
3211
|
-
async function renderMcpManual(language) {
|
|
3212
|
-
const mcpSnapshot = await readMcpToolsetMappingSnapshot();
|
|
3213
|
-
const mcpMapping = renderMcpToolsetMappingSection(language, mcpSnapshot);
|
|
3214
|
-
const mcpSetup = renderMcpToolsetSetupGuideSection(language, mcpSnapshot);
|
|
3215
|
-
const mcpManualDetails = renderMcpToolsetManualDetailsSection(language, mcpSnapshot);
|
|
3216
|
-
if (language === 'zh') {
|
|
3217
|
-
return (fmtHeader('.minds/mcp.yaml') +
|
|
3218
|
-
fmtList([
|
|
3219
|
-
'每个 MCP `serverId` 注册一个 toolset,toolset 名称 = `serverId`(不加 `mcp_` 前缀)。成员通过 `members.<id>.toolsets` 选择能用哪些 MCP toolset。',
|
|
3220
|
-
'支持热重载:编辑 `.minds/mcp.yaml` 后通常无需重启 Dominds;必要时用 `mcp_restart`。',
|
|
3221
|
-
'默认按“每个对话租用一个 MCP client”运行(更安全):首次使用该 toolset 会产生 sticky reminder,完成后用 `mcp_release` 释放;如确实是无状态服务器,可配置 `truely-stateless: true` 允许跨对话共享。',
|
|
3222
|
-
'stdio 配置格式:`command` 必须是字符串(可执行命令),参数放在 `args`(string[],可省略,默认空数组)。`cwd` 可选(字符串):用于固定相对路径解析目录。',
|
|
3223
|
-
'用 `tools.whitelist/blacklist` 控制暴露的工具,用 `transform` 做命名变换。',
|
|
3224
|
-
'常见坑:stdio transport 需要可执行命令路径正确,且受成员权限(目录 + 扩展名:`*_dirs/no_*_dirs/*_file_ext_names/no_*_file_ext_names`)约束;HTTP transport 需要服务可达(url/端口/网络)。',
|
|
3225
|
-
'高频坑(stdio 路径):若未设置 `cwd`,相对路径按 Dominds 进程工作目录(通常 rtws 根目录)解析;建议显式配置 `cwd` 或直接使用绝对路径。`cwd` 必须存在且是目录。',
|
|
3226
|
-
'可选手册字段:你可以在 `servers.<serverId>.manual` 放手册内容。支持 `content`(总说明)+ `sections`(章节列表),用于告诉智能体该 toolset 该怎么用。',
|
|
3227
|
-
'重要:`manual` 缺失并不代表 MCP toolset 不可用;这只是团队管理工作不足。智能体应继续依据每个工具 description/参数自行判断并使用。',
|
|
3228
|
-
'团队管理者建议:配置并验证 MCP 后,应先精读该 server 暴露的每个工具 description/参数,再与人类用户讨论本 rtws 中这些工具的使用意图,最后把“典型用法 + 主要意图方向 + 不可用时业务处置规约”沉淀到 `servers.<serverId>.manual`(`content + sections`)。',
|
|
3229
|
-
'章节组织建议采用“半结构化”:可优先考虑 `何时使用`、`安全边界`、`不可用时业务处置` 这类高价值章节,但不要求所有 toolset 都照抄同一模板。应从真实业务目标出发,决定哪些章节需要展开、哪些只需一句话、哪些可以合并或另起更贴切的标题。',
|
|
3230
|
-
'对每个 MCP toolset,团队管理者仍应刻意写明“不可用时业务处置规约”:至少回答 1) 当前 toolset 暂不可达时是否必须找协调者/专员接手;2) 是否允许走人工或其他工具链降级路径;3) 哪些业务动作在该 toolset 恢复前必须暂停,禁止擅自继续。',
|
|
3231
|
-
'最小诊断流程(建议顺序):1) 先用 `team_mgmt_check_provider({ provider_key: \"<providerKey>\", model: \"\", all_models: false, live: false })` 确认 LLM provider 可用;2) 再检查该成员的目录权限(`man({ \"toolsetId\": \"team_mgmt\", \"topics\": [\"permissions\"] })`);3) 运行 `team_mgmt_validate_mcp_cfg({})` 汇总 `.minds/mcp.yaml` 与 MCP 问题;4) 必要时 `mcp_restart`,用完记得 `mcp_release`。',
|
|
3232
|
-
]) +
|
|
3233
|
-
fmtCodeBlock('yaml', [
|
|
3234
|
-
'# 最小模板(stdio)',
|
|
3235
|
-
'version: 1',
|
|
3236
|
-
'servers:',
|
|
3237
|
-
' sdk_stdio:',
|
|
3238
|
-
' truely-stateless: false',
|
|
3239
|
-
' transport: stdio',
|
|
3240
|
-
' command: npx',
|
|
3241
|
-
" args: ['-y', '@some/mcp-server@latest']",
|
|
3242
|
-
' cwd: "."',
|
|
3243
|
-
' env: {}',
|
|
3244
|
-
' tools: { whitelist: [], blacklist: [] }',
|
|
3245
|
-
' transform: []',
|
|
3246
|
-
' manual:',
|
|
3247
|
-
' content: |',
|
|
3248
|
-
' 这个 MCP toolset 负责 xx,优先用于 xx 场景。',
|
|
3249
|
-
' sections:',
|
|
3250
|
-
" - title: '何时使用'",
|
|
3251
|
-
' content: |',
|
|
3252
|
-
' 1) 当你需要 ...',
|
|
3253
|
-
' 2) 执行前先确认 ...',
|
|
3254
|
-
" - title: '安全边界'",
|
|
3255
|
-
' content: |',
|
|
3256
|
-
' - 不要用于 ...',
|
|
3257
|
-
' - 若失败先看 ...',
|
|
3258
|
-
" - title: '不可用时业务处置'",
|
|
3259
|
-
' content: |',
|
|
3260
|
-
' - 若该 toolset 暂时不可达,先找 @coordinator(或指定协调者)确认是否改走降级路径。',
|
|
3261
|
-
' - 仅允许改用 ... 作为临时替代;若涉及 ...,必须等待该 MCP 恢复,不可继续。',
|
|
3262
|
-
]) +
|
|
3263
|
-
fmtCodeBlock('yaml', [
|
|
3264
|
-
'# stdio 路径示例(最小)',
|
|
3265
|
-
'# 相对路径:配合 cwd 固定解析目录',
|
|
3266
|
-
'command: node',
|
|
3267
|
-
"args: ['./mcp/server.js']",
|
|
3268
|
-
'cwd: "/absolute/path/to/project"',
|
|
3269
|
-
'',
|
|
3270
|
-
'# 绝对路径:更稳,不依赖 cwd',
|
|
3271
|
-
'command: node',
|
|
3272
|
-
"args: ['/absolute/path/to/mcp/server.js']",
|
|
3273
|
-
]) +
|
|
3274
|
-
fmtCodeBlock('yaml', [
|
|
3275
|
-
'# 最小模板(HTTP)',
|
|
3276
|
-
'version: 1',
|
|
3277
|
-
'servers:',
|
|
3278
|
-
' sdk_http:',
|
|
3279
|
-
' truely-stateless: false',
|
|
3280
|
-
' transport: streamable_http',
|
|
3281
|
-
' url: http://127.0.0.1:3000/mcp',
|
|
3282
|
-
' tools: { whitelist: [], blacklist: [] }',
|
|
3283
|
-
' transform: []',
|
|
3284
|
-
' manual:',
|
|
3285
|
-
' content: "用于远端 MCP 接口调用"',
|
|
3286
|
-
' sections:',
|
|
3287
|
-
" UseCases: '适用于 ...'",
|
|
3288
|
-
" Guardrails: '避免 ...'",
|
|
3289
|
-
]) +
|
|
3290
|
-
mcpMapping +
|
|
3291
|
-
mcpSetup +
|
|
3292
|
-
mcpManualDetails);
|
|
3293
|
-
}
|
|
3294
|
-
return (fmtHeader('.minds/mcp.yaml') +
|
|
3295
|
-
fmtList([
|
|
3296
|
-
'Each MCP `serverId` registers one toolset, and the toolset name is exactly `serverId` (no `mcp_` prefix). Members choose MCP access via `members.<id>.toolsets`.',
|
|
3297
|
-
'Hot reload: edits usually apply without restarting Dominds; use `mcp_restart` when needed.',
|
|
3298
|
-
"Default is per-dialog MCP client leasing (safer): first use adds a sticky reminder; call `mcp_release` when you're sure you won't need the toolset soon. If the server is truly stateless, set `truely-stateless: true` to allow cross-dialog sharing.",
|
|
3299
|
-
'Stdio shape: `command` must be a string executable; parameters go in `args` (string[], optional, defaults to empty). Optional `cwd` (string) fixes the working directory used for relative paths.',
|
|
3300
|
-
'Use `tools.whitelist/blacklist` for exposure control and `transform` for naming transforms.',
|
|
3301
|
-
'Common pitfalls: stdio transport needs a correct executable/command path, and is subject to member permissions (directory + extension: `*_dirs/no_*_dirs/*_file_ext_names/no_*_file_ext_names`); HTTP transport requires the server URL to be reachable.',
|
|
3302
|
-
'High-frequency pitfall (stdio paths): if `cwd` is omitted, relative paths are resolved from Dominds process cwd (usually rtws root). Prefer setting `cwd` explicitly or use absolute paths. `cwd` must exist and be a directory.',
|
|
3303
|
-
'Optional manual field: place guide text at `servers.<serverId>.manual`. Supported shapes: `content` (overview) + `sections` (chapter list) to explain practical usage for this toolset.',
|
|
3304
|
-
'Important: missing `manual` does not mean the MCP toolset is unavailable. It only indicates team-management coverage is incomplete; continue by reading each tool description/argument schema.',
|
|
3305
|
-
'Team-manager recommendation: after MCP config is validated, carefully read descriptions/arguments of each exposed tool, discuss intended usage for this rtws with the human user, then write `servers.<serverId>.manual` (`content + sections`) capturing typical usage patterns, primary intent directions, and unavailable-case business handling rules.',
|
|
3306
|
-
'Use a semi-structured chapter shape: high-value sections often include `When To Use`, `Guardrails`, and `Business Handling When Unavailable`, but do not force every toolset into one fixed template. Start from the real business goal, then decide which sections deserve depth, which can stay brief, and which should be merged or renamed to fit the scenario.',
|
|
3307
|
-
'For each MCP toolset, still document unavailable-case business rules explicitly: at minimum answer 1) whether a temporarily unavailable toolset must be escalated to a coordinator or specialist, 2) whether a manual or alternate-tool fallback path is allowed, and 3) which business actions must pause until this toolset recovers.',
|
|
3308
|
-
'Minimal diagnostic flow: 1) run `team_mgmt_check_provider({ provider_key: \"<providerKey>\", model: \"\", all_models: false, live: false })` to confirm the LLM provider works; 2) review member directory permissions (`man({ "toolsetId": "team_mgmt", "topics": ["permissions"] })`); 3) run `team_mgmt_validate_mcp_cfg({})` to summarize `.minds/mcp.yaml` + MCP issues; 4) use `mcp_restart` if needed, and `mcp_release` when done.',
|
|
3309
|
-
]) +
|
|
3310
|
-
fmtCodeBlock('yaml', [
|
|
3311
|
-
'# Minimal template (stdio)',
|
|
3312
|
-
'version: 1',
|
|
3313
|
-
'servers:',
|
|
3314
|
-
' sdk_stdio:',
|
|
3315
|
-
' truely-stateless: false',
|
|
3316
|
-
' transport: stdio',
|
|
3317
|
-
' command: npx',
|
|
3318
|
-
" args: ['-y', '@some/mcp-server@latest']",
|
|
3319
|
-
' cwd: "."',
|
|
3320
|
-
' env: {}',
|
|
3321
|
-
' tools: { whitelist: [], blacklist: [] }',
|
|
3322
|
-
' transform: []',
|
|
3323
|
-
' manual:',
|
|
3324
|
-
' content: |',
|
|
3325
|
-
' This MCP toolset is for xx and should be preferred in xx cases.',
|
|
3326
|
-
' sections:',
|
|
3327
|
-
" - title: 'When To Use'",
|
|
3328
|
-
' content: |',
|
|
3329
|
-
' 1) Use when ...',
|
|
3330
|
-
' 2) Confirm ... before execution.',
|
|
3331
|
-
" - title: 'Guardrails'",
|
|
3332
|
-
' content: |',
|
|
3333
|
-
' - Avoid using for ...',
|
|
3334
|
-
' - On failures, first inspect ...',
|
|
3335
|
-
" - title: 'Business Handling When Unavailable'",
|
|
3336
|
-
' content: |',
|
|
3337
|
-
' - If this toolset is temporarily unavailable, ask @coordinator (or the designated coordinator) whether to switch to the fallback path.',
|
|
3338
|
-
' - Only use ... as an interim fallback; if the task touches ..., wait for this MCP to recover instead of proceeding.',
|
|
3339
|
-
]) +
|
|
3340
|
-
fmtCodeBlock('yaml', [
|
|
3341
|
-
'# stdio path example (minimal)',
|
|
3342
|
-
'# Relative path: stable with explicit cwd',
|
|
3343
|
-
'command: node',
|
|
3344
|
-
"args: ['./mcp/server.js']",
|
|
3345
|
-
'cwd: "/absolute/path/to/project"',
|
|
3346
|
-
'',
|
|
3347
|
-
'# Absolute path: more stable, independent of cwd',
|
|
3348
|
-
'command: node',
|
|
3349
|
-
"args: ['/absolute/path/to/mcp/server.js']",
|
|
3350
|
-
]) +
|
|
3351
|
-
fmtCodeBlock('yaml', [
|
|
3352
|
-
'# Minimal template (HTTP)',
|
|
3353
|
-
'version: 1',
|
|
3354
|
-
'servers:',
|
|
3355
|
-
' sdk_http:',
|
|
3356
|
-
' truely-stateless: false',
|
|
3357
|
-
' transport: streamable_http',
|
|
3358
|
-
' url: http://127.0.0.1:3000/mcp',
|
|
3359
|
-
' tools: { whitelist: [], blacklist: [] }',
|
|
3360
|
-
' transform: []',
|
|
3361
|
-
' manual:',
|
|
3362
|
-
' content: "For remote MCP endpoint calls"',
|
|
3363
|
-
' sections:',
|
|
3364
|
-
" UseCases: 'Use for ...'",
|
|
3365
|
-
" Guardrails: 'Avoid ...'",
|
|
3366
|
-
]) +
|
|
3367
|
-
mcpMapping +
|
|
3368
|
-
mcpSetup +
|
|
3369
|
-
mcpManualDetails);
|
|
3370
|
-
}
|
|
3371
3209
|
function renderPermissionsManual(language) {
|
|
3372
3210
|
if (language === 'zh') {
|
|
3373
3211
|
return (fmtHeader('权限(目录 + 扩展名)') +
|
|
@@ -3880,532 +3718,6 @@ async function renderModelParamsManual(language) {
|
|
|
3880
3718
|
summary +
|
|
3881
3719
|
'\n');
|
|
3882
3720
|
}
|
|
3883
|
-
function firstNonEmptyLine(raw) {
|
|
3884
|
-
for (const line of raw.split('\n')) {
|
|
3885
|
-
const trimmed = line.trim();
|
|
3886
|
-
if (trimmed !== '')
|
|
3887
|
-
return trimmed;
|
|
3888
|
-
}
|
|
3889
|
-
return raw.trim();
|
|
3890
|
-
}
|
|
3891
|
-
function isObjectRecord(value) {
|
|
3892
|
-
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
3893
|
-
}
|
|
3894
|
-
function parseMcpManualByServer(rawText) {
|
|
3895
|
-
const manualByServerId = new Map();
|
|
3896
|
-
const invalidByServerId = new Map();
|
|
3897
|
-
let parsedRoot;
|
|
3898
|
-
try {
|
|
3899
|
-
parsedRoot = yaml_1.default.parse(rawText);
|
|
3900
|
-
}
|
|
3901
|
-
catch {
|
|
3902
|
-
return { manualByServerId, invalidByServerId };
|
|
3903
|
-
}
|
|
3904
|
-
if (!isObjectRecord(parsedRoot)) {
|
|
3905
|
-
return { manualByServerId, invalidByServerId };
|
|
3906
|
-
}
|
|
3907
|
-
const serversVal = parsedRoot['servers'];
|
|
3908
|
-
if (!isObjectRecord(serversVal)) {
|
|
3909
|
-
return { manualByServerId, invalidByServerId };
|
|
3910
|
-
}
|
|
3911
|
-
for (const [serverId, serverVal] of Object.entries(serversVal)) {
|
|
3912
|
-
if (!isObjectRecord(serverVal))
|
|
3913
|
-
continue;
|
|
3914
|
-
const manualVal = serverVal['manual'];
|
|
3915
|
-
if (manualVal === undefined || manualVal === null)
|
|
3916
|
-
continue;
|
|
3917
|
-
const parsed = parseMcpManualField(serverId, manualVal);
|
|
3918
|
-
if (parsed.kind === 'present') {
|
|
3919
|
-
manualByServerId.set(serverId, parsed.manual);
|
|
3920
|
-
continue;
|
|
3921
|
-
}
|
|
3922
|
-
if (parsed.kind === 'invalid') {
|
|
3923
|
-
invalidByServerId.set(serverId, parsed.errorText);
|
|
3924
|
-
}
|
|
3925
|
-
}
|
|
3926
|
-
return { manualByServerId, invalidByServerId };
|
|
3927
|
-
}
|
|
3928
|
-
function parseMcpManualField(serverId, value) {
|
|
3929
|
-
const fieldPath = `servers.${serverId}.manual`;
|
|
3930
|
-
if (typeof value === 'string') {
|
|
3931
|
-
const text = value.trim();
|
|
3932
|
-
if (text === '') {
|
|
3933
|
-
return { kind: 'invalid', errorText: `${fieldPath} must not be empty` };
|
|
3934
|
-
}
|
|
3935
|
-
return { kind: 'present', manual: { content: text, sections: [] } };
|
|
3936
|
-
}
|
|
3937
|
-
if (!isObjectRecord(value)) {
|
|
3938
|
-
return {
|
|
3939
|
-
kind: 'invalid',
|
|
3940
|
-
errorText: `${fieldPath} must be either a string, or an object with optional content + sections`,
|
|
3941
|
-
};
|
|
3942
|
-
}
|
|
3943
|
-
const contentVal = value['content'];
|
|
3944
|
-
let content;
|
|
3945
|
-
if (contentVal !== undefined) {
|
|
3946
|
-
if (!isNonEmptyString(contentVal)) {
|
|
3947
|
-
return {
|
|
3948
|
-
kind: 'invalid',
|
|
3949
|
-
errorText: `${fieldPath}.content must be a non-empty string when provided`,
|
|
3950
|
-
};
|
|
3951
|
-
}
|
|
3952
|
-
content = contentVal.trim();
|
|
3953
|
-
}
|
|
3954
|
-
const sectionsVal = value['sections'];
|
|
3955
|
-
const sections = [];
|
|
3956
|
-
if (sectionsVal !== undefined) {
|
|
3957
|
-
if (Array.isArray(sectionsVal)) {
|
|
3958
|
-
for (let i = 0; i < sectionsVal.length; i++) {
|
|
3959
|
-
const sectionVal = sectionsVal[i];
|
|
3960
|
-
if (!isObjectRecord(sectionVal)) {
|
|
3961
|
-
return {
|
|
3962
|
-
kind: 'invalid',
|
|
3963
|
-
errorText: `${fieldPath}.sections[${i}] must be an object with title/content non-empty strings`,
|
|
3964
|
-
};
|
|
3965
|
-
}
|
|
3966
|
-
const title = sectionVal['title'];
|
|
3967
|
-
const sectionContent = sectionVal['content'];
|
|
3968
|
-
if (!isNonEmptyString(title) || !isNonEmptyString(sectionContent)) {
|
|
3969
|
-
return {
|
|
3970
|
-
kind: 'invalid',
|
|
3971
|
-
errorText: `${fieldPath}.sections[${i}] must provide non-empty title/content strings`,
|
|
3972
|
-
};
|
|
3973
|
-
}
|
|
3974
|
-
sections.push({ title: title.trim(), content: sectionContent.trim() });
|
|
3975
|
-
}
|
|
3976
|
-
}
|
|
3977
|
-
else if (isObjectRecord(sectionsVal)) {
|
|
3978
|
-
for (const [sectionTitle, sectionContent] of Object.entries(sectionsVal)) {
|
|
3979
|
-
if (!isNonEmptyString(sectionTitle) || !isNonEmptyString(sectionContent)) {
|
|
3980
|
-
return {
|
|
3981
|
-
kind: 'invalid',
|
|
3982
|
-
errorText: `${fieldPath}.sections object entries must be non-empty string -> string`,
|
|
3983
|
-
};
|
|
3984
|
-
}
|
|
3985
|
-
sections.push({ title: sectionTitle.trim(), content: sectionContent.trim() });
|
|
3986
|
-
}
|
|
3987
|
-
}
|
|
3988
|
-
else {
|
|
3989
|
-
return {
|
|
3990
|
-
kind: 'invalid',
|
|
3991
|
-
errorText: `${fieldPath}.sections must be either [{ title, content }] or { "<title>": "<content>" }`,
|
|
3992
|
-
};
|
|
3993
|
-
}
|
|
3994
|
-
}
|
|
3995
|
-
// Note: contentFile is handled by the runtime in config.ts (separate from this validation).
|
|
3996
|
-
// We simply accept the descriptor without requiring content/sections so that contentFile-based
|
|
3997
|
-
// manuals are not flagged as invalid here.
|
|
3998
|
-
return { kind: 'present', manual: { content, sections } };
|
|
3999
|
-
}
|
|
4000
|
-
function describeMcpManualState(language, state) {
|
|
4001
|
-
if (state.kind === 'present') {
|
|
4002
|
-
const contentText = state.manual.content && state.manual.content.trim() !== ''
|
|
4003
|
-
? language === 'zh'
|
|
4004
|
-
? '有'
|
|
4005
|
-
: 'yes'
|
|
4006
|
-
: language === 'zh'
|
|
4007
|
-
? '无'
|
|
4008
|
-
: 'no';
|
|
4009
|
-
return language === 'zh'
|
|
4010
|
-
? `手册=已配置(content=${contentText},sections=${state.manual.sections.length})`
|
|
4011
|
-
: `manual=configured (content=${contentText}, sections=${state.manual.sections.length})`;
|
|
4012
|
-
}
|
|
4013
|
-
if (state.kind === 'invalid') {
|
|
4014
|
-
return language === 'zh'
|
|
4015
|
-
? `手册=声明无效(${firstNonEmptyLine(state.errorText)};不影响 toolset 可用性,但这是团队管理配置问题)`
|
|
4016
|
-
: `manual=invalid declaration (${firstNonEmptyLine(state.errorText)}; toolset availability is unaffected, but team management should fix this)`;
|
|
4017
|
-
}
|
|
4018
|
-
return language === 'zh'
|
|
4019
|
-
? '手册=缺失(不影响 toolset 可用性;这是团队管理配置不足,请根据每个工具 description/参数自行判断使用)'
|
|
4020
|
-
: 'manual=missing (toolset availability is unaffected; this is a team-management gap, so rely on each tool description/arguments and proceed)';
|
|
4021
|
-
}
|
|
4022
|
-
function inferAutoGeneratedMcpIntentDirections(language, toolNames) {
|
|
4023
|
-
const names = toolNames.map((name) => name.toLowerCase());
|
|
4024
|
-
const out = [];
|
|
4025
|
-
const pushUnique = (line) => {
|
|
4026
|
-
if (!out.includes(line))
|
|
4027
|
-
out.push(line);
|
|
4028
|
-
};
|
|
4029
|
-
const has = (needle) => names.some((name) => name.includes(needle));
|
|
4030
|
-
if (has('browser') || has('page') || has('playwright') || has('screenshot')) {
|
|
4031
|
-
pushUnique(language === 'zh'
|
|
4032
|
-
? '网页/浏览器自动化:用于页面操作、采样、信息抓取与可视化回归辅助。'
|
|
4033
|
-
: 'Web/browser automation: page actions, sampling, information extraction, and visual-regression assistance.');
|
|
4034
|
-
}
|
|
4035
|
-
if (has('git') || has('repo') || has('diff') || has('pr') || has('commit')) {
|
|
4036
|
-
pushUnique(language === 'zh'
|
|
4037
|
-
? '仓库协作与变更分析:用于读取仓库状态、比较差异、辅助代码审查。'
|
|
4038
|
-
: 'Repository collaboration and change analysis: inspect repo state, compare diffs, and support review workflows.');
|
|
4039
|
-
}
|
|
4040
|
-
if (has('sql') || has('db') || has('query') || has('table') || has('postgres')) {
|
|
4041
|
-
pushUnique(language === 'zh'
|
|
4042
|
-
? '数据查询/诊断:用于结构化检索与数据一致性排查。'
|
|
4043
|
-
: 'Data query/diagnostics: structured retrieval and data-consistency investigation.');
|
|
4044
|
-
}
|
|
4045
|
-
if (has('k8s') || has('kubectl') || has('deploy') || has('cluster') || has('helm')) {
|
|
4046
|
-
pushUnique(language === 'zh'
|
|
4047
|
-
? '部署与运行状态诊断:用于集群状态检查、发布过程观测与故障定位。'
|
|
4048
|
-
: 'Deployment/runtime diagnostics: cluster-state checks, release observation, and incident localization.');
|
|
4049
|
-
}
|
|
4050
|
-
if (has('ticket') || has('issue') || has('jira') || has('linear')) {
|
|
4051
|
-
pushUnique(language === 'zh'
|
|
4052
|
-
? '任务流转协作:用于工单读取、状态同步与流程追踪。'
|
|
4053
|
-
: 'Ticket/workflow collaboration: ticket lookup, state synchronization, and process tracking.');
|
|
4054
|
-
}
|
|
4055
|
-
if (out.length === 0) {
|
|
4056
|
-
out.push(language === 'zh'
|
|
4057
|
-
? '未识别出明确领域特征:建议按工具 description/参数逐个确认用途,并与人类用户共同定义边界。'
|
|
4058
|
-
: 'No clear domain signature detected: review each tool description/arguments and define boundaries jointly with the human user.');
|
|
4059
|
-
}
|
|
4060
|
-
return out;
|
|
4061
|
-
}
|
|
4062
|
-
function renderAutoGeneratedMcpManualDraftSection(language, entry) {
|
|
4063
|
-
const lines = [];
|
|
4064
|
-
const statusText = entry.status === 'registered'
|
|
4065
|
-
? language === 'zh'
|
|
4066
|
-
? '已加载'
|
|
4067
|
-
: 'loaded'
|
|
4068
|
-
: entry.status === 'declared_unloaded'
|
|
4069
|
-
? language === 'zh'
|
|
4070
|
-
? '已声明但未加载'
|
|
4071
|
-
: 'declared but not loaded'
|
|
4072
|
-
: language === 'zh'
|
|
4073
|
-
? '声明无效'
|
|
4074
|
-
: 'invalid declaration';
|
|
4075
|
-
const transportText = entry.transport === 'invalid' ? 'invalid' : entry.transport === 'stdio' ? 'stdio' : 'http';
|
|
4076
|
-
lines.push(`\n### toolset \`${entry.serverId}\``);
|
|
4077
|
-
lines.push(...fmtList([
|
|
4078
|
-
language === 'zh'
|
|
4079
|
-
? '检测到 `servers.<serverId>.manual` 缺失,以下为自动生成的基础手册草稿(供临时使用)。'
|
|
4080
|
-
: '`servers.<serverId>.manual` is missing. Below is an auto-generated baseline manual draft (temporary use).',
|
|
4081
|
-
language === 'zh'
|
|
4082
|
-
? `运行时状态:status=${statusText},transport=${transportText}。`
|
|
4083
|
-
: `Runtime status: status=${statusText}, transport=${transportText}.`,
|
|
4084
|
-
language === 'zh'
|
|
4085
|
-
? '关键提醒:该草稿不等于最终规范。团队管理者必须与人类用户确认本 rtws 的真实意图后,再写入更准确的正式手册。'
|
|
4086
|
-
: 'Critical reminder: this draft is not the final policy. Team manager must confirm actual rtws intent with the human user, then author a more accurate final manual.',
|
|
4087
|
-
])
|
|
4088
|
-
.trimEnd()
|
|
4089
|
-
.split('\n'));
|
|
4090
|
-
lines.push(...fmtList([
|
|
4091
|
-
language === 'zh'
|
|
4092
|
-
? '章节:tools 列表(运行时快照)'
|
|
4093
|
-
: 'Section: Tools list (runtime snapshot)',
|
|
4094
|
-
])
|
|
4095
|
-
.trimEnd()
|
|
4096
|
-
.split('\n'));
|
|
4097
|
-
if ((entry.loadedToolNames?.length ?? 0) > 0) {
|
|
4098
|
-
const tools = entry.loadedToolNames ?? [];
|
|
4099
|
-
lines.push(...fmtCodeBlock('text', tools.map((tool) => `- ${tool}`))
|
|
4100
|
-
.trimEnd()
|
|
4101
|
-
.split('\n'));
|
|
4102
|
-
}
|
|
4103
|
-
else {
|
|
4104
|
-
lines.push(...fmtList([
|
|
4105
|
-
language === 'zh'
|
|
4106
|
-
? '当前无法给出已加载 tools 清单(通常因为该 server 尚未加载)。先运行 `team_mgmt_validate_mcp_cfg({})`,必要时再 `mcp_restart`。'
|
|
4107
|
-
: 'Loaded tools are not currently available (usually because this server is not loaded yet). Run `team_mgmt_validate_mcp_cfg({})`, then `mcp_restart` if needed.',
|
|
4108
|
-
])
|
|
4109
|
-
.trimEnd()
|
|
4110
|
-
.split('\n'));
|
|
4111
|
-
}
|
|
4112
|
-
lines.push(...fmtList([
|
|
4113
|
-
language === 'zh'
|
|
4114
|
-
? '章节:主要意图方向(自动推测,待确认)'
|
|
4115
|
-
: 'Section: Primary intent directions (auto-inferred, pending confirmation)',
|
|
4116
|
-
])
|
|
4117
|
-
.trimEnd()
|
|
4118
|
-
.split('\n'));
|
|
4119
|
-
lines.push(...fmtList(inferAutoGeneratedMcpIntentDirections(language, entry.loadedToolNames ?? []))
|
|
4120
|
-
.trimEnd()
|
|
4121
|
-
.split('\n'));
|
|
4122
|
-
lines.push(...fmtList([
|
|
4123
|
-
language === 'zh'
|
|
4124
|
-
? '团队管理者后续动作:精读每个工具说明 -> 与人类用户确认意图与边界 -> 明确不可用时是找谁协调、允许哪些降级路径、哪些动作必须暂停 -> 回写 `servers.<serverId>.manual.content + sections`。'
|
|
4125
|
-
: 'Team-manager follow-up: read each tool description carefully -> confirm intent/boundaries with the human user -> decide who coordinates when unavailable, which fallbacks are allowed, and which actions must pause -> write back to `servers.<serverId>.manual.content + sections`.',
|
|
4126
|
-
])
|
|
4127
|
-
.trimEnd()
|
|
4128
|
-
.split('\n'));
|
|
4129
|
-
return lines.join('\n') + '\n';
|
|
4130
|
-
}
|
|
4131
|
-
function renderMcpToolsetManualDetailsSection(language, snapshot) {
|
|
4132
|
-
const header = language === 'zh'
|
|
4133
|
-
? fmtSubHeader('MCP toolset 手册(来自 `.minds/mcp.yaml` 的 `servers.<serverId>.manual`)')
|
|
4134
|
-
: fmtSubHeader('MCP Toolset Manuals (from `.minds/mcp.yaml` `servers.<serverId>.manual`)');
|
|
4135
|
-
if (snapshot.kind !== 'loaded')
|
|
4136
|
-
return '';
|
|
4137
|
-
const entries = snapshot.entries;
|
|
4138
|
-
if (entries.length === 0) {
|
|
4139
|
-
return (header +
|
|
4140
|
-
fmtList([
|
|
4141
|
-
language === 'zh'
|
|
4142
|
-
? '当前没有 MCP toolset 可展示。'
|
|
4143
|
-
: 'There are currently no MCP toolsets to display.',
|
|
4144
|
-
]));
|
|
4145
|
-
}
|
|
4146
|
-
let out = header +
|
|
4147
|
-
fmtList([
|
|
4148
|
-
language === 'zh'
|
|
4149
|
-
? '若 `servers.<serverId>.manual` 已配置,显示正式手册;若缺失,则自动生成基础草稿(含 tools 列表与意图方向草稿)供临时使用。'
|
|
4150
|
-
: 'If `servers.<serverId>.manual` is configured, the formal manual is shown; if missing, an auto-generated baseline draft (including tools list and intent directions draft) is provided for temporary use.',
|
|
4151
|
-
]);
|
|
4152
|
-
for (const entry of entries) {
|
|
4153
|
-
if (entry.manualState.kind === 'missing') {
|
|
4154
|
-
out += renderAutoGeneratedMcpManualDraftSection(language, entry);
|
|
4155
|
-
continue;
|
|
4156
|
-
}
|
|
4157
|
-
if (entry.manualState.kind === 'invalid') {
|
|
4158
|
-
out += `\n### toolset \`${entry.serverId}\`\n`;
|
|
4159
|
-
out += fmtList([
|
|
4160
|
-
language === 'zh'
|
|
4161
|
-
? `\`servers.${entry.serverId}.manual\` 声明无效:${firstNonEmptyLine(entry.manualState.errorText)}`
|
|
4162
|
-
: `\`servers.${entry.serverId}.manual\` is invalid: ${firstNonEmptyLine(entry.manualState.errorText)}`,
|
|
4163
|
-
language === 'zh'
|
|
4164
|
-
? '这不影响 toolset 可用性;请根据工具说明继续使用,并通知团队管理者修复手册字段。'
|
|
4165
|
-
: 'Toolset availability is unaffected; continue by tool-level descriptions and ask the team manager to fix the manual field.',
|
|
4166
|
-
]);
|
|
4167
|
-
continue;
|
|
4168
|
-
}
|
|
4169
|
-
if (entry.manualState.kind !== 'present')
|
|
4170
|
-
continue;
|
|
4171
|
-
const manual = entry.manualState.manual;
|
|
4172
|
-
out += `\n### toolset \`${entry.serverId}\`\n`;
|
|
4173
|
-
if (manual.content && manual.content.trim() !== '') {
|
|
4174
|
-
out +=
|
|
4175
|
-
fmtList([language === 'zh' ? '总说明(content):' : 'Overview (`content`):']) +
|
|
4176
|
-
fmtCodeBlock('markdown', [manual.content]);
|
|
4177
|
-
}
|
|
4178
|
-
else {
|
|
4179
|
-
out += fmtList([
|
|
4180
|
-
language === 'zh'
|
|
4181
|
-
? '总说明(content):(未提供)'
|
|
4182
|
-
: 'Overview (`content`): (not provided)',
|
|
4183
|
-
]);
|
|
4184
|
-
}
|
|
4185
|
-
if (manual.sections.length > 0) {
|
|
4186
|
-
for (const section of manual.sections) {
|
|
4187
|
-
out +=
|
|
4188
|
-
fmtList([language === 'zh' ? `章节:${section.title}` : `Section: ${section.title}`]) +
|
|
4189
|
-
fmtCodeBlock('markdown', [section.content]);
|
|
4190
|
-
}
|
|
4191
|
-
}
|
|
4192
|
-
else {
|
|
4193
|
-
out += fmtList([
|
|
4194
|
-
language === 'zh'
|
|
4195
|
-
? '章节(sections):(未提供)'
|
|
4196
|
-
: 'Sections (`sections`): (not provided)',
|
|
4197
|
-
]);
|
|
4198
|
-
}
|
|
4199
|
-
}
|
|
4200
|
-
return out;
|
|
4201
|
-
}
|
|
4202
|
-
async function readMcpToolsetMappingSnapshot() {
|
|
4203
|
-
const mcpAbsPath = path_1.default.resolve(process.cwd(), MCP_YAML_REL);
|
|
4204
|
-
let rawText;
|
|
4205
|
-
try {
|
|
4206
|
-
rawText = await promises_1.default.readFile(mcpAbsPath, 'utf8');
|
|
4207
|
-
}
|
|
4208
|
-
catch (err) {
|
|
4209
|
-
if (isFsErrWithCode(err) && err.code === 'ENOENT') {
|
|
4210
|
-
return { kind: 'missing' };
|
|
4211
|
-
}
|
|
4212
|
-
return {
|
|
4213
|
-
kind: 'invalid_yaml',
|
|
4214
|
-
errorText: err instanceof Error ? err.message : String(err),
|
|
4215
|
-
};
|
|
4216
|
-
}
|
|
4217
|
-
const parsed = (0, config_1.parseMcpYaml)(rawText);
|
|
4218
|
-
if (!parsed.ok) {
|
|
4219
|
-
return { kind: 'invalid_yaml', errorText: parsed.errorText };
|
|
4220
|
-
}
|
|
4221
|
-
const manualInfo = parseMcpManualByServer(rawText);
|
|
4222
|
-
const registeredToolsets = (0, registry_2.listToolsets)();
|
|
4223
|
-
const invalidByServerId = new Map();
|
|
4224
|
-
for (const invalid of parsed.invalidServers) {
|
|
4225
|
-
invalidByServerId.set(invalid.serverId, invalid.errorText);
|
|
4226
|
-
}
|
|
4227
|
-
const entries = [];
|
|
4228
|
-
for (const serverId of parsed.serverIdsInYamlOrder) {
|
|
4229
|
-
const invalidError = invalidByServerId.get(serverId);
|
|
4230
|
-
const manualError = manualInfo.invalidByServerId.get(serverId);
|
|
4231
|
-
const manual = manualInfo.manualByServerId.get(serverId);
|
|
4232
|
-
const manualState = manualError
|
|
4233
|
-
? { kind: 'invalid', errorText: manualError }
|
|
4234
|
-
: manual
|
|
4235
|
-
? { kind: 'present', manual }
|
|
4236
|
-
: { kind: 'missing' };
|
|
4237
|
-
if (invalidError) {
|
|
4238
|
-
entries.push({
|
|
4239
|
-
serverId,
|
|
4240
|
-
transport: 'invalid',
|
|
4241
|
-
status: 'declared_invalid',
|
|
4242
|
-
errorText: invalidError,
|
|
4243
|
-
manualState,
|
|
4244
|
-
});
|
|
4245
|
-
continue;
|
|
4246
|
-
}
|
|
4247
|
-
const transport = parsed.config.servers[serverId]?.transport ?? 'invalid';
|
|
4248
|
-
const loadedTools = registeredToolsets[serverId];
|
|
4249
|
-
if (loadedTools) {
|
|
4250
|
-
const loadedToolNames = loadedTools.map((t) => t.name);
|
|
4251
|
-
entries.push({
|
|
4252
|
-
serverId,
|
|
4253
|
-
transport,
|
|
4254
|
-
status: 'registered',
|
|
4255
|
-
loadedToolCount: loadedTools.length,
|
|
4256
|
-
loadedToolNames,
|
|
4257
|
-
loadedToolNamesPreview: loadedToolNames.slice(0, 6),
|
|
4258
|
-
manualState,
|
|
4259
|
-
});
|
|
4260
|
-
continue;
|
|
4261
|
-
}
|
|
4262
|
-
entries.push({
|
|
4263
|
-
serverId,
|
|
4264
|
-
transport,
|
|
4265
|
-
status: 'declared_unloaded',
|
|
4266
|
-
manualState,
|
|
4267
|
-
});
|
|
4268
|
-
}
|
|
4269
|
-
return { kind: 'loaded', entries };
|
|
4270
|
-
}
|
|
4271
|
-
function renderMcpToolsetMappingSection(language, snapshot) {
|
|
4272
|
-
const header = language === 'zh'
|
|
4273
|
-
? fmtSubHeader('MCP serverId -> toolset 当前映射(动态读取 .minds/mcp.yaml)')
|
|
4274
|
-
: fmtSubHeader('Current MCP serverId -> toolset mapping (from .minds/mcp.yaml)');
|
|
4275
|
-
if (snapshot.kind === 'missing') {
|
|
4276
|
-
const items = language === 'zh'
|
|
4277
|
-
? [
|
|
4278
|
-
`未发现 \`${MCP_YAML_REL}\`;当前没有可映射的 MCP toolset。`,
|
|
4279
|
-
`设置方法:在 \`${MCP_YAML_REL}\` 增加 \`servers.<serverId>\`,该 \`serverId\` 会映射为同名 toolset。`,
|
|
4280
|
-
]
|
|
4281
|
-
: [
|
|
4282
|
-
`\`${MCP_YAML_REL}\` not found; there are currently no MCP toolsets to map.`,
|
|
4283
|
-
`Setup rule: add \`servers.<serverId>\` in \`${MCP_YAML_REL}\`; that \`serverId\` maps to a toolset with the same name.`,
|
|
4284
|
-
];
|
|
4285
|
-
return header + fmtList(items);
|
|
4286
|
-
}
|
|
4287
|
-
if (snapshot.kind === 'invalid_yaml') {
|
|
4288
|
-
const items = language === 'zh'
|
|
4289
|
-
? [
|
|
4290
|
-
`\`${MCP_YAML_REL}\` 解析失败,暂时无法生成 serverId -> toolset 映射。`,
|
|
4291
|
-
`错误:${firstNonEmptyLine(snapshot.errorText)}`,
|
|
4292
|
-
`先运行 \`team_mgmt_validate_mcp_cfg({})\` 修复配置,再查看映射。`,
|
|
4293
|
-
]
|
|
4294
|
-
: [
|
|
4295
|
-
`Failed to parse \`${MCP_YAML_REL}\`; cannot build serverId -> toolset mapping yet.`,
|
|
4296
|
-
`Error: ${firstNonEmptyLine(snapshot.errorText)}`,
|
|
4297
|
-
`Run \`team_mgmt_validate_mcp_cfg({})\` first, then re-check mapping.`,
|
|
4298
|
-
];
|
|
4299
|
-
return header + fmtList(items);
|
|
4300
|
-
}
|
|
4301
|
-
if (snapshot.entries.length === 0) {
|
|
4302
|
-
const items = language === 'zh'
|
|
4303
|
-
? [
|
|
4304
|
-
`\`${MCP_YAML_REL}\` 已存在,但 \`servers\` 为空;当前没有 MCP toolset。`,
|
|
4305
|
-
`添加 \`servers.<serverId>\` 后,对应 \`serverId\` 会映射为同名 toolset。`,
|
|
4306
|
-
]
|
|
4307
|
-
: [
|
|
4308
|
-
`\`${MCP_YAML_REL}\` exists but \`servers\` is empty; there are currently no MCP toolsets.`,
|
|
4309
|
-
`After adding \`servers.<serverId>\`, that \`serverId\` maps to a same-name toolset.`,
|
|
4310
|
-
];
|
|
4311
|
-
return header + fmtList(items);
|
|
4312
|
-
}
|
|
4313
|
-
const lines = [];
|
|
4314
|
-
for (const entry of snapshot.entries) {
|
|
4315
|
-
const transportText = entry.transport === 'invalid' ? 'invalid' : entry.transport === 'stdio' ? 'stdio' : 'http';
|
|
4316
|
-
const manualText = describeMcpManualState(language, entry.manualState);
|
|
4317
|
-
if (entry.status === 'registered') {
|
|
4318
|
-
const preview = entry.loadedToolNamesPreview ?? [];
|
|
4319
|
-
const previewText = preview.length > 0
|
|
4320
|
-
? preview.join(', ') +
|
|
4321
|
-
(entry.loadedToolCount !== undefined && entry.loadedToolCount > preview.length
|
|
4322
|
-
? ', ...'
|
|
4323
|
-
: '')
|
|
4324
|
-
: '(none)';
|
|
4325
|
-
lines.push(language === 'zh'
|
|
4326
|
-
? `\`servers.${entry.serverId}\` -> toolset \`${entry.serverId}\`(transport=${transportText},状态=已加载,tools=${entry.loadedToolCount ?? 0}:${previewText};${manualText})`
|
|
4327
|
-
: `\`servers.${entry.serverId}\` -> toolset \`${entry.serverId}\` (transport=${transportText}, status=loaded, tools=${entry.loadedToolCount ?? 0}: ${previewText}; ${manualText})`);
|
|
4328
|
-
continue;
|
|
4329
|
-
}
|
|
4330
|
-
if (entry.status === 'declared_unloaded') {
|
|
4331
|
-
lines.push(language === 'zh'
|
|
4332
|
-
? `\`servers.${entry.serverId}\` -> toolset \`${entry.serverId}\`(transport=${transportText},状态=已声明但未加载;${manualText})`
|
|
4333
|
-
: `\`servers.${entry.serverId}\` -> toolset \`${entry.serverId}\` (transport=${transportText}, status=declared but not loaded; ${manualText})`);
|
|
4334
|
-
continue;
|
|
4335
|
-
}
|
|
4336
|
-
lines.push(language === 'zh'
|
|
4337
|
-
? `\`servers.${entry.serverId}\` -> toolset \`${entry.serverId}\`(状态=声明无效:${firstNonEmptyLine(entry.errorText ?? '')};${manualText})`
|
|
4338
|
-
: `\`servers.${entry.serverId}\` -> toolset \`${entry.serverId}\` (status=invalid declaration: ${firstNonEmptyLine(entry.errorText ?? '')}; ${manualText})`);
|
|
4339
|
-
}
|
|
4340
|
-
const tail = language === 'zh'
|
|
4341
|
-
? [
|
|
4342
|
-
'说明:`已声明但未加载` 通常表示当前会话尚未完成 MCP 重载,或 server 启动失败。',
|
|
4343
|
-
'说明:MCP toolset “没有 manual” 不等于“不可用”。无 manual 仅表示团队管理者没有提供章节化手册;你应继续阅读每个工具的 description/参数并谨慎使用。',
|
|
4344
|
-
'建议:运行 `team_mgmt_validate_mcp_cfg({})`,必要时执行 `mcp_restart`。',
|
|
4345
|
-
]
|
|
4346
|
-
: [
|
|
4347
|
-
'`declared but not loaded` usually means MCP reload has not completed in the current session, or server startup failed.',
|
|
4348
|
-
'Important: “missing manual” for an MCP toolset does NOT mean unavailable. It only means the team manager did not provide chapterized manual text; continue by reading each tool description/arguments and use with care.',
|
|
4349
|
-
'Recommendation: run `team_mgmt_validate_mcp_cfg({})`, then `mcp_restart` if needed.',
|
|
4350
|
-
];
|
|
4351
|
-
return header + fmtList(lines.concat(tail));
|
|
4352
|
-
}
|
|
4353
|
-
function renderMcpToolsetSetupGuideSection(language, snapshot) {
|
|
4354
|
-
const title = language === 'zh'
|
|
4355
|
-
? fmtSubHeader('MCP toolset 设置方法与示例')
|
|
4356
|
-
: fmtSubHeader('How To Set Up MCP Toolsets (with example)');
|
|
4357
|
-
const fallbackServerId = 'your_mcp_server';
|
|
4358
|
-
const exampleServerId = snapshot.kind === 'loaded' && snapshot.entries.length > 0
|
|
4359
|
-
? (snapshot.entries[0]?.serverId ?? fallbackServerId)
|
|
4360
|
-
: fallbackServerId;
|
|
4361
|
-
const exampleTransport = snapshot.kind === 'loaded'
|
|
4362
|
-
? (snapshot.entries.find((e) => e.transport !== 'invalid')?.transport ?? 'stdio')
|
|
4363
|
-
: 'stdio';
|
|
4364
|
-
const notes = language === 'zh'
|
|
4365
|
-
? fmtList([
|
|
4366
|
-
`步骤 1:在 \`${MCP_YAML_REL}\` 声明 \`servers.${exampleServerId}\`。`,
|
|
4367
|
-
`步骤 2:在 \`${TEAM_YAML_REL}\` 的 \`members.<id>.toolsets\` 添加 \`${exampleServerId}\`。`,
|
|
4368
|
-
`规则:MCP toolset 名称恒等于 \`serverId\`(不加前缀)。`,
|
|
4369
|
-
])
|
|
4370
|
-
: fmtList([
|
|
4371
|
-
`Step 1: declare \`servers.${exampleServerId}\` in \`${MCP_YAML_REL}\`.`,
|
|
4372
|
-
`Step 2: add \`${exampleServerId}\` under \`members.<id>.toolsets\` in \`${TEAM_YAML_REL}\`.`,
|
|
4373
|
-
`Rule: MCP toolset name is exactly the \`serverId\` (no prefix).`,
|
|
4374
|
-
]);
|
|
4375
|
-
const mcpExample = exampleTransport === 'streamable_http'
|
|
4376
|
-
? fmtCodeBlock('yaml', [
|
|
4377
|
-
'# .minds/mcp.yaml',
|
|
4378
|
-
'version: 1',
|
|
4379
|
-
'servers:',
|
|
4380
|
-
` ${exampleServerId}:`,
|
|
4381
|
-
' truely-stateless: false',
|
|
4382
|
-
' transport: streamable_http',
|
|
4383
|
-
' url: http://127.0.0.1:3000/mcp',
|
|
4384
|
-
' tools: { whitelist: [], blacklist: [] }',
|
|
4385
|
-
' transform: []',
|
|
4386
|
-
])
|
|
4387
|
-
: fmtCodeBlock('yaml', [
|
|
4388
|
-
'# .minds/mcp.yaml',
|
|
4389
|
-
'version: 1',
|
|
4390
|
-
'servers:',
|
|
4391
|
-
` ${exampleServerId}:`,
|
|
4392
|
-
' truely-stateless: false',
|
|
4393
|
-
' transport: stdio',
|
|
4394
|
-
' command: npx',
|
|
4395
|
-
" args: ['-y', '@some/mcp-server@latest']",
|
|
4396
|
-
' tools: { whitelist: [], blacklist: [] }',
|
|
4397
|
-
' transform: []',
|
|
4398
|
-
]);
|
|
4399
|
-
const teamExample = fmtCodeBlock('yaml', [
|
|
4400
|
-
'# .minds/team.yaml',
|
|
4401
|
-
'members:',
|
|
4402
|
-
' operator:',
|
|
4403
|
-
' toolsets:',
|
|
4404
|
-
' - ws_read',
|
|
4405
|
-
` - ${exampleServerId}`,
|
|
4406
|
-
]);
|
|
4407
|
-
return title + notes + mcpExample + teamExample;
|
|
4408
|
-
}
|
|
4409
3721
|
function renderToolsetCapabilitySummary(language, ids, toolsetsById) {
|
|
4410
3722
|
const header = language === 'zh' ? fmtSubHeader('工具集能力摘要') : fmtSubHeader('Toolset Capability Summary');
|
|
4411
3723
|
const lines = [];
|
|
@@ -4554,10 +3866,10 @@ async function renderToolsets(language) {
|
|
|
4554
3866
|
]);
|
|
4555
3867
|
const list = fmtList(ids.map((id) => `\`${id}\``));
|
|
4556
3868
|
const capabilitySummary = renderToolsetCapabilitySummary(language, ids, toolsetsById);
|
|
4557
|
-
const mcpSnapshot = await readMcpToolsetMappingSnapshot();
|
|
4558
|
-
const mcpMapping = renderMcpToolsetMappingSection(language, mcpSnapshot);
|
|
4559
|
-
const mcpSetup = renderMcpToolsetSetupGuideSection(language, mcpSnapshot);
|
|
4560
|
-
const mcpManualDetails = renderMcpToolsetManualDetailsSection(language, mcpSnapshot);
|
|
3869
|
+
const mcpSnapshot = await (0, team_mgmt_mcp_manual_1.readMcpToolsetMappingSnapshot)();
|
|
3870
|
+
const mcpMapping = (0, team_mgmt_mcp_manual_1.renderMcpToolsetMappingSection)(language, mcpSnapshot);
|
|
3871
|
+
const mcpSetup = (0, team_mgmt_mcp_manual_1.renderMcpToolsetSetupGuideSection)(language, mcpSnapshot);
|
|
3872
|
+
const mcpManualDetails = (0, team_mgmt_mcp_manual_1.renderMcpToolsetManualDetailsSection)(language, mcpSnapshot);
|
|
4561
3873
|
return (header +
|
|
4562
3874
|
intro +
|
|
4563
3875
|
patterns +
|
|
@@ -4864,8 +4176,8 @@ exports.teamMgmtValidateMcpCfgTool = {
|
|
|
4864
4176
|
const mcpYamlAbs = path_1.default.resolve(cwd, MCP_YAML_REL);
|
|
4865
4177
|
let mcpRaw = null;
|
|
4866
4178
|
let declaredServerCount = 0;
|
|
4179
|
+
let declaredServerIdsInYamlOrder = [];
|
|
4867
4180
|
let fallbackInvalidServers = [];
|
|
4868
|
-
let fallbackInvalidToolsetManuals = [];
|
|
4869
4181
|
try {
|
|
4870
4182
|
const st = await promises_1.default.stat(mcpYamlAbs);
|
|
4871
4183
|
if (!st.isFile()) {
|
|
@@ -4895,9 +4207,8 @@ exports.teamMgmtValidateMcpCfgTool = {
|
|
|
4895
4207
|
return fail(msg, [{ type: 'environment_msg', role: 'user', content: msg }]);
|
|
4896
4208
|
}
|
|
4897
4209
|
declaredServerCount = parsed.serverIdsInYamlOrder.length;
|
|
4210
|
+
declaredServerIdsInYamlOrder = parsed.serverIdsInYamlOrder;
|
|
4898
4211
|
fallbackInvalidServers = parsed.invalidServers;
|
|
4899
|
-
const manualInfo = parseMcpManualByServer(mcpRaw);
|
|
4900
|
-
fallbackInvalidToolsetManuals = [...manualInfo.invalidByServerId.entries()].map(([serverId, errorText]) => ({ serverId, errorText }));
|
|
4901
4212
|
}
|
|
4902
4213
|
catch (err) {
|
|
4903
4214
|
if (!(isFsErrWithCode(err) && err.code === 'ENOENT')) {
|
|
@@ -4916,18 +4227,7 @@ exports.teamMgmtValidateMcpCfgTool = {
|
|
|
4916
4227
|
fallbackOnlyInvalidServers.push(s);
|
|
4917
4228
|
}
|
|
4918
4229
|
}
|
|
4919
|
-
|
|
4920
|
-
for (const s of fallbackInvalidToolsetManuals) {
|
|
4921
|
-
const hasMatchingProblem = activeMcpProblems.some((p) => p.kind === 'mcp_server_error' &&
|
|
4922
|
-
p.detail.serverId === s.serverId &&
|
|
4923
|
-
p.detail.errorText.includes(firstNonEmptyLine(s.errorText)));
|
|
4924
|
-
if (!hasMatchingProblem) {
|
|
4925
|
-
fallbackOnlyInvalidToolsetManuals.push(s);
|
|
4926
|
-
}
|
|
4927
|
-
}
|
|
4928
|
-
if (activeMcpProblems.length === 0 &&
|
|
4929
|
-
fallbackOnlyInvalidServers.length === 0 &&
|
|
4930
|
-
fallbackOnlyInvalidToolsetManuals.length === 0) {
|
|
4230
|
+
if (activeMcpProblems.length === 0 && fallbackOnlyInvalidServers.length === 0) {
|
|
4931
4231
|
const msg = language === 'zh'
|
|
4932
4232
|
? fmtHeader('mcp.yaml 校验通过') +
|
|
4933
4233
|
fmtList([
|
|
@@ -4976,17 +4276,7 @@ exports.teamMgmtValidateMcpCfgTool = {
|
|
|
4976
4276
|
issueLines.push(` serverId: ${s.serverId}`);
|
|
4977
4277
|
issueLines.push(' ' + s.errorText.split('\n').join('\n '));
|
|
4978
4278
|
}
|
|
4979
|
-
|
|
4980
|
-
issueLines.push(`- [error] ${MCP_SERVER_PROBLEM_PREFIX}${s.serverId}/toolset_manual_error`);
|
|
4981
|
-
issueLines.push(` serverId: ${s.serverId}`);
|
|
4982
|
-
issueLines.push(language === 'zh'
|
|
4983
|
-
? ' toolset manual: servers.<serverId>.manual 声明无效'
|
|
4984
|
-
: ' toolset manual: servers.<serverId>.manual invalid declaration');
|
|
4985
|
-
issueLines.push(' ' + s.errorText.split('\n').join('\n '));
|
|
4986
|
-
}
|
|
4987
|
-
const totalIssues = activeMcpProblems.length +
|
|
4988
|
-
fallbackOnlyInvalidServers.length +
|
|
4989
|
-
fallbackOnlyInvalidToolsetManuals.length;
|
|
4279
|
+
const totalIssues = activeMcpProblems.length + fallbackOnlyInvalidServers.length;
|
|
4990
4280
|
const resolvedIssueBlock = resolvedMcpProblems.length > 0
|
|
4991
4281
|
? fmtSubHeader(language === 'zh' ? '已解决但未清理的问题' : 'Resolved But Not Yet Cleared') +
|
|
4992
4282
|
fmtList([
|
|
@@ -5268,141 +4558,6 @@ exports.teamMgmtClearProblemsTool = {
|
|
|
5268
4558
|
}
|
|
5269
4559
|
},
|
|
5270
4560
|
};
|
|
5271
|
-
async function renderTeamMgmtGuideContent(language, topicsRaw = []) {
|
|
5272
|
-
const topics = parseTeamMgmtGuideTopics(topicsRaw);
|
|
5273
|
-
const msgPrefix = language === 'zh'
|
|
5274
|
-
? `(生成时间:${(0, time_1.formatUnifiedTimestamp)(new Date())})\n\n`
|
|
5275
|
-
: `(Generated: ${(0, time_1.formatUnifiedTimestamp)(new Date())})\n\n`;
|
|
5276
|
-
const renderIndex = () => {
|
|
5277
|
-
const topicTitle = (key) => (0, kernel_1.getTeamMgmtGuideTopicTitle)(language, key);
|
|
5278
|
-
if (language === 'zh') {
|
|
5279
|
-
return (fmtHeader('Team Management Manual') +
|
|
5280
|
-
msgPrefix +
|
|
5281
|
-
fmtList([
|
|
5282
|
-
`\`man({ "toolsetId": "team_mgmt", "topics": ["topics"] })\`:${topicTitle('topics')}(你在这里)`,
|
|
5283
|
-
'新手最常见流程:先 `team_mgmt_list_providers({})` / `team_mgmt_list_models({ provider_pattern: "*", model_pattern: "*" })` 确认 provider/model keys → 再写 `.minds/team.yaml` → 再写 `.minds/team/<id>/persona.*.md` → 再跑 `team_mgmt_check_provider({ provider_key: "<providerKey>", model: "", all_models: false, live: false })`。',
|
|
5284
|
-
'',
|
|
5285
|
-
`\`man({ "toolsetId": "team_mgmt", "topics": ["team"] })\`:${topicTitle('team')} — .minds/team.yaml(团队花名册、工具集、目录权限入口)`,
|
|
5286
|
-
`\`man({ "toolsetId": "team_mgmt", "topics": ["minds"] })\`:${topicTitle('minds')} — .minds/team/<id>/*(persona/knowhow/pitfalls 资产怎么写)`,
|
|
5287
|
-
`\`man({ "toolsetId": "team_mgmt", "topics": ["skills"] })\`:${topicTitle('skills')} — .minds/skills/*(公开 skill 格式迁移、字段映射、app 化边界)`,
|
|
5288
|
-
`\`man({ "toolsetId": "team_mgmt", "topics": ["priming"] })\`:${topicTitle('priming')} — .minds/priming/*(启动脚本如何编写、维护与复用)`,
|
|
5289
|
-
'`启动脚本修改后建议立即运行:`team_mgmt_validate_priming_scripts({})`',
|
|
5290
|
-
`\`man({ "toolsetId": "team_mgmt", "topics": ["env"] })\`:${topicTitle('env')} — .minds/env.*.md(运行环境提示:在团队介绍之前注入)`,
|
|
5291
|
-
`\`man({ "toolsetId": "team_mgmt", "topics": ["permissions"] })\`:${topicTitle('permissions')} — 目录+扩展名权限(*_dirs/no_*_dirs/*_file_ext_names/no_*_file_ext_names 语义与冲突规则)`,
|
|
5292
|
-
`\`man({ "toolsetId": "team_mgmt", "topics": ["toolsets"] })\`:${topicTitle('toolsets')} — toolsets 列表(当前已注册 toolsets;常见三种授权模式)`,
|
|
5293
|
-
`\`man({ "toolsetId": "team_mgmt", "topics": ["llm"] })\`:${topicTitle('llm')} — .minds/llm.yaml(provider key 如何定义/引用;env var 安全边界)`,
|
|
5294
|
-
`\`man({ "toolsetId": "team_mgmt", "topics": ["mcp"] })\`:${topicTitle('mcp')} — .minds/mcp.yaml(MCP serverId→toolset;热重载与租用;可复制最小模板)`,
|
|
5295
|
-
`\`man({ "toolsetId": "team_mgmt", "topics": ["troubleshooting"] })\`:${topicTitle('troubleshooting')} — 按症状定位;优先 list_providers/list_models → check_provider`,
|
|
5296
|
-
'',
|
|
5297
|
-
`\`man({ "toolsetId": "team_mgmt", "topics": ["team","member-properties"] })\`:${topicTitle('team')} + ${topicTitle('member-properties')} — 成员字段表(members.<id> 字段参考)`,
|
|
5298
|
-
`\`man({ "toolsetId": "team_mgmt", "topics": ["llm","builtin-defaults"] })\`:${topicTitle('llm')} + ${topicTitle('builtin-defaults')} — 内置 defaults 摘要(内置 provider/model 概览与合并语义)`,
|
|
5299
|
-
`\`man({ "toolsetId": "team_mgmt", "topics": ["llm","model-params"] })\`:${topicTitle('llm')} + ${topicTitle('model-params')} — 模型参数参考(model_params / model_param_options)`,
|
|
5300
|
-
]));
|
|
5301
|
-
}
|
|
5302
|
-
return (fmtHeader('Team Management Manual') +
|
|
5303
|
-
msgPrefix +
|
|
5304
|
-
fmtList([
|
|
5305
|
-
`\`man({ "toolsetId": "team_mgmt", "topics": ["topics"] })\`: ${topicTitle('topics')} (you are here)`,
|
|
5306
|
-
'Common starter flow: run `team_mgmt_list_providers({})` / `team_mgmt_list_models({ provider_pattern: \"*\", model_pattern: \"*\" })` to confirm provider/model keys → write `.minds/team.yaml` → write `.minds/team/<id>/persona.*.md` → run `team_mgmt_check_provider({ provider_key: "<providerKey>", model: "", all_models: false, live: false })`. ',
|
|
5307
|
-
'',
|
|
5308
|
-
`\`man({ "toolsetId": "team_mgmt", "topics": ["team"] })\`: ${topicTitle('team')} — .minds/team.yaml (roster/toolsets/permissions entrypoint)`,
|
|
5309
|
-
`\`man({ "toolsetId": "team_mgmt", "topics": ["minds"] })\`: ${topicTitle('minds')} — .minds/team/<id>/* (persona/knowhow/pitfalls assets)`,
|
|
5310
|
-
`\`man({ "toolsetId": "team_mgmt", "topics": ["skills"] })\`: ${topicTitle('skills')} — .minds/skills/* (public skill migration, field mapping, app boundary)`,
|
|
5311
|
-
`\`man({ "toolsetId": "team_mgmt", "topics": ["priming"] })\`: ${topicTitle('priming')} — .minds/priming/* (how to author, maintain, and reuse startup scripts)`,
|
|
5312
|
-
'After editing startup scripts, run: `team_mgmt_validate_priming_scripts({})`.',
|
|
5313
|
-
`\`man({ "toolsetId": "team_mgmt", "topics": ["env"] })\`: ${topicTitle('env')} — .minds/env.*.md (runtime intro injected before Team Directory)`,
|
|
5314
|
-
`\`man({ "toolsetId": "team_mgmt", "topics": ["permissions"] })\`: ${topicTitle('permissions')} — directory + extension permissions (semantics + conflict rules)`,
|
|
5315
|
-
`\`man({ "toolsetId": "team_mgmt", "topics": ["toolsets"] })\`: ${topicTitle('toolsets')} — toolsets list (registered toolsets + common patterns)`,
|
|
5316
|
-
`\`man({ "toolsetId": "team_mgmt", "topics": ["llm"] })\`: ${topicTitle('llm')} — .minds/llm.yaml (provider keys, env var boundaries)`,
|
|
5317
|
-
`\`man({ "toolsetId": "team_mgmt", "topics": ["mcp"] })\`: ${topicTitle('mcp')} — .minds/mcp.yaml (serverId→toolset, hot reload, leasing, minimal templates)`,
|
|
5318
|
-
`\`man({ "toolsetId": "team_mgmt", "topics": ["troubleshooting"] })\`: ${topicTitle('troubleshooting')} — symptom → steps; start with list_providers/list_models, then check_provider`,
|
|
5319
|
-
'',
|
|
5320
|
-
`\`man({ "toolsetId": "team_mgmt", "topics": ["team","member-properties"] })\`: ${topicTitle('team')} + ${topicTitle('member-properties')} — member field reference (members.<id>)`,
|
|
5321
|
-
`\`man({ "toolsetId": "team_mgmt", "topics": ["llm","builtin-defaults"] })\`: ${topicTitle('llm')} + ${topicTitle('builtin-defaults')} — built-in defaults summary (what/when/merge behavior)`,
|
|
5322
|
-
`\`man({ "toolsetId": "team_mgmt", "topics": ["llm","model-params"] })\`: ${topicTitle('llm')} + ${topicTitle('model-params')} — \`model_params\` and \`model_param_options\` reference`,
|
|
5323
|
-
]));
|
|
5324
|
-
};
|
|
5325
|
-
const want = (t) => topics.includes(t);
|
|
5326
|
-
try {
|
|
5327
|
-
if (topics.length === 0) {
|
|
5328
|
-
return renderIndex();
|
|
5329
|
-
}
|
|
5330
|
-
if (want('topics')) {
|
|
5331
|
-
return renderIndex();
|
|
5332
|
-
}
|
|
5333
|
-
if (want('team') && want('member-properties')) {
|
|
5334
|
-
return renderMemberProperties(language);
|
|
5335
|
-
}
|
|
5336
|
-
if (want('team')) {
|
|
5337
|
-
return renderTeamManual(language);
|
|
5338
|
-
}
|
|
5339
|
-
if (want('llm') && want('builtin-defaults')) {
|
|
5340
|
-
return await renderBuiltinDefaults(language);
|
|
5341
|
-
}
|
|
5342
|
-
if (want('llm') && want('model-params')) {
|
|
5343
|
-
return await renderModelParamsManual(language);
|
|
5344
|
-
}
|
|
5345
|
-
if (want('llm')) {
|
|
5346
|
-
return language === 'zh'
|
|
5347
|
-
? fmtHeader('.minds/llm.yaml') +
|
|
5348
|
-
fmtList([
|
|
5349
|
-
'定义 provider key → model 映射(用于 `.minds/team.yaml` 的 `member_defaults.provider` / `members.<id>.provider` 引用)。',
|
|
5350
|
-
'快速自检:用 `team_mgmt_list_providers({})` 列出内置/rtws provider keys、env var 是否配置;用 `team_mgmt_list_models({ source: \"effective\", provider_pattern: \"*\", model_pattern: \"*\" })` 列出“合并后”的模型与 `model_param_options`。',
|
|
5351
|
-
'最小示例:\n```yaml\nproviders:\n my_provider:\n apiKeyEnvVar: MY_PROVIDER_API_KEY\n models:\n my_model: { name: "my-model-id" }\n```\n然后在 `.minds/team.yaml` 里引用 `provider: my_provider` / `model: my_model`。',
|
|
5352
|
-
'覆盖/合并语义:`.minds/llm.yaml` 会在内置 defaults 之上做覆盖(以当前实现为准);定义一个 provider key 并不意味着“禁用其他内置 provider”。',
|
|
5353
|
-
'不要在文件里存 API key,使用环境变量(apiKeyEnvVar)。',
|
|
5354
|
-
'member_defaults.provider/model 需要引用这里的 key。',
|
|
5355
|
-
'`model_param_options` 可选:用于记录该 provider 支持的 `.minds/team.yaml model_params` 选项(文档用途)。',
|
|
5356
|
-
'`apiQuirks` 可选:写在 `providers.<providerKey>.apiQuirks`,类型是 `string|string[]`。它是 provider 级 transport / 网关兼容开关,用来描述“这个供应商/网关的 API 有非标准行为”,不是 `.minds/team.yaml` 的成员参数,也不是 `model_params`。',
|
|
5357
|
-
'使用原则:只有在你确认某个上游网关确实偏离了标准协议,而且 Dominds 已为这个偏差实现了命名 quirk 时才配置;不要把它当作随意调参入口。当前实现里,未知 quirk 值通常不会报错,但也不会带来任何效果。',
|
|
5358
|
-
'当前已知示例:OpenAI Responses 包装层支持 `apiQuirks: xcode.best`(或数组里包含它)。它一方面会把供应商额外发出的 `keepalive` 流事件识别为 heartbeat,而不是当作异常事件处理;另一方面也会对该网关特有的失败模式做 provider-specific failure handling,包括“同一对话上下文连续返回 empty response”时先做少量临时重试;如果在同一未变化上下文里连续达到阈值,就判定这是 provider 侧 same-context deadlock,而不是普通基础设施抖动:此时继续沿用同一上下文自动重试大概率仍然不会有真实进展,必须引入新的信息或新的指令(例如补充上下文、改写问题、换一个切入方式,或在确实需要人类判断时调用 askHuman)。这类 provider/API retry 状态在同一次 driver 自动续跑链里会继续沿用,不因中途换 course 而自动清零;若当前对话启用了鞭策,driver 也会优先判断是否能按鞭策逻辑直接续跑一次,而不是先落入 stopped,并且一旦 driver 接受这次自动恢复资格,就会立刻记作已消费;以及把网关返回的 HTML 版 502 Bad Gateway 错误页和 `500 auth_unavailable: no auth available` 这类基础设施失败归类为 conservative 策略重试。最小示例:\n```yaml\nproviders:\n my_gateway:\n apiType: openai\n baseUrl: https://example.invalid/v1\n apiKeyEnvVar: MY_GATEWAY_API_KEY\n apiQuirks: xcode.best\n models:\n my_model: { name: \"upstream-model-id\" }\n```',
|
|
5359
|
-
'边界提醒:`apiQuirks` 只影响实现里显式消费它的 provider/generator。就当前实现看,至少 OpenAI Responses 路径会读取它;不要假设所有 `apiType` 都支持或需要它。若配置后行为仍异常,应继续检查上游网关文档、抓流事件类型,并结合 `team_mgmt_check_provider(...)` / 运行日志排查。',
|
|
5360
|
-
])
|
|
5361
|
-
: fmtHeader('.minds/llm.yaml') +
|
|
5362
|
-
fmtList([
|
|
5363
|
-
'Defines provider keys → model keys (referenced by `.minds/team.yaml` via `member_defaults.provider` / `members.<id>.provider`).',
|
|
5364
|
-
'Quick checks: use `team_mgmt_list_providers({})` to list built-in/rtws providers + env-var readiness; use `team_mgmt_list_models({ source: \"effective\", provider_pattern: \"*\", model_pattern: \"*\" })` to list merged models and `model_param_options`.',
|
|
5365
|
-
'Minimal example:\n```yaml\nproviders:\n my_provider:\n apiKeyEnvVar: MY_PROVIDER_API_KEY\n models:\n my_model: { name: "my-model-id" }\n```\nThen reference `provider: my_provider` and `model: my_model` in `.minds/team.yaml`.',
|
|
5366
|
-
'Merge/override: `.minds/llm.yaml` overrides built-in defaults (per current implementation); defining one provider does not imply disabling other built-in providers.',
|
|
5367
|
-
'Do not store API keys in the file; use env vars via apiKeyEnvVar.',
|
|
5368
|
-
'member_defaults.provider/model must reference these keys.',
|
|
5369
|
-
'Optional: `model_param_options` documents `.minds/team.yaml model_params` knobs (documentation only).',
|
|
5370
|
-
'`apiQuirks` is optional under `providers.<providerKey>.apiQuirks`, with type `string|string[]`. It is a provider-level transport / gateway compatibility switch for non-standard upstream API behavior. It is not a `.minds/team.yaml` member field and not part of `model_params`.',
|
|
5371
|
-
'Use it only when you have confirmed that an upstream gateway deviates from the expected protocol and Dominds has an explicitly named quirk for that deviation. Do not treat it as a generic tuning field. In the current implementation, unknown quirk values are usually ignored rather than rejected, so a typo may silently do nothing.',
|
|
5372
|
-
'Known current example: the OpenAI Responses wrapper supports `apiQuirks: xcode.best` (or an array containing it). It not only treats vendor-emitted `keepalive` stream events as heartbeat events instead of unexpected protocol noise, but also applies provider-specific failure handling for gateway-specific failures, including repeated empty responses in the same unchanged dialog context (a few temporary retries first; once the unchanged-context streak reaches the threshold, Dominds treats it as a provider-side same-context deadlock rather than ordinary infrastructure flakiness, which means repeating the same automatic retry path is no longer expected to make real progress and fresh information or fresh instructions are required, such as adding context, reframing the ask, changing the angle, or calling askHuman when human judgment is genuinely needed; this provider/API retry state intentionally continues across course changes within the same driver auto-continue chain; if Diligence Push is enabled for the dialog, the driver will first see whether it can continue once through that path before falling into stopped, and that recovery budget is considered consumed as soon as the driver accepts that path) and gateway-returned HTML 502 Bad Gateway pages plus `500 auth_unavailable: no auth available` infrastructure failures classified into conservative retry. Minimal example:\n```yaml\nproviders:\n my_gateway:\n apiType: openai\n baseUrl: https://example.invalid/v1\n apiKeyEnvVar: MY_GATEWAY_API_KEY\n apiQuirks: xcode.best\n models:\n my_model: { name: \"upstream-model-id\" }\n```',
|
|
5373
|
-
'Boundary reminder: `apiQuirks` only affects providers/generators that explicitly read it in code. In the current implementation, at least the OpenAI Responses path consumes it; do not assume every `apiType` supports or needs it. If behavior is still wrong after setting it, continue with upstream gateway docs, raw stream event inspection, and `team_mgmt_check_provider(...)` / runtime logs.',
|
|
5374
|
-
]);
|
|
5375
|
-
}
|
|
5376
|
-
if (want('mcp')) {
|
|
5377
|
-
return await renderMcpManual(language);
|
|
5378
|
-
}
|
|
5379
|
-
if (want('minds')) {
|
|
5380
|
-
return renderMindsManual(language);
|
|
5381
|
-
}
|
|
5382
|
-
if (want('skills')) {
|
|
5383
|
-
return renderSkillsManual(language);
|
|
5384
|
-
}
|
|
5385
|
-
if (want('priming')) {
|
|
5386
|
-
return renderPrimingManual(language);
|
|
5387
|
-
}
|
|
5388
|
-
if (want('env')) {
|
|
5389
|
-
return renderEnvManual(language);
|
|
5390
|
-
}
|
|
5391
|
-
if (want('permissions')) {
|
|
5392
|
-
return renderPermissionsManual(language);
|
|
5393
|
-
}
|
|
5394
|
-
if (want('toolsets')) {
|
|
5395
|
-
return await renderToolsets(language);
|
|
5396
|
-
}
|
|
5397
|
-
if (want('troubleshooting')) {
|
|
5398
|
-
return renderTroubleshooting(language);
|
|
5399
|
-
}
|
|
5400
|
-
return renderIndex();
|
|
5401
|
-
}
|
|
5402
|
-
catch (err) {
|
|
5403
|
-
throw err;
|
|
5404
|
-
}
|
|
5405
|
-
}
|
|
5406
4561
|
exports.teamMgmtTools = [
|
|
5407
4562
|
exports.teamMgmtCheckProviderTool,
|
|
5408
4563
|
exports.teamMgmtListProvidersTool,
|