vibe-coding-master 0.4.33 → 0.4.34
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.
|
@@ -24,8 +24,9 @@ export function createLarkRegistrationClient(deps = {}) {
|
|
|
24
24
|
return {
|
|
25
25
|
async init(domain) {
|
|
26
26
|
const payload = await postRegistration(domain, { action: "init" });
|
|
27
|
-
const
|
|
28
|
-
|
|
27
|
+
const data = responseData(payload);
|
|
28
|
+
const methods = Array.isArray(data.supported_auth_methods)
|
|
29
|
+
? data.supported_auth_methods.filter((value) => typeof value === "string")
|
|
29
30
|
: [];
|
|
30
31
|
if (!methods.includes("client_secret")) {
|
|
31
32
|
throw new Error(`Lark QR setup does not support client_secret auth. Supported methods: ${methods.join(", ") || "none"}.`);
|
|
@@ -38,11 +39,12 @@ export function createLarkRegistrationClient(deps = {}) {
|
|
|
38
39
|
auth_method: "client_secret",
|
|
39
40
|
request_user_info: "open_id"
|
|
40
41
|
});
|
|
41
|
-
const
|
|
42
|
+
const data = responseData(payload);
|
|
43
|
+
const deviceCode = stringOrNull(data.device_code);
|
|
42
44
|
if (!deviceCode) {
|
|
43
45
|
throw new Error("Lark QR setup did not return a device_code.");
|
|
44
46
|
}
|
|
45
|
-
const qrUrl = appendQrTrackingParams(stringOrNull(
|
|
47
|
+
const qrUrl = appendQrTrackingParams(stringOrNull(data.verification_uri_complete) ?? "");
|
|
46
48
|
if (!qrUrl) {
|
|
47
49
|
throw new Error("Lark QR setup did not return a QR URL.");
|
|
48
50
|
}
|
|
@@ -50,9 +52,9 @@ export function createLarkRegistrationClient(deps = {}) {
|
|
|
50
52
|
domain,
|
|
51
53
|
deviceCode,
|
|
52
54
|
qrUrl,
|
|
53
|
-
userCode: stringOrNull(
|
|
54
|
-
intervalSeconds: positiveNumberOr(
|
|
55
|
-
expiresInSeconds: positiveNumberOr(
|
|
55
|
+
userCode: stringOrNull(data.user_code),
|
|
56
|
+
intervalSeconds: positiveNumberOr(data.interval, 5),
|
|
57
|
+
expiresInSeconds: positiveNumberOr(data.expire_in, 600)
|
|
56
58
|
};
|
|
57
59
|
},
|
|
58
60
|
async poll(input) {
|
|
@@ -61,11 +63,12 @@ export function createLarkRegistrationClient(deps = {}) {
|
|
|
61
63
|
device_code: input.deviceCode,
|
|
62
64
|
tp: "ob_app"
|
|
63
65
|
});
|
|
64
|
-
const
|
|
66
|
+
const data = responseData(payload);
|
|
67
|
+
const userInfo = isObject(data.user_info) ? data.user_info : {};
|
|
65
68
|
const tenantBrand = stringOrNull(userInfo.tenant_brand);
|
|
66
69
|
const domain = tenantBrand === "lark" ? "lark" : input.domain;
|
|
67
|
-
const appId = stringOrNull(
|
|
68
|
-
const appSecret = stringOrNull(
|
|
70
|
+
const appId = stringOrNull(data.client_id);
|
|
71
|
+
const appSecret = stringOrNull(data.client_secret);
|
|
69
72
|
if (appId && appSecret) {
|
|
70
73
|
const bot = await probeBot(fetchImpl, {
|
|
71
74
|
appId,
|
|
@@ -82,20 +85,31 @@ export function createLarkRegistrationClient(deps = {}) {
|
|
|
82
85
|
botOpenId: bot.botOpenId
|
|
83
86
|
};
|
|
84
87
|
}
|
|
85
|
-
const error = stringOrNull(payload.error);
|
|
88
|
+
const error = stringOrNull(data.error) ?? stringOrNull(payload.error);
|
|
86
89
|
if (error === "expired_token") {
|
|
87
90
|
return { status: "expired", message: "Lark QR setup expired. Start a new setup." };
|
|
88
91
|
}
|
|
89
92
|
if (error === "access_denied") {
|
|
90
93
|
return { status: "failed", message: "Lark QR setup was denied." };
|
|
91
94
|
}
|
|
95
|
+
const errorDescription = stringOrNull(data.error_description)
|
|
96
|
+
?? stringOrNull(payload.error_description)
|
|
97
|
+
?? stringOrNull(data.message)
|
|
98
|
+
?? stringOrNull(payload.message)
|
|
99
|
+
?? stringOrNull(data.msg)
|
|
100
|
+
?? stringOrNull(payload.msg);
|
|
92
101
|
return {
|
|
93
102
|
status: "wait",
|
|
94
|
-
message: error && error !== "authorization_pending"
|
|
103
|
+
message: error && error !== "authorization_pending"
|
|
104
|
+
? [error, errorDescription].filter(Boolean).join(": ")
|
|
105
|
+
: undefined
|
|
95
106
|
};
|
|
96
107
|
}
|
|
97
108
|
};
|
|
98
109
|
}
|
|
110
|
+
function responseData(payload) {
|
|
111
|
+
return isObject(payload.data) ? payload.data : payload;
|
|
112
|
+
}
|
|
99
113
|
async function probeBot(fetchImpl, input) {
|
|
100
114
|
try {
|
|
101
115
|
const tokenPayload = await fetchJson(fetchImpl, `${OPEN_BASE_URLS[input.domain]}/open-apis/auth/v3/tenant_access_token/internal`, {
|
|
@@ -155,7 +169,7 @@ async function fetchJson(fetchImpl, url, init = {}) {
|
|
|
155
169
|
throw new Error("Lark setup response was not a JSON object.");
|
|
156
170
|
}
|
|
157
171
|
if (!response.ok && !payload.error) {
|
|
158
|
-
throw new Error(
|
|
172
|
+
throw new Error(`Lark QR setup request failed: ${response.status} ${response.statusText}${formatPayloadError(payload)}`);
|
|
159
173
|
}
|
|
160
174
|
return payload;
|
|
161
175
|
}
|
|
@@ -169,18 +183,30 @@ async function fetchJson(fetchImpl, url, init = {}) {
|
|
|
169
183
|
clearTimeout(timeout);
|
|
170
184
|
}
|
|
171
185
|
}
|
|
186
|
+
function formatPayloadError(payload) {
|
|
187
|
+
const data = responseData(payload);
|
|
188
|
+
const message = [
|
|
189
|
+
stringOrNull(data.error) ?? stringOrNull(payload.error),
|
|
190
|
+
stringOrNull(data.error_description) ?? stringOrNull(payload.error_description),
|
|
191
|
+
stringOrNull(data.message) ?? stringOrNull(payload.message),
|
|
192
|
+
stringOrNull(data.msg) ?? stringOrNull(payload.msg),
|
|
193
|
+
typeof data.code === "number" || typeof data.code === "string" ? `code ${data.code}` : null,
|
|
194
|
+
typeof payload.code === "number" || typeof payload.code === "string" ? `code ${payload.code}` : null
|
|
195
|
+
].filter(Boolean).join(": ");
|
|
196
|
+
return message ? ` (${message})` : "";
|
|
197
|
+
}
|
|
172
198
|
function appendQrTrackingParams(value) {
|
|
173
199
|
if (!value) {
|
|
174
200
|
return "";
|
|
175
201
|
}
|
|
176
202
|
try {
|
|
177
203
|
const url = new URL(value);
|
|
178
|
-
url.searchParams.set("from", "
|
|
179
|
-
url.searchParams.set("tp", "
|
|
204
|
+
url.searchParams.set("from", "hermes");
|
|
205
|
+
url.searchParams.set("tp", "hermes");
|
|
180
206
|
return url.toString();
|
|
181
207
|
}
|
|
182
208
|
catch {
|
|
183
|
-
return `${value}${value.includes("?") ? "&" : "?"}from=
|
|
209
|
+
return `${value}${value.includes("?") ? "&" : "?"}from=hermes&tp=hermes`;
|
|
184
210
|
}
|
|
185
211
|
}
|
|
186
212
|
function positiveNumberOr(input, fallback) {
|
|
@@ -14,6 +14,7 @@ const POLL_ERROR_BACKOFF_MS = 2_000;
|
|
|
14
14
|
const POLL_LONG_BACKOFF_MS = 30_000;
|
|
15
15
|
const MAX_FAILURES_BEFORE_LONG_BACKOFF = 3;
|
|
16
16
|
const DEFAULT_POLL_TIMEOUT_MS = 35_000;
|
|
17
|
+
const LARK_REGISTRATION_CONFIRM_TIMEOUT_MS = 15_000;
|
|
17
18
|
const MAX_LATEST_PM_REPLY_CHARS = 8_000;
|
|
18
19
|
const GATEWAY_TRANSLATION_FAILURE_TEXT = "PM 回复已收到,但翻译失败。\n发送 /retry 重新翻译。";
|
|
19
20
|
const COMMANDS_ALLOWED_WHEN_DISABLED = new Set([
|
|
@@ -938,17 +939,25 @@ export function createGatewayService(deps) {
|
|
|
938
939
|
message: "Lark QR setup expired. Start a new setup."
|
|
939
940
|
};
|
|
940
941
|
}
|
|
941
|
-
const
|
|
942
|
+
const confirmDeadline = Date.now() + LARK_REGISTRATION_CONFIRM_TIMEOUT_MS;
|
|
943
|
+
let result = await larkRegistration.poll({
|
|
942
944
|
domain: larkRegistrationState.domain,
|
|
943
945
|
deviceCode: larkRegistrationState.deviceCode
|
|
944
946
|
});
|
|
947
|
+
while (result.status === "wait" && Date.now() < confirmDeadline) {
|
|
948
|
+
await sleep(Math.min(larkRegistrationState.intervalSeconds * 1000, 3_000), new AbortController().signal);
|
|
949
|
+
result = await larkRegistration.poll({
|
|
950
|
+
domain: larkRegistrationState.domain,
|
|
951
|
+
deviceCode: larkRegistrationState.deviceCode
|
|
952
|
+
});
|
|
953
|
+
}
|
|
945
954
|
if (result.status !== "confirmed") {
|
|
946
955
|
if (result.status === "expired" || result.status === "failed") {
|
|
947
956
|
larkRegistrationState = null;
|
|
948
957
|
}
|
|
949
958
|
return {
|
|
950
959
|
status: result.status,
|
|
951
|
-
message: result.message
|
|
960
|
+
message: result.message ?? (result.status === "wait" ? "Lark has not returned app credentials yet. Confirm again in a moment." : undefined)
|
|
952
961
|
};
|
|
953
962
|
}
|
|
954
963
|
if (!result.appId || !result.appSecret || !result.domain) {
|
|
@@ -1339,7 +1348,10 @@ function normalizeBaseUrl(input, fallback) {
|
|
|
1339
1348
|
if (!trimmed) {
|
|
1340
1349
|
return fallback;
|
|
1341
1350
|
}
|
|
1342
|
-
if (
|
|
1351
|
+
if (/^https:\/\/lark:\/\//i.test(trimmed)) {
|
|
1352
|
+
return trimmed.replace(/^https:\/\//i, "").replace(/\/+$/, "");
|
|
1353
|
+
}
|
|
1354
|
+
if (/^[a-z][a-z0-9+.-]*:\/\//i.test(trimmed)) {
|
|
1343
1355
|
return trimmed.replace(/\/+$/, "");
|
|
1344
1356
|
}
|
|
1345
1357
|
return `https://${trimmed.replace(/\/+$/, "")}`;
|
|
@@ -289,7 +289,10 @@ function normalizeBaseUrl(input, fallback = DEFAULT_BASE_URL) {
|
|
|
289
289
|
if (!raw) {
|
|
290
290
|
return fallback;
|
|
291
291
|
}
|
|
292
|
-
if (
|
|
292
|
+
if (/^https:\/\/lark:\/\//i.test(raw)) {
|
|
293
|
+
return raw.replace(/^https:\/\//i, "").replace(/\/+$/, "");
|
|
294
|
+
}
|
|
295
|
+
if (/^[a-z][a-z0-9+.-]*:\/\//i.test(raw)) {
|
|
293
296
|
return raw.replace(/\/+$/, "");
|
|
294
297
|
}
|
|
295
298
|
return `https://${raw.replace(/\/+$/, "")}`;
|