@xmanrui/dsh-im 4.19.1 → 4.20.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.
Files changed (53) hide show
  1. package/README.en.md +96 -4
  2. package/README.md +96 -4
  3. package/lib/client.js +666 -217
  4. package/lib/index.js +277 -273
  5. package/package.json +13 -1
  6. package/plugin-src/client/channels/weixin/api.js +35 -17
  7. package/plugin-src/client/channels/weixin/connection-error.js +68 -0
  8. package/plugin-src/client/channels/weixin/index.js +36 -12
  9. package/plugin-src/client/i18n.js +2 -0
  10. package/plugin-src/client/index.js +15 -0
  11. package/plugin-src/client/interface-language.js +89 -0
  12. package/plugin-src/host/channels/shared/startup.mjs +30 -4
  13. package/plugin-src/host/channels/weixin/connection-supervisor.mjs +13 -1
  14. package/plugin-src/host/channels/weixin/index.mjs +12 -3
  15. package/plugin-src/host/channels/weixin/production.mjs +53 -3
  16. package/plugin-src/host/channels/weixin/rpc.mjs +22 -17
  17. package/plugin-src/host/host-language-rpc.mjs +71 -0
  18. package/plugin-src/host/host-language.mjs +157 -0
  19. package/plugin-src/host/index.mjs +15 -2
  20. package/scripts/verify-interface-language.mjs +333 -0
  21. package/src/channels/dingtalk/dingtalk-bridge.mjs +4 -1
  22. package/src/channels/dingtalk/dingtalk-menu.mjs +8 -4
  23. package/src/channels/discord/discord-runtime.mjs +1 -1
  24. package/src/channels/feishu/bridge.mjs +44 -13
  25. package/src/channels/qq/qq-bridge.mjs +12 -4
  26. package/src/channels/qq/qq-menu.mjs +11 -8
  27. package/src/channels/shared/bot-workspace-store.mjs +532 -40
  28. package/src/channels/shared/command-catalog.mjs +5 -0
  29. package/src/channels/shared/compact-command.mjs +14 -4
  30. package/src/channels/shared/control-command.mjs +1 -1
  31. package/src/channels/shared/deferred-delivery-coordinator.mjs +1 -1
  32. package/src/channels/shared/history-command.mjs +1 -1
  33. package/src/channels/shared/i18n-en/discord.mjs +2 -0
  34. package/src/channels/shared/i18n-en/shared-a.mjs +41 -0
  35. package/src/channels/shared/i18n-en/telegram.mjs +5 -0
  36. package/src/channels/shared/i18n-en/weixin.mjs +2 -0
  37. package/src/channels/shared/i18n.mjs +46 -3
  38. package/src/channels/shared/interface-language-store.mjs +127 -0
  39. package/src/channels/shared/interface-language.mjs +51 -0
  40. package/src/channels/shared/model-command.mjs +5 -3
  41. package/src/channels/shared/token-bot-controller.mjs +26 -0
  42. package/src/channels/shared/workspace-command.mjs +114 -9
  43. package/src/channels/shared/workspace-session.mjs +55 -5
  44. package/src/channels/telegram/telegram-runtime.mjs +76 -14
  45. package/src/channels/wecom/wecom-bridge.mjs +2 -2
  46. package/src/channels/weixin/connection-error.en.mjs +116 -0
  47. package/src/channels/weixin/connection-error.mjs +204 -0
  48. package/src/channels/weixin/diagnostic-details.mjs +40 -0
  49. package/src/channels/weixin/state-store.mjs +4 -3
  50. package/src/channels/weixin/weixin-api.mjs +20 -8
  51. package/src/channels/weixin/weixin-bridge.mjs +3 -2
  52. package/src/channels/weixin/weixin-controller.mjs +133 -104
  53. package/src/channels/weixin/weixin-runtime.mjs +35 -24
