dingtalk-wiki 1.2.4 → 1.2.5
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/index.js +79 -24
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -850,7 +850,11 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
850
850
|
properties: {
|
|
851
851
|
doc_key: {
|
|
852
852
|
type: 'string',
|
|
853
|
-
description: '
|
|
853
|
+
description: '文档标识。支持 wiki nodes 的 nodeId(dentryUuid)、docKey,或文档 URL。重要:create_wiki_doc 返回的 nodeId 不能用于内容读写,请使用 docKey 或 dentryUuid。若传入 create 的 nodeId,需额外提供 workspace_id 以自动查找'
|
|
854
|
+
},
|
|
855
|
+
workspace_id: {
|
|
856
|
+
type: 'string',
|
|
857
|
+
description: '知识库 ID(可选)。当 doc_key 来自 create_wiki_doc 返回的 nodeId 时,提供此参数可自动查找正确的 dentryUuid'
|
|
854
858
|
},
|
|
855
859
|
operator_id: {
|
|
856
860
|
type: 'string',
|
|
@@ -868,12 +872,16 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
868
872
|
properties: {
|
|
869
873
|
doc_key: {
|
|
870
874
|
type: 'string',
|
|
871
|
-
description: '
|
|
875
|
+
description: '文档标识。支持 wiki nodes 的 nodeId(dentryUuid)、docKey,或文档 URL。重要:create_wiki_doc 返回的 nodeId 不能用于内容读写,请使用 docKey 或 dentryUuid。若传入 create 的 nodeId,需额外提供 workspace_id 以自动查找'
|
|
872
876
|
},
|
|
873
877
|
content: {
|
|
874
878
|
type: 'string',
|
|
875
879
|
description: '要写入的 Markdown 内容'
|
|
876
880
|
},
|
|
881
|
+
workspace_id: {
|
|
882
|
+
type: 'string',
|
|
883
|
+
description: '知识库 ID(可选)。当 doc_key 来自 create_wiki_doc 返回的 nodeId 时,提供此参数可自动查找正确的 dentryUuid'
|
|
884
|
+
},
|
|
877
885
|
operator_id: {
|
|
878
886
|
type: 'string',
|
|
879
887
|
description: '操作者 unionid(不传则使用默认用户)'
|
|
@@ -1144,6 +1152,33 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
1144
1152
|
};
|
|
1145
1153
|
});
|
|
1146
1154
|
|
|
1155
|
+
async function resolveDocKey(docKey, operatorId, dingtalkInstance) {
|
|
1156
|
+
const rawInput = docKey;
|
|
1157
|
+
|
|
1158
|
+
// 从 URL 中提取 ID
|
|
1159
|
+
const urlMatch = String(docKey).match(/\/i\/nodes\/([^\/\?#]+)/);
|
|
1160
|
+
docKey = urlMatch ? urlMatch[1] : docKey;
|
|
1161
|
+
|
|
1162
|
+
try {
|
|
1163
|
+
const nodeInfo = await dingtalkInstance.docRequest('GET', `/v2.0/wiki/nodes/${docKey}`, { operatorId });
|
|
1164
|
+
const node = nodeInfo.node || nodeInfo;
|
|
1165
|
+
|
|
1166
|
+
// wiki/nodes 的 nodeId = dentryUuid,直接可用
|
|
1167
|
+
// 但 node.document.docKey 可能是不同的值,优先使用
|
|
1168
|
+
if (node.document?.docKey) {
|
|
1169
|
+
return node.document.docKey;
|
|
1170
|
+
}
|
|
1171
|
+
// 部分响应直接把 docKey 放在顶层
|
|
1172
|
+
if (node.docKey) {
|
|
1173
|
+
return node.docKey;
|
|
1174
|
+
}
|
|
1175
|
+
} catch (e) {
|
|
1176
|
+
// 传入 create nodeId 时 wiki/nodes 会拒绝,静默 fallback
|
|
1177
|
+
}
|
|
1178
|
+
|
|
1179
|
+
return docKey;
|
|
1180
|
+
}
|
|
1181
|
+
|
|
1147
1182
|
// 工具调用处理
|
|
1148
1183
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
1149
1184
|
const { name, arguments: args } = request.params;
|
|
@@ -1297,11 +1332,14 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1297
1332
|
'',
|
|
1298
1333
|
`${typeIcon} ${name}`,
|
|
1299
1334
|
`🗂️ 类型: ${doc_type}`,
|
|
1300
|
-
`🆔 Node ID: ${doc.nodeId}
|
|
1335
|
+
`🆔 Node ID: ${doc.nodeId}`,
|
|
1301
1336
|
];
|
|
1302
1337
|
|
|
1303
1338
|
if (doc.docKey) {
|
|
1304
|
-
lines.push(`🔑 DocKey
|
|
1339
|
+
lines.push(`🔑 DocKey(用于内容读写): ${doc.docKey}`);
|
|
1340
|
+
}
|
|
1341
|
+
if (doc.dentryUuid) {
|
|
1342
|
+
lines.push(`📄 dentryUuid(用于内容读写): ${doc.dentryUuid}`);
|
|
1305
1343
|
}
|
|
1306
1344
|
if (doc.url) {
|
|
1307
1345
|
lines.push(`🔗 链接: ${doc.url}`);
|
|
@@ -1319,8 +1357,10 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1319
1357
|
url: doc.url || '',
|
|
1320
1358
|
type: doc_type,
|
|
1321
1359
|
});
|
|
1322
|
-
|
|
1323
|
-
|
|
1360
|
+
const contentId = doc.docKey || doc.dentryUuid || doc.nodeId;
|
|
1361
|
+
if (args.content && contentId) {
|
|
1362
|
+
dingtalk.docRequest('POST', `/v1.0/doc/suites/documents/${contentId}/overwriteContent`, {
|
|
1363
|
+
operatorId: opId,
|
|
1324
1364
|
data: { content: args.content, contentType: 'markdown' }
|
|
1325
1365
|
}).catch(() => {});
|
|
1326
1366
|
}
|
|
@@ -1557,19 +1597,27 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1557
1597
|
}
|
|
1558
1598
|
|
|
1559
1599
|
case 'get_wiki_doc_content': {
|
|
1560
|
-
const { doc_key: docKey, operator_id } = args;
|
|
1600
|
+
const { doc_key: docKey, workspace_id: workspaceId, operator_id } = args;
|
|
1561
1601
|
if (operator_id) {
|
|
1562
1602
|
dingtalk.setOperatorId(operator_id);
|
|
1563
1603
|
}
|
|
1564
1604
|
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1605
|
+
let realDocKey = await resolveDocKey(docKey, operator_id || null, dingtalk);
|
|
1606
|
+
|
|
1607
|
+
// 如果 resolve 后值没变(可能是 create 返回的 nodeId),尝试搜索 API 查找
|
|
1608
|
+
if (realDocKey === docKey && workspaceId) {
|
|
1609
|
+
try {
|
|
1610
|
+
const searchRes = await dingtalk.docRequest('GET', `/v1.0/doc/docs`, {
|
|
1611
|
+
operatorId: operator_id || null,
|
|
1612
|
+
extraParams: { workspaceId, keyword: '', maxResults: 50 }
|
|
1613
|
+
});
|
|
1614
|
+
const docs = searchRes.docs || [];
|
|
1615
|
+
const matched = docs.find(d => d.nodeBO?.nodeId === docKey || d.nodeBO?.nodeId === realDocKey) || docs[0];
|
|
1616
|
+
if (matched?.nodeBO?.nodeId) {
|
|
1617
|
+
realDocKey = matched.nodeBO.nodeId;
|
|
1618
|
+
}
|
|
1619
|
+
} catch (e) { /* ignore */ }
|
|
1620
|
+
}
|
|
1573
1621
|
|
|
1574
1622
|
const result = await dingtalk.docRequest('GET', `/v1.0/doc/suites/documents/${realDocKey}/blocks`, { operatorId: operator_id || null });
|
|
1575
1623
|
const blocks = result.result?.data || [];
|
|
@@ -1590,19 +1638,26 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1590
1638
|
}
|
|
1591
1639
|
|
|
1592
1640
|
case 'update_wiki_doc_content': {
|
|
1593
|
-
const { doc_key: docKey, content, operator_id } = args;
|
|
1641
|
+
const { doc_key: docKey, content, workspace_id: workspaceId, operator_id } = args;
|
|
1594
1642
|
if (operator_id) {
|
|
1595
1643
|
dingtalk.setOperatorId(operator_id);
|
|
1596
1644
|
}
|
|
1597
1645
|
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1646
|
+
let realDocKey = await resolveDocKey(docKey, operator_id || null, dingtalk);
|
|
1647
|
+
|
|
1648
|
+
if (realDocKey === docKey && workspaceId) {
|
|
1649
|
+
try {
|
|
1650
|
+
const searchRes = await dingtalk.docRequest('GET', `/v1.0/doc/docs`, {
|
|
1651
|
+
operatorId: operator_id || null,
|
|
1652
|
+
extraParams: { workspaceId, keyword: '', maxResults: 50 }
|
|
1653
|
+
});
|
|
1654
|
+
const docs = searchRes.docs || [];
|
|
1655
|
+
const matched = docs.find(d => d.nodeBO?.nodeId === docKey || d.nodeBO?.nodeId === realDocKey) || docs[0];
|
|
1656
|
+
if (matched?.nodeBO?.nodeId) {
|
|
1657
|
+
realDocKey = matched.nodeBO.nodeId;
|
|
1658
|
+
}
|
|
1659
|
+
} catch (e) { /* ignore */ }
|
|
1660
|
+
}
|
|
1606
1661
|
|
|
1607
1662
|
await dingtalk.docRequest('POST', `/v1.0/doc/suites/documents/${realDocKey}/overwriteContent`, {
|
|
1608
1663
|
operatorId: operator_id || null,
|