visionclaw 0.1.199-beta.2 → 0.1.199-beta.3
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/agent/command-handlers.d.ts.map +1 -1
- package/dist/agent/command-handlers.js +49 -0
- package/dist/agent/command-handlers.js.map +1 -1
- package/dist/channels/interface.d.ts +9 -0
- package/dist/channels/interface.d.ts.map +1 -1
- package/dist/channels/manager.d.ts.map +1 -1
- package/dist/channels/manager.js +14 -0
- package/dist/channels/manager.js.map +1 -1
- package/dist/channels/qq-onboard.d.ts +73 -0
- package/dist/channels/qq-onboard.d.ts.map +1 -0
- package/dist/channels/qq-onboard.js +190 -0
- package/dist/channels/qq-onboard.js.map +1 -0
- package/dist/channels/qq.d.ts +78 -0
- package/dist/channels/qq.d.ts.map +1 -0
- package/dist/channels/qq.js +604 -0
- package/dist/channels/qq.js.map +1 -0
- package/dist/channels/telegram.d.ts.map +1 -1
- package/dist/channels/telegram.js +6 -1
- package/dist/channels/telegram.js.map +1 -1
- package/dist/config/types.d.ts +14 -0
- package/dist/config/types.d.ts.map +1 -1
- package/dist/config/types.js +16 -0
- package/dist/config/types.js.map +1 -1
- package/dist/i18n/messages.d.ts +20 -0
- package/dist/i18n/messages.d.ts.map +1 -1
- package/dist/i18n/messages.js +21 -0
- package/dist/i18n/messages.js.map +1 -1
- package/dist-agent/bundle.cjs +1155 -314
- package/package.json +1 -1
- package/dist/agent/applied-credential-signature.d.ts +0 -53
- package/dist/agent/applied-credential-signature.d.ts.map +0 -1
- package/dist/agent/applied-credential-signature.js +0 -137
- package/dist/agent/applied-credential-signature.js.map +0 -1
- package/dist/agent/engines/client-factory.d.ts +0 -63
- package/dist/agent/engines/client-factory.d.ts.map +0 -1
- package/dist/agent/engines/client-factory.js +0 -382
- package/dist/agent/engines/client-factory.js.map +0 -1
- package/dist/agent/engines/engine.d.ts +0 -8
- package/dist/agent/engines/engine.d.ts.map +0 -1
- package/dist/agent/engines/engine.js +0 -15
- package/dist/agent/engines/engine.js.map +0 -1
- package/dist/agent/engines/openai/file-session.d.ts +0 -19
- package/dist/agent/engines/openai/file-session.d.ts.map +0 -1
- package/dist/agent/engines/openai/file-session.js +0 -78
- package/dist/agent/engines/openai/file-session.js.map +0 -1
- package/dist/agent/engines/openai/file-tools.d.ts +0 -35
- package/dist/agent/engines/openai/file-tools.d.ts.map +0 -1
- package/dist/agent/engines/openai/file-tools.js +0 -194
- package/dist/agent/engines/openai/file-tools.js.map +0 -1
- package/dist/agent/engines/openai/session.d.ts +0 -55
- package/dist/agent/engines/openai/session.d.ts.map +0 -1
- package/dist/agent/engines/openai/session.js +0 -447
- package/dist/agent/engines/openai/session.js.map +0 -1
- package/dist/agent/engines/openai/tools.d.ts +0 -15
- package/dist/agent/engines/openai/tools.d.ts.map +0 -1
- package/dist/agent/engines/openai/tools.js +0 -221
- package/dist/agent/engines/openai/tools.js.map +0 -1
- package/dist/agent/memory-preload.d.ts +0 -55
- package/dist/agent/memory-preload.d.ts.map +0 -1
- package/dist/agent/memory-preload.js +0 -166
- package/dist/agent/memory-preload.js.map +0 -1
- package/dist/agent/providers/claude/cli-resolver.d.ts +0 -16
- package/dist/agent/providers/claude/cli-resolver.d.ts.map +0 -1
- package/dist/agent/providers/claude/cli-resolver.js +0 -83
- package/dist/agent/providers/claude/cli-resolver.js.map +0 -1
- package/dist/agent/providers/claude/session-browser-policy.d.ts +0 -9
- package/dist/agent/providers/claude/session-browser-policy.d.ts.map +0 -1
- package/dist/agent/providers/claude/session-browser-policy.js +0 -49
- package/dist/agent/providers/claude/session-browser-policy.js.map +0 -1
- package/dist/agent/providers/claude/session.d.ts +0 -304
- package/dist/agent/providers/claude/session.d.ts.map +0 -1
- package/dist/agent/providers/claude/session.js +0 -1236
- package/dist/agent/providers/claude/session.js.map +0 -1
- package/dist/agent/providers/client-factory.d.ts +0 -60
- package/dist/agent/providers/client-factory.d.ts.map +0 -1
- package/dist/agent/providers/client-factory.js +0 -400
- package/dist/agent/providers/client-factory.js.map +0 -1
- package/dist/agent/providers/openai/file-session.d.ts +0 -19
- package/dist/agent/providers/openai/file-session.d.ts.map +0 -1
- package/dist/agent/providers/openai/file-session.js +0 -78
- package/dist/agent/providers/openai/file-session.js.map +0 -1
- package/dist/agent/providers/openai/session.d.ts +0 -55
- package/dist/agent/providers/openai/session.d.ts.map +0 -1
- package/dist/agent/providers/openai/session.js +0 -447
- package/dist/agent/providers/openai/session.js.map +0 -1
- package/dist/agent/providers/openai/tools.d.ts +0 -15
- package/dist/agent/providers/openai/tools.d.ts.map +0 -1
- package/dist/agent/providers/openai/tools.js +0 -229
- package/dist/agent/providers/openai/tools.js.map +0 -1
- package/dist/agent/providers/session-types.d.ts +0 -153
- package/dist/agent/providers/session-types.d.ts.map +0 -1
- package/dist/agent/providers/session-types.js +0 -2
- package/dist/agent/providers/session-types.js.map +0 -1
- package/dist/agent/providers/system-prompt-log.d.ts +0 -9
- package/dist/agent/providers/system-prompt-log.d.ts.map +0 -1
- package/dist/agent/providers/system-prompt-log.js +0 -46
- package/dist/agent/providers/system-prompt-log.js.map +0 -1
- package/dist/agent/transcript-backfill.d.ts +0 -54
- package/dist/agent/transcript-backfill.d.ts.map +0 -1
- package/dist/agent/transcript-backfill.js +0 -604
- package/dist/agent/transcript-backfill.js.map +0 -1
- package/dist/agent/transcript-indexer.d.ts +0 -200
- package/dist/agent/transcript-indexer.d.ts.map +0 -1
- package/dist/agent/transcript-indexer.js +0 -775
- package/dist/agent/transcript-indexer.js.map +0 -1
- package/dist/agent/transcript-memory-migrations.d.ts +0 -25
- package/dist/agent/transcript-memory-migrations.d.ts.map +0 -1
- package/dist/agent/transcript-memory-migrations.js +0 -87
- package/dist/agent/transcript-memory-migrations.js.map +0 -1
- package/dist/agent/tunnel-credential-handler.d.ts +0 -90
- package/dist/agent/tunnel-credential-handler.d.ts.map +0 -1
- package/dist/agent/tunnel-credential-handler.js +0 -162
- package/dist/agent/tunnel-credential-handler.js.map +0 -1
- package/dist/agent/usage-backfill-handler.d.ts +0 -18
- package/dist/agent/usage-backfill-handler.d.ts.map +0 -1
- package/dist/agent/usage-backfill-handler.js +0 -69
- package/dist/agent/usage-backfill-handler.js.map +0 -1
- package/dist/agent/usage-gate.d.ts +0 -25
- package/dist/agent/usage-gate.d.ts.map +0 -1
- package/dist/agent/usage-gate.js +0 -83
- package/dist/agent/usage-gate.js.map +0 -1
- package/dist/agent/usage-handler.d.ts +0 -7
- package/dist/agent/usage-handler.d.ts.map +0 -1
- package/dist/agent/usage-handler.js +0 -28
- package/dist/agent/usage-handler.js.map +0 -1
- package/dist/agent/usage-report-builder.d.ts +0 -26
- package/dist/agent/usage-report-builder.d.ts.map +0 -1
- package/dist/agent/usage-report-builder.js +0 -80
- package/dist/agent/usage-report-builder.js.map +0 -1
- package/dist/agent/usage-report-queue.d.ts +0 -26
- package/dist/agent/usage-report-queue.d.ts.map +0 -1
- package/dist/agent/usage-report-queue.js +0 -199
- package/dist/agent/usage-report-queue.js.map +0 -1
- package/dist/agent/usage-report-types.d.ts +0 -41
- package/dist/agent/usage-report-types.d.ts.map +0 -1
- package/dist/agent/usage-report-types.js +0 -2
- package/dist/agent/usage-report-types.js.map +0 -1
- package/dist/agent/usage-reporter.d.ts +0 -31
- package/dist/agent/usage-reporter.d.ts.map +0 -1
- package/dist/agent/usage-reporter.js +0 -102
- package/dist/agent/usage-reporter.js.map +0 -1
- package/dist/agent/wake-cycle-tool-tracker.d.ts +0 -39
- package/dist/agent/wake-cycle-tool-tracker.d.ts.map +0 -1
- package/dist/agent/wake-cycle-tool-tracker.js +0 -72
- package/dist/agent/wake-cycle-tool-tracker.js.map +0 -1
- package/dist/billing/payg-handler.d.ts +0 -29
- package/dist/billing/payg-handler.d.ts.map +0 -1
- package/dist/billing/payg-handler.js +0 -92
- package/dist/billing/payg-handler.js.map +0 -1
- package/dist/billing/payment-handler.d.ts +0 -24
- package/dist/billing/payment-handler.d.ts.map +0 -1
- package/dist/billing/payment-handler.js +0 -101
- package/dist/billing/payment-handler.js.map +0 -1
- package/dist/builtin-skills/catalog/phone-adb-automation/SKILL.md +0 -412
- package/dist/builtin-skills/catalog/phone-adb-automation/phone_input.sh +0 -132
- package/dist/builtin-skills/catalog/phone-adb-automation/phone_launch.sh +0 -166
- package/dist/builtin-skills/catalog/phone-adb-automation/phone_screenshot.sh +0 -87
- package/dist/builtin-skills/catalog/phone-adb-automation/phone_security_kbd.py +0 -174
- package/dist/builtin-skills/catalog/phone-adb-automation/phone_setup.sh +0 -274
- package/dist/builtin-skills/catalog/phone-adb-automation/phone_swipe.sh +0 -111
- package/dist/builtin-skills/catalog/phone-adb-automation/phone_tap.sh +0 -87
- package/dist/builtin-skills/catalog/phone-adb-automation/phone_ui_parse.py +0 -176
- package/dist/builtin-skills/catalog/phone-adb-automation/phone_wake_unlock.sh +0 -67
- package/dist/builtin-skills/transcribe-audio/SKILL.md +0 -122
- package/dist/data-processing/convert-demo-cli.d.ts +0 -7
- package/dist/data-processing/convert-demo-cli.d.ts.map +0 -1
- package/dist/data-processing/convert-demo-cli.js +0 -30
- package/dist/data-processing/convert-demo-cli.js.map +0 -1
- package/dist/data-processing/convert-demo.d.ts +0 -26
- package/dist/data-processing/convert-demo.d.ts.map +0 -1
- package/dist/data-processing/convert-demo.js +0 -233
- package/dist/data-processing/convert-demo.js.map +0 -1
- package/dist/obs/rdp/icons/icons/app_windows.svg +0 -4
- package/dist/obs/rdp/icons/icons/clip_get.svg +0 -4
- package/dist/obs/rdp/icons/icons/clip_send.svg +0 -4
- package/dist/obs/rdp/icons/icons/clip_shared.svg +0 -4
- package/dist/obs/rdp/icons/icons/clipboard.svg +0 -4
- package/dist/obs/rdp/icons/icons/clipboard_shared.svg +0 -4
- package/dist/obs/rdp/icons/icons/control.svg +0 -4
- package/dist/obs/rdp/icons/icons/desktop.svg +0 -4
- package/dist/obs/rdp/icons/icons/display.svg +0 -4
- package/dist/obs/rdp/icons/icons/launchpad.svg +0 -4
- package/dist/obs/rdp/icons/icons/mission_control.svg +0 -4
- package/dist/obs/rdp/icons/icons/screenshot.svg +0 -4
- package/dist/obs/rdp/icons/icons/zoom_actual.svg +0 -4
- package/dist/obs/rdp/icons/icons/zoom_fit.svg +0 -4
- package/dist/obs/rdp/icons/icons/zoom_in.svg +0 -4
- package/dist/obs/rdp/icons/icons/zoom_out.svg +0 -4
- package/dist/obs/tunnel-telemetry.d.ts +0 -46
- package/dist/obs/tunnel-telemetry.d.ts.map +0 -1
- package/dist/obs/tunnel-telemetry.js +0 -70
- package/dist/obs/tunnel-telemetry.js.map +0 -1
- package/dist/onboarding/cloudflared-cert.d.ts +0 -15
- package/dist/onboarding/cloudflared-cert.d.ts.map +0 -1
- package/dist/onboarding/cloudflared-cert.js +0 -57
- package/dist/onboarding/cloudflared-cert.js.map +0 -1
- package/dist/realtime/websocket.d.ts +0 -7
- package/dist/realtime/websocket.d.ts.map +0 -1
- package/dist/realtime/websocket.js +0 -65
- package/dist/realtime/websocket.js.map +0 -1
- package/dist/service/gbox-tun.d.ts +0 -14
- package/dist/service/gbox-tun.d.ts.map +0 -1
- package/dist/service/gbox-tun.js +0 -315
- package/dist/service/gbox-tun.js.map +0 -1
- package/dist/skills/installed.d.ts +0 -11
- package/dist/skills/installed.d.ts.map +0 -1
- package/dist/skills/installed.js +0 -35
- package/dist/skills/installed.js.map +0 -1
- package/dist/tools/coordinate-resolver.d.ts +0 -30
- package/dist/tools/coordinate-resolver.d.ts.map +0 -1
- package/dist/tools/coordinate-resolver.js +0 -104
- package/dist/tools/coordinate-resolver.js.map +0 -1
- package/dist/utils/wechat-monitor.d.ts +0 -21
- package/dist/utils/wechat-monitor.d.ts.map +0 -1
- package/dist/utils/wechat-monitor.js +0 -88
- package/dist/utils/wechat-monitor.js.map +0 -1
- package/dist-agent/realtime/assets/index.html +0 -1058
- package/dist-agent/realtime/assets/samples/alloy.mp3 +0 -0
- package/dist-agent/realtime/assets/samples/ash.mp3 +0 -0
- package/dist-agent/realtime/assets/samples/ballad.mp3 +0 -0
- package/dist-agent/realtime/assets/samples/cedar.mp3 +0 -0
- package/dist-agent/realtime/assets/samples/coral.mp3 +0 -0
- package/dist-agent/realtime/assets/samples/echo.mp3 +0 -0
- package/dist-agent/realtime/assets/samples/marin.mp3 +0 -0
- package/dist-agent/realtime/assets/samples/sage.mp3 +0 -0
- package/dist-agent/realtime/assets/samples/shimmer.mp3 +0 -0
- package/dist-agent/realtime/assets/samples/verse.mp3 +0 -0
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import crypto from "node:crypto";
|
|
2
|
+
import { logger } from "../logger.js";
|
|
3
|
+
/**
|
|
4
|
+
* QQ Bot scan-to-configure (QR-code onboarding) helpers.
|
|
5
|
+
*
|
|
6
|
+
* Ported from Hermes' `qqbot/onboard.py` + `crypto.py`. Drives the
|
|
7
|
+
* unauthenticated `q.qq.com` bind-task endpoints so an owner can stand up a QQ
|
|
8
|
+
* Bot application by scanning a QR code in the QQ app — no manual AppID/Secret
|
|
9
|
+
* entry. The server encrypts the bot's client secret under a locally-generated
|
|
10
|
+
* AES key so the secret never travels in plaintext.
|
|
11
|
+
*
|
|
12
|
+
* Reference: https://bot.q.qq.com/wiki/develop/api-v2/
|
|
13
|
+
*/
|
|
14
|
+
/** Portal host for the bind-task endpoints. Override via QQ_PORTAL_HOST. */
|
|
15
|
+
export function getPortalHost() {
|
|
16
|
+
const override = process.env.QQ_PORTAL_HOST?.trim();
|
|
17
|
+
return override && override.length > 0 ? override : "q.qq.com";
|
|
18
|
+
}
|
|
19
|
+
const ONBOARD_CREATE_PATH = "/lite/create_bind_task";
|
|
20
|
+
const ONBOARD_POLL_PATH = "/lite/poll_bind_result";
|
|
21
|
+
/** Seconds between poll_bind_result calls. */
|
|
22
|
+
export const ONBOARD_POLL_INTERVAL_MS = 2_000;
|
|
23
|
+
/** Max times we rebuild an expired task before giving up. */
|
|
24
|
+
export const ONBOARD_MAX_REFRESHES = 3;
|
|
25
|
+
/** Overall onboarding deadline. */
|
|
26
|
+
export const ONBOARD_TIMEOUT_MS = 600_000;
|
|
27
|
+
/** Bind status codes returned by poll_bind_result. */
|
|
28
|
+
export var BindStatus;
|
|
29
|
+
(function (BindStatus) {
|
|
30
|
+
BindStatus[BindStatus["NONE"] = 0] = "NONE";
|
|
31
|
+
BindStatus[BindStatus["PENDING"] = 1] = "PENDING";
|
|
32
|
+
BindStatus[BindStatus["COMPLETED"] = 2] = "COMPLETED";
|
|
33
|
+
BindStatus[BindStatus["EXPIRED"] = 3] = "EXPIRED";
|
|
34
|
+
})(BindStatus || (BindStatus = {}));
|
|
35
|
+
/**
|
|
36
|
+
* Standard headers for q.qq.com requests. The portal returns a JavaScript
|
|
37
|
+
* anti-bot challenge page instead of JSON unless `Accept: application/json`
|
|
38
|
+
* is set explicitly.
|
|
39
|
+
*/
|
|
40
|
+
function portalHeaders() {
|
|
41
|
+
return {
|
|
42
|
+
"Content-Type": "application/json",
|
|
43
|
+
Accept: "application/json",
|
|
44
|
+
"User-Agent": "VisionClawQQBot/1.0 (+https://visionclaw.dev)",
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/** Generate a 256-bit AES key, base64-encoded, for create_bind_task. */
|
|
48
|
+
export function generateBindKey() {
|
|
49
|
+
return crypto.randomBytes(32).toString("base64");
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Decrypt a base64 AES-256-GCM ciphertext produced by the portal.
|
|
53
|
+
*
|
|
54
|
+
* Layout after base64-decoding: `IV(12) ‖ ciphertext(N) ‖ AuthTag(16)`.
|
|
55
|
+
* No additional authenticated data. Returns the plaintext client secret.
|
|
56
|
+
*/
|
|
57
|
+
export function decryptSecret(encryptedBase64, keyBase64) {
|
|
58
|
+
const key = Buffer.from(keyBase64, "base64");
|
|
59
|
+
const raw = Buffer.from(encryptedBase64, "base64");
|
|
60
|
+
if (raw.length < 12 + 16) {
|
|
61
|
+
throw new Error("QQ decryptSecret: ciphertext too short");
|
|
62
|
+
}
|
|
63
|
+
const iv = raw.subarray(0, 12);
|
|
64
|
+
const tag = raw.subarray(raw.length - 16);
|
|
65
|
+
const ciphertext = raw.subarray(12, raw.length - 16);
|
|
66
|
+
const decipher = crypto.createDecipheriv("aes-256-gcm", key, iv);
|
|
67
|
+
decipher.setAuthTag(tag);
|
|
68
|
+
const plaintext = Buffer.concat([decipher.update(ciphertext), decipher.final()]);
|
|
69
|
+
return plaintext.toString("utf8");
|
|
70
|
+
}
|
|
71
|
+
async function portalPost(path, body, timeoutMs) {
|
|
72
|
+
const url = `https://${getPortalHost()}${path}`;
|
|
73
|
+
const controller = new AbortController();
|
|
74
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
75
|
+
try {
|
|
76
|
+
const resp = await fetch(url, {
|
|
77
|
+
method: "POST",
|
|
78
|
+
headers: portalHeaders(),
|
|
79
|
+
body: JSON.stringify(body),
|
|
80
|
+
signal: controller.signal,
|
|
81
|
+
});
|
|
82
|
+
if (!resp.ok) {
|
|
83
|
+
throw new Error(`HTTP ${resp.status}`);
|
|
84
|
+
}
|
|
85
|
+
return (await resp.json());
|
|
86
|
+
}
|
|
87
|
+
finally {
|
|
88
|
+
clearTimeout(timer);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Create a bind task. Returns the task id and the locally-held AES key used
|
|
93
|
+
* later to decrypt the bot secret.
|
|
94
|
+
*/
|
|
95
|
+
export async function createBindTask() {
|
|
96
|
+
const aesKey = generateBindKey();
|
|
97
|
+
const data = await portalPost(ONBOARD_CREATE_PATH, { key: aesKey }, 10_000);
|
|
98
|
+
if (data.retcode !== 0) {
|
|
99
|
+
throw new Error(data.msg ?? "create_bind_task failed");
|
|
100
|
+
}
|
|
101
|
+
const taskId = data.data?.task_id;
|
|
102
|
+
if (typeof taskId !== "string" || !taskId) {
|
|
103
|
+
throw new Error("create_bind_task: missing task_id in response");
|
|
104
|
+
}
|
|
105
|
+
return { taskId, aesKey };
|
|
106
|
+
}
|
|
107
|
+
/** Poll the bind result for a task id. */
|
|
108
|
+
export async function pollBindResult(taskId) {
|
|
109
|
+
const data = await portalPost(ONBOARD_POLL_PATH, { task_id: taskId }, 10_000);
|
|
110
|
+
if (data.retcode !== 0) {
|
|
111
|
+
throw new Error(data.msg ?? "poll_bind_result failed");
|
|
112
|
+
}
|
|
113
|
+
const d = data.data ?? {};
|
|
114
|
+
const asString = (v) => {
|
|
115
|
+
if (typeof v === "string")
|
|
116
|
+
return v;
|
|
117
|
+
if (typeof v === "number")
|
|
118
|
+
return String(v);
|
|
119
|
+
return "";
|
|
120
|
+
};
|
|
121
|
+
return {
|
|
122
|
+
status: (typeof d.status === "number" ? d.status : 0),
|
|
123
|
+
appId: asString(d.bot_appid),
|
|
124
|
+
encryptedSecret: asString(d.bot_encrypt_secret),
|
|
125
|
+
userOpenId: asString(d.user_openid),
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
/** Build the QR-code target URL for a task id. `_wv=2` is required so the QQ app launches on mobile. */
|
|
129
|
+
export function buildConnectUrl(taskId) {
|
|
130
|
+
return `https://${getPortalHost()}/qqbot/openclaw/connect.html?task_id=${encodeURIComponent(taskId)}&_wv=2&source=visionclaw`;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Run the full scan-to-configure flow: create a task, hand the connect URL to
|
|
134
|
+
* the caller (so it can render a QR code), then poll until the scan completes,
|
|
135
|
+
* the task expires too many times, or the overall deadline passes.
|
|
136
|
+
*
|
|
137
|
+
* @param onTask invoked with the connect URL each time a (re)new task is created.
|
|
138
|
+
* @param shouldAbort optional cancellation hook polled between attempts.
|
|
139
|
+
*/
|
|
140
|
+
export async function qrRegister(opts) {
|
|
141
|
+
const now = opts.now ?? (() => Date.now());
|
|
142
|
+
const sleep = opts.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
|
|
143
|
+
const deadline = now() + ONBOARD_TIMEOUT_MS;
|
|
144
|
+
for (let refreshCount = 0; refreshCount <= ONBOARD_MAX_REFRESHES; refreshCount++) {
|
|
145
|
+
if (opts.shouldAbort?.())
|
|
146
|
+
return null;
|
|
147
|
+
let task;
|
|
148
|
+
try {
|
|
149
|
+
task = await createBindTask();
|
|
150
|
+
}
|
|
151
|
+
catch (err) {
|
|
152
|
+
logger.warn(`[QQ onboard] create_bind_task failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
await opts.onTask(buildConnectUrl(task.taskId), task.taskId);
|
|
156
|
+
let expired = false;
|
|
157
|
+
while (now() < deadline) {
|
|
158
|
+
if (opts.shouldAbort?.())
|
|
159
|
+
return null;
|
|
160
|
+
let result;
|
|
161
|
+
try {
|
|
162
|
+
result = await pollBindResult(task.taskId);
|
|
163
|
+
}
|
|
164
|
+
catch {
|
|
165
|
+
await sleep(ONBOARD_POLL_INTERVAL_MS);
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
if (result.status === BindStatus.COMPLETED) {
|
|
169
|
+
const clientSecret = decryptSecret(result.encryptedSecret, task.aesKey);
|
|
170
|
+
return { appId: result.appId, clientSecret, userOpenId: result.userOpenId };
|
|
171
|
+
}
|
|
172
|
+
if (result.status === BindStatus.EXPIRED) {
|
|
173
|
+
if (refreshCount >= ONBOARD_MAX_REFRESHES) {
|
|
174
|
+
logger.warn(`[QQ onboard] QR expired ${ONBOARD_MAX_REFRESHES} times — giving up`);
|
|
175
|
+
return null;
|
|
176
|
+
}
|
|
177
|
+
expired = true;
|
|
178
|
+
break; // outer loop rebuilds the task
|
|
179
|
+
}
|
|
180
|
+
await sleep(ONBOARD_POLL_INTERVAL_MS);
|
|
181
|
+
}
|
|
182
|
+
if (!expired) {
|
|
183
|
+
// Deadline reached without completing.
|
|
184
|
+
logger.warn(`[QQ onboard] poll timed out after ${ONBOARD_TIMEOUT_MS}ms`);
|
|
185
|
+
return null;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return null;
|
|
189
|
+
}
|
|
190
|
+
//# sourceMappingURL=qq-onboard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qq-onboard.js","sourceRoot":"","sources":["../../src/channels/qq-onboard.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { EventEmitter } from "node:events";
|
|
2
|
+
import type { VisionClawConfig } from "../config/types.js";
|
|
3
|
+
import type { ChannelAdapter, MessageAttachment, ReplyContext } from "./interface.js";
|
|
4
|
+
export declare class QQAdapter extends EventEmitter implements ChannelAdapter {
|
|
5
|
+
readonly name = "qq";
|
|
6
|
+
private config;
|
|
7
|
+
private ws;
|
|
8
|
+
private running;
|
|
9
|
+
private accessToken;
|
|
10
|
+
private tokenExpiresAt;
|
|
11
|
+
private tokenRefreshing;
|
|
12
|
+
private heartbeatTimer;
|
|
13
|
+
private heartbeatIntervalMs;
|
|
14
|
+
private lastSeq;
|
|
15
|
+
private sessionId;
|
|
16
|
+
private backoffIdx;
|
|
17
|
+
private lastMsgIdByChat;
|
|
18
|
+
private seenMsgIds;
|
|
19
|
+
private msgSeqCounters;
|
|
20
|
+
constructor(config: VisionClawConfig);
|
|
21
|
+
start(): Promise<void>;
|
|
22
|
+
stop(): Promise<void>;
|
|
23
|
+
private ensureToken;
|
|
24
|
+
private getGatewayUrl;
|
|
25
|
+
private connectLoop;
|
|
26
|
+
/**
|
|
27
|
+
* Open one WebSocket connection and pump events until it closes.
|
|
28
|
+
* Resolves with `true` if the close was fatal (caller must stop reconnecting),
|
|
29
|
+
* `false` otherwise.
|
|
30
|
+
*/
|
|
31
|
+
private runConnection;
|
|
32
|
+
private dispatch;
|
|
33
|
+
private sendIdentify;
|
|
34
|
+
private sendResume;
|
|
35
|
+
private startHeartbeat;
|
|
36
|
+
private clearHeartbeat;
|
|
37
|
+
private sendJson;
|
|
38
|
+
private closeWs;
|
|
39
|
+
private onMessage;
|
|
40
|
+
private parseAttachments;
|
|
41
|
+
private stripAtMention;
|
|
42
|
+
private parseTimestamp;
|
|
43
|
+
private rememberMsgId;
|
|
44
|
+
sendMessage(to: string, message: string, attachments?: MessageAttachment[], replyTo?: ReplyContext): Promise<void>;
|
|
45
|
+
private sendText;
|
|
46
|
+
/** Map an attachment type to the QQ file_type code (1=image, 2=video, 3=voice, 4=file). */
|
|
47
|
+
private fileTypeFor;
|
|
48
|
+
/** Send media the QQ platform fetches itself from a public URL. */
|
|
49
|
+
private sendMediaByUrl;
|
|
50
|
+
/**
|
|
51
|
+
* Send a local file (read from att.localPath, or att.base64 when already
|
|
52
|
+
* encoded) by uploading its base64 payload via the file_data field.
|
|
53
|
+
*/
|
|
54
|
+
private sendMediaByBase64;
|
|
55
|
+
/**
|
|
56
|
+
* Shared tail for both upload paths: POST the upload body to the files
|
|
57
|
+
* endpoint, then send the returned file_info as a media message.
|
|
58
|
+
*/
|
|
59
|
+
private uploadAndSendMedia;
|
|
60
|
+
private apiRequest;
|
|
61
|
+
private resolveChatType;
|
|
62
|
+
private resolveReplyMsgId;
|
|
63
|
+
/**
|
|
64
|
+
* Split a message into <=MAX_MESSAGE_LENGTH chunks on Unicode code-point
|
|
65
|
+
* boundaries. `Array.from` iterates by code point, so emoji and other
|
|
66
|
+
* astral-plane characters are never cut across their surrogate pair.
|
|
67
|
+
*/
|
|
68
|
+
private splitMessage;
|
|
69
|
+
/**
|
|
70
|
+
* Next msg_seq for a send key (the reply msg_id when threading, else the
|
|
71
|
+
* chat id). QQ rejects a reused (msg_id, msg_seq) pair, so each chunk of a
|
|
72
|
+
* multi-part reply needs a distinct, monotonically increasing seq. The map
|
|
73
|
+
* is capped to avoid unbounded growth across many chats.
|
|
74
|
+
*/
|
|
75
|
+
private nextMsgSeq;
|
|
76
|
+
private sleep;
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=qq.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qq.d.ts","sourceRoot":"","sources":["../../src/channels/qq.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAK3C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,KAAK,EAAE,cAAc,EAAkB,iBAAiB,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AA6DtG,qBAAa,SAAU,SAAQ,YAAa,YAAW,cAAc;IACnE,QAAQ,CAAC,IAAI,QAAQ;IACrB,OAAO,CAAC,MAAM,CAAmB;IAEjC,OAAO,CAAC,EAAE,CAA0B;IACpC,OAAO,CAAC,OAAO,CAAS;IAExB,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,eAAe,CAAgC;IAEvD,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,mBAAmB,CAAU;IACrC,OAAO,CAAC,OAAO,CAAuB;IACtC,OAAO,CAAC,SAAS,CAAuB;IAExC,OAAO,CAAC,UAAU,CAAK;IAGvB,OAAO,CAAC,eAAe,CAA6B;IACpD,OAAO,CAAC,UAAU,CAAqB;IAGvC,OAAO,CAAC,cAAc,CAA6B;gBAEvC,MAAM,EAAE,gBAAgB;IASpC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAYhB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;YAkBb,WAAW;YAmCX,aAAa;YAiBb,WAAW;IAyBzB;;;;OAIG;IACH,OAAO,CAAC,aAAa;YAiEP,QAAQ;YAuDR,YAAY;YAcZ,UAAU;IASxB,OAAO,CAAC,cAAc;IAStB,OAAO,CAAC,cAAc;IAOtB,OAAO,CAAC,QAAQ;IAMhB,OAAO,CAAC,OAAO;IAcf,OAAO,CAAC,SAAS;IAwDjB,OAAO,CAAC,gBAAgB;IAoBxB,OAAO,CAAC,cAAc;IAMtB,OAAO,CAAC,cAAc;IAMtB,OAAO,CAAC,aAAa;IAaf,WAAW,CACf,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,MAAM,EACf,WAAW,CAAC,EAAE,iBAAiB,EAAE,EACjC,OAAO,CAAC,EAAE,YAAY,GACrB,OAAO,CAAC,IAAI,CAAC;YA0BF,QAAQ;IAgBtB,2FAA2F;IAC3F,OAAO,CAAC,WAAW;IAInB,mEAAmE;YACrD,cAAc;IAY5B;;;OAGG;YACW,iBAAiB;IA0B/B;;;OAGG;YACW,kBAAkB;YAiClB,UAAU;IAqBxB,OAAO,CAAC,eAAe;IAOvB,OAAO,CAAC,iBAAiB;IAMzB;;;;OAIG;IACH,OAAO,CAAC,YAAY;IAUpB;;;;;OAKG;IACH,OAAO,CAAC,UAAU;IAYlB,OAAO,CAAC,KAAK;CAGd"}
|