dlinkclaw-openclaw 2026.8.24-alpha.1
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.en.md +46 -0
- package/README.md +25 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +1 -0
- package/dist/package.json +95 -0
- package/dist/src/account.d.ts +53 -0
- package/dist/src/account.js +394 -0
- package/dist/src/channel.d.ts +17 -0
- package/dist/src/channel.js +153 -0
- package/dist/src/client/client-manager.d.ts +4 -0
- package/dist/src/client/client-manager.js +10 -0
- package/dist/src/client/const.d.ts +37 -0
- package/dist/src/client/const.js +155 -0
- package/dist/src/client/crypto.d.ts +47 -0
- package/dist/src/client/crypto.js +260 -0
- package/dist/src/client/dl-client.d.ts +99 -0
- package/dist/src/client/dl-client.js +535 -0
- package/dist/src/client/dl-http.d.ts +27 -0
- package/dist/src/client/dl-http.js +223 -0
- package/dist/src/client/media-handler.d.ts +21 -0
- package/dist/src/client/media-handler.js +196 -0
- package/dist/src/client/message.d.ts +96 -0
- package/dist/src/client/message.js +1204 -0
- package/dist/src/client/timeout.d.ts +20 -0
- package/dist/src/client/timeout.js +36 -0
- package/dist/src/client/types.d.ts +224 -0
- package/dist/src/client/types.js +1 -0
- package/dist/src/monitor.d.ts +17 -0
- package/dist/src/monitor.js +320 -0
- package/dist/src/outbound.d.ts +4 -0
- package/dist/src/outbound.js +83 -0
- package/dist/src/policy.d.ts +42 -0
- package/dist/src/policy.js +205 -0
- package/dist/src/runtime.d.ts +9 -0
- package/dist/src/runtime.js +65 -0
- package/dist/src/services/index.d.ts +41 -0
- package/dist/src/services/index.js +225 -0
- package/dist/src/services/services.d.ts +152 -0
- package/dist/src/services/services.js +1066 -0
- package/dist/src/services/types.d.ts +391 -0
- package/dist/src/services/types.js +5 -0
- package/dist/src/services/ws-client.d.ts +174 -0
- package/dist/src/services/ws-client.js +866 -0
- package/dist/src/utils.d.ts +20 -0
- package/dist/src/utils.js +128 -0
- package/ext_capabilities/workrelay-speak/CLONE_GUIDE.md +129 -0
- package/ext_capabilities/workrelay-speak/HARDWARE.md +84 -0
- package/ext_capabilities/workrelay-speak/QWEN_GUIDE.md +151 -0
- package/ext_capabilities/workrelay-speak/README.md +79 -0
- package/ext_capabilities/workrelay-speak/__pycache__/patch-kokoro-en.cpython-312.pyc +0 -0
- package/ext_capabilities/workrelay-speak/install.sh +280 -0
- package/ext_capabilities/workrelay-speak/install.sh.bak-20260814 +376 -0
- package/ext_capabilities/workrelay-speak/manifest.json +49 -0
- package/ext_capabilities/workrelay-speak/patch-kokoro-en.py +85 -0
- package/ext_capabilities/workrelay-speak/status.sh +90 -0
- package/ext_capabilities/workrelay-speak/workrelay-tts.sh +118 -0
- package/ext_capabilities/workrelay-speak-luxtts/README.md +44 -0
- package/ext_capabilities/workrelay-speak-luxtts/install.sh +282 -0
- package/ext_capabilities/workrelay-speak-luxtts/manifest.json +49 -0
- package/ext_capabilities/workrelay-speak-luxtts/samples/45ea2e2c-0863-4966-a739-8bff8817f4c0.wav +0 -0
- package/ext_capabilities/workrelay-speak-luxtts/samples/800e5af4-cba5-441e-8003-6d36f35409e6.wav +0 -0
- package/ext_capabilities/workrelay-speak-luxtts/samples/85fafe01-d4d6-4a48-890e-9ae113f21905.wav +0 -0
- package/ext_capabilities/workrelay-speak-luxtts/samples/reference_text.txt +4 -0
- package/ext_capabilities/workrelay-speak-luxtts/samples/stone-sample-6.4s.wav +0 -0
- package/ext_capabilities/workrelay-speak-luxtts/status.sh +94 -0
- package/ext_capabilities/workrelay-speak-luxtts/workrelay-tts.sh +98 -0
- package/ext_capabilities/workrelay-transcribe/README.md +76 -0
- package/ext_capabilities/workrelay-transcribe/__pycache__/transcribe.cpython-312.pyc +0 -0
- package/ext_capabilities/workrelay-transcribe/__pycache__/transcribe_server.cpython-312.pyc +0 -0
- package/ext_capabilities/workrelay-transcribe/install.sh +207 -0
- package/ext_capabilities/workrelay-transcribe/manifest.json +42 -0
- package/ext_capabilities/workrelay-transcribe/status.sh +62 -0
- package/ext_capabilities/workrelay-transcribe/transcribe.py +56 -0
- package/ext_capabilities/workrelay-transcribe/transcribe_server.py +116 -0
- package/ext_capabilities/workrelay-transcribe/voicebox-transcribe.sh +88 -0
- package/openclaw.plugin.json +142 -0
- package/package.json +95 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""WorkRelay 语音转录引擎 - 基于 faster-whisper."""
|
|
3
|
+
|
|
4
|
+
import sys
|
|
5
|
+
import os
|
|
6
|
+
from faster_whisper import WhisperModel
|
|
7
|
+
|
|
8
|
+
MODEL_NAME = os.environ.get("WR_WHISPER_MODEL", "small")
|
|
9
|
+
MODEL = None
|
|
10
|
+
MODEL_CACHE = os.environ.get(
|
|
11
|
+
"WR_WHISPER_CACHE",
|
|
12
|
+
os.path.join(os.path.expanduser("~"), ".cache", "faster-whisper"),
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def load_model():
|
|
17
|
+
global MODEL
|
|
18
|
+
MODEL = WhisperModel(
|
|
19
|
+
MODEL_NAME,
|
|
20
|
+
device="cpu",
|
|
21
|
+
compute_type="int8",
|
|
22
|
+
download_root=MODEL_CACHE,
|
|
23
|
+
)
|
|
24
|
+
print(f"[WorkRelay] Whisper model '{MODEL_NAME}' loaded", file=sys.stderr)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def transcribe(audio_path: str, language: str = "zh") -> str:
|
|
28
|
+
if MODEL is None:
|
|
29
|
+
load_model()
|
|
30
|
+
segments, info = MODEL.transcribe(
|
|
31
|
+
audio_path,
|
|
32
|
+
language=language,
|
|
33
|
+
beam_size=5,
|
|
34
|
+
vad_filter=True,
|
|
35
|
+
)
|
|
36
|
+
return " ".join(s.text.strip() for s in segments)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
if __name__ == "__main__":
|
|
40
|
+
if len(sys.argv) < 2:
|
|
41
|
+
print("Usage: transcribe.py <audio_file> [language]", file=sys.stderr)
|
|
42
|
+
sys.exit(1)
|
|
43
|
+
|
|
44
|
+
audio_file = sys.argv[1]
|
|
45
|
+
lang = sys.argv[2] if len(sys.argv) > 2 else "zh"
|
|
46
|
+
|
|
47
|
+
if not os.path.isfile(audio_file):
|
|
48
|
+
print(f"ERROR: file not found: {audio_file}", file=sys.stderr)
|
|
49
|
+
sys.exit(1)
|
|
50
|
+
|
|
51
|
+
try:
|
|
52
|
+
result = transcribe(audio_file, lang)
|
|
53
|
+
print(result.strip())
|
|
54
|
+
except Exception as e:
|
|
55
|
+
print(f"ERROR: {e}", file=sys.stderr)
|
|
56
|
+
sys.exit(1)
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""WorkRelay 语音转录常驻服务(2026-08-12)
|
|
3
|
+
faster-whisper 模型加载一次后常驻内存,避免每次转写重复加载模型(省 3-5 秒)。
|
|
4
|
+
HTTP 接口:
|
|
5
|
+
POST /transcribe multipart/form-data: file=<audio>
|
|
6
|
+
GET /health 健康检查
|
|
7
|
+
启动:python3 transcribe_server.py [port] (默认 17890)
|
|
8
|
+
"""
|
|
9
|
+
import sys
|
|
10
|
+
import os
|
|
11
|
+
import json
|
|
12
|
+
import tempfile
|
|
13
|
+
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
|
|
14
|
+
from urllib.parse import urlparse
|
|
15
|
+
|
|
16
|
+
from faster_whisper import WhisperModel
|
|
17
|
+
|
|
18
|
+
PORT = int(os.environ.get("WR_WHISPER_PORT", "17890"))
|
|
19
|
+
MODEL_NAME = os.environ.get("WR_WHISPER_MODEL", "small")
|
|
20
|
+
MODEL_CACHE = os.environ.get(
|
|
21
|
+
"WR_WHISPER_CACHE",
|
|
22
|
+
os.path.join(os.path.expanduser("~"), ".cache", "faster-whisper"),
|
|
23
|
+
)
|
|
24
|
+
LANGUAGE = os.environ.get("WR_WHISPER_LANG", "zh")
|
|
25
|
+
|
|
26
|
+
_model = None
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def get_model():
|
|
30
|
+
global _model
|
|
31
|
+
if _model is None:
|
|
32
|
+
_model = WhisperModel(
|
|
33
|
+
MODEL_NAME,
|
|
34
|
+
device="cpu",
|
|
35
|
+
compute_type="int8",
|
|
36
|
+
download_root=MODEL_CACHE,
|
|
37
|
+
)
|
|
38
|
+
return _model
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class Handler(BaseHTTPRequestHandler):
|
|
42
|
+
def log_message(self, fmt, *args): # 安静模式
|
|
43
|
+
pass
|
|
44
|
+
|
|
45
|
+
def _send_json(self, code: int, obj: dict):
|
|
46
|
+
body = json.dumps(obj, ensure_ascii=False).encode("utf-8")
|
|
47
|
+
self.send_response(code)
|
|
48
|
+
self.send_header("Content-Type", "application/json; charset=utf-8")
|
|
49
|
+
self.send_header("Content-Length", str(len(body)))
|
|
50
|
+
self.end_headers()
|
|
51
|
+
self.wfile.write(body)
|
|
52
|
+
|
|
53
|
+
def do_GET(self):
|
|
54
|
+
path = urlparse(self.path).path
|
|
55
|
+
if path == "/health":
|
|
56
|
+
self._send_json(200, {"status": "ok", "model": MODEL_NAME})
|
|
57
|
+
else:
|
|
58
|
+
self._send_json(404, {"error": "not found"})
|
|
59
|
+
|
|
60
|
+
def do_POST(self):
|
|
61
|
+
path = urlparse(self.path).path
|
|
62
|
+
if path != "/transcribe":
|
|
63
|
+
self._send_json(404, {"error": "not found"})
|
|
64
|
+
return
|
|
65
|
+
try:
|
|
66
|
+
# 解析 multipart(只取第一个 file 字段)
|
|
67
|
+
content_type = self.headers.get("Content-Type", "")
|
|
68
|
+
boundary = None
|
|
69
|
+
if "boundary=" in content_type:
|
|
70
|
+
boundary = content_type.split("boundary=")[1].strip().strip('"')
|
|
71
|
+
if not boundary:
|
|
72
|
+
self._send_json(400, {"error": "missing boundary"})
|
|
73
|
+
return
|
|
74
|
+
|
|
75
|
+
body = self.rfile.read(int(self.headers.get("Content-Length", "0")))
|
|
76
|
+
# 极简 multipart 解析:按 boundary 切块,找 filename + 内容
|
|
77
|
+
parts = body.split(b"--" + boundary.encode())
|
|
78
|
+
audio_data = None
|
|
79
|
+
for part in parts:
|
|
80
|
+
if b'filename="' in part and b"\r\n\r\n" in part:
|
|
81
|
+
_, data = part.split(b"\r\n\r\n", 1)
|
|
82
|
+
audio_data = data.rstrip(b"\r\n--")
|
|
83
|
+
break
|
|
84
|
+
if audio_data is None:
|
|
85
|
+
self._send_json(400, {"error": "no file part"})
|
|
86
|
+
return
|
|
87
|
+
|
|
88
|
+
with tempfile.NamedTemporaryFile(suffix=".webm", delete=False) as tmp:
|
|
89
|
+
tmp.write(audio_data)
|
|
90
|
+
tmp_path = tmp.name
|
|
91
|
+
try:
|
|
92
|
+
model = get_model()
|
|
93
|
+
segments, _info = model.transcribe(
|
|
94
|
+
tmp_path, language=LANGUAGE, beam_size=5, vad_filter=True
|
|
95
|
+
)
|
|
96
|
+
text = " ".join(s.text.strip() for s in segments)
|
|
97
|
+
self._send_json(200, {"text": text})
|
|
98
|
+
finally:
|
|
99
|
+
try:
|
|
100
|
+
os.remove(tmp_path)
|
|
101
|
+
except OSError:
|
|
102
|
+
pass
|
|
103
|
+
except Exception as e: # noqa: BLE001
|
|
104
|
+
self._send_json(500, {"error": str(e)})
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def main():
|
|
108
|
+
server = ThreadingHTTPServer(("127.0.0.1", PORT), Handler)
|
|
109
|
+
# 先加载模型(启动即常驻)
|
|
110
|
+
get_model()
|
|
111
|
+
print(f"[WorkRelay] whisper server ready: http://127.0.0.1:{PORT} model={MODEL_NAME}", flush=True)
|
|
112
|
+
server.serve_forever()
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
if __name__ == "__main__":
|
|
116
|
+
main()
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# WorkRelay 语音转录桥接脚本
|
|
3
|
+
# 优先本地 faster-whisper 常驻服务(模型常驻内存,免重复加载),服务不可用时回退直接转写
|
|
4
|
+
# 环境变量:
|
|
5
|
+
# WR_WHISPER_HOST - 常驻服务地址(默认 127.0.0.1)
|
|
6
|
+
# WR_WHISPER_PORT - 常驻服务端口(默认 17890)
|
|
7
|
+
# WR_WHISPER_MODEL - 本地模型名(默认 small)
|
|
8
|
+
# WR_FALLBACK_URL - 远程转录服务 URL(可选,不设则仅本地)
|
|
9
|
+
|
|
10
|
+
set -e
|
|
11
|
+
|
|
12
|
+
AUDIO_FILE="$1"
|
|
13
|
+
SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"
|
|
14
|
+
|
|
15
|
+
if [ ! -f "$AUDIO_FILE" ]; then
|
|
16
|
+
echo "ERROR: audio file not found: $AUDIO_FILE" >&2
|
|
17
|
+
exit 1
|
|
18
|
+
fi
|
|
19
|
+
|
|
20
|
+
WH_HOST="${WR_WHISPER_HOST:-127.0.0.1}"
|
|
21
|
+
WH_PORT="${WR_WHISPER_PORT:-17890}"
|
|
22
|
+
|
|
23
|
+
# ── 第1步:常驻服务(模型常驻内存,转写快)──
|
|
24
|
+
result=$(curl -s --connect-timeout 2 --max-time 60 \
|
|
25
|
+
-X POST "http://${WH_HOST}:${WH_PORT}/transcribe" \
|
|
26
|
+
-F "file=@${AUDIO_FILE}" 2>/dev/null)
|
|
27
|
+
if [ -n "$result" ]; then
|
|
28
|
+
text=$(echo "$result" | python3 -c "
|
|
29
|
+
import sys, json
|
|
30
|
+
try:
|
|
31
|
+
data = json.load(sys.stdin)
|
|
32
|
+
if data.get('text'):
|
|
33
|
+
print(data['text'].strip())
|
|
34
|
+
else:
|
|
35
|
+
print('ERROR: ' + str(data.get('error', 'unknown')))
|
|
36
|
+
except Exception:
|
|
37
|
+
print('ERROR: bad response')
|
|
38
|
+
" 2>/dev/null)
|
|
39
|
+
if [ -n "$text" ] && [[ "$text" != ERROR:* ]]; then
|
|
40
|
+
echo "$text"
|
|
41
|
+
exit 0
|
|
42
|
+
fi
|
|
43
|
+
fi
|
|
44
|
+
|
|
45
|
+
# ── 第2步:直接本地 faster-whisper(常驻服务未启动时的回退)──
|
|
46
|
+
result=$(python3 "$SCRIPT_DIR/transcribe.py" "$AUDIO_FILE" 2>/tmp/wr-transcribe-err.log)
|
|
47
|
+
exit_code=$?
|
|
48
|
+
|
|
49
|
+
if [ $exit_code -eq 0 ] && [ -n "$result" ]; then
|
|
50
|
+
# 排除以 ERROR: 开头的输出(有些 Python 错误仍返回 exit 0)
|
|
51
|
+
if [[ "$result" != ERROR:* ]]; then
|
|
52
|
+
echo "$result"
|
|
53
|
+
exit 0
|
|
54
|
+
fi
|
|
55
|
+
fi
|
|
56
|
+
|
|
57
|
+
# 本地失败日志
|
|
58
|
+
cat /tmp/wr-transcribe-err.log >&2
|
|
59
|
+
rm -f /tmp/wr-transcribe-err.log
|
|
60
|
+
|
|
61
|
+
# ── 第3步:远程 fallback(如果配置了) ──
|
|
62
|
+
if [ -n "${WR_FALLBACK_URL:-}" ]; then
|
|
63
|
+
result=$(curl -s --connect-timeout 5 --max-time 60 \
|
|
64
|
+
-X POST "$WR_FALLBACK_URL" \
|
|
65
|
+
-F "file=@${AUDIO_FILE}" \
|
|
66
|
+
-F "language=zh" 2>&1)
|
|
67
|
+
|
|
68
|
+
# 尝试解析 JSON 响应
|
|
69
|
+
text=$(echo "$result" | python3 -c "
|
|
70
|
+
import sys, json
|
|
71
|
+
try:
|
|
72
|
+
data = json.load(sys.stdin)
|
|
73
|
+
for key in ('text','transcript','result'):
|
|
74
|
+
if data.get(key):
|
|
75
|
+
print(data[key].strip())
|
|
76
|
+
break
|
|
77
|
+
except:
|
|
78
|
+
pass
|
|
79
|
+
" 2>/dev/null)
|
|
80
|
+
|
|
81
|
+
if [ -n "$text" ]; then
|
|
82
|
+
echo "$text"
|
|
83
|
+
exit 0
|
|
84
|
+
fi
|
|
85
|
+
fi
|
|
86
|
+
|
|
87
|
+
echo "ERROR: transcription failed (local whisper + remote fallback both failed)" >&2
|
|
88
|
+
exit 1
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "dlink",
|
|
3
|
+
"channels": [
|
|
4
|
+
"dlink"
|
|
5
|
+
],
|
|
6
|
+
"skills": [
|
|
7
|
+
"./skills"
|
|
8
|
+
],
|
|
9
|
+
"configSchema": {
|
|
10
|
+
"type": "object",
|
|
11
|
+
"additionalProperties": false,
|
|
12
|
+
"properties": {
|
|
13
|
+
"apiKey": {
|
|
14
|
+
"type": "string",
|
|
15
|
+
"description": "朵联 apiKey"
|
|
16
|
+
},
|
|
17
|
+
"baseUrl": {
|
|
18
|
+
"type": "string",
|
|
19
|
+
"description": "朵联回调URL",
|
|
20
|
+
"default": "https://wr.nduoke.cn"
|
|
21
|
+
},
|
|
22
|
+
"secret": {
|
|
23
|
+
"type": "string",
|
|
24
|
+
"description": "朵联签名密钥"
|
|
25
|
+
},
|
|
26
|
+
"enabled": {
|
|
27
|
+
"type": "boolean",
|
|
28
|
+
"default": true
|
|
29
|
+
},
|
|
30
|
+
"accountId": {
|
|
31
|
+
"type": "string",
|
|
32
|
+
"description": "账号标识",
|
|
33
|
+
"default": "default"
|
|
34
|
+
},
|
|
35
|
+
"mediaMaxMb": {
|
|
36
|
+
"type": "number",
|
|
37
|
+
"description": "媒体大小上限(MB),OpenClaw 核心出站媒体校验读取,默认 100",
|
|
38
|
+
"default": 100
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
"setup": {
|
|
43
|
+
"requiresRuntime": true,
|
|
44
|
+
"prompts": [
|
|
45
|
+
{
|
|
46
|
+
"name": "apiKey",
|
|
47
|
+
"type": "input",
|
|
48
|
+
"message": "请输入朵联 API Key:",
|
|
49
|
+
"validate": "required"
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"name": "secret",
|
|
53
|
+
"type": "input",
|
|
54
|
+
"message": "请输入朵联签名密钥:",
|
|
55
|
+
"validate": "required"
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"name": "baseUrl",
|
|
59
|
+
"type": "input",
|
|
60
|
+
"message": "请输入朵联回调地址:",
|
|
61
|
+
"default": "https://wr.nduoke.cn",
|
|
62
|
+
"validate": "required"
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"name": "accountId",
|
|
66
|
+
"type": "input",
|
|
67
|
+
"message": "请输入账号标识(默认: default):",
|
|
68
|
+
"default": "default"
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"name": "enabled",
|
|
72
|
+
"type": "confirm",
|
|
73
|
+
"message": "是否立即启用朵联通道?",
|
|
74
|
+
"default": true
|
|
75
|
+
}
|
|
76
|
+
]
|
|
77
|
+
},
|
|
78
|
+
"channelConfigs": {
|
|
79
|
+
"dlink": {
|
|
80
|
+
"schema": {
|
|
81
|
+
"type": "object",
|
|
82
|
+
"additionalProperties": false,
|
|
83
|
+
"properties": {
|
|
84
|
+
"apiKey": {
|
|
85
|
+
"type": "string",
|
|
86
|
+
"description": "朵联 apiKey"
|
|
87
|
+
},
|
|
88
|
+
"baseUrl": {
|
|
89
|
+
"type": "string",
|
|
90
|
+
"description": "朵联回调URL",
|
|
91
|
+
"default": "https://wr.nduoke.cn"
|
|
92
|
+
},
|
|
93
|
+
"secret": {
|
|
94
|
+
"type": "string",
|
|
95
|
+
"description": "朵联签名密钥"
|
|
96
|
+
},
|
|
97
|
+
"enabled": {
|
|
98
|
+
"type": "boolean",
|
|
99
|
+
"default": true
|
|
100
|
+
},
|
|
101
|
+
"accountId": {
|
|
102
|
+
"type": "string",
|
|
103
|
+
"description": "账号标识",
|
|
104
|
+
"default": "default"
|
|
105
|
+
},
|
|
106
|
+
"mediaMaxMb": {
|
|
107
|
+
"type": "number",
|
|
108
|
+
"description": "媒体大小上限(MB),OpenClaw 核心出站媒体校验读取,默认 100",
|
|
109
|
+
"default": 100
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
"label": "朵联 DLinkClaw",
|
|
114
|
+
"description": "朵联 DLinkClaw OpenClaw 接入通道",
|
|
115
|
+
"commands": {
|
|
116
|
+
"nativeCommandsAutoEnabled": false
|
|
117
|
+
},
|
|
118
|
+
"uiHints": {
|
|
119
|
+
"apiKey": {
|
|
120
|
+
"label": "API Key",
|
|
121
|
+
"help": "朵联平台的 API 密钥,在朵联控制台获取",
|
|
122
|
+
"placeholder": "请输入 API Key",
|
|
123
|
+
"sensitive": true
|
|
124
|
+
},
|
|
125
|
+
"secret": {
|
|
126
|
+
"label": "签名密钥",
|
|
127
|
+
"help": "朵联平台的签名密钥,用于消息加解密与签名认证",
|
|
128
|
+
"placeholder": "请输入签名密钥",
|
|
129
|
+
"sensitive": true
|
|
130
|
+
},
|
|
131
|
+
"baseUrl": {
|
|
132
|
+
"label": "回调地址",
|
|
133
|
+
"help": "朵联消息回调的服务器地址",
|
|
134
|
+
"placeholder": "https://wr.nduoke.cn"
|
|
135
|
+
},
|
|
136
|
+
"enabled": {
|
|
137
|
+
"label": "启用通道"
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "dlinkclaw-openclaw",
|
|
3
|
+
"version": "2026.8.24-alpha.1",
|
|
4
|
+
"description": "DLinkClaw OpenClaw channel plugin — 朵联 OpenClaw 接入通道",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"DLinkClaw",
|
|
7
|
+
"openclaw",
|
|
8
|
+
"朵联",
|
|
9
|
+
"钉钉",
|
|
10
|
+
"QQ",
|
|
11
|
+
"企业微信",
|
|
12
|
+
"飞书"
|
|
13
|
+
],
|
|
14
|
+
"publishConfig": {
|
|
15
|
+
"access": "public"
|
|
16
|
+
},
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsc && terser dist/index.js --output dist/index.js --compress --mangle --module",
|
|
19
|
+
"dev": "tsc --watch",
|
|
20
|
+
"prepublishOnly": "npm run build"
|
|
21
|
+
},
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"author": "rock.chen<szygnet@qq.com>",
|
|
24
|
+
"type": "module",
|
|
25
|
+
"types": "./dist/index.d.ts",
|
|
26
|
+
"main": "./index.ts",
|
|
27
|
+
"exports": {
|
|
28
|
+
".": {
|
|
29
|
+
"types": "./dist/index.d.ts",
|
|
30
|
+
"import": "./dist/index.js"
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"files": [
|
|
34
|
+
"dist",
|
|
35
|
+
"skills",
|
|
36
|
+
"ext_capabilities",
|
|
37
|
+
"openclaw.plugin.json",
|
|
38
|
+
"README.md"
|
|
39
|
+
],
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"axios": "^1.15.2",
|
|
42
|
+
"file-type": "^21.3.1",
|
|
43
|
+
"form-data": "^4.0.5",
|
|
44
|
+
"mime-types": "^3.0.2",
|
|
45
|
+
"mqtt": "^5.10.0",
|
|
46
|
+
"qrcode-terminal": "^0.12.0",
|
|
47
|
+
"uuid": "^14.0.2",
|
|
48
|
+
"ws": "^8.20.0"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@types/mime-types": "^3.0.1",
|
|
52
|
+
"@types/ws": "^8.18.1",
|
|
53
|
+
"terser": "^5.46.1",
|
|
54
|
+
"typescript": "^5.3.3"
|
|
55
|
+
},
|
|
56
|
+
"peerDependencies": {
|
|
57
|
+
"openclaw": ">=2026.7.1"
|
|
58
|
+
},
|
|
59
|
+
"openclaw": {
|
|
60
|
+
"extensions": [
|
|
61
|
+
"./index.ts"
|
|
62
|
+
],
|
|
63
|
+
"installDependencies": true,
|
|
64
|
+
"channel": {
|
|
65
|
+
"id": "dlink",
|
|
66
|
+
"label": "朵联 DLinkClaw",
|
|
67
|
+
"selectionLabel": "朵联(DLinkClaw)",
|
|
68
|
+
"docsPath": "/channels/DLinkClaw-openclaw",
|
|
69
|
+
"docsLabel": "DLinkClaw-openclaw",
|
|
70
|
+
"blurb": "朵联 DLinkClaw OpenClaw 接入通道, 本地部署连接朵联客户端, 支持企业微信、QQ、钉钉、飞书, 无需公网IP.",
|
|
71
|
+
"aliases": [
|
|
72
|
+
"dlink",
|
|
73
|
+
"DLinkClaw",
|
|
74
|
+
"朵联"
|
|
75
|
+
],
|
|
76
|
+
"order": 90,
|
|
77
|
+
"quickstartAllowFrom": true,
|
|
78
|
+
"isDebug": false,
|
|
79
|
+
"preferSessionLookupForAnnounceTarget": true
|
|
80
|
+
},
|
|
81
|
+
"install": {
|
|
82
|
+
"npmSpec": "DLinkClaw-openclaw",
|
|
83
|
+
"localPath": "extensions/DLinkClaw-openclaw",
|
|
84
|
+
"defaultChoice": "npm"
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
"repository": {
|
|
88
|
+
"type": "git",
|
|
89
|
+
"url": "https://github.com/rockychen2016/DLinkClaw-openclaw.git"
|
|
90
|
+
},
|
|
91
|
+
"homepage": "https://github.com/rockychen2016/DLinkClaw-openclaw#readme",
|
|
92
|
+
"bugs": {
|
|
93
|
+
"url": "https://github.com/rockychen2016/DLinkClaw-openclaw/issues"
|
|
94
|
+
}
|
|
95
|
+
}
|