dominds 1.17.3 → 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 +15 -0
- 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 +17 -16
- package/dist/tools/pending-tellask-reminder.js +4 -2
- 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-LNaSxjvr.js → _basePickBy-CgM-M_q8.js} +3 -3
- package/webapp/dist/assets/{_basePickBy-LNaSxjvr.js.map → _basePickBy-CgM-M_q8.js.map} +1 -1
- package/webapp/dist/assets/{_baseUniq-Bj1hx6jk.js → _baseUniq-B06twih4.js} +2 -2
- package/webapp/dist/assets/{_baseUniq-Bj1hx6jk.js.map → _baseUniq-B06twih4.js.map} +1 -1
- package/webapp/dist/assets/{arc-Bpj1nPA2.js → arc-CoXJvjeB.js} +2 -2
- package/webapp/dist/assets/{arc-Bpj1nPA2.js.map → arc-CoXJvjeB.js.map} +1 -1
- package/webapp/dist/assets/{architectureDiagram-2XIMDMQ5-CoXbtvnz.js → architectureDiagram-2XIMDMQ5-BLFRWTKn.js} +7 -7
- package/webapp/dist/assets/{architectureDiagram-2XIMDMQ5-CoXbtvnz.js.map → architectureDiagram-2XIMDMQ5-BLFRWTKn.js.map} +1 -1
- package/webapp/dist/assets/{blockDiagram-WCTKOSBZ-CIN9vlJ6.js → blockDiagram-WCTKOSBZ-CYRE6deu.js} +7 -7
- package/webapp/dist/assets/{blockDiagram-WCTKOSBZ-CIN9vlJ6.js.map → blockDiagram-WCTKOSBZ-CYRE6deu.js.map} +1 -1
- package/webapp/dist/assets/{c4Diagram-IC4MRINW-C5JZR-oM.js → c4Diagram-IC4MRINW-B26QTIJt.js} +3 -3
- package/webapp/dist/assets/{c4Diagram-IC4MRINW-C5JZR-oM.js.map → c4Diagram-IC4MRINW-B26QTIJt.js.map} +1 -1
- package/webapp/dist/assets/{channel-D5Xdg9yM.js → channel-C5U2W0P9.js} +2 -2
- package/webapp/dist/assets/{channel-D5Xdg9yM.js.map → channel-C5U2W0P9.js.map} +1 -1
- package/webapp/dist/assets/{chunk-4BX2VUAB-D4Rve4FO.js → chunk-4BX2VUAB-7z2PgnSv.js} +2 -2
- package/webapp/dist/assets/{chunk-4BX2VUAB-D4Rve4FO.js.map → chunk-4BX2VUAB-7z2PgnSv.js.map} +1 -1
- package/webapp/dist/assets/{chunk-55IACEB6-DpabCDXg.js → chunk-55IACEB6-6sRVmXqs.js} +2 -2
- package/webapp/dist/assets/{chunk-55IACEB6-DpabCDXg.js.map → chunk-55IACEB6-6sRVmXqs.js.map} +1 -1
- package/webapp/dist/assets/{chunk-FMBD7UC4-BoBj8MAm.js → chunk-FMBD7UC4-BwYp8OtY.js} +2 -2
- package/webapp/dist/assets/{chunk-FMBD7UC4-BoBj8MAm.js.map → chunk-FMBD7UC4-BwYp8OtY.js.map} +1 -1
- package/webapp/dist/assets/{chunk-JSJVCQXG-CEy0qXdN.js → chunk-JSJVCQXG-CRq8LK53.js} +2 -2
- package/webapp/dist/assets/{chunk-JSJVCQXG-CEy0qXdN.js.map → chunk-JSJVCQXG-CRq8LK53.js.map} +1 -1
- package/webapp/dist/assets/{chunk-KX2RTZJC-CDdtREQb.js → chunk-KX2RTZJC-CzFE355P.js} +2 -2
- package/webapp/dist/assets/{chunk-KX2RTZJC-CDdtREQb.js.map → chunk-KX2RTZJC-CzFE355P.js.map} +1 -1
- package/webapp/dist/assets/{chunk-NQ4KR5QH-_1ihDJTW.js → chunk-NQ4KR5QH-3cQSOzCt.js} +4 -4
- package/webapp/dist/assets/{chunk-NQ4KR5QH-_1ihDJTW.js.map → chunk-NQ4KR5QH-3cQSOzCt.js.map} +1 -1
- package/webapp/dist/assets/{chunk-QZHKN3VN-B4dXlOb4.js → chunk-QZHKN3VN-DWkpxb-w.js} +2 -2
- package/webapp/dist/assets/{chunk-QZHKN3VN-B4dXlOb4.js.map → chunk-QZHKN3VN-DWkpxb-w.js.map} +1 -1
- package/webapp/dist/assets/{chunk-WL4C6EOR-C13IEcmo.js → chunk-WL4C6EOR-DkpfoQzK.js} +6 -6
- package/webapp/dist/assets/{chunk-WL4C6EOR-C13IEcmo.js.map → chunk-WL4C6EOR-DkpfoQzK.js.map} +1 -1
- package/webapp/dist/assets/{classDiagram-VBA2DB6C-CFBgFxCH.js → classDiagram-VBA2DB6C-mVfJeuZL.js} +7 -7
- package/webapp/dist/assets/{classDiagram-VBA2DB6C-CFBgFxCH.js.map → classDiagram-VBA2DB6C-mVfJeuZL.js.map} +1 -1
- package/webapp/dist/assets/{classDiagram-v2-RAHNMMFH-CFBgFxCH.js → classDiagram-v2-RAHNMMFH-mVfJeuZL.js} +7 -7
- package/webapp/dist/assets/{classDiagram-v2-RAHNMMFH-CFBgFxCH.js.map → classDiagram-v2-RAHNMMFH-mVfJeuZL.js.map} +1 -1
- package/webapp/dist/assets/{clone-TK1nHACc.js → clone-5uLJc7AC.js} +2 -2
- package/webapp/dist/assets/{clone-TK1nHACc.js.map → clone-5uLJc7AC.js.map} +1 -1
- package/webapp/dist/assets/{cose-bilkent-S5V4N54A-BKcU9sie.js → cose-bilkent-S5V4N54A-CoiJzdQi.js} +2 -2
- package/webapp/dist/assets/{cose-bilkent-S5V4N54A-BKcU9sie.js.map → cose-bilkent-S5V4N54A-CoiJzdQi.js.map} +1 -1
- package/webapp/dist/assets/{dagre-KLK3FWXG-h-3iGD6Y.js → dagre-KLK3FWXG-DU_3BSOq.js} +7 -7
- package/webapp/dist/assets/{dagre-KLK3FWXG-h-3iGD6Y.js.map → dagre-KLK3FWXG-DU_3BSOq.js.map} +1 -1
- package/webapp/dist/assets/{diagram-E7M64L7V-ekBLF-yk.js → diagram-E7M64L7V-DgqOvF1U.js} +8 -8
- package/webapp/dist/assets/{diagram-E7M64L7V-ekBLF-yk.js.map → diagram-E7M64L7V-DgqOvF1U.js.map} +1 -1
- package/webapp/dist/assets/{diagram-IFDJBPK2-D_G2oKiI.js → diagram-IFDJBPK2-CFWMc1oD.js} +7 -7
- package/webapp/dist/assets/{diagram-IFDJBPK2-D_G2oKiI.js.map → diagram-IFDJBPK2-CFWMc1oD.js.map} +1 -1
- package/webapp/dist/assets/{diagram-P4PSJMXO-27xx1y5D.js → diagram-P4PSJMXO-lrqvXDXp.js} +7 -7
- package/webapp/dist/assets/{diagram-P4PSJMXO-27xx1y5D.js.map → diagram-P4PSJMXO-lrqvXDXp.js.map} +1 -1
- package/webapp/dist/assets/{erDiagram-INFDFZHY-CZSSh9wl.js → erDiagram-INFDFZHY-C28KjRkA.js} +5 -5
- package/webapp/dist/assets/{erDiagram-INFDFZHY-CZSSh9wl.js.map → erDiagram-INFDFZHY-C28KjRkA.js.map} +1 -1
- package/webapp/dist/assets/{flowDiagram-PKNHOUZH-Bm92lWNi.js → flowDiagram-PKNHOUZH-DkxGh-JF.js} +7 -7
- package/webapp/dist/assets/{flowDiagram-PKNHOUZH-Bm92lWNi.js.map → flowDiagram-PKNHOUZH-DkxGh-JF.js.map} +1 -1
- package/webapp/dist/assets/{ganttDiagram-A5KZAMGK-C5VpKam7.js → ganttDiagram-A5KZAMGK-BmZnHD96.js} +3 -3
- package/webapp/dist/assets/{ganttDiagram-A5KZAMGK-C5VpKam7.js.map → ganttDiagram-A5KZAMGK-BmZnHD96.js.map} +1 -1
- package/webapp/dist/assets/{gitGraphDiagram-K3NZZRJ6-DzPVChwE.js → gitGraphDiagram-K3NZZRJ6-xiHqomZC.js} +8 -8
- package/webapp/dist/assets/{gitGraphDiagram-K3NZZRJ6-DzPVChwE.js.map → gitGraphDiagram-K3NZZRJ6-xiHqomZC.js.map} +1 -1
- package/webapp/dist/assets/{graph-DZP1hBZG.js → graph-ozb0amP0.js} +3 -3
- package/webapp/dist/assets/{graph-DZP1hBZG.js.map → graph-ozb0amP0.js.map} +1 -1
- package/webapp/dist/assets/{index-Btsmlz6h.js → index-Cyx7eev_.js} +698 -149
- package/webapp/dist/assets/{index-Btsmlz6h.js.map → index-Cyx7eev_.js.map} +1 -1
- package/webapp/dist/assets/{infoDiagram-LFFYTUFH-yRov6uGE.js → infoDiagram-LFFYTUFH-fLl_TA1F.js} +6 -6
- package/webapp/dist/assets/{infoDiagram-LFFYTUFH-yRov6uGE.js.map → infoDiagram-LFFYTUFH-fLl_TA1F.js.map} +1 -1
- package/webapp/dist/assets/{ishikawaDiagram-PHBUUO56-DFo_y5-j.js → ishikawaDiagram-PHBUUO56-ZL9tBKUr.js} +2 -2
- package/webapp/dist/assets/{ishikawaDiagram-PHBUUO56-DFo_y5-j.js.map → ishikawaDiagram-PHBUUO56-ZL9tBKUr.js.map} +1 -1
- package/webapp/dist/assets/{journeyDiagram-4ABVD52K-DFHL6Mn9.js → journeyDiagram-4ABVD52K--aRyymZs.js} +5 -5
- package/webapp/dist/assets/{journeyDiagram-4ABVD52K-DFHL6Mn9.js.map → journeyDiagram-4ABVD52K--aRyymZs.js.map} +1 -1
- package/webapp/dist/assets/{kanban-definition-K7BYSVSG-Dn8AcHXb.js → kanban-definition-K7BYSVSG-BO_QdW_O.js} +3 -3
- package/webapp/dist/assets/{kanban-definition-K7BYSVSG-Dn8AcHXb.js.map → kanban-definition-K7BYSVSG-BO_QdW_O.js.map} +1 -1
- package/webapp/dist/assets/{layout-BdLHhC4z.js → layout-Bu3Xw0z2.js} +5 -5
- package/webapp/dist/assets/{layout-BdLHhC4z.js.map → layout-Bu3Xw0z2.js.map} +1 -1
- package/webapp/dist/assets/{linear-Czx4z_fP.js → linear-Bq77itJm.js} +2 -2
- package/webapp/dist/assets/{linear-Czx4z_fP.js.map → linear-Bq77itJm.js.map} +1 -1
- package/webapp/dist/assets/{mindmap-definition-YRQLILUH-CXqQMYCg.js → mindmap-definition-YRQLILUH-CHB8qv8L.js} +4 -4
- package/webapp/dist/assets/{mindmap-definition-YRQLILUH-CXqQMYCg.js.map → mindmap-definition-YRQLILUH-CHB8qv8L.js.map} +1 -1
- package/webapp/dist/assets/{pieDiagram-SKSYHLDU-CqDocKnB.js → pieDiagram-SKSYHLDU-Cxg_wh4K.js} +8 -8
- package/webapp/dist/assets/{pieDiagram-SKSYHLDU-CqDocKnB.js.map → pieDiagram-SKSYHLDU-Cxg_wh4K.js.map} +1 -1
- package/webapp/dist/assets/{quadrantDiagram-337W2JSQ-CiWVSFIH.js → quadrantDiagram-337W2JSQ-DFguuaS9.js} +3 -3
- package/webapp/dist/assets/{quadrantDiagram-337W2JSQ-CiWVSFIH.js.map → quadrantDiagram-337W2JSQ-DFguuaS9.js.map} +1 -1
- package/webapp/dist/assets/{requirementDiagram-Z7DCOOCP-CZJEyik8.js → requirementDiagram-Z7DCOOCP--tJ_dfsT.js} +4 -4
- package/webapp/dist/assets/{requirementDiagram-Z7DCOOCP-CZJEyik8.js.map → requirementDiagram-Z7DCOOCP--tJ_dfsT.js.map} +1 -1
- package/webapp/dist/assets/{sankeyDiagram-WA2Y5GQK-Dw75ByKP.js → sankeyDiagram-WA2Y5GQK-f0zWimMc.js} +2 -2
- package/webapp/dist/assets/{sankeyDiagram-WA2Y5GQK-Dw75ByKP.js.map → sankeyDiagram-WA2Y5GQK-f0zWimMc.js.map} +1 -1
- package/webapp/dist/assets/{sequenceDiagram-2WXFIKYE-Bb-cjLgg.js → sequenceDiagram-2WXFIKYE-dwXRRnyq.js} +4 -4
- package/webapp/dist/assets/{sequenceDiagram-2WXFIKYE-Bb-cjLgg.js.map → sequenceDiagram-2WXFIKYE-dwXRRnyq.js.map} +1 -1
- package/webapp/dist/assets/{stateDiagram-RAJIS63D-BvpG0ZSP.js → stateDiagram-RAJIS63D-DToxcEC2.js} +9 -9
- package/webapp/dist/assets/{stateDiagram-RAJIS63D-BvpG0ZSP.js.map → stateDiagram-RAJIS63D-DToxcEC2.js.map} +1 -1
- package/webapp/dist/assets/{stateDiagram-v2-FVOUBMTO-7bxKEt97.js → stateDiagram-v2-FVOUBMTO-BY5hDUqz.js} +5 -5
- package/webapp/dist/assets/{stateDiagram-v2-FVOUBMTO-7bxKEt97.js.map → stateDiagram-v2-FVOUBMTO-BY5hDUqz.js.map} +1 -1
- package/webapp/dist/assets/{timeline-definition-YZTLITO2-CRqRYWEl.js → timeline-definition-YZTLITO2-CT3WRcFt.js} +3 -3
- package/webapp/dist/assets/{timeline-definition-YZTLITO2-CRqRYWEl.js.map → timeline-definition-YZTLITO2-CT3WRcFt.js.map} +1 -1
- package/webapp/dist/assets/{treemap-KZPCXAKY-Bu5JpxPM.js → treemap-KZPCXAKY-Lnkh2bpd.js} +5 -5
- package/webapp/dist/assets/{treemap-KZPCXAKY-Bu5JpxPM.js.map → treemap-KZPCXAKY-Lnkh2bpd.js.map} +1 -1
- package/webapp/dist/assets/{vennDiagram-LZ73GAT5-DAB652Qx.js → vennDiagram-LZ73GAT5-CYSLSh1w.js} +2 -2
- package/webapp/dist/assets/{vennDiagram-LZ73GAT5-DAB652Qx.js.map → vennDiagram-LZ73GAT5-CYSLSh1w.js.map} +1 -1
- package/webapp/dist/assets/{xychartDiagram-JWTSCODW-D0U7VqPG.js → xychartDiagram-JWTSCODW-DgvaqrGO.js} +3 -3
- package/webapp/dist/assets/{xychartDiagram-JWTSCODW-D0U7VqPG.js.map → xychartDiagram-JWTSCODW-DgvaqrGO.js.map} +1 -1
- package/webapp/dist/index.html +1 -1
package/dist/apps-host/host.js
CHANGED
|
@@ -82,7 +82,16 @@ function parseReminderRequest(value) {
|
|
|
82
82
|
if (echoback === null) {
|
|
83
83
|
throw new Error('Invalid app tool reminder request: upsert.echoback must be boolean');
|
|
84
84
|
}
|
|
85
|
-
|
|
85
|
+
const renderModeRaw = value['renderMode'];
|
|
86
|
+
const renderMode = renderModeRaw === undefined
|
|
87
|
+
? undefined
|
|
88
|
+
: renderModeRaw === 'plain' || renderModeRaw === 'markdown'
|
|
89
|
+
? renderModeRaw
|
|
90
|
+
: null;
|
|
91
|
+
if (renderMode === null) {
|
|
92
|
+
throw new Error('Invalid app tool reminder request: upsert.renderMode must be plain|markdown');
|
|
93
|
+
}
|
|
94
|
+
return { kind: 'upsert', ownerRef, content, meta, position, echoback, renderMode };
|
|
86
95
|
}
|
|
87
96
|
throw new Error(`Invalid app tool reminder request kind: ${String(kind)}`);
|
|
88
97
|
}
|
|
@@ -138,7 +147,9 @@ function isReminderState(value) {
|
|
|
138
147
|
if (meta !== undefined && !isJsonValue(meta))
|
|
139
148
|
return false;
|
|
140
149
|
const echoback = value['echoback'];
|
|
141
|
-
|
|
150
|
+
const renderMode = value['renderMode'];
|
|
151
|
+
return ((echoback === undefined || typeof echoback === 'boolean') &&
|
|
152
|
+
(renderMode === undefined || renderMode === 'plain' || renderMode === 'markdown'));
|
|
142
153
|
}
|
|
143
154
|
function isReminderApplyResult(value) {
|
|
144
155
|
if (!isRecord(value))
|
|
@@ -46,7 +46,15 @@ function parseReminderState(v, at) {
|
|
|
46
46
|
const echoback = echobackRaw === undefined ? undefined : typeof echobackRaw === 'boolean' ? echobackRaw : null;
|
|
47
47
|
if (echoback === null)
|
|
48
48
|
throw new Error(`Invalid ${at}.echoback: must be boolean`);
|
|
49
|
-
|
|
49
|
+
const renderModeRaw = v['renderMode'];
|
|
50
|
+
const renderMode = renderModeRaw === undefined
|
|
51
|
+
? undefined
|
|
52
|
+
: renderModeRaw === 'plain' || renderModeRaw === 'markdown'
|
|
53
|
+
? renderModeRaw
|
|
54
|
+
: null;
|
|
55
|
+
if (renderMode === null)
|
|
56
|
+
throw new Error(`Invalid ${at}.renderMode: must be plain|markdown`);
|
|
57
|
+
return { content, meta: metaRaw, echoback, renderMode };
|
|
50
58
|
}
|
|
51
59
|
function parseReminderApplyRequest(v, at) {
|
|
52
60
|
if (!isRecord(v))
|
|
@@ -75,6 +83,14 @@ function parseReminderApplyRequest(v, at) {
|
|
|
75
83
|
const echoback = echobackRaw === undefined ? undefined : typeof echobackRaw === 'boolean' ? echobackRaw : null;
|
|
76
84
|
if (echoback === null)
|
|
77
85
|
throw new Error(`Invalid ${at}.echoback: must be boolean`);
|
|
86
|
+
const renderModeRaw = v['renderMode'];
|
|
87
|
+
const renderMode = renderModeRaw === undefined
|
|
88
|
+
? undefined
|
|
89
|
+
: renderModeRaw === 'plain' || renderModeRaw === 'markdown'
|
|
90
|
+
? renderModeRaw
|
|
91
|
+
: null;
|
|
92
|
+
if (renderMode === null)
|
|
93
|
+
throw new Error(`Invalid ${at}.renderMode: must be plain|markdown`);
|
|
78
94
|
return {
|
|
79
95
|
kind: 'upsert',
|
|
80
96
|
ownerRef,
|
|
@@ -82,6 +98,7 @@ function parseReminderApplyRequest(v, at) {
|
|
|
82
98
|
meta: metaRaw,
|
|
83
99
|
position,
|
|
84
100
|
echoback,
|
|
101
|
+
renderMode,
|
|
85
102
|
};
|
|
86
103
|
}
|
|
87
104
|
if (kind === 'delete') {
|
package/dist/dialog-fork.js
CHANGED
package/dist/dialog.js
CHANGED
|
@@ -374,6 +374,7 @@ class Dialog {
|
|
|
374
374
|
meta,
|
|
375
375
|
echoback: options?.echoback,
|
|
376
376
|
scope: options?.scope ?? 'dialog',
|
|
377
|
+
renderMode: options?.renderMode,
|
|
377
378
|
});
|
|
378
379
|
const insertIndex = position !== undefined ? position : this.reminders.length;
|
|
379
380
|
if (insertIndex < 0 || insertIndex > this.reminders.length) {
|
|
@@ -405,6 +406,7 @@ class Dialog {
|
|
|
405
406
|
scope: oldReminder.scope,
|
|
406
407
|
createdAt: oldReminder.createdAt,
|
|
407
408
|
priority: oldReminder.priority,
|
|
409
|
+
renderMode: options?.renderMode ?? oldReminder.renderMode,
|
|
408
410
|
});
|
|
409
411
|
this.reminders[index] = updatedReminder;
|
|
410
412
|
this.touchReminders();
|
|
@@ -479,6 +481,7 @@ class Dialog {
|
|
|
479
481
|
scope: reminder.scope,
|
|
480
482
|
createdAt: reminder.createdAt,
|
|
481
483
|
priority: reminder.priority,
|
|
484
|
+
renderMode: reminder.renderMode,
|
|
482
485
|
});
|
|
483
486
|
const contentChanged = updatedReminder.content !== reminder.content;
|
|
484
487
|
const metaChanged = updatedReminder.meta !== reminder.meta;
|
|
@@ -539,8 +542,10 @@ class Dialog {
|
|
|
539
542
|
content: r.content,
|
|
540
543
|
meta: r.meta,
|
|
541
544
|
reminder_id: r.id,
|
|
545
|
+
renderRevision: (0, tool_1.computeReminderRenderRevision)(r),
|
|
542
546
|
echoback: (0, tool_1.reminderEchoBackEnabled)(r),
|
|
543
547
|
scope: r.scope,
|
|
548
|
+
renderMode: r.renderMode ?? 'markdown',
|
|
544
549
|
}));
|
|
545
550
|
// Emit full_reminders_update event with complete reminder list including metadata
|
|
546
551
|
const fullRemindersEvt = {
|
package/dist/docs/mcp-support.md
CHANGED
|
@@ -423,9 +423,12 @@ servers:
|
|
|
423
423
|
# Tool name transforms (optional)
|
|
424
424
|
transform: []
|
|
425
425
|
|
|
426
|
-
# Optional
|
|
426
|
+
# Optional manual information
|
|
427
|
+
# - contentFile: formal runtime manual for man({ "toolsetId": "<serverId>" })
|
|
428
|
+
# - content/sections: extra inline team-management guidance
|
|
427
429
|
# (missing manual does NOT make the toolset unavailable)
|
|
428
430
|
manual:
|
|
431
|
+
contentFile: ".minds/manuals/<serverId>"
|
|
429
432
|
content: "What this MCP toolset is for"
|
|
430
433
|
sections:
|
|
431
434
|
- title: "When To Use"
|
|
@@ -385,15 +385,15 @@ Notes:
|
|
|
385
385
|
- MCP tool names are global across all toolsets (built-in + MCP). Collisions cause tools to be
|
|
386
386
|
skipped and should surface via Problems + logs.
|
|
387
387
|
- `mcp_admin` is a built-in toolset that contains `mcp_restart` (best-effort per-server restart).
|
|
388
|
-
- Optional
|
|
389
|
-
- `
|
|
390
|
-
- `sections`:
|
|
388
|
+
- Optional manual information can live in `.minds/mcp.yaml` at `servers.<serverId>.manual`:
|
|
389
|
+
- `contentFile`: the topic-file directory prefix for the formal runtime manual; the final `man({ "toolsetId": "<serverId>" })` content shown to the LLM is loaded from here
|
|
390
|
+
- `content` / `sections`: inline team-management guidance shown in the `team_mgmt` MCP chapter (`sections` supports `[{ title, content }]` or `{ "<title>": "<content>" }`)
|
|
391
391
|
- Missing manual does **not** mean the toolset is unavailable; it means team-manager documentation
|
|
392
392
|
is incomplete. Agents should continue by reading each tool’s own description/arguments.
|
|
393
393
|
- Team-manager recommendation: after MCP config validation passes, carefully read each exposed tool
|
|
394
|
-
description, discuss intended rtws usage with the human user, then write
|
|
395
|
-
`
|
|
396
|
-
|
|
394
|
+
description, discuss intended rtws usage with the human user, then write the formal manual into
|
|
395
|
+
`manual.contentFile`; if extra team-management interpretation is still useful, add inline
|
|
396
|
+
`content + sections` alongside it.
|
|
397
397
|
- Use a semi-structured chapter shape: high-value sections often include `When To Use`,
|
|
398
398
|
`Guardrails`, and `Business Handling When Unavailable`, but do not force every toolset into one
|
|
399
399
|
fixed template. Start from the real business goal, then decide which sections deserve depth,
|
|
@@ -431,8 +431,9 @@ servers:
|
|
|
431
431
|
# Tool name transforms
|
|
432
432
|
transform: [] # optional
|
|
433
433
|
|
|
434
|
-
# Optional
|
|
434
|
+
# Optional manual information
|
|
435
435
|
manual:
|
|
436
|
+
contentFile: ".minds/manuals/<serverId>" # formal runtime manual for man({ "toolsetId": "<serverId>" })
|
|
436
437
|
content: "What this MCP toolset is for"
|
|
437
438
|
sections:
|
|
438
439
|
- title: "When To Use"
|
|
@@ -322,11 +322,11 @@ members:
|
|
|
322
322
|
|
|
323
323
|
- MCP 工具名称在所有工具集(内置 + MCP)中是全局的。冲突导致工具被跳过,应通过问题 + 日志暴露
|
|
324
324
|
- `mcp_admin` 是一个内置工具集,包含 `mcp_restart`(每个服务器最佳努力重启)
|
|
325
|
-
- 可选手册:可在 `.minds/mcp.yaml` 的 `servers.<serverId>.manual`
|
|
326
|
-
- `
|
|
327
|
-
- `sections
|
|
325
|
+
- 可选手册:可在 `.minds/mcp.yaml` 的 `servers.<serverId>.manual` 提供手册相关信息:
|
|
326
|
+
- `contentFile`:正式 runtime 手册的 topic 文件目录前缀;`man({ "toolsetId": "<serverId>" })` 最终给 LLM 看的正文从这里加载
|
|
327
|
+
- `content` / `sections`:补充给 `team_mgmt` MCP 章节看的 inline 团队管理说明(`sections` 支持 `[{ title, content }]` 或 `{ "<title>": "<content>" }`)
|
|
328
328
|
- 没有手册 **不代表** 该 toolset 不可用;这只表示团队管理文档覆盖不足。智能体应继续依据每个工具自身的 description/参数来使用。
|
|
329
|
-
- 建议团队管理者在 MCP 配置验证通过后:先精读该 server 暴露的每个工具说明,再与人类用户讨论本 rtws
|
|
329
|
+
- 建议团队管理者在 MCP 配置验证通过后:先精读该 server 暴露的每个工具说明,再与人类用户讨论本 rtws 的使用意图,然后把正式手册沉淀到 `manual.contentFile`;如仍需额外写团队管理层解释,再补 inline `content + sections`。
|
|
330
330
|
- 章节组织建议采用“半结构化”:可优先考虑 `何时使用`、`安全边界`、`不可用时业务处置` 这类高价值章节,但不要求所有 toolset 都照抄同一模板。应从真实业务目标出发,决定哪些章节需要展开、哪些只需一句话、哪些可以合并或改名成更贴切的标题。
|
|
331
331
|
- 对每个 MCP toolset,建议刻意写明“不可用时业务处置规约”,至少回答:
|
|
332
332
|
- 当前 toolset 暂不可达时,是否必须找协调者/专员接手
|
|
@@ -360,8 +360,9 @@ servers:
|
|
|
360
360
|
# 工具名称转换
|
|
361
361
|
transform: [] # 可选
|
|
362
362
|
|
|
363
|
-
#
|
|
363
|
+
# 可选:手册相关信息
|
|
364
364
|
manual:
|
|
365
|
+
contentFile: ".minds/manuals/<serverId>" # 正式 runtime 手册(供 man({ "toolsetId": "<serverId>" }) 读取)
|
|
365
366
|
content: "该 MCP toolset 的用途说明"
|
|
366
367
|
sections:
|
|
367
368
|
- title: "何时使用"
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export type McpToolsetManualSection = {
|
|
2
|
+
title: string;
|
|
3
|
+
content: string;
|
|
4
|
+
};
|
|
5
|
+
export type McpToolsetManual = {
|
|
6
|
+
content?: string;
|
|
7
|
+
contentFile?: string;
|
|
8
|
+
sections: ReadonlyArray<McpToolsetManualSection>;
|
|
9
|
+
};
|
|
10
|
+
export type McpToolsetManualState = {
|
|
11
|
+
kind: 'missing';
|
|
12
|
+
} | {
|
|
13
|
+
kind: 'invalid';
|
|
14
|
+
errorText: string;
|
|
15
|
+
} | {
|
|
16
|
+
kind: 'present';
|
|
17
|
+
manual: McpToolsetManual;
|
|
18
|
+
};
|
|
19
|
+
export type McpToolsetManualByServer = {
|
|
20
|
+
manualByServerId: ReadonlyMap<string, McpToolsetManual>;
|
|
21
|
+
invalidByServerId: ReadonlyMap<string, string>;
|
|
22
|
+
warningTextByServerId: ReadonlyMap<string, string>;
|
|
23
|
+
};
|
|
24
|
+
export declare function emptyMcpToolsetManualByServer(): McpToolsetManualByServer;
|
|
25
|
+
export declare function mcpToolsetManualProblemPrefix(serverId: string): string;
|
|
26
|
+
export declare function mcpWorkspaceManualProblemPrefix(): string;
|
|
27
|
+
export declare function parseMcpManualByServer(rawText: string): McpToolsetManualByServer;
|
|
28
|
+
export declare function reconcileMcpToolsetManualProblems(params: {
|
|
29
|
+
serverIds: ReadonlyArray<string>;
|
|
30
|
+
manualInfo: McpToolsetManualByServer;
|
|
31
|
+
measureRenderedWorkspaceMcpTopicRawChars: () => Promise<number>;
|
|
32
|
+
workspaceManualPath: string;
|
|
33
|
+
}): Promise<void>;
|
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.emptyMcpToolsetManualByServer = emptyMcpToolsetManualByServer;
|
|
7
|
+
exports.mcpToolsetManualProblemPrefix = mcpToolsetManualProblemPrefix;
|
|
8
|
+
exports.mcpWorkspaceManualProblemPrefix = mcpWorkspaceManualProblemPrefix;
|
|
9
|
+
exports.parseMcpManualByServer = parseMcpManualByServer;
|
|
10
|
+
exports.reconcileMcpToolsetManualProblems = reconcileMcpToolsetManualProblems;
|
|
11
|
+
const time_1 = require("@longrun-ai/kernel/utils/time");
|
|
12
|
+
const yaml_1 = __importDefault(require("yaml"));
|
|
13
|
+
const problems_1 = require("../problems");
|
|
14
|
+
const output_limit_1 = require("../tools/manual/output-limit");
|
|
15
|
+
const render_1 = require("../tools/manual/render");
|
|
16
|
+
const registry_1 = require("../tools/registry");
|
|
17
|
+
const MCP_SERVER_PROBLEM_PREFIX = 'mcp/server/';
|
|
18
|
+
function isObjectRecord(value) {
|
|
19
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
20
|
+
}
|
|
21
|
+
function isNonEmptyString(value) {
|
|
22
|
+
return typeof value === 'string' && value.trim() !== '';
|
|
23
|
+
}
|
|
24
|
+
function emptyMcpToolsetManualByServer() {
|
|
25
|
+
return {
|
|
26
|
+
manualByServerId: new Map(),
|
|
27
|
+
invalidByServerId: new Map(),
|
|
28
|
+
warningTextByServerId: new Map(),
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function mcpToolsetManualProblemPrefix(serverId) {
|
|
32
|
+
return `${MCP_SERVER_PROBLEM_PREFIX}${serverId}/toolset_manual_`;
|
|
33
|
+
}
|
|
34
|
+
function mcpWorkspaceManualProblemPrefix() {
|
|
35
|
+
return 'mcp/workspace_manual_';
|
|
36
|
+
}
|
|
37
|
+
function parseMcpManualByServer(rawText) {
|
|
38
|
+
const manualByServerId = new Map();
|
|
39
|
+
const invalidByServerId = new Map();
|
|
40
|
+
const warningTextByServerId = new Map();
|
|
41
|
+
let parsedRoot;
|
|
42
|
+
try {
|
|
43
|
+
parsedRoot = yaml_1.default.parse(rawText);
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return { manualByServerId, invalidByServerId, warningTextByServerId };
|
|
47
|
+
}
|
|
48
|
+
if (!isObjectRecord(parsedRoot)) {
|
|
49
|
+
return { manualByServerId, invalidByServerId, warningTextByServerId };
|
|
50
|
+
}
|
|
51
|
+
const serversVal = parsedRoot['servers'];
|
|
52
|
+
if (!isObjectRecord(serversVal)) {
|
|
53
|
+
return { manualByServerId, invalidByServerId, warningTextByServerId };
|
|
54
|
+
}
|
|
55
|
+
for (const [serverId, serverVal] of Object.entries(serversVal)) {
|
|
56
|
+
if (!isObjectRecord(serverVal))
|
|
57
|
+
continue;
|
|
58
|
+
const manualVal = serverVal['manual'];
|
|
59
|
+
if (manualVal === undefined || manualVal === null)
|
|
60
|
+
continue;
|
|
61
|
+
const parsed = parseMcpManualField(serverId, manualVal);
|
|
62
|
+
if (parsed.warningText !== undefined) {
|
|
63
|
+
warningTextByServerId.set(serverId, parsed.warningText);
|
|
64
|
+
}
|
|
65
|
+
if (parsed.kind === 'present') {
|
|
66
|
+
manualByServerId.set(serverId, parsed.manual);
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
invalidByServerId.set(serverId, parsed.errorText);
|
|
70
|
+
}
|
|
71
|
+
return { manualByServerId, invalidByServerId, warningTextByServerId };
|
|
72
|
+
}
|
|
73
|
+
function parseMcpManualField(serverId, value) {
|
|
74
|
+
const fieldPath = `servers.${serverId}.manual`;
|
|
75
|
+
if (typeof value === 'string') {
|
|
76
|
+
const text = value.trim();
|
|
77
|
+
if (text === '') {
|
|
78
|
+
return { kind: 'invalid', errorText: `${fieldPath} must not be empty` };
|
|
79
|
+
}
|
|
80
|
+
return { kind: 'present', manual: { content: text, sections: [] } };
|
|
81
|
+
}
|
|
82
|
+
if (!isObjectRecord(value)) {
|
|
83
|
+
return {
|
|
84
|
+
kind: 'invalid',
|
|
85
|
+
errorText: `${fieldPath} must be either a string, or an object with optional content, contentFile, sections`,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
const supportedKeys = new Set(['content', 'contentFile', 'sections']);
|
|
89
|
+
const unknownKeys = Object.keys(value).filter((key) => !supportedKeys.has(key));
|
|
90
|
+
const warningText = unknownKeys.length > 0
|
|
91
|
+
? `${fieldPath} contains unsupported extra field(s): ${unknownKeys
|
|
92
|
+
.map((key) => `${fieldPath}.${key}`)
|
|
93
|
+
.join(', ')} (only content, contentFile, sections are used)`
|
|
94
|
+
: undefined;
|
|
95
|
+
const contentVal = value['content'];
|
|
96
|
+
let content;
|
|
97
|
+
if (contentVal !== undefined) {
|
|
98
|
+
if (!isNonEmptyString(contentVal)) {
|
|
99
|
+
return {
|
|
100
|
+
kind: 'invalid',
|
|
101
|
+
errorText: `${fieldPath}.content must be a non-empty string when provided`,
|
|
102
|
+
...(warningText !== undefined ? { warningText } : {}),
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
content = contentVal.trim();
|
|
106
|
+
}
|
|
107
|
+
const contentFileVal = value['contentFile'];
|
|
108
|
+
let contentFile;
|
|
109
|
+
if (contentFileVal !== undefined) {
|
|
110
|
+
if (!isNonEmptyString(contentFileVal)) {
|
|
111
|
+
return {
|
|
112
|
+
kind: 'invalid',
|
|
113
|
+
errorText: `${fieldPath}.contentFile must be a non-empty string when provided`,
|
|
114
|
+
...(warningText !== undefined ? { warningText } : {}),
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
contentFile = contentFileVal.trim();
|
|
118
|
+
}
|
|
119
|
+
const sectionsVal = value['sections'];
|
|
120
|
+
const sections = [];
|
|
121
|
+
if (sectionsVal !== undefined) {
|
|
122
|
+
if (Array.isArray(sectionsVal)) {
|
|
123
|
+
for (let i = 0; i < sectionsVal.length; i++) {
|
|
124
|
+
const sectionVal = sectionsVal[i];
|
|
125
|
+
if (!isObjectRecord(sectionVal)) {
|
|
126
|
+
return {
|
|
127
|
+
kind: 'invalid',
|
|
128
|
+
errorText: `${fieldPath}.sections[${i}] must be an object with title/content non-empty strings`,
|
|
129
|
+
...(warningText !== undefined ? { warningText } : {}),
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
const title = sectionVal['title'];
|
|
133
|
+
const sectionContent = sectionVal['content'];
|
|
134
|
+
if (!isNonEmptyString(title) || !isNonEmptyString(sectionContent)) {
|
|
135
|
+
return {
|
|
136
|
+
kind: 'invalid',
|
|
137
|
+
errorText: `${fieldPath}.sections[${i}] must provide non-empty title/content strings`,
|
|
138
|
+
...(warningText !== undefined ? { warningText } : {}),
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
sections.push({ title: title.trim(), content: sectionContent.trim() });
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
else if (isObjectRecord(sectionsVal)) {
|
|
145
|
+
for (const [sectionTitle, sectionContent] of Object.entries(sectionsVal)) {
|
|
146
|
+
if (!isNonEmptyString(sectionTitle) || !isNonEmptyString(sectionContent)) {
|
|
147
|
+
return {
|
|
148
|
+
kind: 'invalid',
|
|
149
|
+
errorText: `${fieldPath}.sections object entries must be non-empty string -> string`,
|
|
150
|
+
...(warningText !== undefined ? { warningText } : {}),
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
sections.push({ title: sectionTitle.trim(), content: sectionContent.trim() });
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
return {
|
|
158
|
+
kind: 'invalid',
|
|
159
|
+
errorText: `${fieldPath}.sections must be either [{ title, content }] or { "<title>": "<content>" }`,
|
|
160
|
+
...(warningText !== undefined ? { warningText } : {}),
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
if (content === undefined && contentFile === undefined && sections.length === 0) {
|
|
165
|
+
return {
|
|
166
|
+
kind: 'invalid',
|
|
167
|
+
errorText: `${fieldPath} must provide at least one of content, contentFile, or sections`,
|
|
168
|
+
...(warningText !== undefined ? { warningText } : {}),
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
return {
|
|
172
|
+
kind: 'present',
|
|
173
|
+
manual: { content, contentFile, sections },
|
|
174
|
+
...(warningText !== undefined ? { warningText } : {}),
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
function buildMcpToolsetManualInvalidProblem(serverId, errorText) {
|
|
178
|
+
return {
|
|
179
|
+
kind: 'mcp_server_error',
|
|
180
|
+
source: 'mcp',
|
|
181
|
+
id: `${mcpToolsetManualProblemPrefix(serverId)}error`,
|
|
182
|
+
severity: 'error',
|
|
183
|
+
timestamp: (0, time_1.formatUnifiedTimestamp)(new Date()),
|
|
184
|
+
message: `MCP server '${serverId}' manual declaration is invalid`,
|
|
185
|
+
messageI18n: {
|
|
186
|
+
en: `MCP server '${serverId}' manual declaration is invalid`,
|
|
187
|
+
zh: `MCP server '${serverId}' 的手册声明无效`,
|
|
188
|
+
},
|
|
189
|
+
detailTextI18n: {
|
|
190
|
+
en: errorText,
|
|
191
|
+
zh: errorText,
|
|
192
|
+
},
|
|
193
|
+
detail: { serverId, errorText },
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
function buildMcpToolsetManualUnknownFieldsProblem(serverId, warningText) {
|
|
197
|
+
return {
|
|
198
|
+
kind: 'mcp_server_error',
|
|
199
|
+
source: 'mcp',
|
|
200
|
+
id: `${mcpToolsetManualProblemPrefix(serverId)}unknown_fields`,
|
|
201
|
+
severity: 'warning',
|
|
202
|
+
timestamp: (0, time_1.formatUnifiedTimestamp)(new Date()),
|
|
203
|
+
message: `MCP server '${serverId}' manual declaration has unsupported extra fields`,
|
|
204
|
+
messageI18n: {
|
|
205
|
+
en: `MCP server '${serverId}' manual declaration has unsupported extra fields`,
|
|
206
|
+
zh: `MCP server '${serverId}' 的手册声明含有不支持的附加字段`,
|
|
207
|
+
},
|
|
208
|
+
detailTextI18n: {
|
|
209
|
+
en: `${warningText}\nThese extra fields are ignored by the manual loader. Keep only content, contentFile, and sections under \`servers.${serverId}.manual\`.`,
|
|
210
|
+
zh: `${warningText}\n这些附加字段会被手册加载器忽略。请仅在 \`servers.${serverId}.manual\` 下保留 content、contentFile、sections。`,
|
|
211
|
+
},
|
|
212
|
+
detail: { serverId, errorText: warningText },
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
function buildMcpToolsetManualTooLargeProblem(args) {
|
|
216
|
+
const errorText = `man({ "toolsetId": "${args.serverId}" }) rendered manual exceeds limit (${args.renderedChars} chars > ${args.limitChars} chars)`;
|
|
217
|
+
return {
|
|
218
|
+
kind: 'mcp_server_error',
|
|
219
|
+
source: 'mcp',
|
|
220
|
+
id: `${mcpToolsetManualProblemPrefix(args.serverId)}too_large`,
|
|
221
|
+
severity: 'error',
|
|
222
|
+
timestamp: (0, time_1.formatUnifiedTimestamp)(new Date()),
|
|
223
|
+
message: `MCP server '${args.serverId}' manual result is too large`,
|
|
224
|
+
messageI18n: {
|
|
225
|
+
en: `MCP server '${args.serverId}' manual result is too large`,
|
|
226
|
+
zh: `MCP server '${args.serverId}' 的手册结果过长`,
|
|
227
|
+
},
|
|
228
|
+
detailTextI18n: {
|
|
229
|
+
en: `${errorText}\nThe actual MCP toolset manual shown to the LLM is too large. Split the handbook by business topic so the default \`man({ "toolsetId": "${args.serverId}" })\` result stays within ${args.limitChars} chars.`,
|
|
230
|
+
zh: `\`man({ "toolsetId": "${args.serverId}" })\` 的实际手册结果过长(${args.renderedChars} chars > ${args.limitChars} chars)\n请按业务主题拆小手册,保证默认 \`man({ "toolsetId": "${args.serverId}" })\` 结果不超过 ${args.limitChars} chars。`,
|
|
231
|
+
},
|
|
232
|
+
detail: { serverId: args.serverId, errorText },
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
function buildMcpWorkspaceManualTooLargeProblem(args) {
|
|
236
|
+
const errorText = `man({ "toolsetId": "team_mgmt", "topics": ["mcp"] }) rendered manual exceeds limit (${args.renderedChars} chars > ${args.limitChars} chars)`;
|
|
237
|
+
return {
|
|
238
|
+
kind: 'mcp_workspace_config_error',
|
|
239
|
+
source: 'mcp',
|
|
240
|
+
id: `${mcpWorkspaceManualProblemPrefix()}team_mgmt_mcp_too_large`,
|
|
241
|
+
severity: 'error',
|
|
242
|
+
timestamp: (0, time_1.formatUnifiedTimestamp)(new Date()),
|
|
243
|
+
message: 'Rendered MCP handbook topic is too large',
|
|
244
|
+
messageI18n: {
|
|
245
|
+
en: 'Rendered MCP handbook topic is too large',
|
|
246
|
+
zh: 'MCP 手册主题的渲染结果过长',
|
|
247
|
+
},
|
|
248
|
+
detailTextI18n: {
|
|
249
|
+
en: `${errorText}\nThis check measures the final handbook content shown to the LLM. Split MCP handbook content so \`man({ "toolsetId": "team_mgmt", "topics": ["mcp"] })\` stays within ${args.limitChars} chars.`,
|
|
250
|
+
zh: `\`man({ "toolsetId": "team_mgmt", "topics": ["mcp"] })\` 的实际手册结果过长(${args.renderedChars} chars > ${args.limitChars} chars)\n该检查衡量的是最终给 LLM 看的手册内容。请拆小 MCP 手册内容,保证该结果不超过 ${args.limitChars} chars。`,
|
|
251
|
+
},
|
|
252
|
+
detail: { filePath: args.workspaceManualPath, errorText },
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
function measureRenderedToolsetManualRawChars(serverId) {
|
|
256
|
+
const tools = (0, registry_1.getToolset)(serverId);
|
|
257
|
+
const meta = (0, registry_1.getToolsetMeta)(serverId);
|
|
258
|
+
if (!tools || meta?.source !== 'mcp')
|
|
259
|
+
return null;
|
|
260
|
+
const availableToolNames = new Set(tools.map((tool) => tool.name));
|
|
261
|
+
const zh = (0, render_1.renderToolsetManual)({
|
|
262
|
+
toolsetId: serverId,
|
|
263
|
+
language: 'zh',
|
|
264
|
+
request: {},
|
|
265
|
+
availableToolNames,
|
|
266
|
+
});
|
|
267
|
+
const en = (0, render_1.renderToolsetManual)({
|
|
268
|
+
toolsetId: serverId,
|
|
269
|
+
language: 'en',
|
|
270
|
+
request: {},
|
|
271
|
+
availableToolNames,
|
|
272
|
+
});
|
|
273
|
+
if (!zh.foundToolset || !en.foundToolset)
|
|
274
|
+
return null;
|
|
275
|
+
return Math.max(zh.content.length, en.content.length);
|
|
276
|
+
}
|
|
277
|
+
async function reconcileMcpToolsetManualProblems(params) {
|
|
278
|
+
const desiredServerIds = new Set(params.serverIds);
|
|
279
|
+
const stalePrefixes = new Set();
|
|
280
|
+
for (const problem of (0, problems_1.listProblems)({ source: 'mcp' })) {
|
|
281
|
+
const match = problem.id.match(/^(mcp\/server\/[^/]+\/toolset_manual_)/);
|
|
282
|
+
if (!match || typeof match[1] !== 'string')
|
|
283
|
+
continue;
|
|
284
|
+
const serverId = problem.kind === 'mcp_server_error' ? problem.detail.serverId : null;
|
|
285
|
+
if (serverId !== null && desiredServerIds.has(serverId))
|
|
286
|
+
continue;
|
|
287
|
+
stalePrefixes.add(match[1]);
|
|
288
|
+
}
|
|
289
|
+
for (const prefix of stalePrefixes) {
|
|
290
|
+
(0, problems_1.reconcileProblemsByPrefix)(prefix, []);
|
|
291
|
+
}
|
|
292
|
+
const workspaceDesired = [];
|
|
293
|
+
const teamMgmtMcpTopicChars = await params.measureRenderedWorkspaceMcpTopicRawChars();
|
|
294
|
+
if (teamMgmtMcpTopicChars > output_limit_1.MANUAL_SINGLE_REQUEST_CHAR_LIMIT) {
|
|
295
|
+
workspaceDesired.push(buildMcpWorkspaceManualTooLargeProblem({
|
|
296
|
+
renderedChars: teamMgmtMcpTopicChars,
|
|
297
|
+
limitChars: output_limit_1.MANUAL_SINGLE_REQUEST_CHAR_LIMIT,
|
|
298
|
+
workspaceManualPath: params.workspaceManualPath,
|
|
299
|
+
}));
|
|
300
|
+
}
|
|
301
|
+
(0, problems_1.reconcileProblemsByPrefix)(mcpWorkspaceManualProblemPrefix(), workspaceDesired);
|
|
302
|
+
for (const serverId of params.serverIds) {
|
|
303
|
+
const desired = [];
|
|
304
|
+
const invalid = params.manualInfo.invalidByServerId.get(serverId);
|
|
305
|
+
if (invalid !== undefined) {
|
|
306
|
+
desired.push(buildMcpToolsetManualInvalidProblem(serverId, invalid));
|
|
307
|
+
}
|
|
308
|
+
const warningText = params.manualInfo.warningTextByServerId.get(serverId);
|
|
309
|
+
if (warningText !== undefined) {
|
|
310
|
+
desired.push(buildMcpToolsetManualUnknownFieldsProblem(serverId, warningText));
|
|
311
|
+
}
|
|
312
|
+
const renderedToolsetManualChars = measureRenderedToolsetManualRawChars(serverId);
|
|
313
|
+
if (renderedToolsetManualChars !== null &&
|
|
314
|
+
renderedToolsetManualChars > output_limit_1.MANUAL_SINGLE_REQUEST_CHAR_LIMIT) {
|
|
315
|
+
desired.push(buildMcpToolsetManualTooLargeProblem({
|
|
316
|
+
serverId,
|
|
317
|
+
renderedChars: renderedToolsetManualChars,
|
|
318
|
+
limitChars: output_limit_1.MANUAL_SINGLE_REQUEST_CHAR_LIMIT,
|
|
319
|
+
}));
|
|
320
|
+
}
|
|
321
|
+
(0, problems_1.reconcileProblemsByPrefix)(mcpToolsetManualProblemPrefix(serverId), desired);
|
|
322
|
+
}
|
|
323
|
+
}
|
package/dist/mcp/supervisor.js
CHANGED
|
@@ -51,7 +51,9 @@ const work_language_1 = require("../runtime/work-language");
|
|
|
51
51
|
const tool_1 = require("../tool");
|
|
52
52
|
const spec_1 = require("../tools/manual/spec");
|
|
53
53
|
const registry_1 = require("../tools/registry");
|
|
54
|
+
const team_mgmt_mcp_manual_1 = require("../tools/team_mgmt-mcp-manual");
|
|
54
55
|
const config_1 = require("./config");
|
|
56
|
+
const manual_problems_1 = require("./manual-problems");
|
|
55
57
|
const sdk_client_1 = require("./sdk-client");
|
|
56
58
|
const server_runtime_1 = require("./server-runtime");
|
|
57
59
|
const tool_names_1 = require("./tool-names");
|
|
@@ -533,20 +535,24 @@ async function reloadNow(reason) {
|
|
|
533
535
|
// Deletion is treated as empty config.
|
|
534
536
|
await applyWorkspaceConfig({ version: 1, servers: {} }, [], [], [], `missing file (${reason})`);
|
|
535
537
|
clearWorkspaceConfigProblem();
|
|
538
|
+
await reconcileMcpManualProblemsForRuntime([], null);
|
|
536
539
|
return;
|
|
537
540
|
}
|
|
538
541
|
clearDeclaredServerRuntimeCatalog();
|
|
542
|
+
await reconcileMcpManualProblemsForRuntime([], null);
|
|
539
543
|
upsertWorkspaceConfigProblem(`Failed to read ${MCP_YAML_PATH}: ${String(err)}`);
|
|
540
544
|
return;
|
|
541
545
|
}
|
|
542
546
|
const parsed = (0, config_1.parseMcpYaml)(rawText);
|
|
543
547
|
if (!parsed.ok) {
|
|
544
548
|
clearDeclaredServerRuntimeCatalog();
|
|
549
|
+
await reconcileMcpManualProblemsForRuntime([], null);
|
|
545
550
|
upsertWorkspaceConfigProblem(parsed.errorText);
|
|
546
551
|
return;
|
|
547
552
|
}
|
|
548
553
|
clearWorkspaceConfigProblem();
|
|
549
554
|
await applyWorkspaceConfig(parsed.config, parsed.invalidServers, parsed.serverIdsInYamlOrder, parsed.validServerIdsInYamlOrder, reason);
|
|
555
|
+
await reconcileMcpManualProblemsForRuntime(parsed.serverIdsInYamlOrder, rawText);
|
|
550
556
|
}
|
|
551
557
|
async function restartServerNow(serverId) {
|
|
552
558
|
let rawText;
|
|
@@ -558,13 +564,16 @@ async function restartServerNow(serverId) {
|
|
|
558
564
|
if (code === 'ENOENT') {
|
|
559
565
|
// Deletion is treated as empty config, so restart cannot proceed.
|
|
560
566
|
clearWorkspaceConfigProblem();
|
|
567
|
+
await reconcileMcpManualProblemsForRuntime([], null);
|
|
561
568
|
return { ok: false, errorText: `Cannot restart '${serverId}': ${MCP_YAML_PATH} is missing` };
|
|
562
569
|
}
|
|
570
|
+
await reconcileMcpManualProblemsForRuntime([], null);
|
|
563
571
|
upsertWorkspaceConfigProblem(`Failed to read ${MCP_YAML_PATH}: ${String(err)}`);
|
|
564
572
|
return { ok: false, errorText: `Failed to read ${MCP_YAML_PATH}: ${String(err)}` };
|
|
565
573
|
}
|
|
566
574
|
const parsed = (0, config_1.parseMcpYaml)(rawText);
|
|
567
575
|
if (!parsed.ok) {
|
|
576
|
+
await reconcileMcpManualProblemsForRuntime([], null);
|
|
568
577
|
upsertWorkspaceConfigProblem(parsed.errorText);
|
|
569
578
|
return { ok: false, errorText: parsed.errorText };
|
|
570
579
|
}
|
|
@@ -572,11 +581,13 @@ async function restartServerNow(serverId) {
|
|
|
572
581
|
const invalid = parsed.invalidServers.find((s) => s.serverId === serverId);
|
|
573
582
|
if (invalid) {
|
|
574
583
|
replaceDeclaredServerRuntimeCatalog(parsed.config, parsed.invalidServers, parsed.serverIdsInYamlOrder);
|
|
584
|
+
await reconcileMcpManualProblemsForRuntime(parsed.serverIdsInYamlOrder, rawText);
|
|
575
585
|
upsertMcpServerConfigInvalidProblem(serverId, invalid.errorText);
|
|
576
586
|
return { ok: false, errorText: invalid.errorText };
|
|
577
587
|
}
|
|
578
588
|
const serverCfg = parsed.config.servers[serverId];
|
|
579
589
|
if (!serverCfg) {
|
|
590
|
+
await reconcileMcpManualProblemsForRuntime(parsed.serverIdsInYamlOrder, rawText);
|
|
580
591
|
return {
|
|
581
592
|
ok: false,
|
|
582
593
|
errorText: `MCP server '${serverId}' is not configured in ${MCP_YAML_PATH}`,
|
|
@@ -588,6 +599,7 @@ async function restartServerNow(serverId) {
|
|
|
588
599
|
replaceDeclaredServerRuntimeCatalog(parsed.config, parsed.invalidServers, parsed.serverIdsInYamlOrder);
|
|
589
600
|
const res = await tryBuildServerState(serverCfg, desiredToolsetName, fingerprint);
|
|
590
601
|
if (!res.ok) {
|
|
602
|
+
await reconcileMcpManualProblemsForRuntime(parsed.serverIdsInYamlOrder, rawText);
|
|
591
603
|
upsertDeclaredServerRuntimeError(serverId, res.errorText);
|
|
592
604
|
upsertMcpServerRuntimeUnavailableProblem(serverId, res.errorText, res.detailTextI18n);
|
|
593
605
|
return { ok: false, errorText: res.errorText };
|
|
@@ -602,8 +614,18 @@ async function restartServerNow(serverId) {
|
|
|
602
614
|
serverStateById.set(serverId, res.state);
|
|
603
615
|
(0, problems_1.reconcileProblemsByPrefix)(problemPrefixForServer(serverId), res.state.problems);
|
|
604
616
|
reorderMcpToolsetsInRegistry(parsed.serverIdsInYamlOrder);
|
|
617
|
+
await reconcileMcpManualProblemsForRuntime(parsed.serverIdsInYamlOrder, rawText);
|
|
605
618
|
return { ok: true };
|
|
606
619
|
}
|
|
620
|
+
async function reconcileMcpManualProblemsForRuntime(serverIdsInYamlOrder, rawText) {
|
|
621
|
+
const manualInfo = rawText === null ? (0, manual_problems_1.emptyMcpToolsetManualByServer)() : (0, manual_problems_1.parseMcpManualByServer)(rawText);
|
|
622
|
+
await (0, manual_problems_1.reconcileMcpToolsetManualProblems)({
|
|
623
|
+
serverIds: serverIdsInYamlOrder,
|
|
624
|
+
manualInfo,
|
|
625
|
+
measureRenderedWorkspaceMcpTopicRawChars: team_mgmt_mcp_manual_1.measureRenderedTeamMgmtMcpTopicRawChars,
|
|
626
|
+
workspaceManualPath: MCP_YAML_PATH,
|
|
627
|
+
});
|
|
628
|
+
}
|
|
607
629
|
function upsertWorkspaceConfigProblem(errorText) {
|
|
608
630
|
(0, problems_1.upsertProblem)({
|
|
609
631
|
kind: 'mcp_workspace_config_error',
|
|
@@ -707,7 +729,7 @@ async function applyWorkspaceConfig(config, invalidServers, serverIdsInYamlOrder
|
|
|
707
729
|
unregisterServer(state);
|
|
708
730
|
state.dispatch.requestStop();
|
|
709
731
|
serverStateById.delete(serverId);
|
|
710
|
-
(0, problems_1.
|
|
732
|
+
(0, problems_1.reconcileProblemsByPrefix)(problemPrefixForServer(serverId), []);
|
|
711
733
|
}
|
|
712
734
|
// Surface invalid server config errors (while keeping last-known-good runtimes registered).
|
|
713
735
|
for (const s of invalidServers) {
|