@xmanrui/dsh-im 4.20.0 → 4.20.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xmanrui/dsh-im",
3
- "version": "4.20.0",
3
+ "version": "4.20.1",
4
4
  "description": "把十一种 IM 渠道和公网 AI Office 接入本机 DeepSeek Harness。 Connect eleven IM channels and a public AI Office to a local DeepSeek Harness.",
5
5
  "keywords": [
6
6
  "deepseek-harness",
@@ -23,7 +23,7 @@ export default {
23
23
  '暂无可用选项。': 'No options are available.',
24
24
  '预设仅用于之后的新会话。': 'Presets apply to future new sessions.',
25
25
  '部分模型暂不可用,可稍后重试。': 'Some models are unavailable. Try again later.',
26
- '工作区已变化,请从新菜单重新选择。': 'The workspace changed. Please select again from the new menu.',
26
+ '工作区已变化,请发送 /m 重新打开菜单后选择。': 'The workspace changed. Send /m to reopen the menu and select again.',
27
27
  // Help text (wecom-bridge.mjs)
28
28
  '企业微信机器人已连接 DeepSeek Harness。': 'The Enterprise WeChat bot is connected to DeepSeek Harness.',
29
29
 
@@ -608,21 +608,11 @@ export class WecomHarnessBridge {
608
608
  return structuredClone(this.#status);
609
609
  }
610
610
 
611
- #mainMenu() {
612
- return wecomMenu({
613
- workspace: this.#harness.currentWorkspace?.(),
614
- workspaces: [[t('更多选项…'), '/menu workspaces']],
615
- });
616
- }
617
-
618
- async #showMain(frame, { welcome = false } = {}) {
611
+ async #showMain(frame) {
619
612
  const previousFailure = this.#status.lastMessageError;
620
613
  const key = conversationKey(frame);
621
614
  const workspace = this.#harness.currentWorkspace?.();
622
615
  const sessionId = this.#state.sessionFor(key);
623
- // The welcome reply has a five-second deadline. Show immediate controls,
624
- // then load the selectors independently of that reply window.
625
- if (welcome) await this.#sendMenu(frame, this.#mainMenu(), { welcome: true });
626
616
  const options = { signal: this.#signal };
627
617
  const settled = await Promise.allSettled([
628
618
  workspacePathSnapshot(this.#harness, options),
@@ -650,12 +640,10 @@ export class WecomHarnessBridge {
650
640
  currentPreset: currentPreset ? `/preset ${/^\d+$/u.test(currentPreset) ? 'id:' : ''}${currentPreset}` : '/preset --default',
651
641
  presetLabel: settings?.agentPresetCatalog?.items.find((item) => item.id === currentPreset)?.label,
652
642
  });
653
- await this.#sendMenu(frame, settingsMenu, { active: welcome });
654
- if (!welcome) {
655
- await this.#sendMenu(frame, wecomMenu({ workspace,
656
- workspaces: (paths?.paths ?? (workspace ? [workspace] : [])).map((path) => [path, `/workspace ${path}`]),
657
- }), { active: true });
658
- }
643
+ await this.#sendMenu(frame, settingsMenu);
644
+ await this.#sendMenu(frame, wecomMenu({ workspace,
645
+ workspaces: (paths?.paths ?? (workspace ? [workspace] : [])).map((path) => [path, `/workspace ${path}`]),
646
+ }), { active: true });
659
647
  this.#clearMenuFailure(previousFailure);
660
648
  }
661
649
 
@@ -682,17 +670,14 @@ export class WecomHarnessBridge {
682
670
  return wecomTemplateCard(menu, taskId);
683
671
  }
684
672
 
685
- async #sendMenu(frame, menu, { welcome = false, active = false } = {}) {
673
+ async #sendMenu(frame, menu, { active = false } = {}) {
686
674
  this.#signal?.throwIfAborted();
687
675
  const body = bodyOf(frame);
688
676
  const chatId = body.chattype === 'group' ? body.chatid : body.from.userid;
689
677
  const card = this.#rememberMenu(frame, menu);