@@ -55,7 +55,8 @@ export class QqMenuStore {
55
55
  const entry = this.#entries.get(this.#key(route, actor));
56
56
  if (!entry || entry.used || !entry.view || entry.expiresAt <= this.#now()
57
57
  || (token && token !== entry.token)) return { error: t('这个菜单已过期,请回复 /m 重新打开。') };
58
- if (entry.workspace !== context.workspace || entry.sessionId !== context.sessionId) {
58
+ if (entry.workspace !== context.workspace || entry.sessionWorkspace !== context.sessionWorkspace
59
+ || entry.sessionId !== context.sessionId) {
59
60
  entry.used = true;
60
61
  return { error: t('会话或工作区已变化,请重新发送 /m。') };
61
62
  }
@@ -80,13 +81,15 @@ export function qqMenuPage(list, requestedPage = 0) {
80
81
  list.choices.length ? '' : t('暂无可用选项。')].filter(Boolean).join('\n'), entries, columns: 2 };
81
82
  }
82
83
 
83
- async function catalogFor(harness, sessionId, options) {
84
- const session = sessionId ? harness.workspaceSession?.(sessionId) : null;
84
+ async function catalogFor(harness, sessionId, key, options) {
85
+ const session = sessionId ? harness.workspaceSession?.(sessionId, key) : null;
85
86
  return typeof session?.models === 'function' ? session.models(options) : harness.listModels(options);
86
87
  }
87
88
 
88
89
  export async function qqMenuView(name, harness, state, key, { signal, busy = false } = {}) {
89
90
  const workspace = harness.currentWorkspace?.();
91
+ const sessionWorkspace = typeof harness.currentConversationWorkspace === 'function'
92
+ ? harness.currentConversationWorkspace(key) : workspace;
90
93
  const sessionId = state.sessionFor(key);
91
94
  const options = { signal };
92
95
  const archived = state.includesArchivedSessions?.() === true;
@@ -94,8 +97,8 @@ export async function qqMenuView(name, harness, state, key, { signal, busy = fal
94
97
  if (name === 'main' || name === 'status') {
95
98
  if (name === 'status') await harness.ensureRunning(options);
96
99
  const results = await Promise.allSettled([
97
- harness.listWorkspaceSessions?.(workspace, options),
98
- catalogFor(harness, sessionId, options),
100
+ harness.listWorkspaceSessions?.(name === 'main' ? sessionWorkspace : workspace, options),
101
+ catalogFor(harness, sessionId, key, options),
99
102
  harness.agentPresetSettings?.(options),
100
103
  ]);
101
104
  signal?.throwIfAborted();
@@ -125,8 +128,8 @@ export async function qqMenuView(name, harness, state, key, { signal, busy = fal
125
128
  ] };
126
129
  }
127
130
  if (name === 'sessions') {
128
- const listed = await harness.listWorkspaceSessions(workspace, options);
129
- return qqMenuPage({ title: t('📋 会话列表'), detail: clean(workspace), choices: visibleSessions(listed).map((item) =>
131
+ const listed = await harness.listWorkspaceSessions(sessionWorkspace, options);
132
+ return qqMenuPage({ title: t('📋 会话列表'), detail: clean(sessionWorkspace), choices: visibleSessions(listed).map((item) =>
130
133
  command(`${item.sessionId === sessionId ? '✓ ' : ''}${clean(item.title || item.sessionId, 70)}${item.archived ? t('(已归档)') : ''}`, `/session ${item.sessionId}`)) });
131
134
  }
132
135
  if (name === 'workspaces') {
@@ -135,7 +138,7 @@ export async function qqMenuView(name, harness, state, key, { signal, busy = fal
135
138
  command(`${path === workspace ? '✓ ' : ''}${clean(path)}`, `/workspace ${path}`)) });
136
139
  }
137
140
  if (name === 'models') {
138
- const catalog = await catalogFor(harness, sessionId, options);
141
+ const catalog = await catalogFor(harness, sessionId, key, options);
139
142
  return qqMenuPage({ title: t('🧠 模型'), detail: catalog.failures?.length ? t('部分模型暂不可用,可稍后重试。') : '',
140
143
  choices: catalog.groups.flatMap((group) => group.models.map((model) => command(
141
144
  `${catalog.current?.provider === group.id && catalog.current?.model === model.id ? '✓ ' : ''}${clean(group.name, 30)} · ${clean(model.name, 60)}`,