opencode-feishu 0.5.0 → 0.6.0

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 CHANGED
@@ -99237,6 +99237,9 @@ var TITLE_PREFIX = "Feishu";
99237
99237
  function buildSessionKey(chatType, id) {
99238
99238
  return `${SESSION_KEY_PREFIX}-${chatType}-${id}`;
99239
99239
  }
99240
+ function generateSessionTitle(sessionKey) {
99241
+ return `${TITLE_PREFIX}-${sessionKey}-${Date.now()}`;
99242
+ }
99240
99243
  async function getOrCreateSession(client, sessionKey, directory) {
99241
99244
  const titlePrefix = `${TITLE_PREFIX}-${sessionKey}-`;
99242
99245
  const query = directory ? { directory } : void 0;
@@ -99255,7 +99258,7 @@ async function getOrCreateSession(client, sessionKey, directory) {
99255
99258
  if (best?.id) return { id: best.id, title: best.title };
99256
99259
  }
99257
99260
  }
99258
- const title = `${titlePrefix}${Date.now()}`;
99261
+ const title = generateSessionTitle(sessionKey);
99259
99262
  const createResp = await client.session.create({ query, body: { title } });
99260
99263
  if (!createResp?.data?.id) {
99261
99264
  const err = createResp?.error;
@@ -99265,6 +99268,33 @@ async function getOrCreateSession(client, sessionKey, directory) {
99265
99268
  }
99266
99269
  return { id: createResp.data.id, title: createResp.data.title };
99267
99270
  }
99271
+ async function forkSession(client, oldSessionId, sessionKey, directory) {
99272
+ const query = directory ? { directory } : void 0;
99273
+ const resp = await client.session.fork({
99274
+ path: { id: oldSessionId },
99275
+ query,
99276
+ body: {}
99277
+ });
99278
+ if (!resp?.data?.id) {
99279
+ const err = resp?.error;
99280
+ throw new Error(
99281
+ `Fork \u4F1A\u8BDD\u5931\u8D25: ${err ? JSON.stringify(err) : "unknown"}`
99282
+ );
99283
+ }
99284
+ const title = generateSessionTitle(sessionKey);
99285
+ const updateResp = await client.session.update({
99286
+ path: { id: resp.data.id },
99287
+ query,
99288
+ body: { title }
99289
+ });
99290
+ if (!updateResp?.data?.id) {
99291
+ const err = updateResp?.error;
99292
+ throw new Error(
99293
+ `\u66F4\u65B0 forked session \u6807\u9898\u5931\u8D25: ${err ? JSON.stringify(err) : "unknown"}`
99294
+ );
99295
+ }
99296
+ return { id: resp.data.id, title };
99297
+ }
99268
99298
 
99269
99299
  // src/handler/chat.ts
99270
99300
  var activeAutoPrompts = /* @__PURE__ */ new Map();
@@ -99280,18 +99310,19 @@ async function handleChat(ctx, deps) {
99280
99310
  activeAutoPrompts.delete(sessionKey);
99281
99311
  log("info", "\u7528\u6237\u4ECB\u5165\uFF0C\u81EA\u52A8\u63D0\u793A\u5DF2\u4E2D\u65AD", { sessionKey });
99282
99312
  }
99283
- const session = await getOrCreateSession(client, sessionKey, directory);
99313
+ let session = await getOrCreateSession(client, sessionKey, directory);
99284
99314
  const parts = await buildPromptParts(feishuClient, messageId, messageType, rawContent, content, chatType, senderId, log);
99285
99315
  if (!parts.length) return;
99286
99316
  if (!shouldReply) {
99287
99317
  try {
99288
- await client.session.prompt({
99289
- path: { id: session.id },
99318
+ session = await promptWithForkRecovery({
99319
+ client,
99320
+ session,
99321
+ sessionKey,
99322
+ directory,
99290
99323
  query,
99291
- body: {
99292
- parts,
99293
- noReply: true
99294
- }
99324
+ log,
99325
+ body: { parts, noReply: true }
99295
99326
  });
99296
99327
  } catch (err) {
99297
99328
  log("warn", "\u9759\u9ED8\u8F6C\u53D1\u5931\u8D25", {
@@ -99306,6 +99337,7 @@ async function handleChat(ctx, deps) {
99306
99337
  const stablePolls = config.stablePolls;
99307
99338
  let placeholderId = "";
99308
99339
  let done = false;
99340
+ let oldSessionId = session.id;
99309
99341
  const timer = thinkingDelay > 0 ? setTimeout(async () => {
99310
99342
  if (done) return;
99311
99343
  try {
@@ -99323,13 +99355,21 @@ async function handleChat(ctx, deps) {
99323
99355
  }
99324
99356
  }, thinkingDelay) : null;
99325
99357
  try {
99326
- await client.session.prompt({
99327
- path: { id: session.id },
99358
+ session = await promptWithForkRecovery({
99359
+ client,
99360
+ session,
99361
+ sessionKey,
99362
+ directory,
99328
99363
  query,
99329
- body: {
99330
- parts
99331
- }
99364
+ log,
99365
+ body: { parts }
99332
99366
  });
99367
+ if (session.id !== oldSessionId) {
99368
+ unregisterPending(oldSessionId);
99369
+ if (placeholderId) {
99370
+ registerPending(session.id, { chatId, placeholderId, feishuClient });
99371
+ }
99372
+ }
99333
99373
  const finalText = await pollForResponse(client, session.id, { timeout, pollInterval, stablePolls, query });
99334
99374
  await replyOrUpdate(feishuClient, chatId, placeholderId, finalText || "\u26A0\uFE0F \u54CD\u5E94\u8D85\u65F6");
99335
99375
  const { autoPrompt } = config;
@@ -99375,6 +99415,7 @@ async function handleChat(ctx, deps) {
99375
99415
  done = true;
99376
99416
  if (timer) clearTimeout(timer);
99377
99417
  unregisterPending(session.id);
99418
+ if (session.id !== oldSessionId) unregisterPending(oldSessionId);
99378
99419
  }
99379
99420
  }
99380
99421
  async function buildPromptParts(feishuClient, messageId, messageType, rawContent, textContent, chatType, senderId, log) {
@@ -99446,6 +99487,24 @@ function abortableSleep(ms, signal) {
99446
99487
  signal.addEventListener("abort", onAbort, { once: true });
99447
99488
  });
99448
99489
  }
99490
+ function isModelNotFoundError(err) {
99491
+ const msg = err instanceof Error ? err.message : String(err);
99492
+ return msg.includes("ProviderModelNotFound") || msg.includes("ModelNotFound");
99493
+ }
99494
+ async function promptWithForkRecovery(opts) {
99495
+ const { client, sessionKey, directory, query, log, body } = opts;
99496
+ let { session } = opts;
99497
+ const doPrompt = (s) => client.session.prompt({ path: { id: s.id }, query, body });
99498
+ try {
99499
+ await doPrompt(session);
99500
+ } catch (err) {
99501
+ if (!isModelNotFoundError(err)) throw err;
99502
+ log("warn", "\u4F1A\u8BDD\u6A21\u578B\u4E0D\u517C\u5BB9\uFF0Cfork \u65E7\u4F1A\u8BDD\u91CD\u8BD5", { oldSessionId: session.id });
99503
+ session = await forkSession(client, session.id, sessionKey, directory);
99504
+ await doPrompt(session);
99505
+ }
99506
+ return session;
99507
+ }
99449
99508
  function extractLastAssistantText(messages) {
99450
99509
  const assistant = messages.filter((m) => m.info?.role === "assistant").pop();
99451
99510
  const parts = assistant?.parts ?? [];