690
- const operation = welcome ? 'replyWelcome'
691
- : active || this.#cardFrames.has(frame) ? 'sendMessage' : 'replyTemplateCard';
678
+ const operation = active || this.#cardFrames.has(frame) ? 'sendMessage' : 'replyTemplateCard';
692
679
  try {
693
- if (welcome) {
694
- await this.#client.replyWelcome(frame, { msgtype: 'template_card', template_card: card });
695
- } else if (active || this.#cardFrames.has(frame)) {
680
+ if (active || this.#cardFrames.has(frame)) {
696
681
  await this.#client.sendMessage(chatId, { msgtype: 'template_card', template_card: card });
697
682
  } else {
698
683
  await this.#client.replyTemplateCard(frame, card);
@@ -704,16 +689,7 @@ export class WecomHarnessBridge {
704
689
  // Only a definite card rejection can safely fall back to text.
705
690
  if (error.code !== 'channel-delivery-failed' || error.providerCode === undefined) throw error;
706
691
  this.#logger.warn?.('[dsh-im:wecom] menu delivery failed; using text:', wecomSendDiagnostic(error));
707
- if (welcome) {
708
- const content = wecomMenuText(menu);
709
- try {
710
- await this.#client.replyWelcome(frame, { msgtype: 'text', text: { content } });
711
- } catch (cause) {
712
- throw wecomSendError(cause, 'replyWelcome');
713
- }
714
- } else {
715
- await this.#sendImmediate(frame, chatId, wecomMenuText(menu));
716
- }
692
+ await this.#sendImmediate(frame, chatId, wecomMenuText(menu));
717
693
  }
718
694
  }
719
695
 
@@ -744,7 +720,7 @@ export class WecomHarnessBridge {
744
720
  const body = bodyOf(frame);
745
721
  const senderId = nonEmptyString(body.from?.userid);
746
722
  const type = body.event?.eventtype;
747
- if (!senderId || !['enter_chat', 'template_card_event'].includes(type)) return;
723
+ if (!senderId || type !== 'template_card_event') return;
748
724
  const chattype = body.chattype ?? (body.chatid ? 'group' : 'single');
749
725
  if (!['single', 'group'].includes(chattype) || (chattype === 'group' && !body.chatid)) return;
750
726
  const normalized = { ...frame, body: { ...body, chattype } };
@@ -753,17 +729,13 @@ export class WecomHarnessBridge {
753
729
  conversationType: chattype === 'single' ? 'direct' : 'group', senderIds: senderId, isCommand: true,
754
730
  });
755
731
  if (!access.allowed) {
756
- if (type === 'template_card_event' && access.reason === 'command-not-allowed') {
732
+ if (access.reason === 'command-not-allowed') {
757
733
  await this.#sendActive(chatId, t(COMMAND_PERMISSION_DENIED_MESSAGE));
758
734
  }
759
735
  return;
760
736
  }
761
737
  await this.#state.markSeen(body.msgid);
762
738
  const key = conversationKey(normalized);
763
- if (type === 'enter_chat') {
764
- if (chattype === 'single') await this.#showMain(normalized, { welcome: true });
765
- return;
766
- }
767
739
  // Live callbacks nest these fields; older SDK examples show them flat.
768
740
  const callback = body.event.template_card_event ?? body.event;
769
741
  const entry = this.#menus.get(callback.task_id);
@@ -807,7 +779,7 @@ export class WecomHarnessBridge {
807
779
  const navigation = commands.find((command) => parseWecomMenu(command));
808
780
  if (navigation) commands = [navigation];
809
781
  if (!navigation && entry.workspace !== this.#harness.currentWorkspace?.()) {
810
- await this.#sendActive(chatId, t('工作区已变化,请从新菜单重新选择。'));
782
+ await this.#sendActive(chatId, t('工作区已变化,请发送 /m 重新打开菜单后选择。'));
811
783
  } else {
812
784
  for (const [index, command] of commands.entries()) {
813
785
  const commandFrame = { ...normalized, body: { ...normalized.body,
@@ -818,10 +790,6 @@ export class WecomHarnessBridge {
818
790
  }
819
791
  if (!commands.length) await this.#sendActive(chatId, t('设置未改变。'));
820
792
  }
821
- if (!navigation) {
822
- this.#cardFrames.add(normalized);
823
- await this.#showMain(normalized);
824
- }
825
793
  }
826
794
 
827
795
  async #runMenuCommand(frame, text, _harness, _state, key) {
@@ -168,7 +168,7 @@ export class WecomRuntime {
168
168
  client.on('reconnecting', onReconnecting);
169
169
  client.on('error', onError);
170
170
  client.on('message', onMessage);
171
- client.on('event.enter_chat', (frame) => this.#bridge?.acceptEvent(frame));
171
+ // Menus are opened explicitly with /m or /menu; chat entry stays silent.
172
172
  client.on('event.template_card_event', (frame) => this.#bridge?.acceptEvent(frame));
173
173
 
174
174
  let timer;