opencode-feishu 1.1.0 → 1.2.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
@@ -11587,7 +11587,7 @@ var require_object_inspect = __commonJS({
11587
11587
  "double": /(["\\])/g,
11588
11588
  single: /(['\\])/g
11589
11589
  };
11590
- module2.exports = function inspect_(obj, options, depth, seen2) {
11590
+ module2.exports = function inspect_(obj, options, depth, seen) {
11591
11591
  var opts = options || {};
11592
11592
  if (has(opts, "quoteStyle") && !has(quotes, opts.quoteStyle)) {
11593
11593
  throw new TypeError('option "quoteStyle" must be "single" or "double"');
@@ -11637,15 +11637,15 @@ var require_object_inspect = __commonJS({
11637
11637
  return isArray2(obj) ? "[Array]" : "[Object]";
11638
11638
  }
11639
11639
  var indent = getIndent(opts, depth);
11640
- if (typeof seen2 === "undefined") {
11641
- seen2 = [];
11642
- } else if (indexOf(seen2, obj) >= 0) {
11640
+ if (typeof seen === "undefined") {
11641
+ seen = [];
11642
+ } else if (indexOf(seen, obj) >= 0) {
11643
11643
  return "[Circular]";
11644
11644
  }
11645
11645
  function inspect(value, from, noIndent) {
11646
11646
  if (from) {
11647
- seen2 = $arrSlice.call(seen2);
11648
- seen2.push(from);
11647
+ seen = $arrSlice.call(seen);
11648
+ seen.push(from);
11649
11649
  }
11650
11650
  if (noIndent) {
11651
11651
  var newOpts = {
@@ -11654,9 +11654,9 @@ var require_object_inspect = __commonJS({
11654
11654
  if (has(opts, "quoteStyle")) {
11655
11655
  newOpts.quoteStyle = opts.quoteStyle;
11656
11656
  }
11657
- return inspect_(value, newOpts, depth + 1, seen2);
11657
+ return inspect_(value, newOpts, depth + 1, seen);
11658
11658
  }
11659
- return inspect_(value, opts, depth + 1, seen2);
11659
+ return inspect_(value, opts, depth + 1, seen);
11660
11660
  }
11661
11661
  if (typeof obj === "function" && !isRegExp2(obj)) {
11662
11662
  var name = nameOf(obj);
@@ -13718,7 +13718,7 @@ var require_lodash2 = __commonJS({
13718
13718
  if (stacked && stack.get(other)) {
13719
13719
  return stacked == other;
13720
13720
  }
13721
- var index = -1, result = true, seen2 = bitmask & UNORDERED_COMPARE_FLAG ? new SetCache() : void 0;
13721
+ var index = -1, result = true, seen = bitmask & UNORDERED_COMPARE_FLAG ? new SetCache() : void 0;
13722
13722
  stack.set(array2, other);
13723
13723
  stack.set(other, array2);
13724
13724
  while (++index < arrLength) {
@@ -13733,10 +13733,10 @@ var require_lodash2 = __commonJS({
13733
13733
  result = false;
13734
13734
  break;
13735
13735
  }
13736
- if (seen2) {
13736
+ if (seen) {
13737
13737
  if (!arraySome(other, function(othValue2, othIndex) {
13738
- if (!seen2.has(othIndex) && (arrValue === othValue2 || equalFunc(arrValue, othValue2, customizer, bitmask, stack))) {
13739
- return seen2.add(othIndex);
13738
+ if (!seen.has(othIndex) && (arrValue === othValue2 || equalFunc(arrValue, othValue2, customizer, bitmask, stack))) {
13739
+ return seen.add(othIndex);
13740
13740
  }
13741
13741
  })) {
13742
13742
  result = false;
@@ -109648,14 +109648,14 @@ function initializeContext(params) {
109648
109648
  function process2(schema, ctx, _params = { path: [], schemaPath: [] }) {
109649
109649
  var _a2;
109650
109650
  const def = schema._zod.def;
109651
- const seen2 = ctx.seen.get(schema);
109652
- if (seen2) {
109653
- seen2.count++;
109651
+ const seen = ctx.seen.get(schema);
109652
+ if (seen) {
109653
+ seen.count++;
109654
109654
  const isCycle = _params.schemaPath.includes(schema);
109655
109655
  if (isCycle) {
109656
- seen2.cycle = _params.path;
109656
+ seen.cycle = _params.path;
109657
109657
  }
109658
- return seen2.schema;
109658
+ return seen.schema;
109659
109659
  }
109660
109660
  const result = { schema: {}, count: 1, cycle: void 0, path: _params.path };
109661
109661
  ctx.seen.set(schema, result);
@@ -109738,12 +109738,12 @@ function extractDefs(ctx, schema) {
109738
109738
  if (entry[1].schema.$ref) {
109739
109739
  return;
109740
109740
  }
109741
- const seen2 = entry[1];
109741
+ const seen = entry[1];
109742
109742
  const { ref, defId } = makeURI(entry);
109743
- seen2.def = { ...seen2.schema };
109743
+ seen.def = { ...seen.schema };
109744
109744
  if (defId)
109745
- seen2.defId = defId;
109746
- const schema2 = seen2.schema;
109745
+ seen.defId = defId;
109746
+ const schema2 = seen.schema;
109747
109747
  for (const key in schema2) {
109748
109748
  delete schema2[key];
109749
109749
  }
@@ -109751,16 +109751,16 @@ function extractDefs(ctx, schema) {
109751
109751
  };
109752
109752
  if (ctx.cycles === "throw") {
109753
109753
  for (const entry of ctx.seen.entries()) {
109754
- const seen2 = entry[1];
109755
- if (seen2.cycle) {
109756
- throw new Error(`Cycle detected: #/${seen2.cycle?.join("/")}/<root>
109754
+ const seen = entry[1];
109755
+ if (seen.cycle) {
109756
+ throw new Error(`Cycle detected: #/${seen.cycle?.join("/")}/<root>
109757
109757
 
109758
109758
  Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.`);
109759
109759
  }
109760
109760
  }
109761
109761
  }
109762
109762
  for (const entry of ctx.seen.entries()) {
109763
- const seen2 = entry[1];
109763
+ const seen = entry[1];
109764
109764
  if (schema === entry[0]) {
109765
109765
  extractToDef(entry);
109766
109766
  continue;
@@ -109777,11 +109777,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
109777
109777
  extractToDef(entry);
109778
109778
  continue;
109779
109779
  }
109780
- if (seen2.cycle) {
109780
+ if (seen.cycle) {
109781
109781
  extractToDef(entry);
109782
109782
  continue;
109783
109783
  }
109784
- if (seen2.count > 1) {
109784
+ if (seen.count > 1) {
109785
109785
  if (ctx.reused === "ref") {
109786
109786
  extractToDef(entry);
109787
109787
  continue;
@@ -109794,13 +109794,13 @@ function finalize(ctx, schema) {
109794
109794
  if (!root)
109795
109795
  throw new Error("Unprocessed schema. This is a bug in Zod.");
109796
109796
  const flattenRef = (zodSchema) => {
109797
- const seen2 = ctx.seen.get(zodSchema);
109798
- if (seen2.ref === null)
109797
+ const seen = ctx.seen.get(zodSchema);
109798
+ if (seen.ref === null)
109799
109799
  return;
109800
- const schema2 = seen2.def ?? seen2.schema;
109800
+ const schema2 = seen.def ?? seen.schema;
109801
109801
  const _cached = { ...schema2 };
109802
- const ref = seen2.ref;
109803
- seen2.ref = null;
109802
+ const ref = seen.ref;
109803
+ seen.ref = null;
109804
109804
  if (ref) {
109805
109805
  flattenRef(ref);
109806
109806
  const refSeen = ctx.seen.get(ref);
@@ -109852,7 +109852,7 @@ function finalize(ctx, schema) {
109852
109852
  ctx.override({
109853
109853
  zodSchema,
109854
109854
  jsonSchema: schema2,
109855
- path: seen2.path ?? []
109855
+ path: seen.path ?? []
109856
109856
  });
109857
109857
  };
109858
109858
  for (const entry of [...ctx.seen.entries()].reverse()) {
@@ -109875,9 +109875,9 @@ function finalize(ctx, schema) {
109875
109875
  Object.assign(result, root.def ?? root.schema);
109876
109876
  const defs = ctx.external?.defs ?? {};
109877
109877
  for (const entry of ctx.seen.entries()) {
109878
- const seen2 = entry[1];
109879
- if (seen2.def && seen2.defId) {
109880
- defs[seen2.defId] = seen2.def;
109878
+ const seen = entry[1];
109879
+ if (seen.def && seen.defId) {
109880
+ defs[seen.defId] = seen.def;
109881
109881
  }
109882
109882
  }
109883
109883
  if (ctx.external) ; else {
@@ -110371,9 +110371,9 @@ var recordProcessor = (schema, ctx, _json, params) => {
110371
110371
  var nullableProcessor = (schema, ctx, json2, params) => {
110372
110372
  const def = schema._zod.def;
110373
110373
  const inner = process2(def.innerType, ctx, params);
110374
- const seen2 = ctx.seen.get(schema);
110374
+ const seen = ctx.seen.get(schema);
110375
110375
  if (ctx.target === "openapi-3.0") {
110376
- seen2.ref = def.innerType;
110376
+ seen.ref = def.innerType;
110377
110377
  json2.nullable = true;
110378
110378
  } else {
110379
110379
  json2.anyOf = [inner, { type: "null" }];
@@ -110382,29 +110382,29 @@ var nullableProcessor = (schema, ctx, json2, params) => {
110382
110382
  var nonoptionalProcessor = (schema, ctx, _json, params) => {
110383
110383
  const def = schema._zod.def;
110384
110384
  process2(def.innerType, ctx, params);
110385
- const seen2 = ctx.seen.get(schema);
110386
- seen2.ref = def.innerType;
110385
+ const seen = ctx.seen.get(schema);
110386
+ seen.ref = def.innerType;
110387
110387
  };
110388
110388
  var defaultProcessor = (schema, ctx, json2, params) => {
110389
110389
  const def = schema._zod.def;
110390
110390
  process2(def.innerType, ctx, params);
110391
- const seen2 = ctx.seen.get(schema);
110392
- seen2.ref = def.innerType;
110391
+ const seen = ctx.seen.get(schema);
110392
+ seen.ref = def.innerType;
110393
110393
  json2.default = JSON.parse(JSON.stringify(def.defaultValue));
110394
110394
  };
110395
110395
  var prefaultProcessor = (schema, ctx, json2, params) => {
110396
110396
  const def = schema._zod.def;
110397
110397
  process2(def.innerType, ctx, params);
110398
- const seen2 = ctx.seen.get(schema);
110399
- seen2.ref = def.innerType;
110398
+ const seen = ctx.seen.get(schema);
110399
+ seen.ref = def.innerType;
110400
110400
  if (ctx.io === "input")
110401
110401
  json2._prefault = JSON.parse(JSON.stringify(def.defaultValue));
110402
110402
  };
110403
110403
  var catchProcessor = (schema, ctx, json2, params) => {
110404
110404
  const def = schema._zod.def;
110405
110405
  process2(def.innerType, ctx, params);
110406
- const seen2 = ctx.seen.get(schema);
110407
- seen2.ref = def.innerType;
110406
+ const seen = ctx.seen.get(schema);
110407
+ seen.ref = def.innerType;
110408
110408
  let catchValue;
110409
110409
  try {
110410
110410
  catchValue = def.catchValue(void 0);
@@ -110417,33 +110417,33 @@ var pipeProcessor = (schema, ctx, _json, params) => {
110417
110417
  const def = schema._zod.def;
110418
110418
  const innerType = ctx.io === "input" ? def.in._zod.def.type === "transform" ? def.out : def.in : def.out;
110419
110419
  process2(innerType, ctx, params);
110420
- const seen2 = ctx.seen.get(schema);
110421
- seen2.ref = innerType;
110420
+ const seen = ctx.seen.get(schema);
110421
+ seen.ref = innerType;
110422
110422
  };
110423
110423
  var readonlyProcessor = (schema, ctx, json2, params) => {
110424
110424
  const def = schema._zod.def;
110425
110425
  process2(def.innerType, ctx, params);
110426
- const seen2 = ctx.seen.get(schema);
110427
- seen2.ref = def.innerType;
110426
+ const seen = ctx.seen.get(schema);
110427
+ seen.ref = def.innerType;
110428
110428
  json2.readOnly = true;
110429
110429
  };
110430
110430
  var promiseProcessor = (schema, ctx, _json, params) => {
110431
110431
  const def = schema._zod.def;
110432
110432
  process2(def.innerType, ctx, params);
110433
- const seen2 = ctx.seen.get(schema);
110434
- seen2.ref = def.innerType;
110433
+ const seen = ctx.seen.get(schema);
110434
+ seen.ref = def.innerType;
110435
110435
  };
110436
110436
  var optionalProcessor = (schema, ctx, _json, params) => {
110437
110437
  const def = schema._zod.def;
110438
110438
  process2(def.innerType, ctx, params);
110439
- const seen2 = ctx.seen.get(schema);
110440
- seen2.ref = def.innerType;
110439
+ const seen = ctx.seen.get(schema);
110440
+ seen.ref = def.innerType;
110441
110441
  };
110442
110442
  var lazyProcessor = (schema, ctx, _json, params) => {
110443
110443
  const innerType = schema._zod.innerType;
110444
110444
  process2(innerType, ctx, params);
110445
- const seen2 = ctx.seen.get(schema);
110446
- seen2.ref = innerType;
110445
+ const seen = ctx.seen.get(schema);
110446
+ seen.ref = innerType;
110447
110447
  };
110448
110448
  var allProcessors = {
110449
110449
  string: stringProcessor,
@@ -112507,8 +112507,8 @@ config(en_default());
112507
112507
  // src/types.ts
112508
112508
  var AutoPromptSchema = external_exports.object({
112509
112509
  enabled: external_exports.boolean().default(false),
112510
- intervalSeconds: external_exports.number().int().positive().default(30),
112511
- maxIterations: external_exports.number().int().positive().default(10),
112510
+ intervalSeconds: external_exports.number().int().positive().max(300).default(30),
112511
+ maxIterations: external_exports.number().int().positive().max(100).default(10),
112512
112512
  message: external_exports.string().min(1).default("\u8BF7\u540C\u6B65\u5F53\u524D\u8FDB\u5EA6\uFF0C\u5982\u9700\u5E2E\u52A9\u8BF7\u8BF4\u660E"),
112513
112513
  idleThreshold: external_exports.number().int().min(1).default(2),
112514
112514
  idleMaxLength: external_exports.number().int().min(10).default(50)
@@ -112516,10 +112516,10 @@ var AutoPromptSchema = external_exports.object({
112516
112516
  var FeishuConfigSchema = external_exports.object({
112517
112517
  appId: external_exports.string().min(1, "appId \u4E0D\u80FD\u4E3A\u7A7A"),
112518
112518
  appSecret: external_exports.string().min(1, "appSecret \u4E0D\u80FD\u4E3A\u7A7A"),
112519
- timeout: external_exports.number().int().positive().default(12e4),
112519
+ timeout: external_exports.number().int().positive().max(6e5).default(12e4),
112520
112520
  thinkingDelay: external_exports.number().int().nonnegative().default(2500),
112521
112521
  logLevel: external_exports.enum(["fatal", "error", "warn", "info", "debug", "trace"]).default("info"),
112522
- maxHistoryMessages: external_exports.number().int().positive().default(200),
112522
+ maxHistoryMessages: external_exports.number().int().positive().max(500).default(200),
112523
112523
  pollInterval: external_exports.number().int().positive().default(1e3),
112524
112524
  stablePolls: external_exports.number().int().positive().default(3),
112525
112525
  dedupTtl: external_exports.number().int().positive().default(10 * 60 * 1e3),
@@ -112714,37 +112714,40 @@ function buildQuestionCard(request) {
112714
112714
  }
112715
112715
 
112716
112716
  // src/feishu/sender.ts
112717
+ async function wrapSendCall(fn, idExtractor = (res) => res?.data?.message_id ?? "") {
112718
+ try {
112719
+ const res = await fn();
112720
+ return { ok: true, messageId: idExtractor(res) };
112721
+ } catch (err) {
112722
+ return { ok: false, error: err instanceof Error ? err.message : String(err) };
112723
+ }
112724
+ }
112717
112725
  async function sendTextMessage(client, chatId, text) {
112718
112726
  if (!chatId?.trim()) {
112719
112727
  return { ok: false, error: "No chat_id provided" };
112720
112728
  }
112721
- try {
112722
- const res = await client.im.message.create({
112729
+ return wrapSendCall(
112730
+ () => client.im.message.create({
112723
112731
  params: { receive_id_type: "chat_id" },
112724
112732
  data: {
112725
112733
  receive_id: chatId.trim(),
112726
112734
  msg_type: "text",
112727
112735
  content: JSON.stringify({ text })
112728
112736
  }
112729
- });
112730
- return { ok: true, messageId: res?.data?.message_id ?? "" };
112731
- } catch (err) {
112732
- return { ok: false, error: err instanceof Error ? err.message : String(err) };
112733
- }
112737
+ })
112738
+ );
112734
112739
  }
112735
112740
  async function updateMessage(client, messageId, text) {
112736
- try {
112737
- await client.im.message.update({
112741
+ return wrapSendCall(
112742
+ () => client.im.message.update({
112738
112743
  path: { message_id: messageId },
112739
112744
  data: {
112740
112745
  msg_type: "text",
112741
112746
  content: JSON.stringify({ text })
112742
112747
  }
112743
- });
112744
- return { ok: true, messageId };
112745
- } catch (err) {
112746
- return { ok: false, error: err instanceof Error ? err.message : String(err) };
112747
- }
112748
+ }),
112749
+ () => messageId
112750
+ );
112748
112751
  }
112749
112752
  async function deleteMessage(client, messageId) {
112750
112753
  try {
@@ -112756,49 +112759,71 @@ async function sendInteractiveCard(client, chatId, card) {
112756
112759
  if (!chatId?.trim()) {
112757
112760
  return { ok: false, error: "No chat_id provided" };
112758
112761
  }
112759
- try {
112760
- const res = await client.im.message.create({
112762
+ return wrapSendCall(
112763
+ () => client.im.message.create({
112761
112764
  params: { receive_id_type: "chat_id" },
112762
112765
  data: {
112763
112766
  receive_id: chatId.trim(),
112764
112767
  msg_type: "interactive",
112765
112768
  content: JSON.stringify(card)
112766
112769
  }
112767
- });
112768
- return { ok: true, messageId: res?.data?.message_id ?? "" };
112769
- } catch (err) {
112770
- return { ok: false, error: err instanceof Error ? err.message : String(err) };
112771
- }
112770
+ })
112771
+ );
112772
112772
  }
112773
112773
  async function sendCardMessage(client, chatId, cardId) {
112774
112774
  if (!chatId?.trim()) {
112775
112775
  return { ok: false, error: "No chat_id provided" };
112776
112776
  }
112777
- try {
112778
- const res = await client.im.message.create({
112777
+ return wrapSendCall(
112778
+ () => client.im.message.create({
112779
112779
  params: { receive_id_type: "chat_id" },
112780
112780
  data: {
112781
112781
  receive_id: chatId.trim(),
112782
112782
  msg_type: "interactive",
112783
112783
  content: JSON.stringify({ type: "card_kit", data: { card_id: cardId } })
112784
112784
  }
112785
- });
112786
- return { ok: true, messageId: res?.data?.message_id ?? "" };
112787
- } catch (err) {
112788
- return { ok: false, error: err instanceof Error ? err.message : String(err) };
112789
- }
112785
+ })
112786
+ );
112790
112787
  }
112791
112788
 
112789
+ // src/utils/ttl-map.ts
112790
+ var TtlMap = class {
112791
+ constructor(defaultTtlMs) {
112792
+ this.defaultTtlMs = defaultTtlMs;
112793
+ }
112794
+ data = /* @__PURE__ */ new Map();
112795
+ timers = /* @__PURE__ */ new Map();
112796
+ get(key) {
112797
+ return this.data.get(key);
112798
+ }
112799
+ has(key) {
112800
+ return this.data.has(key);
112801
+ }
112802
+ set(key, value, ttlMs) {
112803
+ this.delete(key);
112804
+ this.data.set(key, value);
112805
+ const timer = setTimeout(() => {
112806
+ this.data.delete(key);
112807
+ this.timers.delete(key);
112808
+ }, ttlMs ?? this.defaultTtlMs);
112809
+ timer.unref();
112810
+ this.timers.set(key, timer);
112811
+ }
112812
+ delete(key) {
112813
+ const timer = this.timers.get(key);
112814
+ if (timer) {
112815
+ clearTimeout(timer);
112816
+ this.timers.delete(key);
112817
+ }
112818
+ this.data.delete(key);
112819
+ }
112820
+ };
112821
+
112792
112822
  // src/handler/interactive.ts
112793
- var SEEN_TTL_MS = 10 * 60 * 1e3;
112794
- var seenRequestIds = /* @__PURE__ */ new Map();
112823
+ var seenIds = new TtlMap(10 * 60 * 1e3);
112795
112824
  function markSeen(requestId) {
112796
- const now = Date.now();
112797
- for (const [id, ts] of seenRequestIds) {
112798
- if (now - ts > SEEN_TTL_MS) seenRequestIds.delete(id);
112799
- }
112800
- if (seenRequestIds.has(requestId)) return false;
112801
- seenRequestIds.set(requestId, now);
112825
+ if (seenIds.has(requestId)) return false;
112826
+ seenIds.set(requestId, true);
112802
112827
  return true;
112803
112828
  }
112804
112829
  function handlePermissionRequested(request, chatId, deps) {
@@ -112866,19 +112891,14 @@ function buildCallbackResponse(action) {
112866
112891
  }
112867
112892
 
112868
112893
  // src/feishu/dedup.ts
112869
- var seenTtlMs = 10 * 60 * 1e3;
112870
- var seen = /* @__PURE__ */ new Map();
112894
+ var dedup = new TtlMap(10 * 60 * 1e3);
112871
112895
  function initDedup(ttl) {
112872
- seenTtlMs = ttl;
112896
+ dedup = new TtlMap(ttl);
112873
112897
  }
112874
112898
  function isDuplicate(messageId) {
112875
- const now = Date.now();
112876
- for (const [k, ts] of seen) {
112877
- if (now - ts > seenTtlMs) seen.delete(k);
112878
- }
112879
112899
  if (!messageId) return false;
112880
- if (seen.has(messageId)) return true;
112881
- seen.set(messageId, now);
112900
+ if (dedup.has(messageId)) return true;
112901
+ dedup.set(messageId, true);
112882
112902
  return false;
112883
112903
  }
112884
112904
 
@@ -113316,57 +113336,24 @@ function emit(sessionId, action) {
113316
113336
 
113317
113337
  // src/handler/event.ts
113318
113338
  var pendingBySession = /* @__PURE__ */ new Map();
113319
- var sessionErrors = /* @__PURE__ */ new Map();
113320
- var sessionErrorTimeouts = /* @__PURE__ */ new Map();
113321
- var SESSION_ERROR_TTL_MS = 3e4;
113322
- var retryAttempts = /* @__PURE__ */ new Map();
113323
- var retryAttemptTimeouts = /* @__PURE__ */ new Map();
113339
+ var sessionErrors = new TtlMap(3e4);
113340
+ var retryAttempts = new TtlMap(36e5);
113324
113341
  var MAX_RETRY_ATTEMPTS = 2;
113325
- var RETRY_ATTEMPTS_TTL_MS = 36e5;
113326
113342
  function clearRetryAttempts(sessionKey) {
113327
113343
  retryAttempts.delete(sessionKey);
113328
- const timer = retryAttemptTimeouts.get(sessionKey);
113329
- if (timer) {
113330
- clearTimeout(timer);
113331
- retryAttemptTimeouts.delete(sessionKey);
113332
- }
113333
113344
  }
113334
113345
  function getRetryAttempts(sessionKey) {
113335
113346
  return retryAttempts.get(sessionKey) ?? 0;
113336
113347
  }
113337
113348
  function setRetryAttempts(sessionKey, count) {
113338
113349
  retryAttempts.set(sessionKey, count);
113339
- const existing = retryAttemptTimeouts.get(sessionKey);
113340
- if (existing) clearTimeout(existing);
113341
- const timeoutId = setTimeout(() => {
113342
- retryAttempts.delete(sessionKey);
113343
- retryAttemptTimeouts.delete(sessionKey);
113344
- }, RETRY_ATTEMPTS_TTL_MS);
113345
- retryAttemptTimeouts.set(sessionKey, timeoutId);
113346
113350
  }
113347
113351
  function getSessionError(sessionId) {
113348
113352
  return sessionErrors.get(sessionId);
113349
113353
  }
113350
113354
  function clearSessionError(sessionId) {
113351
- const timer = sessionErrorTimeouts.get(sessionId);
113352
- if (timer) {
113353
- clearTimeout(timer);
113354
- sessionErrorTimeouts.delete(sessionId);
113355
- }
113356
113355
  sessionErrors.delete(sessionId);
113357
113356
  }
113358
- function setSessionError(sessionId, message, fields) {
113359
- const existing = sessionErrorTimeouts.get(sessionId);
113360
- if (existing) {
113361
- clearTimeout(existing);
113362
- }
113363
- sessionErrors.set(sessionId, { message, fields });
113364
- const timeoutId = setTimeout(() => {
113365
- sessionErrors.delete(sessionId);
113366
- sessionErrorTimeouts.delete(sessionId);
113367
- }, SESSION_ERROR_TTL_MS);
113368
- sessionErrorTimeouts.set(sessionId, timeoutId);
113369
- }
113370
113357
  function registerPending(sessionId, payload) {
113371
113358
  pendingBySession.set(sessionId, { ...payload, textBuffer: "", expectedMessageId: void 0 });
113372
113359
  }
@@ -113417,111 +113404,115 @@ async function handleEvent(event, deps) {
113417
113404
  switch (event.type) {
113418
113405
  case "message.part.updated": {
113419
113406
  const part = event.properties.part;
113420
- if (!part) break;
113421
- const sessionId = part.sessionID;
113422
- if (!sessionId) break;
113423
- const payload = pendingBySession.get(sessionId);
113407
+ if (!part?.sessionID) break;
113408
+ const payload = pendingBySession.get(part.sessionID);
113424
113409
  if (!payload) break;
113425
- const messageId = part.messageID;
113426
- if (messageId) {
113427
- if (!payload.expectedMessageId) {
113428
- payload.expectedMessageId = messageId;
113429
- } else if (payload.expectedMessageId !== messageId) {
113430
- break;
113431
- }
113432
- } else if (payload.expectedMessageId) {
113433
- break;
113434
- }
113435
- const partSessionId = part.sessionID;
113436
- if (part.type === "tool") {
113437
- const p = part;
113438
- const toolName = String(p.toolName ?? p.name ?? "unknown");
113439
- const callID = String(p.toolCallID ?? p.id ?? "");
113440
- const hasError = p.error !== void 0 && p.error !== null;
113441
- const rawState = p.state != null ? String(p.state) : hasError ? "error" : "running";
113442
- const toolState = rawState === "completed" || rawState === "error" ? rawState : "running";
113443
- if (partSessionId) {
113444
- emit(partSessionId, {
113445
- type: "tool-state-changed",
113446
- sessionId: partSessionId,
113447
- callID,
113448
- tool: toolName,
113449
- state: toolState
113450
- });
113451
- }
113452
- break;
113453
- }
113454
- const delta = event.properties.delta;
113455
- if (delta) {
113456
- payload.textBuffer += delta;
113457
- } else {
113458
- const fullText = extractPartText(part);
113459
- if (fullText) {
113460
- payload.textBuffer = fullText;
113461
- }
113462
- }
113463
- if (payload.textBuffer) {
113464
- const res = await updateMessage(payload.feishuClient, payload.placeholderId, payload.textBuffer.trim());
113465
- if (!res.ok) ;
113466
- }
113467
- if (partSessionId) {
113468
- emit(partSessionId, {
113469
- type: "text-updated",
113470
- sessionId: partSessionId,
113471
- messageId: part.messageID,
113472
- delta: delta ?? void 0,
113473
- fullText: payload.textBuffer
113474
- });
113475
- }
113410
+ await handleMessagePartUpdated(event, part, payload);
113476
113411
  break;
113477
113412
  }
113478
- case "session.error": {
113479
- const props = event.properties;
113480
- const sessionId = props.sessionID;
113481
- if (!sessionId) break;
113482
- const error48 = props.error;
113483
- let errMsg;
113484
- if (typeof error48 === "string") {
113485
- errMsg = error48;
113486
- } else if (error48 && typeof error48 === "object") {
113487
- const e = error48;
113488
- const rawDataMsg = e.data && typeof e.data === "object" && "message" in e.data ? e.data.message : void 0;
113489
- const dataMsg = rawDataMsg != null ? String(rawDataMsg) : void 0;
113490
- errMsg = String(e.message ?? dataMsg ?? e.type ?? e.name ?? "An unexpected error occurred");
113491
- } else {
113492
- errMsg = String(error48);
113493
- }
113494
- const fields = extractErrorFields(error48);
113495
- deps.log("warn", "\u6536\u5230 session.error \u4E8B\u4EF6", { sessionId, errMsg });
113496
- setSessionError(sessionId, errMsg, fields);
113413
+ case "session.error":
113414
+ handleSessionErrorEvent(event, deps);
113497
113415
  break;
113498
- }
113499
- default: {
113500
- const evtType = event.type;
113501
- const evtProps = event.properties ?? {};
113502
- const evtSessionId = evtProps.sessionID;
113503
- if (evtType === "permission.asked" && evtSessionId) {
113504
- emit(evtSessionId, {
113505
- type: "permission-requested",
113506
- sessionId: evtSessionId,
113507
- request: evtProps
113508
- });
113509
- deps.log("info", "permission.asked \u4E8B\u4EF6\u5DF2\u5206\u53D1", { sessionId: evtSessionId });
113510
- } else if (evtType === "question.asked" && evtSessionId) {
113511
- emit(evtSessionId, {
113512
- type: "question-requested",
113513
- sessionId: evtSessionId,
113514
- request: evtProps
113515
- });
113516
- deps.log("info", "question.asked \u4E8B\u4EF6\u5DF2\u5206\u53D1", { sessionId: evtSessionId });
113517
- } else if (evtType === "session.idle" && evtSessionId) {
113518
- emit(evtSessionId, {
113519
- type: "session-idle",
113520
- sessionId: evtSessionId
113521
- });
113522
- }
113416
+ default:
113417
+ handleV2Event(event, deps);
113523
113418
  break;
113419
+ }
113420
+ }
113421
+ async function handleMessagePartUpdated(event, part, payload) {
113422
+ const messageId = part.messageID;
113423
+ if (messageId) {
113424
+ if (!payload.expectedMessageId) {
113425
+ payload.expectedMessageId = messageId;
113426
+ } else if (payload.expectedMessageId !== messageId) {
113427
+ return;
113524
113428
  }
113429
+ } else if (payload.expectedMessageId) {
113430
+ return;
113431
+ }
113432
+ const partSessionId = part.sessionID;
113433
+ if (part.type === "tool") {
113434
+ const p = part;
113435
+ const toolName = String(p.toolName ?? p.name ?? "unknown");
113436
+ const callID = String(p.toolCallID ?? p.id ?? "");
113437
+ const hasError = p.error !== void 0 && p.error !== null;
113438
+ const rawState = p.state != null ? String(p.state) : hasError ? "error" : "running";
113439
+ const toolState = rawState === "completed" || rawState === "error" ? rawState : "running";
113440
+ if (partSessionId) {
113441
+ emit(partSessionId, {
113442
+ type: "tool-state-changed",
113443
+ sessionId: partSessionId,
113444
+ callID,
113445
+ tool: toolName,
113446
+ state: toolState
113447
+ });
113448
+ }
113449
+ return;
113450
+ }
113451
+ const delta = event.properties.delta;
113452
+ if (delta) {
113453
+ payload.textBuffer += delta;
113454
+ } else {
113455
+ const fullText = extractPartText(part);
113456
+ if (fullText) {
113457
+ payload.textBuffer = fullText;
113458
+ }
113459
+ }
113460
+ if (payload.textBuffer) {
113461
+ await updateMessage(payload.feishuClient, payload.placeholderId, payload.textBuffer.trim());
113462
+ }
113463
+ if (partSessionId) {
113464
+ emit(partSessionId, {
113465
+ type: "text-updated",
113466
+ sessionId: partSessionId,
113467
+ messageId: part.messageID,
113468
+ delta: delta ?? void 0,
113469
+ fullText: payload.textBuffer
113470
+ });
113471
+ }
113472
+ }
113473
+ function handleSessionErrorEvent(event, deps) {
113474
+ const props = event.properties;
113475
+ const sessionId = props.sessionID;
113476
+ if (!sessionId) return;
113477
+ const error48 = props.error;
113478
+ let errMsg;
113479
+ if (typeof error48 === "string") {
113480
+ errMsg = error48;
113481
+ } else if (error48 && typeof error48 === "object") {
113482
+ const e = error48;
113483
+ const asStr = (v) => typeof v === "string" && v.trim().length > 0 ? v : void 0;
113484
+ const rawDataMsg = e.data && typeof e.data === "object" && "message" in e.data ? e.data.message : void 0;
113485
+ errMsg = asStr(e.message) ?? asStr(rawDataMsg) ?? asStr(e.type) ?? asStr(e.name) ?? "An unexpected error occurred";
113486
+ } else {
113487
+ errMsg = String(error48);
113488
+ }
113489
+ const fields = extractErrorFields(error48);
113490
+ deps.log("warn", "\u6536\u5230 session.error \u4E8B\u4EF6", { sessionId, errMsg });
113491
+ sessionErrors.set(sessionId, { message: errMsg, fields });
113492
+ }
113493
+ function handleV2Event(event, deps) {
113494
+ const evtType = event.type;
113495
+ const evtProps = event.properties ?? {};
113496
+ const evtSessionId = evtProps.sessionID;
113497
+ if (evtType === "permission.asked" && evtSessionId) {
113498
+ emit(evtSessionId, {
113499
+ type: "permission-requested",
113500
+ sessionId: evtSessionId,
113501
+ request: evtProps
113502
+ });
113503
+ deps.log("info", "permission.asked \u4E8B\u4EF6\u5DF2\u5206\u53D1", { sessionId: evtSessionId });
113504
+ } else if (evtType === "question.asked" && evtSessionId) {
113505
+ emit(evtSessionId, {
113506
+ type: "question-requested",
113507
+ sessionId: evtSessionId,
113508
+ request: evtProps
113509
+ });
113510
+ deps.log("info", "question.asked \u4E8B\u4EF6\u5DF2\u5206\u53D1", { sessionId: evtSessionId });
113511
+ } else if (evtType === "session.idle" && evtSessionId) {
113512
+ emit(evtSessionId, {
113513
+ type: "session-idle",
113514
+ sessionId: evtSessionId
113515
+ });
113525
113516
  }
113526
113517
  }
113527
113518
  function extractPartText(part) {
@@ -113532,6 +113523,128 @@ function extractPartText(part) {
113532
113523
  return "";
113533
113524
  }
113534
113525
 
113526
+ // src/handler/error-recovery.ts
113527
+ var SessionErrorDetected = class extends Error {
113528
+ constructor(sessionError) {
113529
+ super(sessionError.message);
113530
+ this.sessionError = sessionError;
113531
+ this.name = "SessionErrorDetected";
113532
+ }
113533
+ };
113534
+ async function getGlobalDefaultModel(client, directory) {
113535
+ const query = directory ? { directory } : void 0;
113536
+ const { data: config2 } = await client.config.get({ query });
113537
+ const model = config2?.model;
113538
+ if (!model || !model.includes("/")) return void 0;
113539
+ const slash = model.indexOf("/");
113540
+ const providerID = model.slice(0, slash).trim();
113541
+ const modelID = model.slice(slash + 1).trim();
113542
+ if (!providerID || !modelID) return void 0;
113543
+ return { providerID, modelID };
113544
+ }
113545
+ function extractSessionError(err, sessionId) {
113546
+ const result = err instanceof SessionErrorDetected ? err.sessionError : getSessionError(sessionId);
113547
+ clearSessionError(sessionId);
113548
+ return result;
113549
+ }
113550
+ async function tryModelRecovery(params) {
113551
+ const {
113552
+ sessionError,
113553
+ sessionId,
113554
+ sessionKey,
113555
+ client,
113556
+ directory,
113557
+ parts,
113558
+ timeout,
113559
+ pollInterval,
113560
+ stablePolls,
113561
+ query,
113562
+ signal,
113563
+ log,
113564
+ poll
113565
+ } = params;
113566
+ log("info", "\u9519\u8BEF\u5B57\u6BB5\u68C0\u67E5", {
113567
+ sessionKey,
113568
+ fields: sessionError.fields,
113569
+ isModel: isModelError(sessionError.fields)
113570
+ });
113571
+ if (!isModelError(sessionError.fields)) {
113572
+ return { recovered: false, sessionError };
113573
+ }
113574
+ const attempts = getRetryAttempts(sessionKey);
113575
+ if (attempts >= MAX_RETRY_ATTEMPTS) {
113576
+ log("warn", "\u5DF2\u8FBE\u91CD\u8BD5\u4E0A\u9650\uFF0C\u653E\u5F03\u6062\u590D", { sessionKey, attempts });
113577
+ return { recovered: false, sessionError };
113578
+ }
113579
+ try {
113580
+ let modelOverride;
113581
+ try {
113582
+ modelOverride = await getGlobalDefaultModel(client, directory);
113583
+ } catch (configErr) {
113584
+ log("warn", "\u8BFB\u53D6\u5168\u5C40\u6A21\u578B\u914D\u7F6E\u5931\u8D25", {
113585
+ sessionKey,
113586
+ error: configErr instanceof Error ? configErr.message : String(configErr)
113587
+ });
113588
+ }
113589
+ if (!modelOverride) {
113590
+ log("warn", "\u5168\u5C40\u9ED8\u8BA4\u6A21\u578B\u672A\u914D\u7F6E\uFF0C\u653E\u5F03\u6062\u590D", { sessionKey });
113591
+ return { recovered: false, sessionError };
113592
+ }
113593
+ setRetryAttempts(sessionKey, attempts + 1);
113594
+ log("info", "\u4F7F\u7528\u5168\u5C40\u9ED8\u8BA4\u6A21\u578B\u6062\u590D", {
113595
+ sessionKey,
113596
+ providerID: modelOverride.providerID,
113597
+ modelID: modelOverride.modelID
113598
+ });
113599
+ clearSessionError(sessionId);
113600
+ await client.session.promptAsync({
113601
+ path: { id: sessionId },
113602
+ query,
113603
+ body: { parts: [...parts], model: modelOverride }
113604
+ });
113605
+ const finalText = await poll(client, sessionId, {
113606
+ timeout,
113607
+ pollInterval,
113608
+ stablePolls,
113609
+ query,
113610
+ signal
113611
+ });
113612
+ log("info", "\u6A21\u578B\u6062\u590D\u540E\u54CD\u5E94\u5B8C\u6210", {
113613
+ sessionKey,
113614
+ sessionId,
113615
+ output: finalText || "(empty)"
113616
+ });
113617
+ clearRetryAttempts(sessionKey);
113618
+ log("info", "\u6A21\u578B\u4E0D\u517C\u5BB9\u6062\u590D\u6210\u529F", {
113619
+ sessionId,
113620
+ sessionKey,
113621
+ model: `${modelOverride.providerID}/${modelOverride.modelID}`,
113622
+ attempt: attempts + 1
113623
+ });
113624
+ return { recovered: true, text: finalText };
113625
+ } catch (recoveryErr) {
113626
+ if (recoveryErr instanceof Error && recoveryErr.name === "AbortError") {
113627
+ throw recoveryErr;
113628
+ }
113629
+ const errMsg = recoveryErr instanceof Error ? recoveryErr.message : String(recoveryErr);
113630
+ let updatedError;
113631
+ if (recoveryErr instanceof SessionErrorDetected) {
113632
+ updatedError = recoveryErr.sessionError;
113633
+ clearSessionError(sessionId);
113634
+ } else {
113635
+ const sseError = getSessionError(sessionId);
113636
+ if (sseError) {
113637
+ updatedError = sseError;
113638
+ clearSessionError(sessionId);
113639
+ } else {
113640
+ updatedError = { message: errMsg, fields: [] };
113641
+ }
113642
+ }
113643
+ log("error", "\u6A21\u578B\u6062\u590D\u5931\u8D25", { sessionId, sessionKey, error: errMsg });
113644
+ return { recovered: false, sessionError: updatedError };
113645
+ }
113646
+ }
113647
+
113535
113648
  // src/session.ts
113536
113649
  var SESSION_KEY_PREFIX = "feishu";
113537
113650
  var TITLE_PREFIX = "Feishu";
@@ -113907,108 +114020,50 @@ async function handleChat(ctx, deps, signal) {
113907
114020
  await abortCleanup(streamingCard, feishuClient, placeholderId);
113908
114021
  return void 0;
113909
114022
  }
113910
- let sessionError;
113911
- if (err instanceof SessionErrorDetected) {
113912
- sessionError = err.sessionError;
113913
- clearSessionError(session.id);
113914
- } else {
113915
- sessionError = getSessionError(session.id);
113916
- clearSessionError(session.id);
113917
- }
114023
+ const sessionError = extractSessionError(err, session.id);
114024
+ let displayError = sessionError;
113918
114025
  if (sessionError) {
113919
- log("info", "\u9519\u8BEF\u5B57\u6BB5\u68C0\u67E5", {
113920
- sessionKey,
113921
- fields: sessionError.fields,
113922
- isModel: isModelError(sessionError.fields)
113923
- });
113924
- }
113925
- if (sessionError && isModelError(sessionError.fields)) {
113926
- const attempts = getRetryAttempts(sessionKey);
113927
- if (attempts < MAX_RETRY_ATTEMPTS) {
113928
- try {
113929
- let modelOverride;
113930
- try {
113931
- modelOverride = await getGlobalDefaultModel(client, directory);
113932
- } catch (configErr) {
113933
- log("warn", "\u8BFB\u53D6\u5168\u5C40\u6A21\u578B\u914D\u7F6E\u5931\u8D25", {
113934
- sessionKey,
113935
- error: configErr instanceof Error ? configErr.message : String(configErr)
113936
- });
113937
- }
113938
- if (!modelOverride) {
113939
- log("warn", "\u5168\u5C40\u9ED8\u8BA4\u6A21\u578B\u672A\u914D\u7F6E\uFF0C\u653E\u5F03\u6062\u590D", { sessionKey });
113940
- } else {
113941
- setRetryAttempts(sessionKey, attempts + 1);
113942
- log("info", "\u4F7F\u7528\u5168\u5C40\u9ED8\u8BA4\u6A21\u578B\u6062\u590D", {
113943
- sessionKey,
113944
- providerID: modelOverride.providerID,
113945
- modelID: modelOverride.modelID
113946
- });
113947
- clearSessionError(session.id);
113948
- await client.session.promptAsync({
113949
- path: { id: session.id },
113950
- query,
113951
- body: { ...baseBody, model: modelOverride }
113952
- });
113953
- const finalText = await pollForResponse(client, session.id, { timeout, pollInterval, stablePolls, query, signal });
113954
- log("info", "\u6A21\u578B\u6062\u590D\u540E\u54CD\u5E94\u5B8C\u6210", {
113955
- sessionKey,
113956
- sessionId: session.id,
113957
- output: finalText || "(empty)"
113958
- });
113959
- clearRetryAttempts(sessionKey);
113960
- await finalizeReply(streamingCard, feishuClient, chatId, placeholderId, finalText || "\u26A0\uFE0F \u54CD\u5E94\u8D85\u65F6");
113961
- log("info", "\u6A21\u578B\u4E0D\u517C\u5BB9\u6062\u590D\u6210\u529F", {
113962
- sessionId: session.id,
113963
- sessionKey,
113964
- model: `${modelOverride.providerID}/${modelOverride.modelID}`,
113965
- attempt: attempts + 1
113966
- });
113967
- if (config2.autoPrompt.enabled && shouldReply) {
113968
- return { sessionId: session.id, sessionKey, chatId, deps };
113969
- }
113970
- return void 0;
113971
- }
113972
- } catch (recoveryErr) {
113973
- if (recoveryErr instanceof Error && recoveryErr.name === "AbortError") {
113974
- log("info", "\u6A21\u578B\u6062\u590D\u88AB\u4E2D\u65AD", { sessionKey });
113975
- await abortCleanup(streamingCard, feishuClient, placeholderId);
113976
- return void 0;
113977
- }
113978
- const errMsg = recoveryErr instanceof Error ? recoveryErr.message : String(recoveryErr);
113979
- if (recoveryErr instanceof SessionErrorDetected) {
113980
- sessionError = recoveryErr.sessionError;
113981
- clearSessionError(session.id);
113982
- } else {
113983
- const sseError = getSessionError(session.id);
113984
- if (sseError) {
113985
- sessionError = sseError;
113986
- clearSessionError(session.id);
113987
- } else {
113988
- sessionError = { message: errMsg, fields: [] };
113989
- }
113990
- }
113991
- log("error", "\u6A21\u578B\u6062\u590D\u5931\u8D25", {
113992
- sessionId: session.id,
113993
- sessionKey,
113994
- error: errMsg
113995
- });
113996
- }
113997
- } else {
113998
- log("warn", "\u5DF2\u8FBE\u91CD\u8BD5\u4E0A\u9650\uFF0C\u653E\u5F03\u6062\u590D", {
114026
+ try {
114027
+ const recovery = await tryModelRecovery({
114028
+ sessionError,
114029
+ sessionId: session.id,
113999
114030
  sessionKey,
114000
- attempts
114031
+ client,
114032
+ directory,
114033
+ parts,
114034
+ timeout,
114035
+ pollInterval,
114036
+ stablePolls,
114037
+ query,
114038
+ signal,
114039
+ log,
114040
+ poll: pollForResponse
114001
114041
  });
114042
+ if (recovery.recovered) {
114043
+ await finalizeReply(streamingCard, feishuClient, chatId, placeholderId, recovery.text || "\u26A0\uFE0F \u54CD\u5E94\u8D85\u65F6");
114044
+ if (config2.autoPrompt.enabled && shouldReply) {
114045
+ return { sessionId: session.id, sessionKey, chatId, deps };
114046
+ }
114047
+ return void 0;
114048
+ }
114049
+ displayError = recovery.sessionError;
114050
+ } catch (abortErr) {
114051
+ if (abortErr instanceof Error && abortErr.name === "AbortError") {
114052
+ log("info", "\u6A21\u578B\u6062\u590D\u88AB\u4E2D\u65AD", { sessionKey });
114053
+ await abortCleanup(streamingCard, feishuClient, placeholderId);
114054
+ return void 0;
114055
+ }
114056
+ throw abortErr;
114002
114057
  }
114003
114058
  }
114004
114059
  const thrownError = err instanceof Error ? err.message : String(err);
114005
- const errorMessage = sessionError?.message || thrownError;
114060
+ const errorMessage = displayError?.message || thrownError;
114006
114061
  log("error", "\u5BF9\u8BDD\u5904\u7406\u5931\u8D25", {
114007
114062
  sessionId: session.id,
114008
114063
  sessionKey,
114009
114064
  chatType,
114010
114065
  error: thrownError,
114011
- ...sessionError ? { sessionError: sessionError.message } : {}
114066
+ ...displayError ? { sessionError: displayError.message } : {}
114012
114067
  });
114013
114068
  await finalizeReply(streamingCard, feishuClient, chatId, placeholderId, "\u274C " + errorMessage);
114014
114069
  } finally {
@@ -114018,17 +114073,6 @@ async function handleChat(ctx, deps, signal) {
114018
114073
  unregisterPending(activeSessionId);
114019
114074
  }
114020
114075
  }
114021
- async function getGlobalDefaultModel(client, directory) {
114022
- const query = directory ? { directory } : void 0;
114023
- const { data: config2 } = await client.config.get({ query });
114024
- const model = config2?.model;
114025
- if (!model || !model.includes("/")) return void 0;
114026
- const slash = model.indexOf("/");
114027
- const providerID = model.slice(0, slash).trim();
114028
- const modelID = model.slice(slash + 1).trim();
114029
- if (!providerID || !modelID) return void 0;
114030
- return { providerID, modelID };
114031
- }
114032
114076
  async function buildPromptParts(feishuClient, messageId, messageType, rawContent, textContent, chatType, senderId, log) {
114033
114077
  if (messageType === "text") {
114034
114078
  let promptText = textContent;
@@ -114043,13 +114087,6 @@ async function buildPromptParts(feishuClient, messageId, messageType, rawContent
114043
114087
  }
114044
114088
  return parts;
114045
114089
  }
114046
- var SessionErrorDetected = class extends Error {
114047
- constructor(sessionError) {
114048
- super(sessionError.message);
114049
- this.sessionError = sessionError;
114050
- this.name = "SessionErrorDetected";
114051
- }
114052
- };
114053
114090
  async function pollForResponse(client, sessionId, opts) {
114054
114091
  const { timeout, pollInterval, stablePolls, query, signal } = opts;
114055
114092
  const start = Date.now();
@@ -114170,6 +114207,7 @@ function extractLastAssistantText(messages) {
114170
114207
  }
114171
114208
 
114172
114209
  // src/handler/session-queue.ts
114210
+ var QUEUE_MONITOR_INTERVAL_MS = 200;
114173
114211
  var states = /* @__PURE__ */ new Map();
114174
114212
  function getOrCreateState(sessionKey) {
114175
114213
  const existing = states.get(sessionKey);
@@ -114317,7 +114355,7 @@ async function drainLoop(sessionKey, state) {
114317
114355
  const autoPromptController = new AbortController();
114318
114356
  const monitor = setInterval(() => {
114319
114357
  if (state.queue.length > 0) autoPromptController.abort();
114320
- }, 200);
114358
+ }, QUEUE_MONITOR_INTERVAL_MS);
114321
114359
  try {
114322
114360
  const result = await runOneAutoPromptIteration(
114323
114361
  autoPromptCtx,
@@ -114480,21 +114518,9 @@ var FeishuPlugin = async (ctx) => {
114480
114518
  });
114481
114519
  };
114482
114520
  const configPath = join(homedir(), ".config", "opencode", "plugins", "feishu.json");
114483
- if (!existsSync(configPath)) {
114484
- throw new Error(
114485
- `\u7F3A\u5C11\u98DE\u4E66\u914D\u7F6E\u6587\u4EF6\uFF1A\u8BF7\u521B\u5EFA ${configPath}\uFF0C\u5185\u5BB9\u4E3A {"appId":"cli_xxx","appSecret":"xxx"}`
114486
- );
114487
- }
114488
114521
  let resolvedConfig;
114489
114522
  try {
114490
- const raw = resolveEnvPlaceholders(
114491
- JSON.parse(readFileSync(configPath, "utf-8"))
114492
- );
114493
- const parsed = FeishuConfigSchema.parse(raw);
114494
- resolvedConfig = {
114495
- ...parsed,
114496
- directory: expandDirectoryPath(parsed.directory ?? ctx.directory ?? "")
114497
- };
114523
+ resolvedConfig = loadAndValidateConfig(configPath, ctx.directory ?? "");
114498
114524
  } catch (e) {
114499
114525
  if (e instanceof external_exports.ZodError) {
114500
114526
  const details = e.issues.map((i) => ` - ${i.path.join(".")}: ${i.message}`).join("\n");
@@ -114573,6 +114599,14 @@ ${details}`);
114573
114599
  };
114574
114600
  return hooks;
114575
114601
  };
114602
+ function loadAndValidateConfig(configPath, ctxDirectory) {
114603
+ if (!existsSync(configPath)) {
114604
+ throw new Error(`\u7F3A\u5C11\u98DE\u4E66\u914D\u7F6E\u6587\u4EF6\uFF1A\u8BF7\u521B\u5EFA ${configPath}\uFF0C\u5185\u5BB9\u4E3A {"appId":"cli_xxx","appSecret":"xxx"}`);
114605
+ }
114606
+ const raw = resolveEnvPlaceholders(JSON.parse(readFileSync(configPath, "utf-8")));
114607
+ const parsed = FeishuConfigSchema.parse(raw);
114608
+ return { ...parsed, directory: expandDirectoryPath(parsed.directory ?? ctxDirectory ?? "") };
114609
+ }
114576
114610
  function expandDirectoryPath(dir) {
114577
114611
  if (!dir) return dir;
114578
114612
  if (dir.startsWith("~")) {