@lotaber_wang/openclaw-dc-plugin 0.1.10 → 0.1.11
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/README.md +10 -7
- package/index.js +140 -27
- package/lib/mcp-bridge.js +19 -8
- package/openclaw.plugin.json +2 -2
- package/package.json +11 -3
- package/skills/taptap-dc-ops-brief/SKILL.md +3 -3
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
## 安装
|
|
17
17
|
|
|
18
18
|
```bash
|
|
19
|
-
openclaw plugins install @lotaber_wang/openclaw-dc-plugin@0.1.
|
|
19
|
+
openclaw plugins install @lotaber_wang/openclaw-dc-plugin@0.1.11
|
|
20
20
|
```
|
|
21
21
|
|
|
22
22
|
安装完成后,建议立刻执行一次检查:
|
|
@@ -31,7 +31,7 @@ openclaw plugins inspect openclaw-dc-plugin
|
|
|
31
31
|
|
|
32
32
|
推荐通知文案:
|
|
33
33
|
|
|
34
|
-
`TapTap DC 插件已安装完成。OpenClaw
|
|
34
|
+
`TapTap DC 插件已安装完成。OpenClaw 接下来如需重启 Gateway,应先提示用户;重启完成后即可使用 taptap_dc_* 工具。`
|
|
35
35
|
|
|
36
36
|
执行顺序要求:
|
|
37
37
|
|
|
@@ -52,9 +52,9 @@ openclaw gateway restart
|
|
|
52
52
|
## 推荐安装流程
|
|
53
53
|
|
|
54
54
|
```bash
|
|
55
|
-
openclaw plugins install @lotaber_wang/openclaw-dc-plugin@0.1.
|
|
55
|
+
openclaw plugins install @lotaber_wang/openclaw-dc-plugin@0.1.11
|
|
56
56
|
openclaw plugins inspect openclaw-dc-plugin
|
|
57
|
-
echo 'TapTap DC 插件已安装完成。OpenClaw
|
|
57
|
+
echo 'TapTap DC 插件已安装完成。OpenClaw 接下来如需重启 Gateway,应先提示用户;重启完成后即可使用 taptap_dc_* 工具。'
|
|
58
58
|
openclaw gateway restart
|
|
59
59
|
```
|
|
60
60
|
|
|
@@ -130,7 +130,7 @@ openclaw gateway restart
|
|
|
130
130
|
|
|
131
131
|
如果安装后看不到 `taptap_dc_*` 工具,优先按这个顺序排查:
|
|
132
132
|
|
|
133
|
-
1. 确认安装的是 `@lotaber_wang/openclaw-dc-plugin@0.1.
|
|
133
|
+
1. 确认安装的是 `@lotaber_wang/openclaw-dc-plugin@0.1.11` 或更新版本
|
|
134
134
|
2. 执行 `openclaw plugins inspect openclaw-dc-plugin`
|
|
135
135
|
3. 如果宿主要求重启 Gateway,先向用户发送安装完成提示
|
|
136
136
|
4. 再执行 `openclaw gateway restart`
|
|
@@ -158,11 +158,14 @@ openclaw gateway restart
|
|
|
158
158
|
- OpenClaw 进程是否有临时目录写权限
|
|
159
159
|
- OpenClaw 是否已经完成 Gateway 重启
|
|
160
160
|
|
|
161
|
-
从 `0.1.
|
|
161
|
+
从 `0.1.11` 开始,插件安装链路与 bridge 会额外做这些兼容处理:
|
|
162
162
|
|
|
163
163
|
- 在 `package.json` 中补充 `openclaw.install.npmSpec`,让安装链路更稳定
|
|
164
|
+
- 在 `package.json` 的 `openclaw.install` 中补充 `postInstallMessage` / `instructions` / `restartCommand`
|
|
165
|
+
- 插件导出对象会同步暴露 `installation` / `installHints`,给宿主额外一层安装提示兜底
|
|
164
166
|
- 在 `openclaw.plugin.json` 中显式开启 `enabledByDefault`
|
|
165
167
|
- 统一插件 id 为 `openclaw-dc-plugin`,避免 manifest id 与 entry hint 不一致
|
|
168
|
+
- 默认仅保留错误级别注册/bridge 日志;详细日志改为 `verbose=true` 时才输出,减少安装后自动重载时的噪音
|
|
166
169
|
- `initialize` 超时后自动切换到无缓冲 / PTY 启动策略重试
|
|
167
170
|
- `initialize` 默认超时提升到 45 秒,避免宿主启动稍慢时过早失败
|
|
168
171
|
- 向内嵌 TapTap runtime 发送 `initialize` 与后续请求时,默认改为裸 JSON + 换行(NDJSON 风格),避免只发 `Content-Length` 帧导致无响应
|
|
@@ -171,4 +174,4 @@ openclaw gateway restart
|
|
|
171
174
|
- 启动时如果 stdout 混入人类可读日志,会先自动丢弃噪音再解析协议消息
|
|
172
175
|
- 如果拿到的是半截 JSON,会先继续等待后续分片,而不是立刻按失败处理
|
|
173
176
|
- 过滤 PTY 场景下被回显到 stdout 的请求消息
|
|
174
|
-
-
|
|
177
|
+
- 授权结果会把裸授权直链放在最前面,并在 `details.preferred_auth_url` / `details.auth_links` 中重复返回,降低宿主偶发吞链路时的影响
|
package/index.js
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
import { readFileSync } from 'node:fs';
|
|
2
|
+
import process from 'node:process';
|
|
2
3
|
import { TapTapMcpBridge } from './lib/mcp-bridge.js';
|
|
3
4
|
|
|
5
|
+
const RESTART_NOTICE =
|
|
6
|
+
'TapTap DC 插件已安装完成。OpenClaw 接下来如需重启 Gateway,应先提示用户;重启完成后即可使用 taptap_dc_* 工具。';
|
|
7
|
+
|
|
8
|
+
const INSTALLATION_GUIDANCE = [
|
|
9
|
+
'如果安装流程判断需要重启 Gateway,先通知用户,再执行重启。',
|
|
10
|
+
`推荐提示文案:${RESTART_NOTICE}`,
|
|
11
|
+
'执行顺序:先提示用户 -> 再执行 gateway restart -> 重启完成后再开始使用 taptap_dc_* 工具。',
|
|
12
|
+
];
|
|
13
|
+
|
|
4
14
|
function toolResult(text, details = {}) {
|
|
5
15
|
return {
|
|
6
16
|
content: [{ type: 'text', text }],
|
|
@@ -98,15 +108,60 @@ function enrichAuthPayload(authPayload) {
|
|
|
98
108
|
null;
|
|
99
109
|
|
|
100
110
|
const wrappedAuthUrl = authPayload.wrapped_auth_url || authPayload.auth_url || null;
|
|
111
|
+
const preferredAuthUrl = directAuthUrl || wrappedAuthUrl || null;
|
|
112
|
+
const authLinks = [
|
|
113
|
+
preferredAuthUrl
|
|
114
|
+
? {
|
|
115
|
+
kind: 'preferred',
|
|
116
|
+
label: '直接点击授权',
|
|
117
|
+
url: preferredAuthUrl,
|
|
118
|
+
}
|
|
119
|
+
: null,
|
|
120
|
+
directAuthUrl && directAuthUrl !== preferredAuthUrl
|
|
121
|
+
? {
|
|
122
|
+
kind: 'direct',
|
|
123
|
+
label: '授权直链',
|
|
124
|
+
url: directAuthUrl,
|
|
125
|
+
}
|
|
126
|
+
: null,
|
|
127
|
+
wrappedAuthUrl && wrappedAuthUrl !== preferredAuthUrl
|
|
128
|
+
? {
|
|
129
|
+
kind: 'wrapped',
|
|
130
|
+
label: 'TapTap 包装授权页',
|
|
131
|
+
url: wrappedAuthUrl,
|
|
132
|
+
}
|
|
133
|
+
: null,
|
|
134
|
+
authPayload.qrcode_url && authPayload.qrcode_url !== preferredAuthUrl
|
|
135
|
+
? {
|
|
136
|
+
kind: 'qrcode',
|
|
137
|
+
label: '授权页直链',
|
|
138
|
+
url: authPayload.qrcode_url,
|
|
139
|
+
}
|
|
140
|
+
: null,
|
|
141
|
+
].filter(Boolean);
|
|
101
142
|
|
|
102
143
|
return {
|
|
103
144
|
...authPayload,
|
|
104
145
|
direct_auth_url: directAuthUrl,
|
|
105
146
|
wrapped_auth_url: wrappedAuthUrl,
|
|
106
|
-
preferred_auth_url:
|
|
147
|
+
preferred_auth_url: preferredAuthUrl,
|
|
148
|
+
authorization_url: preferredAuthUrl,
|
|
149
|
+
mobile_auth_url: preferredAuthUrl,
|
|
150
|
+
auth_links: authLinks,
|
|
151
|
+
next_action:
|
|
152
|
+
'优先打开 preferred_auth_url 完成授权;完成后调用 taptap_dc_complete_authorization。',
|
|
107
153
|
};
|
|
108
154
|
}
|
|
109
155
|
|
|
156
|
+
function isVerboseLoggingEnabled(config = {}) {
|
|
157
|
+
return (
|
|
158
|
+
config?.verbose === true ||
|
|
159
|
+
String(process.env.TAPTAP_MCP_VERBOSE || '')
|
|
160
|
+
.trim()
|
|
161
|
+
.toLowerCase() === 'true'
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
|
|
110
165
|
function normalizeText(value) {
|
|
111
166
|
return String(value || '')
|
|
112
167
|
.trim()
|
|
@@ -245,37 +300,61 @@ function buildBriefText(appTitle, sections, meta = {}) {
|
|
|
245
300
|
|
|
246
301
|
function buildAuthGuideText(authPayload) {
|
|
247
302
|
const enriched = enrichAuthPayload(authPayload);
|
|
303
|
+
if (enriched?.authorized || enriched?.already_authorized) {
|
|
304
|
+
return [
|
|
305
|
+
'TapTap 授权已完成,无需再次扫码或打开授权链接。',
|
|
306
|
+
'如果你刚完成授权,接下来可直接调用 `taptap_dc_quick_brief` 或其他 `taptap_dc_*` 工具。',
|
|
307
|
+
].join('\n');
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
const preferredAuthUrl = enriched?.preferred_auth_url;
|
|
248
311
|
const directAuthUrl = enriched?.direct_auth_url;
|
|
249
312
|
const wrappedAuthUrl = enriched?.wrapped_auth_url;
|
|
250
313
|
const qrcodeUrl = enriched?.qrcode_url;
|
|
251
|
-
const lines = [
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
314
|
+
const lines = ['当前还没有完成 TapTap 授权,请先完成一次授权。'];
|
|
315
|
+
|
|
316
|
+
if (preferredAuthUrl) {
|
|
317
|
+
lines.push(
|
|
318
|
+
'',
|
|
319
|
+
'优先打开下面这条授权直链。这一行会同时保留裸链接,方便手机端直接点击,或在宿主吞掉超链接时复制打开:',
|
|
320
|
+
preferredAuthUrl,
|
|
321
|
+
`<${preferredAuthUrl}>`
|
|
322
|
+
);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
if (preferredAuthUrl || directAuthUrl || wrappedAuthUrl || qrcodeUrl) {
|
|
326
|
+
lines.push(
|
|
327
|
+
'',
|
|
328
|
+
'可点击版本:',
|
|
329
|
+
`- ${buildMarkdownLink('直接点击授权', preferredAuthUrl || directAuthUrl)}`,
|
|
330
|
+
`- ${buildMarkdownLink('打开 TapTap 包装授权页', wrappedAuthUrl)}`,
|
|
331
|
+
`- ${buildMarkdownLink('打开授权页直链', qrcodeUrl || directAuthUrl || preferredAuthUrl)}`
|
|
332
|
+
);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
lines.push(
|
|
262
336
|
'',
|
|
263
|
-
'
|
|
264
|
-
|
|
337
|
+
'如果你在手机上对话,优先直接点上面的第一条裸链接;如果超链接显示异常,优先使用 details.preferred_auth_url。',
|
|
338
|
+
'完成授权后,请继续调用 `taptap_dc_complete_authorization`,然后再次调用 `taptap_dc_quick_brief`。'
|
|
339
|
+
);
|
|
265
340
|
|
|
266
341
|
if (enriched?.device_code) {
|
|
267
342
|
lines.push('', `device_code:${enriched.device_code}`);
|
|
268
343
|
}
|
|
269
344
|
|
|
270
|
-
if (
|
|
345
|
+
if (preferredAuthUrl) {
|
|
346
|
+
lines.push('', `preferred_auth_url:${preferredAuthUrl}`);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
if (directAuthUrl && directAuthUrl !== preferredAuthUrl) {
|
|
271
350
|
lines.push('', `直接授权链接:${directAuthUrl}`);
|
|
272
351
|
}
|
|
273
352
|
|
|
274
|
-
if (wrappedAuthUrl && wrappedAuthUrl !==
|
|
353
|
+
if (wrappedAuthUrl && wrappedAuthUrl !== preferredAuthUrl) {
|
|
275
354
|
lines.push(`TapTap 包装授权链接:${wrappedAuthUrl}`);
|
|
276
355
|
}
|
|
277
356
|
|
|
278
|
-
if (qrcodeUrl && qrcodeUrl !==
|
|
357
|
+
if (qrcodeUrl && qrcodeUrl !== preferredAuthUrl) {
|
|
279
358
|
lines.push(`授权页直链:${qrcodeUrl}`);
|
|
280
359
|
}
|
|
281
360
|
|
|
@@ -385,10 +464,12 @@ function registerProxyTool(api, bridge, definition) {
|
|
|
385
464
|
);
|
|
386
465
|
}
|
|
387
466
|
|
|
388
|
-
function safeRegisterTool(api, logger, registerFn, toolName) {
|
|
467
|
+
function safeRegisterTool(api, logger, verbose, registerFn, toolName) {
|
|
389
468
|
try {
|
|
390
469
|
registerFn();
|
|
391
|
-
|
|
470
|
+
if (verbose) {
|
|
471
|
+
logger?.info?.(`[TapTap DC] Registered OpenClaw tool: ${toolName}`);
|
|
472
|
+
}
|
|
392
473
|
return true;
|
|
393
474
|
} catch (error) {
|
|
394
475
|
logger?.error?.(
|
|
@@ -740,7 +821,18 @@ try {
|
|
|
740
821
|
const plugin = {
|
|
741
822
|
id: 'openclaw-dc-plugin',
|
|
742
823
|
name: 'TapTap DC',
|
|
743
|
-
description:
|
|
824
|
+
description:
|
|
825
|
+
'面向 OpenClaw 的 TapTap DC 插件,内置原始数据工具与运营简报 skill;如需重启 Gateway,应先提示用户。',
|
|
826
|
+
installation: {
|
|
827
|
+
restartRequired: true,
|
|
828
|
+
restartCommand: 'openclaw gateway restart',
|
|
829
|
+
postInstallMessage: RESTART_NOTICE,
|
|
830
|
+
instructions: INSTALLATION_GUIDANCE,
|
|
831
|
+
},
|
|
832
|
+
installHints: {
|
|
833
|
+
beforeRestartMessage: RESTART_NOTICE,
|
|
834
|
+
instructions: INSTALLATION_GUIDANCE,
|
|
835
|
+
},
|
|
744
836
|
configSchema: {
|
|
745
837
|
type: 'object',
|
|
746
838
|
properties: {
|
|
@@ -770,7 +862,10 @@ const plugin = {
|
|
|
770
862
|
},
|
|
771
863
|
register(api) {
|
|
772
864
|
const logger = api.logger;
|
|
773
|
-
|
|
865
|
+
const verbose = isVerboseLoggingEnabled(api.pluginConfig || {});
|
|
866
|
+
if (verbose) {
|
|
867
|
+
logger?.info?.('[TapTap DC] Starting OpenClaw plugin registration');
|
|
868
|
+
}
|
|
774
869
|
|
|
775
870
|
let bridge;
|
|
776
871
|
try {
|
|
@@ -790,7 +885,13 @@ const plugin = {
|
|
|
790
885
|
let successCount = 0;
|
|
791
886
|
|
|
792
887
|
if (
|
|
793
|
-
safeRegisterTool(
|
|
888
|
+
safeRegisterTool(
|
|
889
|
+
api,
|
|
890
|
+
logger,
|
|
891
|
+
verbose,
|
|
892
|
+
() => registerQuickBriefTool(api, bridge),
|
|
893
|
+
'taptap_dc_quick_brief'
|
|
894
|
+
)
|
|
794
895
|
) {
|
|
795
896
|
successCount += 1;
|
|
796
897
|
}
|
|
@@ -800,6 +901,7 @@ const plugin = {
|
|
|
800
901
|
safeRegisterTool(
|
|
801
902
|
api,
|
|
802
903
|
logger,
|
|
904
|
+
verbose,
|
|
803
905
|
() => registerProxyTool(api, bridge, definition),
|
|
804
906
|
definition.name
|
|
805
907
|
)
|
|
@@ -808,11 +910,22 @@ const plugin = {
|
|
|
808
910
|
}
|
|
809
911
|
}
|
|
810
912
|
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
913
|
+
if (successCount !== toolDefinitions.length + 1) {
|
|
914
|
+
logger?.error?.(
|
|
915
|
+
`[TapTap DC] OpenClaw plugin registration incomplete: ${successCount}/${
|
|
916
|
+
toolDefinitions.length + 1
|
|
917
|
+
} tools registered`
|
|
918
|
+
);
|
|
919
|
+
return;
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
if (verbose) {
|
|
923
|
+
logger?.info?.(
|
|
924
|
+
`[TapTap DC] OpenClaw plugin registration completed: ${successCount}/${
|
|
925
|
+
toolDefinitions.length + 1
|
|
926
|
+
} tools registered`
|
|
927
|
+
);
|
|
928
|
+
}
|
|
816
929
|
},
|
|
817
930
|
};
|
|
818
931
|
|
package/lib/mcp-bridge.js
CHANGED
|
@@ -333,6 +333,11 @@ export class TapTapMcpBridge {
|
|
|
333
333
|
constructor(options = {}) {
|
|
334
334
|
this.logger = options.logger;
|
|
335
335
|
this.config = options.config || {};
|
|
336
|
+
this.verbose =
|
|
337
|
+
this.config.verbose === true ||
|
|
338
|
+
String(process.env.TAPTAP_MCP_VERBOSE || '')
|
|
339
|
+
.trim()
|
|
340
|
+
.toLowerCase() === 'true';
|
|
336
341
|
this.child = null;
|
|
337
342
|
this.readyPromise = null;
|
|
338
343
|
this.installPromise = null;
|
|
@@ -342,6 +347,12 @@ export class TapTapMcpBridge {
|
|
|
342
347
|
this.stdoutBuffer = Buffer.alloc(0);
|
|
343
348
|
}
|
|
344
349
|
|
|
350
|
+
logInfo(message) {
|
|
351
|
+
if (this.verbose) {
|
|
352
|
+
this.logger?.info?.(message);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
345
356
|
buildEnv() {
|
|
346
357
|
const env = {
|
|
347
358
|
...process.env,
|
|
@@ -428,7 +439,7 @@ export class TapTapMcpBridge {
|
|
|
428
439
|
mkdirSync(runtimeRoot, { recursive: true });
|
|
429
440
|
mkdirSync(npmCacheDir, { recursive: true });
|
|
430
441
|
|
|
431
|
-
this.
|
|
442
|
+
this.logInfo(
|
|
432
443
|
`[TapTap DC] Local TapTap MCP runtime not found, installing ${packageSpec} into ${runtimeRoot}`
|
|
433
444
|
);
|
|
434
445
|
|
|
@@ -459,7 +470,7 @@ export class TapTapMcpBridge {
|
|
|
459
470
|
output += text;
|
|
460
471
|
const trimmed = text.trim();
|
|
461
472
|
if (trimmed) {
|
|
462
|
-
this.
|
|
473
|
+
this.logInfo(`[TapTap DC][npm] ${trimmed}`);
|
|
463
474
|
}
|
|
464
475
|
};
|
|
465
476
|
|
|
@@ -508,7 +519,7 @@ export class TapTapMcpBridge {
|
|
|
508
519
|
const errors = [];
|
|
509
520
|
|
|
510
521
|
for (const attempt of launchAttempts) {
|
|
511
|
-
this.
|
|
522
|
+
this.logInfo(
|
|
512
523
|
`[TapTap DC] Starting embedded TapTap MCP runtime from ${runtime.source} using ${attempt.label}: ${runtime.serverPath}`
|
|
513
524
|
);
|
|
514
525
|
|
|
@@ -520,7 +531,7 @@ export class TapTapMcpBridge {
|
|
|
520
531
|
} catch (error) {
|
|
521
532
|
const message = error instanceof Error ? error.message : String(error);
|
|
522
533
|
errors.push(`${attempt.label}: ${message}`);
|
|
523
|
-
this.
|
|
534
|
+
this.logInfo(
|
|
524
535
|
`[TapTap DC] Runtime start attempt failed via ${attempt.label}, retrying if possible: ${message}`
|
|
525
536
|
);
|
|
526
537
|
await this.close();
|
|
@@ -657,11 +668,11 @@ export class TapTapMcpBridge {
|
|
|
657
668
|
this.child.stdout.on('data', (chunk) => {
|
|
658
669
|
try {
|
|
659
670
|
this.stdoutBuffer = Buffer.concat([this.stdoutBuffer, chunk]);
|
|
660
|
-
this.stdoutBuffer = trimNonProtocolNoise(this.stdoutBuffer, this.logger);
|
|
671
|
+
this.stdoutBuffer = trimNonProtocolNoise(this.stdoutBuffer, this.verbose ? this.logger : null);
|
|
661
672
|
this.stdoutBuffer = parseMessageBuffer(
|
|
662
673
|
this.stdoutBuffer,
|
|
663
674
|
(message) => this.handleMessage(message),
|
|
664
|
-
this.logger
|
|
675
|
+
this.verbose ? this.logger : null
|
|
665
676
|
);
|
|
666
677
|
} catch (error) {
|
|
667
678
|
this.logger?.error?.(
|
|
@@ -669,14 +680,14 @@ export class TapTapMcpBridge {
|
|
|
669
680
|
error instanceof Error ? error.message : String(error)
|
|
670
681
|
}`
|
|
671
682
|
);
|
|
672
|
-
this.stdoutBuffer = trimNonProtocolNoise(this.stdoutBuffer, this.logger);
|
|
683
|
+
this.stdoutBuffer = trimNonProtocolNoise(this.stdoutBuffer, this.verbose ? this.logger : null);
|
|
673
684
|
}
|
|
674
685
|
});
|
|
675
686
|
|
|
676
687
|
this.child.stderr.on('data', (chunk) => {
|
|
677
688
|
const text = chunk.toString('utf8').trim();
|
|
678
689
|
if (text) {
|
|
679
|
-
this.
|
|
690
|
+
this.logInfo(`[TapTap MCP] ${text}`);
|
|
680
691
|
}
|
|
681
692
|
});
|
|
682
693
|
|
package/openclaw.plugin.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "openclaw-dc-plugin",
|
|
3
3
|
"name": "TapTap DC",
|
|
4
|
-
"description": "面向 OpenClaw 的 TapTap DC 插件,内置原始数据工具与运营简报 skill
|
|
5
|
-
"version": "0.1.
|
|
4
|
+
"description": "面向 OpenClaw 的 TapTap DC 插件,内置原始数据工具与运营简报 skill;如需重启 Gateway,应先提示用户。",
|
|
5
|
+
"version": "0.1.11",
|
|
6
6
|
"enabledByDefault": true,
|
|
7
7
|
"skills": ["./skills"],
|
|
8
8
|
"configSchema": {
|
package/package.json
CHANGED
|
@@ -1,15 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lotaber_wang/openclaw-dc-plugin",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.11",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"description": "TapTap DC 的 OpenClaw 插件,内置原始数据工具与运营简报 skill
|
|
5
|
+
"description": "TapTap DC 的 OpenClaw 插件,内置原始数据工具与运营简报 skill;如需重启 Gateway,应先提示用户。",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"openclaw": {
|
|
8
8
|
"extensions": [
|
|
9
9
|
"./index.js"
|
|
10
10
|
],
|
|
11
11
|
"install": {
|
|
12
|
-
"npmSpec": "@lotaber_wang/openclaw-dc-plugin"
|
|
12
|
+
"npmSpec": "@lotaber_wang/openclaw-dc-plugin",
|
|
13
|
+
"postInstallMessage": "TapTap DC 插件已安装完成。OpenClaw 接下来如需重启 Gateway,应先提示用户;重启完成后即可使用 taptap_dc_* 工具。",
|
|
14
|
+
"restartRequired": true,
|
|
15
|
+
"restartCommand": "openclaw gateway restart",
|
|
16
|
+
"instructions": [
|
|
17
|
+
"如果安装流程判断需要重启 Gateway,先通知用户,再执行重启。",
|
|
18
|
+
"推荐提示文案:TapTap DC 插件已安装完成。OpenClaw 接下来如需重启 Gateway,应先提示用户;重启完成后即可使用 taptap_dc_* 工具。",
|
|
19
|
+
"执行顺序:先提示用户 -> 再执行 gateway restart -> 重启完成后再开始使用 taptap_dc_* 工具。"
|
|
20
|
+
]
|
|
13
21
|
}
|
|
14
22
|
},
|
|
15
23
|
"exports": {
|
|
@@ -19,8 +19,8 @@ description: 生成 TapTap 当前游戏 DC 运营简报与结论解读(商店/
|
|
|
19
19
|
- 如果用户给了游戏名,直接把 `app_name` 传进去
|
|
20
20
|
- 如果用户给了 `app_id`,直接把 `app_id` 传进去
|
|
21
21
|
2. 如果未授权
|
|
22
|
-
- `taptap_dc_quick_brief`
|
|
23
|
-
-
|
|
22
|
+
- `taptap_dc_quick_brief` 会直接返回授权信息,其中最前面的裸链接和 `details.preferred_auth_url` 都应视为首选授权入口
|
|
23
|
+
- 如果用户当前在手机上对话,优先引导用户直接点击第一条裸链接,不要先强调扫码
|
|
24
24
|
- 如果用户当前在桌面端对话,再引导用户打开授权页直链并扫码或转发到手机
|
|
25
25
|
- 用户确认后调用 `taptap_dc_complete_authorization`
|
|
26
26
|
- 然后再次调用 `taptap_dc_quick_brief`
|
|
@@ -45,7 +45,7 @@ description: 生成 TapTap 当前游戏 DC 运营简报与结论解读(商店/
|
|
|
45
45
|
## 关键规则
|
|
46
46
|
|
|
47
47
|
- 这些 plugin tools 返回的是 **raw JSON**,你要自己完成解读,不要把 JSON 原样长篇贴回给用户
|
|
48
|
-
-
|
|
48
|
+
- 当授权工具已经返回授权链接时,优先直接复用第一条裸直链;如果文本里链接缺失,就从 `details.preferred_auth_url` 取值,不要直接退化成“去扫二维码”
|
|
49
49
|
- `page_view_count` 应写成“详情页访问量(PV)”,不要偷换成别的口径
|
|
50
50
|
- `taptap_dc_like_review` / `taptap_dc_reply_review` 只能在用户明确确认后调用
|
|
51
51
|
- 如果回复结果里出现 `need_confirmation=true`,必须先把草稿给用户确认,再决定是否带 `confirm_high_risk=true` 重试
|