dsh-feishu-bot 0.19.8 → 0.19.10
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/cli.js +75 -5
- package/dist/cli.js.map +1 -1
- package/dist/plugin.js +76 -5
- package/dist/plugin.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -4693,7 +4693,7 @@ async function fetchNpmLatestVersion(packageName, registryUrl = defaultRegistryU
|
|
|
4693
4693
|
}
|
|
4694
4694
|
return void 0;
|
|
4695
4695
|
}
|
|
4696
|
-
async function fetchNpmLatestVersionOnce(packageName, registryUrl = defaultRegistryUrl(), timeoutMs =
|
|
4696
|
+
async function fetchNpmLatestVersionOnce(packageName, registryUrl = defaultRegistryUrl(), timeoutMs = NPM_LATEST_TIMEOUT_MS, fetcher = fetch) {
|
|
4697
4697
|
try {
|
|
4698
4698
|
const response = await fetcher(
|
|
4699
4699
|
`${registryUrl}/${encodeURIComponent(packageName)}/latest`,
|
|
@@ -10879,6 +10879,7 @@ async function reply6(ctx, zh, en) {
|
|
|
10879
10879
|
// src/upgrade/update-check.ts
|
|
10880
10880
|
init_own_package();
|
|
10881
10881
|
var UPDATE_CHECK_CACHE_MS = 60 * 6e4;
|
|
10882
|
+
var UPDATE_CHECK_FAILURE_CACHE_MS = 15e3;
|
|
10882
10883
|
var cache;
|
|
10883
10884
|
function upgradeCheckEnabled() {
|
|
10884
10885
|
return (process.env.DSH_LARK_UPGRADE_CHECK ?? "1") !== "0";
|
|
@@ -10894,16 +10895,22 @@ function isNewer(latest, current) {
|
|
|
10894
10895
|
async function latestVersion(options = {}) {
|
|
10895
10896
|
if (!upgradeCheckEnabled()) return void 0;
|
|
10896
10897
|
const now = Date.now();
|
|
10897
|
-
if (cache !== void 0
|
|
10898
|
-
|
|
10898
|
+
if (cache !== void 0) {
|
|
10899
|
+
const ttl = options.cacheMs !== void 0 ? options.cacheMs : cache.failed ? UPDATE_CHECK_FAILURE_CACHE_MS : UPDATE_CHECK_CACHE_MS;
|
|
10900
|
+
if (now - cache.at < ttl) return cache.latest;
|
|
10899
10901
|
}
|
|
10900
10902
|
const probe = options.probe ?? fetchNpmLatestVersionOnce;
|
|
10901
10903
|
const latest = await probe(options.packageName ?? ownPackageInfo().name);
|
|
10902
|
-
cache = {
|
|
10904
|
+
cache = {
|
|
10905
|
+
at: now,
|
|
10906
|
+
latest,
|
|
10907
|
+
failed: latest === void 0,
|
|
10908
|
+
notified: cache?.notified ?? /* @__PURE__ */ new Set()
|
|
10909
|
+
};
|
|
10903
10910
|
return latest;
|
|
10904
10911
|
}
|
|
10905
10912
|
function markNotified(latest) {
|
|
10906
|
-
if (cache === void 0) cache = { at: 0, latest, notified: /* @__PURE__ */ new Set() };
|
|
10913
|
+
if (cache === void 0) cache = { at: 0, latest, failed: false, notified: /* @__PURE__ */ new Set() };
|
|
10907
10914
|
if (cache.notified.has(latest)) return false;
|
|
10908
10915
|
cache.notified.add(latest);
|
|
10909
10916
|
return true;
|
|
@@ -12138,6 +12145,34 @@ async function tryHandleCommand(text, ctx) {
|
|
|
12138
12145
|
import { createHash } from "crypto";
|
|
12139
12146
|
var CARD_STREAM_THROTTLE_MS = 100;
|
|
12140
12147
|
var CARD_PATCH_ATTEMPTS = 2;
|
|
12148
|
+
var MAX_CARD_WITHDRAW_RECOVERIES = 3;
|
|
12149
|
+
function isMessageWithdrawn(error) {
|
|
12150
|
+
const seen = /* @__PURE__ */ new Set();
|
|
12151
|
+
const stack = [error];
|
|
12152
|
+
while (stack.length > 0) {
|
|
12153
|
+
const node = stack.pop();
|
|
12154
|
+
if (node === null || node === void 0) continue;
|
|
12155
|
+
if (typeof node === "string") {
|
|
12156
|
+
if (node.toLowerCase().includes("withdrawn")) return true;
|
|
12157
|
+
continue;
|
|
12158
|
+
}
|
|
12159
|
+
if (typeof node !== "object" || seen.has(node)) continue;
|
|
12160
|
+
seen.add(node);
|
|
12161
|
+
if (Array.isArray(node)) {
|
|
12162
|
+
for (const item of node) stack.push(item);
|
|
12163
|
+
continue;
|
|
12164
|
+
}
|
|
12165
|
+
const record = node;
|
|
12166
|
+
if (record["code"] === 230011) return true;
|
|
12167
|
+
if (typeof record["message"] === "string" && record["message"].toLowerCase().includes("withdrawn")) return true;
|
|
12168
|
+
if (typeof record["msg"] === "string" && record["msg"].toLowerCase().includes("withdrawn")) return true;
|
|
12169
|
+
for (const key of ["response", "data", "error", "errors"]) {
|
|
12170
|
+
const value = record[key];
|
|
12171
|
+
if (value !== void 0 && value !== null) stack.push(value);
|
|
12172
|
+
}
|
|
12173
|
+
}
|
|
12174
|
+
return false;
|
|
12175
|
+
}
|
|
12141
12176
|
function toLarkSendOptions(options) {
|
|
12142
12177
|
const sendOptions = {};
|
|
12143
12178
|
if (options?.replyTo) sendOptions.replyTo = options.replyTo;
|
|
@@ -12172,6 +12207,7 @@ var ResilientCardStreamController = class {
|
|
|
12172
12207
|
timer;
|
|
12173
12208
|
inFlight;
|
|
12174
12209
|
reanchorInFlight;
|
|
12210
|
+
recoveries = 0;
|
|
12175
12211
|
async update(card) {
|
|
12176
12212
|
if (this.closed || this.failed) return;
|
|
12177
12213
|
this.latest = card;
|
|
@@ -12219,6 +12255,7 @@ var ResilientCardStreamController = class {
|
|
|
12219
12255
|
for (let attempt = 1; attempt <= CARD_PATCH_ATTEMPTS; attempt += 1) {
|
|
12220
12256
|
try {
|
|
12221
12257
|
await this.channel.updateCard(this.messageId, snapshot);
|
|
12258
|
+
this.recoveries = 0;
|
|
12222
12259
|
return;
|
|
12223
12260
|
} catch (error) {
|
|
12224
12261
|
lastError = error;
|
|
@@ -12227,6 +12264,19 @@ var ResilientCardStreamController = class {
|
|
|
12227
12264
|
attempt,
|
|
12228
12265
|
error: error instanceof Error ? error.message : String(error)
|
|
12229
12266
|
});
|
|
12267
|
+
if (isMessageWithdrawn(error) && this.recoveries < MAX_CARD_WITHDRAW_RECOVERIES) {
|
|
12268
|
+
try {
|
|
12269
|
+
await this.healFromWithdrawal();
|
|
12270
|
+
} catch (healError) {
|
|
12271
|
+
log.warn("lark-card-stream", "heal-failed", {
|
|
12272
|
+
messageId: this.messageId,
|
|
12273
|
+
error: healError instanceof Error ? healError.message : String(healError)
|
|
12274
|
+
});
|
|
12275
|
+
break;
|
|
12276
|
+
}
|
|
12277
|
+
attempt -= 1;
|
|
12278
|
+
continue;
|
|
12279
|
+
}
|
|
12230
12280
|
}
|
|
12231
12281
|
}
|
|
12232
12282
|
this.failed = true;
|
|
@@ -12246,6 +12296,26 @@ var ResilientCardStreamController = class {
|
|
|
12246
12296
|
});
|
|
12247
12297
|
}
|
|
12248
12298
|
}
|
|
12299
|
+
/**
|
|
12300
|
+
* Re-create the process card at the conversation tail after the target message
|
|
12301
|
+
* was withdrawn (Feishu `230011` / "The message was withdrawn"). The message
|
|
12302
|
+
* is already gone, so there is nothing to recall: we send a fresh card carrying
|
|
12303
|
+
* the latest snapshot and rebind the controller to its new message id. Unlike
|
|
12304
|
+
* `reanchor()` this must NOT `await this.inFlight`, because we are already
|
|
12305
|
+
* running inside the in-flight flush; the recovery budget
|
|
12306
|
+
* (`MAX_CARD_WITHDRAW_RECOVERIES`) is enforced by the caller so a hostile loop
|
|
12307
|
+
* cannot spawn cards forever.
|
|
12308
|
+
*/
|
|
12309
|
+
async healFromWithdrawal() {
|
|
12310
|
+
const card = this.latest;
|
|
12311
|
+
if (card === void 0) throw new Error("Feishu card re-creation has no snapshot to send");
|
|
12312
|
+
this.dirty = false;
|
|
12313
|
+
const sent = await this.channel.send(this.chatId, { card }, {});
|
|
12314
|
+
if (!sent.messageId) throw new Error("Feishu card re-creation returned no message_id");
|
|
12315
|
+
this.messageId = sent.messageId;
|
|
12316
|
+
this.failed = false;
|
|
12317
|
+
this.recoveries += 1;
|
|
12318
|
+
}
|
|
12249
12319
|
/**
|
|
12250
12320
|
* Recall the current card and re-create it as the newest top-level message in
|
|
12251
12321
|
* the chat, rebinding the controller to the fresh message id. Because Feishu
|