opencode-feishu 0.7.8 → 0.7.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/index.js +75 -147
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -99181,30 +99181,30 @@ var pendingBySession = /* @__PURE__ */ new Map();
|
|
|
99181
99181
|
var sessionErrors = /* @__PURE__ */ new Map();
|
|
99182
99182
|
var sessionErrorTimeouts = /* @__PURE__ */ new Map();
|
|
99183
99183
|
var SESSION_ERROR_TTL_MS = 3e4;
|
|
99184
|
-
var
|
|
99185
|
-
var
|
|
99186
|
-
var
|
|
99187
|
-
var
|
|
99188
|
-
function
|
|
99189
|
-
|
|
99190
|
-
const timer =
|
|
99184
|
+
var retryAttempts = /* @__PURE__ */ new Map();
|
|
99185
|
+
var retryAttemptTimeouts = /* @__PURE__ */ new Map();
|
|
99186
|
+
var MAX_RETRY_ATTEMPTS = 2;
|
|
99187
|
+
var RETRY_ATTEMPTS_TTL_MS = 36e5;
|
|
99188
|
+
function clearRetryAttempts(sessionKey) {
|
|
99189
|
+
retryAttempts.delete(sessionKey);
|
|
99190
|
+
const timer = retryAttemptTimeouts.get(sessionKey);
|
|
99191
99191
|
if (timer) {
|
|
99192
99192
|
clearTimeout(timer);
|
|
99193
|
-
|
|
99193
|
+
retryAttemptTimeouts.delete(sessionKey);
|
|
99194
99194
|
}
|
|
99195
99195
|
}
|
|
99196
|
-
function
|
|
99197
|
-
return
|
|
99196
|
+
function getRetryAttempts(sessionKey) {
|
|
99197
|
+
return retryAttempts.get(sessionKey) ?? 0;
|
|
99198
99198
|
}
|
|
99199
|
-
function
|
|
99200
|
-
|
|
99201
|
-
const existing =
|
|
99199
|
+
function setRetryAttempts(sessionKey, count) {
|
|
99200
|
+
retryAttempts.set(sessionKey, count);
|
|
99201
|
+
const existing = retryAttemptTimeouts.get(sessionKey);
|
|
99202
99202
|
if (existing) clearTimeout(existing);
|
|
99203
99203
|
const timeoutId = setTimeout(() => {
|
|
99204
|
-
|
|
99205
|
-
|
|
99206
|
-
},
|
|
99207
|
-
|
|
99204
|
+
retryAttempts.delete(sessionKey);
|
|
99205
|
+
retryAttemptTimeouts.delete(sessionKey);
|
|
99206
|
+
}, RETRY_ATTEMPTS_TTL_MS);
|
|
99207
|
+
retryAttemptTimeouts.set(sessionKey, timeoutId);
|
|
99208
99208
|
}
|
|
99209
99209
|
function getSessionError(sessionId) {
|
|
99210
99210
|
return sessionErrors.get(sessionId);
|
|
@@ -99314,22 +99314,8 @@ function extractPartText(part) {
|
|
|
99314
99314
|
var SESSION_KEY_PREFIX = "feishu";
|
|
99315
99315
|
var TITLE_PREFIX = "Feishu";
|
|
99316
99316
|
var sessionCache = /* @__PURE__ */ new Map();
|
|
99317
|
-
var sessionIdToKeyCache = /* @__PURE__ */ new Map();
|
|
99318
99317
|
function setCachedSession(sessionKey, session) {
|
|
99319
|
-
const oldSession = sessionCache.get(sessionKey);
|
|
99320
|
-
if (oldSession && oldSession.id !== session.id) {
|
|
99321
|
-
sessionIdToKeyCache.delete(oldSession.id);
|
|
99322
|
-
}
|
|
99323
99318
|
sessionCache.set(sessionKey, session);
|
|
99324
|
-
sessionIdToKeyCache.set(session.id, sessionKey);
|
|
99325
|
-
}
|
|
99326
|
-
function invalidateCachedSession(sessionId) {
|
|
99327
|
-
const sessionKey = sessionIdToKeyCache.get(sessionId);
|
|
99328
|
-
if (sessionKey) {
|
|
99329
|
-
sessionCache.delete(sessionKey);
|
|
99330
|
-
sessionIdToKeyCache.delete(sessionId);
|
|
99331
|
-
}
|
|
99332
|
-
return sessionKey;
|
|
99333
99319
|
}
|
|
99334
99320
|
function buildSessionKey(chatType, id) {
|
|
99335
99321
|
return `${SESSION_KEY_PREFIX}-${chatType}-${id}`;
|
|
@@ -99373,57 +99359,6 @@ async function getOrCreateSession(client, sessionKey, directory) {
|
|
|
99373
99359
|
setCachedSession(sessionKey, session);
|
|
99374
99360
|
return session;
|
|
99375
99361
|
}
|
|
99376
|
-
async function forkSession(client, oldSessionId, sessionKey, directory) {
|
|
99377
|
-
const query = directory ? { directory } : void 0;
|
|
99378
|
-
const resp = await client.session.fork({
|
|
99379
|
-
path: { id: oldSessionId },
|
|
99380
|
-
query,
|
|
99381
|
-
body: {}
|
|
99382
|
-
});
|
|
99383
|
-
if (!resp?.data?.id) {
|
|
99384
|
-
const err = resp?.error;
|
|
99385
|
-
throw new Error(
|
|
99386
|
-
`Fork \u4F1A\u8BDD\u5931\u8D25: ${err ? JSON.stringify(err) : "unknown"}`
|
|
99387
|
-
);
|
|
99388
|
-
}
|
|
99389
|
-
const title = generateSessionTitle(sessionKey);
|
|
99390
|
-
const updateResp = await client.session.update({
|
|
99391
|
-
path: { id: resp.data.id },
|
|
99392
|
-
query,
|
|
99393
|
-
body: { title }
|
|
99394
|
-
});
|
|
99395
|
-
if (!updateResp?.data?.id) {
|
|
99396
|
-
const err = updateResp?.error;
|
|
99397
|
-
throw new Error(
|
|
99398
|
-
`\u66F4\u65B0 forked session \u6807\u9898\u5931\u8D25: ${err ? JSON.stringify(err) : "unknown"}`
|
|
99399
|
-
);
|
|
99400
|
-
}
|
|
99401
|
-
return { id: resp.data.id, title };
|
|
99402
|
-
}
|
|
99403
|
-
async function createFreshSession(client, sessionKey, directory) {
|
|
99404
|
-
const query = directory ? { directory } : void 0;
|
|
99405
|
-
const title = generateSessionTitle(sessionKey);
|
|
99406
|
-
const resp = await client.session.create({ query, body: { title } });
|
|
99407
|
-
if (!resp?.data?.id) {
|
|
99408
|
-
const err = resp?.error;
|
|
99409
|
-
throw new Error(
|
|
99410
|
-
`\u521B\u5EFA\u65B0\u4F1A\u8BDD\u5931\u8D25: ${err ? JSON.stringify(err) : "unknown"}`
|
|
99411
|
-
);
|
|
99412
|
-
}
|
|
99413
|
-
return { id: resp.data.id, title: resp.data.title };
|
|
99414
|
-
}
|
|
99415
|
-
async function forkOrCreateSession(client, oldSessionId, sessionKey, directory, log) {
|
|
99416
|
-
try {
|
|
99417
|
-
return await forkSession(client, oldSessionId, sessionKey, directory);
|
|
99418
|
-
} catch (forkErr) {
|
|
99419
|
-
log?.("warn", "Fork \u5931\u8D25\uFF0C\u56DE\u9000\u5230\u521B\u5EFA\u65B0\u4F1A\u8BDD", {
|
|
99420
|
-
oldSessionId,
|
|
99421
|
-
sessionKey,
|
|
99422
|
-
error: forkErr instanceof Error ? forkErr.message : String(forkErr)
|
|
99423
|
-
});
|
|
99424
|
-
return await createFreshSession(client, sessionKey, directory);
|
|
99425
|
-
}
|
|
99426
|
-
}
|
|
99427
99362
|
|
|
99428
99363
|
// src/handler/chat.ts
|
|
99429
99364
|
var SSE_RACE_WAIT_MS = 100;
|
|
@@ -99542,7 +99477,7 @@ async function handleChat(ctx, deps) {
|
|
|
99542
99477
|
sessionId: session.id,
|
|
99543
99478
|
output: finalText || "(empty)"
|
|
99544
99479
|
});
|
|
99545
|
-
|
|
99480
|
+
clearRetryAttempts(sessionKey);
|
|
99546
99481
|
await replyOrUpdate(feishuClient, chatId, placeholderId, finalText || "\u26A0\uFE0F \u54CD\u5E94\u8D85\u65F6");
|
|
99547
99482
|
await runAutoPromptLoop(session.id);
|
|
99548
99483
|
} catch (err) {
|
|
@@ -99557,61 +99492,46 @@ async function handleChat(ctx, deps) {
|
|
|
99557
99492
|
}
|
|
99558
99493
|
}
|
|
99559
99494
|
if (sessionError && isModelError(sessionError.fields)) {
|
|
99560
|
-
const attempts =
|
|
99561
|
-
if (attempts <
|
|
99562
|
-
setForkAttempts(sessionKey, attempts + 1);
|
|
99495
|
+
const attempts = getRetryAttempts(sessionKey);
|
|
99496
|
+
if (attempts < MAX_RETRY_ATTEMPTS) {
|
|
99563
99497
|
try {
|
|
99564
|
-
|
|
99565
|
-
|
|
99566
|
-
|
|
99567
|
-
|
|
99568
|
-
|
|
99569
|
-
|
|
99570
|
-
modelOverride = await resolveLatestModel(client, sessionError.fields, directory);
|
|
99571
|
-
if (modelOverride) {
|
|
99572
|
-
log("info", "\u5DF2\u89E3\u6790\u964D\u7EA7\u6A21\u578B", {
|
|
99573
|
-
sessionKey,
|
|
99574
|
-
providerID: modelOverride.providerID,
|
|
99575
|
-
modelID: modelOverride.modelID
|
|
99576
|
-
});
|
|
99577
|
-
}
|
|
99578
|
-
} catch (modelErr) {
|
|
99579
|
-
log("warn", "\u89E3\u6790\u964D\u7EA7\u6A21\u578B\u5931\u8D25\uFF0C\u5C06\u4F7F\u7528\u9ED8\u8BA4\u6A21\u578B", {
|
|
99498
|
+
const modelOverride = await resolveLatestModel(client, sessionError.fields, directory);
|
|
99499
|
+
if (!modelOverride) {
|
|
99500
|
+
log("warn", "\u65E0\u4EFB\u4F55\u5DF2\u8FDE\u63A5 provider \u6709\u53EF\u7528\u6A21\u578B\uFF0C\u653E\u5F03\u6062\u590D", { sessionKey });
|
|
99501
|
+
} else {
|
|
99502
|
+
setRetryAttempts(sessionKey, attempts + 1);
|
|
99503
|
+
log("info", "\u5DF2\u89E3\u6790\u53EF\u7528\u6A21\u578B\uFF0C\u5728\u540C\u4E00 session \u4E0A\u91CD\u8BD5", {
|
|
99580
99504
|
sessionKey,
|
|
99581
|
-
|
|
99505
|
+
providerID: modelOverride.providerID,
|
|
99506
|
+
modelID: modelOverride.modelID
|
|
99582
99507
|
});
|
|
99508
|
+
await client.session.prompt({
|
|
99509
|
+
path: { id: session.id },
|
|
99510
|
+
query,
|
|
99511
|
+
body: { ...baseBody, model: modelOverride }
|
|
99512
|
+
});
|
|
99513
|
+
const finalText = await pollForResponse(client, session.id, { timeout, pollInterval, stablePolls, query });
|
|
99514
|
+
log("info", "\u6A21\u578B\u6062\u590D\u540E\u54CD\u5E94\u5B8C\u6210", {
|
|
99515
|
+
sessionKey,
|
|
99516
|
+
sessionId: session.id,
|
|
99517
|
+
output: finalText || "(empty)"
|
|
99518
|
+
});
|
|
99519
|
+
clearRetryAttempts(sessionKey);
|
|
99520
|
+
await replyOrUpdate(feishuClient, chatId, placeholderId, finalText || "\u26A0\uFE0F \u54CD\u5E94\u8D85\u65F6");
|
|
99521
|
+
log("info", "\u6A21\u578B\u4E0D\u517C\u5BB9\u6062\u590D\u6210\u529F", {
|
|
99522
|
+
sessionId: session.id,
|
|
99523
|
+
sessionKey,
|
|
99524
|
+
model: `${modelOverride.providerID}/${modelOverride.modelID}`,
|
|
99525
|
+
attempt: attempts + 1
|
|
99526
|
+
});
|
|
99527
|
+
await runAutoPromptLoop(session.id);
|
|
99528
|
+
return;
|
|
99583
99529
|
}
|
|
99584
|
-
unregisterPending(session.id);
|
|
99585
|
-
if (placeholderId) {
|
|
99586
|
-
registerPending(newSession.id, { chatId, placeholderId, feishuClient });
|
|
99587
|
-
}
|
|
99588
|
-
const retryBody = { ...baseBody, ...modelOverride ? { model: modelOverride } : {} };
|
|
99589
|
-
await client.session.prompt({
|
|
99590
|
-
path: { id: newSession.id },
|
|
99591
|
-
query,
|
|
99592
|
-
body: retryBody
|
|
99593
|
-
});
|
|
99594
|
-
const finalText = await pollForResponse(client, newSession.id, { timeout, pollInterval, stablePolls, query });
|
|
99595
|
-
log("info", "\u6062\u590D\u540E\u6A21\u578B\u54CD\u5E94\u5B8C\u6210", {
|
|
99596
|
-
sessionKey,
|
|
99597
|
-
newSessionId: newSession.id,
|
|
99598
|
-
output: finalText || "(empty)"
|
|
99599
|
-
});
|
|
99600
|
-
clearForkAttempts(sessionKey);
|
|
99601
|
-
await replyOrUpdate(feishuClient, chatId, placeholderId, finalText || "\u26A0\uFE0F \u54CD\u5E94\u8D85\u65F6");
|
|
99602
|
-
log("info", "\u6A21\u578B\u4E0D\u517C\u5BB9\u6062\u590D\u6210\u529F", {
|
|
99603
|
-
oldSessionId: session.id,
|
|
99604
|
-
newSessionId: newSession.id,
|
|
99605
|
-
sessionKey,
|
|
99606
|
-
forkAttempt: attempts + 1
|
|
99607
|
-
});
|
|
99608
|
-
await runAutoPromptLoop(newSession.id);
|
|
99609
|
-
return;
|
|
99610
99530
|
} catch (recoveryErr) {
|
|
99611
99531
|
const recoveryErrMsg = recoveryErr instanceof Error ? recoveryErr.message : String(recoveryErr);
|
|
99612
|
-
const
|
|
99613
|
-
if (
|
|
99614
|
-
sessionError =
|
|
99532
|
+
const retryError = getSessionError(session.id);
|
|
99533
|
+
if (retryError) clearSessionError(session.id);
|
|
99534
|
+
sessionError = retryError ?? { message: recoveryErrMsg, fields: [] };
|
|
99615
99535
|
log("error", "\u6A21\u578B\u6062\u590D\u5931\u8D25", {
|
|
99616
99536
|
sessionId: session.id,
|
|
99617
99537
|
sessionKey,
|
|
@@ -99619,7 +99539,7 @@ async function handleChat(ctx, deps) {
|
|
|
99619
99539
|
});
|
|
99620
99540
|
}
|
|
99621
99541
|
} else {
|
|
99622
|
-
log("warn", "\u5DF2\u8FBE
|
|
99542
|
+
log("warn", "\u5DF2\u8FBE\u91CD\u8BD5\u4E0A\u9650\uFF0C\u653E\u5F03\u6062\u590D", {
|
|
99623
99543
|
sessionKey,
|
|
99624
99544
|
attempts
|
|
99625
99545
|
});
|
|
@@ -99643,23 +99563,31 @@ async function handleChat(ctx, deps) {
|
|
|
99643
99563
|
}
|
|
99644
99564
|
}
|
|
99645
99565
|
async function resolveLatestModel(client, errorFields, directory) {
|
|
99646
|
-
const pattern = /model
|
|
99647
|
-
const
|
|
99648
|
-
|
|
99649
|
-
const
|
|
99566
|
+
const pattern = /model\s*not\s*found:?\s*(\w[\w-]*)\/(\S+)/i;
|
|
99567
|
+
const match = errorFields.map((f) => pattern.exec(f)).find(Boolean);
|
|
99568
|
+
const failedProviderID = match?.[1]?.toLowerCase();
|
|
99569
|
+
const failedModelID = match?.[2]?.replace(/\.$/, "");
|
|
99650
99570
|
const query = directory ? { directory } : void 0;
|
|
99651
99571
|
const { data } = await client.provider.list({ query });
|
|
99652
99572
|
if (!data) return void 0;
|
|
99653
|
-
const
|
|
99654
|
-
if (
|
|
99655
|
-
|
|
99573
|
+
const connectedProviders = data.connected ?? [];
|
|
99574
|
+
if (connectedProviders.length === 0) return void 0;
|
|
99575
|
+
for (const pid of connectedProviders) {
|
|
99576
|
+
const defaultModelID = data.default?.[pid];
|
|
99577
|
+
if (defaultModelID && !(pid === failedProviderID && defaultModelID === failedModelID)) {
|
|
99578
|
+
return { providerID: pid, modelID: defaultModelID };
|
|
99579
|
+
}
|
|
99580
|
+
}
|
|
99581
|
+
for (const pid of connectedProviders) {
|
|
99582
|
+
const provider = data.all?.find((p) => p.id === pid);
|
|
99583
|
+
if (!provider?.models) continue;
|
|
99584
|
+
const candidates = Object.values(provider.models).filter((m) => m.status !== "deprecated" && !(pid === failedProviderID && m.id === failedModelID)).sort((a, b) => b.release_date.localeCompare(a.release_date));
|
|
99585
|
+
if (candidates.length > 0) {
|
|
99586
|
+
const best = candidates.find((m) => m.tool_call) ?? candidates[0];
|
|
99587
|
+
return { providerID: pid, modelID: best.id };
|
|
99588
|
+
}
|
|
99656
99589
|
}
|
|
99657
|
-
|
|
99658
|
-
if (!provider?.models) return void 0;
|
|
99659
|
-
const sortedModels = Object.values(provider.models).filter((m) => m.status !== "deprecated").sort((a, b) => b.release_date.localeCompare(a.release_date));
|
|
99660
|
-
if (sortedModels.length === 0) return void 0;
|
|
99661
|
-
const best = sortedModels.find((m) => m.tool_call) ?? sortedModels[0];
|
|
99662
|
-
return { providerID, modelID: best.id };
|
|
99590
|
+
return void 0;
|
|
99663
99591
|
}
|
|
99664
99592
|
async function buildPromptParts(feishuClient, messageId, messageType, rawContent, textContent, chatType, senderId, log) {
|
|
99665
99593
|
if (messageType === "text") {
|
|
@@ -99932,7 +99860,7 @@ var FeishuPlugin = async (ctx) => {
|
|
|
99932
99860
|
const hooks = {
|
|
99933
99861
|
event: async ({ event }) => {
|
|
99934
99862
|
if (!gateway) return;
|
|
99935
|
-
await handleEvent(event, {
|
|
99863
|
+
await handleEvent(event, { log, directory: resolvedConfig.directory });
|
|
99936
99864
|
}
|
|
99937
99865
|
};
|
|
99938
99866
|
return hooks;
|