@opentiny/webmcp-cli 0.0.3 → 0.0.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/bin.cjs +136 -55
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +136 -55
- package/dist/bin.js.map +1 -1
- package/dist/index.cjs +93 -39
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +93 -39
- package/dist/index.js.map +1 -1
- package/dist/webmcp-tools/excalidraw.com.js +3 -1
- package/dist/webmcp-tools/juejin.cn.js +131 -62
- package/dist/webmcp-tools/my.oschina.net.js +4 -2
- package/dist/webmcp-tools/www.baidu.com.js +3 -1
- package/package.json +1 -1
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
"use strict";
|
|
3
3
|
(() => {
|
|
4
4
|
// webmcp-tools/juejin.cn/index.ts
|
|
5
|
+
function isJuejinDraftEditorPage() {
|
|
6
|
+
if (!/^https:\/\/juejin\.cn\/editor\/drafts\//.test(location.href)) {
|
|
7
|
+
return false;
|
|
8
|
+
}
|
|
9
|
+
return !!document.querySelector(".edit-draft .header .title-input");
|
|
10
|
+
}
|
|
5
11
|
var mcp = navigator.modelContext;
|
|
6
12
|
if (!mcp || typeof mcp.registerTool !== "function") {
|
|
7
13
|
console.warn("[webmcp-tools] juejin.cn: navigator.modelContext.registerTool \u672A\u5C31\u7EEA\uFF0C\u8DF3\u8FC7\u6CE8\u5165");
|
|
@@ -37,8 +43,10 @@
|
|
|
37
43
|
if (!content?.trim()) {
|
|
38
44
|
throw new Error("\u53C2\u6570 content \u4E0D\u80FD\u4E3A\u7A7A");
|
|
39
45
|
}
|
|
40
|
-
if (!
|
|
41
|
-
throw new Error(
|
|
46
|
+
if (!isJuejinDraftEditorPage()) {
|
|
47
|
+
throw new Error(
|
|
48
|
+
"\u5F53\u524D\u9875\u9762\u4E0D\u662F\u6398\u91D1\u6587\u7AE0\u7F16\u8F91\u5668\uFF08\u65B0\u5EFA\u6216\u8349\u7A3F\u9875\u5747\u53EF\uFF09\uFF0C\u8BF7\u5148\u6253\u5F00 https://juejin.cn/editor/drafts/new?v=2"
|
|
49
|
+
);
|
|
42
50
|
}
|
|
43
51
|
let decodeContent;
|
|
44
52
|
try {
|
|
@@ -88,11 +96,16 @@
|
|
|
88
96
|
throw new Error("\u672A\u627E\u5230\u6B63\u6587\u7F16\u8F91\u5668\uFF08CodeMirror\uFF09\uFF0C\u8BF7\u786E\u8BA4\u7F16\u8F91\u5668\u9875\u9762\u5DF2\u5B8C\u5168\u52A0\u8F7D");
|
|
89
97
|
}
|
|
90
98
|
return {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
99
|
+
content: [{
|
|
100
|
+
type: "text",
|
|
101
|
+
text: JSON.stringify({
|
|
102
|
+
success: true,
|
|
103
|
+
message: "\u6587\u7AE0\u6807\u9898\u548C\u6B63\u6587\u5DF2\u6210\u529F\u586B\u5199\u5230\u6398\u91D1\u7F16\u8F91\u5668\uFF0C\u8349\u7A3F\u5C06\u81EA\u52A8\u4FDD\u5B58",
|
|
104
|
+
title: title.trim(),
|
|
105
|
+
contentLength: decodeContent.length,
|
|
106
|
+
editor
|
|
107
|
+
})
|
|
108
|
+
}]
|
|
96
109
|
};
|
|
97
110
|
}
|
|
98
111
|
});
|
|
@@ -118,9 +131,15 @@
|
|
|
118
131
|
}
|
|
119
132
|
}
|
|
120
133
|
return {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
134
|
+
content: [{
|
|
135
|
+
type: "text",
|
|
136
|
+
text: JSON.stringify({
|
|
137
|
+
success: true,
|
|
138
|
+
title: title.trim(),
|
|
139
|
+
contentLength: content.length,
|
|
140
|
+
content
|
|
141
|
+
})
|
|
142
|
+
}]
|
|
124
143
|
};
|
|
125
144
|
}
|
|
126
145
|
});
|
|
@@ -147,96 +166,146 @@
|
|
|
147
166
|
required: ["summary"]
|
|
148
167
|
},
|
|
149
168
|
execute: async ({ category = "\u524D\u7AEF", tag = "Vue.js", summary }) => {
|
|
150
|
-
|
|
169
|
+
if (!isJuejinDraftEditorPage()) {
|
|
170
|
+
throw new Error("\u672A\u5904\u4E8E\u6398\u91D1\u6587\u7AE0\u7F16\u8F91\u5668\u9875\u9762\uFF0C\u8BF7\u5148 tabs switch \u5230\u7F16\u8F91\u5668\u6807\u7B7E\u9875\u540E\u518D\u53D1\u5E03");
|
|
171
|
+
}
|
|
172
|
+
const editorRoot = document.querySelector(".edit-draft") ?? document;
|
|
173
|
+
const publishBtn = Array.from(editorRoot.querySelectorAll("button")).find(
|
|
151
174
|
(e) => e.textContent?.trim() === "\u53D1\u5E03"
|
|
152
175
|
);
|
|
153
176
|
if (!publishBtn) {
|
|
154
|
-
throw new Error("\u672A\u627E\u5230\u201C\u53D1\u5E03\u201D\u6309\u94AE\uFF0C\u8BF7\u786E\u8BA4\u5DF2\u5904\u4E8E\u6587\u7AE0\u7F16\u8F91\u5668\u9875\u9762");
|
|
177
|
+
throw new Error("\u672A\u627E\u5230\u201C\u53D1\u5E03\u201D\u6309\u94AE\uFF0C\u8BF7\u786E\u8BA4\u5DF2\u5904\u4E8E\u6587\u7AE0\u7F16\u8F91\u5668\u9875\u9762\u4E14\u9875\u9762\u5DF2\u5B8C\u5168\u52A0\u8F7D");
|
|
155
178
|
}
|
|
156
179
|
publishBtn.click();
|
|
157
180
|
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
158
|
-
const
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
181
|
+
const dialogScope = document.querySelector('.panel, .modal, [role="dialog"]') || document;
|
|
182
|
+
const candidateSelectors = [
|
|
183
|
+
".category-list .item",
|
|
184
|
+
// 掘金:直接命中
|
|
185
|
+
".category-list li",
|
|
186
|
+
".category-list button",
|
|
187
|
+
'.category-list [role="button"]',
|
|
188
|
+
".category-item",
|
|
189
|
+
'[class*="category"] li',
|
|
190
|
+
'[class*="category"] span'
|
|
191
|
+
];
|
|
192
|
+
let catBtn;
|
|
193
|
+
for (const sel of candidateSelectors) {
|
|
194
|
+
catBtn = Array.from(dialogScope.querySelectorAll(sel)).find(
|
|
195
|
+
(e) => e.textContent?.trim() === category
|
|
165
196
|
);
|
|
197
|
+
if (catBtn) break;
|
|
198
|
+
}
|
|
199
|
+
if (!catBtn) {
|
|
200
|
+
catBtn = Array.from(dialogScope.querySelectorAll("div, span, li, button")).find((e) => {
|
|
201
|
+
const el = e;
|
|
202
|
+
return el.textContent?.trim() === category && el.offsetParent !== null;
|
|
203
|
+
});
|
|
166
204
|
}
|
|
167
205
|
if (!catBtn) {
|
|
168
206
|
throw new Error(`\u672A\u627E\u5230\u5206\u7C7B\u6309\u94AE: ${category}`);
|
|
169
207
|
}
|
|
170
208
|
;
|
|
171
209
|
catBtn.click();
|
|
172
|
-
const
|
|
173
|
-
(e) => e.textContent?.includes("\u6DFB\u52A0\u6807\u7B7E")
|
|
174
|
-
);
|
|
175
|
-
if (!tagLabel) {
|
|
176
|
-
throw new Error("\u672A\u627E\u5230\u201C\u6DFB\u52A0\u6807\u7B7E\u201D\u7684\u8868\u5355\u9879");
|
|
177
|
-
}
|
|
178
|
-
const parent = tagLabel.closest(".form-item, .margin-bottom, .entry-form-item");
|
|
179
|
-
const input = parent ? parent.querySelector("input") : null;
|
|
210
|
+
const input = dialogScope.querySelector('.byte-select__input, input[placeholder*="\u641C\u7D22\u6DFB\u52A0\u6807\u7B7E"], input[placeholder*="\u6DFB\u52A0\u6807\u7B7E"], input[placeholder*="\u6807\u7B7E"]');
|
|
180
211
|
if (!input) {
|
|
181
212
|
throw new Error("\u672A\u627E\u5230\u6807\u7B7E\u8F93\u5165\u6846");
|
|
182
213
|
}
|
|
183
214
|
input.focus();
|
|
184
|
-
|
|
185
|
-
|
|
215
|
+
const nativeInputValueSetter = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, "value")?.set;
|
|
216
|
+
if (nativeInputValueSetter) {
|
|
217
|
+
nativeInputValueSetter.call(input, tag);
|
|
218
|
+
} else {
|
|
219
|
+
input.value = tag;
|
|
220
|
+
}
|
|
221
|
+
input.dispatchEvent(new InputEvent("input", { bubbles: true, cancelable: true, data: tag }));
|
|
186
222
|
input.dispatchEvent(new Event("change", { bubbles: true }));
|
|
187
|
-
await new Promise((resolve) => setTimeout(resolve,
|
|
188
|
-
const
|
|
223
|
+
await new Promise((resolve) => setTimeout(resolve, 2e3));
|
|
224
|
+
const tagDropdownItems = Array.from(
|
|
189
225
|
document.querySelectorAll(
|
|
190
|
-
".byte-select-option, .
|
|
226
|
+
".byte-select-option, .byte-select__option, .byte-select-option-wrapper, .select-option, .dropdown-item, .item"
|
|
191
227
|
)
|
|
192
228
|
);
|
|
193
|
-
|
|
229
|
+
let tagItem = tagDropdownItems.find((e) => e.textContent?.trim() === tag);
|
|
230
|
+
if (!tagItem) {
|
|
231
|
+
tagItem = Array.from(document.querySelectorAll('li, [role="option"]')).find((e) => {
|
|
232
|
+
const el = e;
|
|
233
|
+
return el.textContent?.trim() === tag && el.offsetParent !== null;
|
|
234
|
+
});
|
|
235
|
+
}
|
|
194
236
|
if (!tagItem) {
|
|
195
|
-
|
|
237
|
+
const foundTexts = tagDropdownItems.map((e) => e.textContent?.trim()).join(", ");
|
|
238
|
+
throw new Error(`\u6807\u7B7E\u4E0B\u62C9\u9009\u9879\u4E2D\u672A\u627E\u5230\u5339\u914D\u7684: ${tag}\u3002\u5F53\u524D\u627E\u5230\u7684\u9009\u9879\u6709: [${foundTexts}]\uFF0C\u8BF7\u68C0\u67E5\u6807\u7B7E\u540D\u79F0\u662F\u5426\u6B63\u786E\uFF0C\u6216\u624B\u52A8\u6253\u5F00\u4E0B\u62C9\u6846\u9009\u62E9`);
|
|
196
239
|
}
|
|
197
240
|
tagItem.click();
|
|
198
241
|
let finalSummary = summary || "";
|
|
199
|
-
if (finalSummary.length < 50) {
|
|
200
|
-
|
|
201
|
-
finalSummary += "\u3002\u8FD9\u662F\u5173\u4E8E\u672C\u6587\u5185\u5BB9\u7684\u8BE6\u7EC6\u4ECB\u7ECD\uFF0C\u6B22\u8FCE\u9605\u8BFB\u5168\u6587\u4E86\u89E3\u66F4\u591A\u7CBE\u5F69\u7684\u6280\u672F\u7EC6\u8282\u4E0E\u5B9E\u8DF5\u7ECF\u9A8C\u5206\u4EAB\u3002";
|
|
202
|
-
}
|
|
242
|
+
if (finalSummary.length < 50 || finalSummary.length > 100) {
|
|
243
|
+
throw new Error(`\u6458\u8981\u5B57\u6570\u5FC5\u987B\u5728 50 \u5230 100 \u5B57\u4E4B\u95F4\uFF0C\u5F53\u524D\u5B57\u6570\u4E3A\uFF1A${finalSummary.length}\u3002\u8BF7\u91CD\u65B0\u751F\u6210\u6458\u8981\u540E\u518D\u8BD5\u3002`);
|
|
203
244
|
}
|
|
204
|
-
|
|
205
|
-
|
|
245
|
+
const summaryTextarea = dialogScope.querySelector(".byte-input__textarea") || dialogScope.querySelector("textarea") || dialogScope.querySelector('.summary-textarea, textarea[placeholder*="\u6458\u8981"]');
|
|
246
|
+
if (!summaryTextarea) {
|
|
247
|
+
throw new Error("\u672A\u627E\u5230\u6458\u8981\u8F93\u5165\u6846\uFF08.byte-input__textarea\uFF09\uFF0C\u8BF7\u68C0\u67E5\u5F39\u7A97\u662F\u5426\u6B63\u5E38\u6253\u5F00");
|
|
206
248
|
}
|
|
207
|
-
const
|
|
208
|
-
|
|
209
|
-
|
|
249
|
+
const nativeTextareaValueSetter = Object.getOwnPropertyDescriptor(HTMLTextAreaElement.prototype, "value")?.set;
|
|
250
|
+
summaryTextarea.focus();
|
|
251
|
+
if (nativeTextareaValueSetter) {
|
|
252
|
+
nativeTextareaValueSetter.call(summaryTextarea, finalSummary);
|
|
253
|
+
} else {
|
|
210
254
|
summaryTextarea.value = finalSummary;
|
|
211
|
-
summaryTextarea.dispatchEvent(new Event("input", { bubbles: true }));
|
|
212
|
-
summaryTextarea.dispatchEvent(new Event("change", { bubbles: true }));
|
|
213
|
-
summaryTextarea.blur();
|
|
214
|
-
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
215
|
-
}
|
|
216
|
-
const titleClose = Array.from(document.querySelectorAll("*")).find(
|
|
217
|
-
(e) => e.textContent?.trim() === "\u53D1\u5E03\u6587\u7AE0"
|
|
218
|
-
);
|
|
219
|
-
if (titleClose) {
|
|
220
|
-
titleClose.click();
|
|
221
255
|
}
|
|
256
|
+
summaryTextarea.dispatchEvent(new InputEvent("input", { bubbles: true, cancelable: true }));
|
|
257
|
+
summaryTextarea.dispatchEvent(new Event("change", { bubbles: true }));
|
|
258
|
+
summaryTextarea.blur();
|
|
259
|
+
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
260
|
+
input.dispatchEvent(new KeyboardEvent("keydown", { key: "Escape", bubbles: true }));
|
|
261
|
+
input.blur();
|
|
222
262
|
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
223
|
-
|
|
263
|
+
let confirmBtn = Array.from(dialogScope.querySelectorAll("button")).find(
|
|
224
264
|
(e) => e.textContent?.trim() === "\u786E\u5B9A\u5E76\u53D1\u5E03"
|
|
225
265
|
);
|
|
226
266
|
if (!confirmBtn) {
|
|
227
267
|
throw new Error("\u672A\u627E\u5230\u201C\u786E\u5B9A\u5E76\u53D1\u5E03\u201D\u6309\u94AE");
|
|
228
268
|
}
|
|
229
269
|
confirmBtn.click();
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
(
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
270
|
+
const publishResult = await Promise.race([
|
|
271
|
+
// 信号1:轮询检测弹窗是否消失
|
|
272
|
+
new Promise((resolve) => {
|
|
273
|
+
const check = setInterval(() => {
|
|
274
|
+
const panel = document.querySelector(".panel");
|
|
275
|
+
if (!panel || panel.offsetParent === null) {
|
|
276
|
+
clearInterval(check);
|
|
277
|
+
resolve("popup_closed");
|
|
278
|
+
}
|
|
279
|
+
}, 200);
|
|
280
|
+
setTimeout(() => {
|
|
281
|
+
clearInterval(check);
|
|
282
|
+
}, 5e3);
|
|
283
|
+
}),
|
|
284
|
+
// 信号2:监听页面跳转(beforeunload / hashchange 均可触发)
|
|
285
|
+
new Promise((resolve) => {
|
|
286
|
+
const handler = () => resolve("navigating");
|
|
287
|
+
window.addEventListener("beforeunload", handler, { once: true });
|
|
288
|
+
setTimeout(() => {
|
|
289
|
+
window.removeEventListener("beforeunload", handler);
|
|
290
|
+
}, 5e3);
|
|
291
|
+
}),
|
|
292
|
+
// 信号3:超时兜底
|
|
293
|
+
new Promise((resolve) => setTimeout(() => resolve("timeout"), 5e3))
|
|
294
|
+
]);
|
|
295
|
+
if (publishResult === "timeout") {
|
|
296
|
+
const panel = document.querySelector(".panel");
|
|
297
|
+
if (panel && panel.offsetParent !== null) {
|
|
298
|
+
throw new Error("\u53D1\u5E03\u6587\u7AE0\u5931\u8D25\uFF0C\u5F39\u51FA\u6846\u672A\u5173\u95ED\uFF0C\u8BF7\u68C0\u67E5\u5206\u7C7B\u3001\u6807\u7B7E\u6216\u5176\u4ED6\u5FC5\u586B\u9879\u662F\u5426\u6B63\u786E\u586B\u5199");
|
|
299
|
+
}
|
|
236
300
|
}
|
|
237
301
|
return {
|
|
238
|
-
|
|
239
|
-
|
|
302
|
+
content: [{
|
|
303
|
+
type: "text",
|
|
304
|
+
text: JSON.stringify({
|
|
305
|
+
success: true,
|
|
306
|
+
message: `\u81EA\u52A8\u53D1\u5E03\u6D41\u7A0B\u5DF2\u89E6\u53D1\uFF0C\u5206\u7C7B: ${category}, \u6807\u7B7E: ${tag}\uFF0C\u53D1\u5E03\u4FE1\u53F7: ${publishResult}`
|
|
307
|
+
})
|
|
308
|
+
}]
|
|
240
309
|
};
|
|
241
310
|
}
|
|
242
311
|
});
|
|
@@ -4,8 +4,10 @@
|
|
|
4
4
|
// webmcp-tools/my.oschina.net/index.ts
|
|
5
5
|
var mcp = navigator.modelContext;
|
|
6
6
|
if (!mcp || typeof mcp.registerTool !== "function") {
|
|
7
|
-
console.warn("[webmcp-tools]
|
|
8
|
-
} else if (!window.
|
|
7
|
+
console.warn("[webmcp-tools] my.oschina.net: navigator.modelContext.registerTool \u672A\u5C31\u7EEA\uFF0C\u8DF3\u8FC7\u6CE8\u5165");
|
|
8
|
+
} else if (!window.__webmcptools_myoschinanet) {
|
|
9
|
+
;
|
|
10
|
+
window.__webmcptools_myoschinanet = true;
|
|
9
11
|
try {
|
|
10
12
|
mcp.registerTool({
|
|
11
13
|
name: "create_article",
|
|
@@ -5,7 +5,9 @@
|
|
|
5
5
|
var _baiduMcp = navigator.modelContext;
|
|
6
6
|
if (!_baiduMcp || typeof _baiduMcp.registerTool !== "function") {
|
|
7
7
|
console.warn("[webmcp-tools] www.baidu.com: navigator.modelContext.registerTool \u672A\u5C31\u7EEA\uFF0C\u8DF3\u8FC7\u6CE8\u5165");
|
|
8
|
-
} else if (!window.
|
|
8
|
+
} else if (!window.__webmcptools_wwwbaiducom) {
|
|
9
|
+
;
|
|
10
|
+
window.__webmcptools_wwwbaiducom = true;
|
|
9
11
|
try {
|
|
10
12
|
_baiduMcp.registerTool({
|
|
11
13
|
name: "baidu_search",
|