opencode-feishu 0.5.1 → 0.6.1
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 +87 -14
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -99178,6 +99178,17 @@ async function updateMessage(client, messageId, text2) {
|
|
|
99178
99178
|
|
|
99179
99179
|
// src/handler/event.ts
|
|
99180
99180
|
var pendingBySession = /* @__PURE__ */ new Map();
|
|
99181
|
+
var sessionErrors = /* @__PURE__ */ new Map();
|
|
99182
|
+
function trackSessionError(sessionId, error) {
|
|
99183
|
+
if (error.includes("ModelNotFound") || error.includes("ProviderModelNotFound")) {
|
|
99184
|
+
sessionErrors.set(sessionId, error);
|
|
99185
|
+
}
|
|
99186
|
+
}
|
|
99187
|
+
function consumeSessionError(sessionId) {
|
|
99188
|
+
const err = sessionErrors.get(sessionId);
|
|
99189
|
+
if (err) sessionErrors.delete(sessionId);
|
|
99190
|
+
return err;
|
|
99191
|
+
}
|
|
99181
99192
|
function registerPending(sessionId, payload) {
|
|
99182
99193
|
pendingBySession.set(sessionId, { ...payload, textBuffer: "" });
|
|
99183
99194
|
}
|
|
@@ -99212,9 +99223,10 @@ async function handleEvent(event) {
|
|
|
99212
99223
|
const props = event.properties;
|
|
99213
99224
|
const sessionId = props.sessionID;
|
|
99214
99225
|
if (!sessionId) break;
|
|
99226
|
+
const errMsg = props.error?.message ?? String(props.error);
|
|
99227
|
+
trackSessionError(sessionId, errMsg);
|
|
99215
99228
|
const payload = pendingBySession.get(sessionId);
|
|
99216
99229
|
if (!payload) break;
|
|
99217
|
-
const errMsg = props.error?.message ?? String(props.error);
|
|
99218
99230
|
const updateRes = await updateMessage(payload.feishuClient, payload.placeholderId, `\u274C \u4F1A\u8BDD\u9519\u8BEF: ${errMsg}`);
|
|
99219
99231
|
if (!updateRes.ok) {
|
|
99220
99232
|
await sendTextMessage(payload.feishuClient, payload.chatId, `\u274C \u4F1A\u8BDD\u9519\u8BEF: ${errMsg}`);
|
|
@@ -99237,6 +99249,9 @@ var TITLE_PREFIX = "Feishu";
|
|
|
99237
99249
|
function buildSessionKey(chatType, id) {
|
|
99238
99250
|
return `${SESSION_KEY_PREFIX}-${chatType}-${id}`;
|
|
99239
99251
|
}
|
|
99252
|
+
function generateSessionTitle(sessionKey) {
|
|
99253
|
+
return `${TITLE_PREFIX}-${sessionKey}-${Date.now()}`;
|
|
99254
|
+
}
|
|
99240
99255
|
async function getOrCreateSession(client, sessionKey, directory) {
|
|
99241
99256
|
const titlePrefix = `${TITLE_PREFIX}-${sessionKey}-`;
|
|
99242
99257
|
const query = directory ? { directory } : void 0;
|
|
@@ -99255,7 +99270,7 @@ async function getOrCreateSession(client, sessionKey, directory) {
|
|
|
99255
99270
|
if (best?.id) return { id: best.id, title: best.title };
|
|
99256
99271
|
}
|
|
99257
99272
|
}
|
|
99258
|
-
const title =
|
|
99273
|
+
const title = generateSessionTitle(sessionKey);
|
|
99259
99274
|
const createResp = await client.session.create({ query, body: { title } });
|
|
99260
99275
|
if (!createResp?.data?.id) {
|
|
99261
99276
|
const err = createResp?.error;
|
|
@@ -99265,6 +99280,33 @@ async function getOrCreateSession(client, sessionKey, directory) {
|
|
|
99265
99280
|
}
|
|
99266
99281
|
return { id: createResp.data.id, title: createResp.data.title };
|
|
99267
99282
|
}
|
|
99283
|
+
async function forkSession(client, oldSessionId, sessionKey, directory) {
|
|
99284
|
+
const query = directory ? { directory } : void 0;
|
|
99285
|
+
const resp = await client.session.fork({
|
|
99286
|
+
path: { id: oldSessionId },
|
|
99287
|
+
query,
|
|
99288
|
+
body: {}
|
|
99289
|
+
});
|
|
99290
|
+
if (!resp?.data?.id) {
|
|
99291
|
+
const err = resp?.error;
|
|
99292
|
+
throw new Error(
|
|
99293
|
+
`Fork \u4F1A\u8BDD\u5931\u8D25: ${err ? JSON.stringify(err) : "unknown"}`
|
|
99294
|
+
);
|
|
99295
|
+
}
|
|
99296
|
+
const title = generateSessionTitle(sessionKey);
|
|
99297
|
+
const updateResp = await client.session.update({
|
|
99298
|
+
path: { id: resp.data.id },
|
|
99299
|
+
query,
|
|
99300
|
+
body: { title }
|
|
99301
|
+
});
|
|
99302
|
+
if (!updateResp?.data?.id) {
|
|
99303
|
+
const err = updateResp?.error;
|
|
99304
|
+
throw new Error(
|
|
99305
|
+
`\u66F4\u65B0 forked session \u6807\u9898\u5931\u8D25: ${err ? JSON.stringify(err) : "unknown"}`
|
|
99306
|
+
);
|
|
99307
|
+
}
|
|
99308
|
+
return { id: resp.data.id, title };
|
|
99309
|
+
}
|
|
99268
99310
|
|
|
99269
99311
|
// src/handler/chat.ts
|
|
99270
99312
|
var activeAutoPrompts = /* @__PURE__ */ new Map();
|
|
@@ -99280,18 +99322,19 @@ async function handleChat(ctx, deps) {
|
|
|
99280
99322
|
activeAutoPrompts.delete(sessionKey);
|
|
99281
99323
|
log("info", "\u7528\u6237\u4ECB\u5165\uFF0C\u81EA\u52A8\u63D0\u793A\u5DF2\u4E2D\u65AD", { sessionKey });
|
|
99282
99324
|
}
|
|
99283
|
-
|
|
99325
|
+
let session = await getOrCreateSession(client, sessionKey, directory);
|
|
99284
99326
|
const parts = await buildPromptParts(feishuClient, messageId, messageType, rawContent, content, chatType, senderId, log);
|
|
99285
99327
|
if (!parts.length) return;
|
|
99286
99328
|
if (!shouldReply) {
|
|
99287
99329
|
try {
|
|
99288
|
-
await
|
|
99289
|
-
|
|
99330
|
+
session = await promptWithForkRecovery({
|
|
99331
|
+
client,
|
|
99332
|
+
session,
|
|
99333
|
+
sessionKey,
|
|
99334
|
+
directory,
|
|
99290
99335
|
query,
|
|
99291
|
-
|
|
99292
|
-
|
|
99293
|
-
noReply: true
|
|
99294
|
-
}
|
|
99336
|
+
log,
|
|
99337
|
+
body: { parts, noReply: true }
|
|
99295
99338
|
});
|
|
99296
99339
|
} catch (err) {
|
|
99297
99340
|
log("warn", "\u9759\u9ED8\u8F6C\u53D1\u5931\u8D25", {
|
|
@@ -99306,6 +99349,7 @@ async function handleChat(ctx, deps) {
|
|
|
99306
99349
|
const stablePolls = config.stablePolls;
|
|
99307
99350
|
let placeholderId = "";
|
|
99308
99351
|
let done = false;
|
|
99352
|
+
let oldSessionId = session.id;
|
|
99309
99353
|
const timer = thinkingDelay > 0 ? setTimeout(async () => {
|
|
99310
99354
|
if (done) return;
|
|
99311
99355
|
try {
|
|
@@ -99323,13 +99367,21 @@ async function handleChat(ctx, deps) {
|
|
|
99323
99367
|
}
|
|
99324
99368
|
}, thinkingDelay) : null;
|
|
99325
99369
|
try {
|
|
99326
|
-
await
|
|
99327
|
-
|
|
99370
|
+
session = await promptWithForkRecovery({
|
|
99371
|
+
client,
|
|
99372
|
+
session,
|
|
99373
|
+
sessionKey,
|
|
99374
|
+
directory,
|
|
99328
99375
|
query,
|
|
99329
|
-
|
|
99330
|
-
|
|
99331
|
-
}
|
|
99376
|
+
log,
|
|
99377
|
+
body: { parts }
|
|
99332
99378
|
});
|
|
99379
|
+
if (session.id !== oldSessionId) {
|
|
99380
|
+
unregisterPending(oldSessionId);
|
|
99381
|
+
if (placeholderId) {
|
|
99382
|
+
registerPending(session.id, { chatId, placeholderId, feishuClient });
|
|
99383
|
+
}
|
|
99384
|
+
}
|
|
99333
99385
|
const finalText = await pollForResponse(client, session.id, { timeout, pollInterval, stablePolls, query });
|
|
99334
99386
|
await replyOrUpdate(feishuClient, chatId, placeholderId, finalText || "\u26A0\uFE0F \u54CD\u5E94\u8D85\u65F6");
|
|
99335
99387
|
const { autoPrompt } = config;
|
|
@@ -99375,6 +99427,7 @@ async function handleChat(ctx, deps) {
|
|
|
99375
99427
|
done = true;
|
|
99376
99428
|
if (timer) clearTimeout(timer);
|
|
99377
99429
|
unregisterPending(session.id);
|
|
99430
|
+
if (session.id !== oldSessionId) unregisterPending(oldSessionId);
|
|
99378
99431
|
}
|
|
99379
99432
|
}
|
|
99380
99433
|
async function buildPromptParts(feishuClient, messageId, messageType, rawContent, textContent, chatType, senderId, log) {
|
|
@@ -99446,6 +99499,26 @@ function abortableSleep(ms, signal) {
|
|
|
99446
99499
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
99447
99500
|
});
|
|
99448
99501
|
}
|
|
99502
|
+
function isModelNotFoundError(err, sessionId) {
|
|
99503
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
99504
|
+
const tracked = consumeSessionError(sessionId);
|
|
99505
|
+
if (msg.includes("ProviderModelNotFound") || msg.includes("ModelNotFound")) return true;
|
|
99506
|
+
return !!tracked;
|
|
99507
|
+
}
|
|
99508
|
+
async function promptWithForkRecovery(opts) {
|
|
99509
|
+
const { client, sessionKey, directory, query, log, body } = opts;
|
|
99510
|
+
let { session } = opts;
|
|
99511
|
+
const doPrompt = (s) => client.session.prompt({ path: { id: s.id }, query, body });
|
|
99512
|
+
try {
|
|
99513
|
+
await doPrompt(session);
|
|
99514
|
+
} catch (err) {
|
|
99515
|
+
if (!isModelNotFoundError(err, session.id)) throw err;
|
|
99516
|
+
log("warn", "\u4F1A\u8BDD\u6A21\u578B\u4E0D\u517C\u5BB9\uFF0Cfork \u65E7\u4F1A\u8BDD\u91CD\u8BD5", { oldSessionId: session.id });
|
|
99517
|
+
session = await forkSession(client, session.id, sessionKey, directory);
|
|
99518
|
+
await doPrompt(session);
|
|
99519
|
+
}
|
|
99520
|
+
return session;
|
|
99521
|
+
}
|
|
99449
99522
|
function extractLastAssistantText(messages) {
|
|
99450
99523
|
const assistant = messages.filter((m) => m.info?.role === "assistant").pop();
|
|
99451
99524
|
const parts = assistant?.parts ?? [];
|