opencode-feishu 0.7.5 → 0.7.6
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/index.js +70 -22
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -99292,10 +99292,14 @@ async function forkOrCreateSession(client, oldSessionId, sessionKey, directory,
|
|
|
99292
99292
|
}
|
|
99293
99293
|
|
|
99294
99294
|
// src/handler/event.ts
|
|
99295
|
+
function maskKey(sessionKey) {
|
|
99296
|
+
return sessionKey.replace(/-[^-]+$/, "-***");
|
|
99297
|
+
}
|
|
99295
99298
|
var pendingBySession = /* @__PURE__ */ new Map();
|
|
99296
99299
|
var sessionErrors = /* @__PURE__ */ new Map();
|
|
99297
99300
|
var sessionErrorTimeouts = /* @__PURE__ */ new Map();
|
|
99298
99301
|
var SESSION_ERROR_TTL_MS = 3e4;
|
|
99302
|
+
var modelOverrides = /* @__PURE__ */ new Map();
|
|
99299
99303
|
var forkAttempts = /* @__PURE__ */ new Map();
|
|
99300
99304
|
var forkAttemptTimeouts = /* @__PURE__ */ new Map();
|
|
99301
99305
|
var MAX_FORK_ATTEMPTS = 2;
|
|
@@ -99318,6 +99322,12 @@ function setForkAttempts(sessionKey, count) {
|
|
|
99318
99322
|
}, FORK_ATTEMPTS_TTL_MS);
|
|
99319
99323
|
forkAttemptTimeouts.set(sessionKey, timeoutId);
|
|
99320
99324
|
}
|
|
99325
|
+
function getModelOverride(sessionKey) {
|
|
99326
|
+
return modelOverrides.get(sessionKey);
|
|
99327
|
+
}
|
|
99328
|
+
function clearModelOverride(sessionKey) {
|
|
99329
|
+
modelOverrides.delete(sessionKey);
|
|
99330
|
+
}
|
|
99321
99331
|
function getSessionError(sessionId) {
|
|
99322
99332
|
return sessionErrors.get(sessionId);
|
|
99323
99333
|
}
|
|
@@ -99354,19 +99364,26 @@ function migratePending(oldSessionId, newSessionId) {
|
|
|
99354
99364
|
pendingBySession.set(newSessionId, payload);
|
|
99355
99365
|
}
|
|
99356
99366
|
}
|
|
99357
|
-
function
|
|
99358
|
-
if (
|
|
99359
|
-
|
|
99360
|
-
|
|
99361
|
-
if (rawError && typeof rawError === "object") {
|
|
99362
|
-
const e = rawError;
|
|
99367
|
+
function extractErrorFields(error) {
|
|
99368
|
+
if (typeof error === "string") return [error];
|
|
99369
|
+
if (error && typeof error === "object") {
|
|
99370
|
+
const e = error;
|
|
99363
99371
|
const fields = [e.type, e.name, e.message].filter(Boolean).map(String);
|
|
99364
99372
|
if (e.data && typeof e.data === "object" && "message" in e.data) {
|
|
99365
99373
|
const dataMsg = e.data.message;
|
|
99366
99374
|
if (dataMsg) fields.push(String(dataMsg));
|
|
99367
99375
|
}
|
|
99368
|
-
return fields
|
|
99376
|
+
return fields;
|
|
99369
99377
|
}
|
|
99378
|
+
return [String(error)];
|
|
99379
|
+
}
|
|
99380
|
+
function isModelError(errMsg, rawError) {
|
|
99381
|
+
const check = (s) => {
|
|
99382
|
+
const l = s.toLowerCase();
|
|
99383
|
+
return l.includes("model not found") || l.includes("modelnotfound");
|
|
99384
|
+
};
|
|
99385
|
+
if (check(errMsg)) return true;
|
|
99386
|
+
if (rawError) return extractErrorFields(rawError).some(check);
|
|
99370
99387
|
return false;
|
|
99371
99388
|
}
|
|
99372
99389
|
async function handleEvent(event, deps) {
|
|
@@ -99409,39 +99426,47 @@ async function handleEvent(event, deps) {
|
|
|
99409
99426
|
} else {
|
|
99410
99427
|
errMsg = String(error);
|
|
99411
99428
|
}
|
|
99412
|
-
|
|
99413
|
-
type: error.type,
|
|
99414
|
-
name: error.name,
|
|
99415
|
-
dataMessage: error.data?.message
|
|
99416
|
-
} : { raw: String(error) };
|
|
99417
|
-
deps.log("warn", "\u6536\u5230 session.error \u4E8B\u4EF6", {
|
|
99418
|
-
sessionId,
|
|
99419
|
-
error: safeErrorFields,
|
|
99420
|
-
extractedMsg: errMsg
|
|
99421
|
-
});
|
|
99429
|
+
deps.log("warn", "\u6536\u5230 session.error \u4E8B\u4EF6", { sessionId, errMsg });
|
|
99422
99430
|
setSessionError(sessionId, errMsg);
|
|
99423
99431
|
if (isModelError(errMsg, props.error)) {
|
|
99424
99432
|
const sessionKey = invalidateCachedSession(sessionId);
|
|
99425
99433
|
if (sessionKey) {
|
|
99426
99434
|
const attempts = forkAttempts.get(sessionKey) ?? 0;
|
|
99427
99435
|
if (attempts >= MAX_FORK_ATTEMPTS) {
|
|
99428
|
-
deps.log("warn", "\u5DF2\u8FBE fork \u4E0A\u9650\uFF0C\u653E\u5F03\u6062\u590D", { sessionKey, attempts });
|
|
99436
|
+
deps.log("warn", "\u5DF2\u8FBE fork \u4E0A\u9650\uFF0C\u653E\u5F03\u6062\u590D", { sessionKey: maskKey(sessionKey), attempts });
|
|
99429
99437
|
} else {
|
|
99430
99438
|
setForkAttempts(sessionKey, attempts + 1);
|
|
99431
99439
|
try {
|
|
99432
99440
|
const newSession = await forkOrCreateSession(deps.client, sessionId, sessionKey, deps.directory, deps.log);
|
|
99433
99441
|
setCachedSession(sessionKey, newSession);
|
|
99442
|
+
modelOverrides.delete(sessionKey);
|
|
99443
|
+
try {
|
|
99444
|
+
const fallbackModel = await resolveLatestModel(deps.client, props.error ?? errMsg, deps.directory);
|
|
99445
|
+
if (fallbackModel) {
|
|
99446
|
+
modelOverrides.set(sessionKey, fallbackModel);
|
|
99447
|
+
deps.log("info", "\u5DF2\u89E3\u6790\u964D\u7EA7\u6A21\u578B", {
|
|
99448
|
+
sessionKey: maskKey(sessionKey),
|
|
99449
|
+
providerID: fallbackModel.providerID,
|
|
99450
|
+
modelID: fallbackModel.modelID
|
|
99451
|
+
});
|
|
99452
|
+
}
|
|
99453
|
+
} catch (modelErr) {
|
|
99454
|
+
deps.log("warn", "\u89E3\u6790\u964D\u7EA7\u6A21\u578B\u5931\u8D25\uFF0C\u5C06\u4F7F\u7528\u9ED8\u8BA4\u6A21\u578B", {
|
|
99455
|
+
sessionKey: maskKey(sessionKey),
|
|
99456
|
+
error: modelErr instanceof Error ? modelErr.message : String(modelErr)
|
|
99457
|
+
});
|
|
99458
|
+
}
|
|
99434
99459
|
deps.log("warn", "\u6A21\u578B\u4E0D\u517C\u5BB9\uFF0C\u5DF2\u6062\u590D\u4F1A\u8BDD", {
|
|
99435
99460
|
oldSessionId: sessionId,
|
|
99436
99461
|
newSessionId: newSession.id,
|
|
99437
|
-
sessionKey,
|
|
99462
|
+
sessionKey: maskKey(sessionKey),
|
|
99438
99463
|
forkAttempt: attempts + 1
|
|
99439
99464
|
});
|
|
99440
99465
|
migratePending(sessionId, newSession.id);
|
|
99441
99466
|
} catch (recoverErr) {
|
|
99442
99467
|
deps.log("error", "\u4F1A\u8BDD\u6062\u590D\u5931\u8D25", {
|
|
99443
99468
|
sessionId,
|
|
99444
|
-
sessionKey,
|
|
99469
|
+
sessionKey: maskKey(sessionKey),
|
|
99445
99470
|
error: recoverErr instanceof Error ? recoverErr.message : String(recoverErr)
|
|
99446
99471
|
});
|
|
99447
99472
|
}
|
|
@@ -99452,6 +99477,26 @@ async function handleEvent(event, deps) {
|
|
|
99452
99477
|
}
|
|
99453
99478
|
}
|
|
99454
99479
|
}
|
|
99480
|
+
async function resolveLatestModel(client, rawError, directory) {
|
|
99481
|
+
const pattern = /model not found:?\s*(\w[\w-]*)\//i;
|
|
99482
|
+
const fields = extractErrorFields(rawError);
|
|
99483
|
+
const rawProviderID = fields.map((f) => pattern.exec(f)?.[1]).find(Boolean);
|
|
99484
|
+
if (!rawProviderID) return void 0;
|
|
99485
|
+
const providerID = rawProviderID.toLowerCase();
|
|
99486
|
+
const query = directory ? { directory } : void 0;
|
|
99487
|
+
const { data } = await client.provider.list({ query });
|
|
99488
|
+
if (!data) return void 0;
|
|
99489
|
+
const defaultModelID = data.default?.[providerID];
|
|
99490
|
+
if (defaultModelID) {
|
|
99491
|
+
return { providerID, modelID: defaultModelID };
|
|
99492
|
+
}
|
|
99493
|
+
const provider = data.all?.find((p) => p.id === providerID);
|
|
99494
|
+
if (!provider?.models) return void 0;
|
|
99495
|
+
const sortedModels = Object.values(provider.models).filter((m) => m.status !== "deprecated").sort((a, b) => b.release_date.localeCompare(a.release_date));
|
|
99496
|
+
if (sortedModels.length === 0) return void 0;
|
|
99497
|
+
const best = sortedModels.find((m) => m.tool_call) ?? sortedModels[0];
|
|
99498
|
+
return { providerID, modelID: best.id };
|
|
99499
|
+
}
|
|
99455
99500
|
function extractPartText(part) {
|
|
99456
99501
|
if (part.type === "text") return part.text ?? "";
|
|
99457
99502
|
if (part.type === "reasoning" && part.text) return `\u{1F914} \u601D\u8003: ${part.text}
|
|
@@ -99487,12 +99532,14 @@ async function handleChat(ctx, deps) {
|
|
|
99487
99532
|
shouldReply,
|
|
99488
99533
|
parts
|
|
99489
99534
|
});
|
|
99535
|
+
const modelOverride = getModelOverride(sessionKey);
|
|
99536
|
+
const baseBody = { parts, ...modelOverride ? { model: modelOverride } : {} };
|
|
99490
99537
|
if (!shouldReply) {
|
|
99491
99538
|
try {
|
|
99492
99539
|
await client.session.prompt({
|
|
99493
99540
|
path: { id: session.id },
|
|
99494
99541
|
query,
|
|
99495
|
-
body: {
|
|
99542
|
+
body: { ...baseBody, noReply: true }
|
|
99496
99543
|
});
|
|
99497
99544
|
} catch (err) {
|
|
99498
99545
|
log("warn", "\u9759\u9ED8\u8F6C\u53D1\u5931\u8D25", {
|
|
@@ -99527,10 +99574,11 @@ async function handleChat(ctx, deps) {
|
|
|
99527
99574
|
await client.session.prompt({
|
|
99528
99575
|
path: { id: session.id },
|
|
99529
99576
|
query,
|
|
99530
|
-
body:
|
|
99577
|
+
body: baseBody
|
|
99531
99578
|
});
|
|
99532
99579
|
const finalText = await pollForResponse(client, session.id, { timeout, pollInterval, stablePolls, query });
|
|
99533
99580
|
clearForkAttempts(sessionKey);
|
|
99581
|
+
clearModelOverride(sessionKey);
|
|
99534
99582
|
await replyOrUpdate(feishuClient, chatId, placeholderId, finalText || "\u26A0\uFE0F \u54CD\u5E94\u8D85\u65F6");
|
|
99535
99583
|
const { autoPrompt } = config;
|
|
99536
99584
|
if (autoPrompt.enabled && shouldReply) {
|