@xmanrui/dsh-im 4.10.0 → 4.12.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 (62) hide show
  1. package/PROACTIVE_DELIVERY.en.md +15 -1
  2. package/PROACTIVE_DELIVERY.md +15 -1
  3. package/README.en.md +7 -2
  4. package/README.md +8 -3
  5. package/lib/client.js +2341 -1315
  6. package/lib/index.js +250 -245
  7. package/package.json +4 -3
  8. package/plugin-src/client/channel-card-meta.js +9 -1
  9. package/plugin-src/client/channels/dingtalk/api.js +4 -0
  10. package/plugin-src/client/channels/dingtalk/index.js +41 -7
  11. package/plugin-src/client/channels/feishu/api.js +4 -0
  12. package/plugin-src/client/channels/feishu/group-settings.js +581 -0
  13. package/plugin-src/client/channels/feishu/index.js +64 -233
  14. package/plugin-src/client/channels/qq/api.js +4 -0
  15. package/plugin-src/client/channels/qq/index.js +41 -7
  16. package/plugin-src/client/channels/shared/collapsible-account.js +80 -0
  17. package/plugin-src/client/channels/shared/token-api.js +4 -0
  18. package/plugin-src/client/channels/shared/token-channel.js +62 -29
  19. package/plugin-src/client/channels/wecom/api.js +4 -0
  20. package/plugin-src/client/channels/wecom/index.js +41 -7
  21. package/plugin-src/client/channels/weixin/api.js +4 -0
  22. package/plugin-src/client/channels/weixin/index.js +41 -7
  23. package/plugin-src/client/channels/whatsapp/api.js +4 -0
  24. package/plugin-src/client/channels/whatsapp/index.js +40 -7
  25. package/plugin-src/client/delivery-settings.js +73 -5
  26. package/plugin-src/client/i18n.js +22 -0
  27. package/plugin-src/client/model-setting.js +104 -0
  28. package/plugin-src/client/styles.js +62 -0
  29. package/plugin-src/host/channels/dingtalk/production.mjs +3 -0
  30. package/plugin-src/host/channels/dingtalk/rpc.mjs +11 -0
  31. package/plugin-src/host/channels/feishu/production.mjs +3 -0
  32. package/plugin-src/host/channels/feishu/rpc.mjs +16 -0
  33. package/plugin-src/host/channels/qq/production.mjs +3 -0
  34. package/plugin-src/host/channels/qq/rpc.mjs +11 -0
  35. package/plugin-src/host/channels/shared/model-setting-rpc.mjs +19 -0
  36. package/plugin-src/host/channels/shared/production.mjs +3 -0
  37. package/plugin-src/host/channels/shared/rpc.mjs +9 -0
  38. package/plugin-src/host/channels/shared/workspace-rpc.mjs +2 -0
  39. package/plugin-src/host/channels/slack/production.mjs +3 -0
  40. package/plugin-src/host/channels/slack/rpc.mjs +9 -0
  41. package/plugin-src/host/channels/wecom/production.mjs +3 -0
  42. package/plugin-src/host/channels/wecom/rpc.mjs +11 -0
  43. package/plugin-src/host/channels/weixin/production.mjs +3 -0
  44. package/plugin-src/host/channels/weixin/rpc.mjs +11 -0
  45. package/plugin-src/host/channels/whatsapp/production.mjs +3 -0
  46. package/plugin-src/host/channels/whatsapp/rpc.mjs +11 -0
  47. package/plugin-src/host/delivery-adapter.mjs +141 -3
  48. package/plugin-src/host/delivery-rpc.mjs +12 -0
  49. package/plugin-src/host/delivery-service.mjs +110 -3
  50. package/plugin-src/host/delivery-suggestions.mjs +46 -0
  51. package/plugin-src/host/harness-session-coordinator.mjs +6 -5
  52. package/plugin-src/host/index.mjs +18 -1
  53. package/plugin-src/host/session-sync-coordinator.mjs +217 -0
  54. package/scripts/verify-package.mjs +12 -6
  55. package/src/channels/shared/bot-workspace-store.mjs +285 -38
  56. package/src/channels/shared/harness-client.mjs +124 -43
  57. package/src/channels/shared/i18n-en/wecom.mjs +24 -0
  58. package/src/channels/shared/model-setting.mjs +110 -0
  59. package/src/channels/wecom/wecom-bridge.mjs +275 -2
  60. package/src/channels/wecom/wecom-cards.mjs +101 -0
  61. package/src/channels/wecom/wecom-runtime.mjs +2 -0
  62. package/src/channels/whatsapp/whatsapp-runtime.mjs +78 -26
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xmanrui/dsh-im",
3
- "version": "4.10.0",
3
+ "version": "4.12.0",
4
4
  "description": "把九种 IM 机器人和公网 AI Office 接入本机 DeepSeek Harness。 Connect nine IM channels and a public AI Office to a local DeepSeek Harness.",
5
5
  "keywords": [
6
6
  "deepseek-harness",
@@ -89,11 +89,12 @@
89
89
  "platform": "web"
90
90
  },
91
91
  "compatibility": {
92
- "dsh": "0.1.2-alpha.4 || 0.1.2-alpha.5 || 0.1.2-rc.1",
92
+ "dsh": "0.1.2-alpha.4 || 0.1.2-alpha.5 || 0.1.2-rc.1 || 0.1.3-alpha.1",
93
93
  "dshReleases": {
94
94
  "0.1.2-alpha.4": "compatible",
95
95
  "0.1.2-alpha.5": "compatible",
96
- "0.1.2-rc.1": "compatible"
96
+ "0.1.2-rc.1": "compatible",
97
+ "0.1.3-alpha.1": "compatible"
97
98
  },
98
99
  "profiles": [
99
100
  "web"
@@ -22,7 +22,14 @@ function SettingsGlyph() {
22
22
  h('path', { d: 'M19.4 15a1.7 1.7 0 0 0 .34 1.88l.06.06-2.83 2.83-.06-.06a1.7 1.7 0 0 0-1.88-.34 1.7 1.7 0 0 0-1.03 1.55V21h-4v-.08A1.7 1.7 0 0 0 8.97 19.4a1.7 1.7 0 0 0-1.88.34l-.06.06-2.83-2.83.06-.06A1.7 1.7 0 0 0 4.6 15a1.7 1.7 0 0 0-1.52-1.03H3v-4h.08A1.7 1.7 0 0 0 4.6 8.97a1.7 1.7 0 0 0-.34-1.88l-.06-.06L7.03 4.2l.06.06a1.7 1.7 0 0 0 1.88.34A1.7 1.7 0 0 0 10 3.08V3h4v.08a1.7 1.7 0 0 0 1.03 1.52 1.7 1.7 0 0 0 1.88-.34l.06-.06 2.83 2.83-.06.06a1.7 1.7 0 0 0-.34 1.88A1.7 1.7 0 0 0 20.92 10H21v4h-.08A1.7 1.7 0 0 0 19.4 15Z' }));
23
23
  }
24
24
 
25
- export function BotSettingsButton({ channel, botId, botName, connected, accessPolicy }) {
25
+ export function BotSettingsButton({
26
+ channel,
27
+ botId,
28
+ botName,
29
+ connected,
30
+ accessPolicy,
31
+ channelSettings,
32
+ }) {
26
33
  const { openBotSettings } = React.useContext(BotSettingsContext);
27
34
  const tooltipId = React.useId();
28
35
  return h('span', { className: 'dim-botSettingsAction' },
@@ -33,6 +40,7 @@ export function BotSettingsButton({ channel, botId, botName, connected, accessPo
33
40
  'aria-label': '更多机器人设置',
34
41
  'aria-describedby': tooltipId,
35
42
  onClick: () => openBotSettings?.({
43
+ ...(channelSettings && typeof channelSettings === 'object' ? channelSettings : {}),
36
44
  channel,
37
45
  botId,
38
46
  botName,
@@ -1,4 +1,5 @@
1
1
  import { normalizeAgentPresetCatalog, normalizeAgentPresetId, SET_AGENT_PRESET_ENDPOINT } from '../../agent-preset.js';
2
+ import { normalizeModelCatalog, normalizeModelSelection, SET_MODEL_ENDPOINT } from '../../model-setting.js';
2
3
  import { normalizeLastMessageError } from '../../last-message-error.js';
3
4
  import { normalizeAccessPolicy } from '../../../../src/channels/shared/access-policy.mjs';
4
5
  import { normalizeContextEnhancementConfig } from '../../../../src/channels/shared/context-enhancement.mjs';
@@ -14,6 +15,7 @@ export const DINGTALK_ENDPOINTS = Object.freeze({
14
15
  reconnectBot: 'bot.reconnect',
15
16
  deleteBot: 'bot.delete',
16
17
  setWorkspace: 'bot.workspace.set',
18
+ setModel: SET_MODEL_ENDPOINT,
17
19
  setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
18
20
  setContextEnhancement: 'bot.context-enhancement.set',
19
21
  setAccessPolicy: 'bot.access-policy.set',
@@ -181,6 +183,7 @@ function normalizeBot(value) {
181
183
  connected,
182
184
  configured: value.configured !== false,
183
185
  workspace: optionalString(value.workspace, 4_096) ?? '',
186
+ model: normalizeModelSelection(value.model),
184
187
  agentPreset: normalizeAgentPresetId(value.agentPreset),
185
188
  contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
186
189
  ...(Object.hasOwn(value, 'accessPolicy')
@@ -231,6 +234,7 @@ export function normalizeSnapshot(value) {
231
234
  provisioning: source.provisioning ? normalizeProvisioning(source.provisioning) : null,
232
235
  testMessage: normalizeTestMessage(source.testMessage),
233
236
  agentPresetCatalog: normalizeAgentPresetCatalog(source.agentPresetCatalog),
237
+ modelCatalog: normalizeModelCatalog(source.modelCatalog),
234
238
  };
235
239
  }
236
240
 
@@ -1,6 +1,7 @@
1
1
  import * as React from 'react';
2
2
 
3
3
  import { CredentialActionIcon, CredentialBindingPanel, QrActionIcon } from '../../credential-binding.js';
4
+ import { CollapsibleAccountSection } from '../shared/collapsible-account.js';
4
5
  import { h } from '../../i18n.js';
5
6
  import { WorkspaceEditor } from '../../workspace-editor.js';
6
7
  import { ContextEnhancementEditor } from '../../context-enhancement.js';
@@ -9,6 +10,11 @@ import {
9
10
  AgentPresetEditor,
10
11
  EMPTY_AGENT_PRESET_CATALOG,
11
12
  } from '../../agent-preset.js';
13
+ import {
14
+ EMPTY_MODEL_CATALOG,
15
+ ModelCatalogContext,
16
+ ModelEditor,
17
+ } from '../../model-setting.js';
12
18
  import { useWorkspaceSnapshotFence } from '../../workspace-snapshot-fence.js';
13
19
  import {
14
20
  BotSettingsButton,
@@ -238,6 +244,7 @@ export function AccountCard({
238
244
  removing,
239
245
  onReconnect,
240
246
  onWorkspaceSave,
247
+ onModelSave,
241
248
  onAgentPresetSave,
242
249
  onContextEnhancementSave,
243
250
  onRequestRemove,
@@ -250,13 +257,20 @@ export function AccountCard({
250
257
  const summary = account.error?.message ?? (account.connected ? null : account.health.summary);
251
258
  return h('article', { className: 'ddt-card dim-botCard', tabIndex: -1, 'data-bot-id': account.botId },
252
259
  h('div', { className: 'ddt-cardBody dim-botCardBody' },
253
- h('div', { className: 'ddt-accountTop dim-botCardTop' },
260
+ h(CollapsibleAccountSection, {
261
+ id: `ddt-settings-${account.botId.replace(/[^a-zA-Z0-9_-]/g, '-')}`,
262
+ header: h('div', { className: 'ddt-accountTop dim-botCardTop' },
254
263
  h('div', { className: 'ddt-accountIdentity dim-botIdentity' },
255
264
  h('div', { className: 'ddt-avatar dim-botAvatar', 'aria-hidden': 'true' }, h(DingtalkIcon, { size: 29 })),
256
265
  h('div', { className: 'dim-botName' },
257
266
  h('h3', { title: account.bot.name }, account.bot.name),
258
267
  h('p', { title: account.bot.clientIdMasked }, account.bot.clientIdMasked))),
259
- h('div', { className: 'dim-botCardTools' },
268
+ h('div', {
269
+ className: 'dim-botCardTools',
270
+ // The header is the collapse toggle; keep inner controls clickable.
271
+ onClick: (event) => { event.stopPropagation(); },
272
+ onKeyDown: (event) => { if (event.key === 'Enter' || event.key === ' ') event.stopPropagation(); },
273
+ },
260
274
  h(BotStatusMeta, {
261
275
  className: 'ddt-health',
262
276
  dotClassName: 'ddt-dot',
@@ -271,12 +285,18 @@ export function AccountCard({
271
285
  botName: account.bot.name,
272
286
  connected: account.connected,
273
287
  accessPolicy: account.accessPolicy,
274
- }))),
275
- h(WorkspaceEditor, {
288
+ })))
289
+ },
290
+ h(WorkspaceEditor, {
276
291
  workspace: account.workspace,
277
292
  disabled: Boolean(busy),
278
293
  onSave: onWorkspaceSave,
279
294
  }),
295
+ h(ModelEditor, {
296
+ model: account.model,
297
+ disabled: Boolean(busy),
298
+ onSave: onModelSave,
299
+ }),
280
300
  h(AgentPresetEditor, {
281
301
  agentPreset: account.agentPreset,
282
302
  disabled: Boolean(busy),
@@ -303,7 +323,9 @@ export function AccountCard({
303
323
  feedback ? h('div', {
304
324
  className: 'ddt-summary dim-cardFeedback',
305
325
  role: 'status',
306
- }, feedback) : null))),
326
+ }, feedback) : null)),
327
+ ),
328
+ ),
307
329
  removing ? h(RemoveConfirmation, {
308
330
  account,
309
331
  busy: busy === 'delete',
@@ -327,6 +349,7 @@ function AccountList(props) {
327
349
  removing: props.removeTarget === account.botId,
328
350
  onReconnect: () => props.onReconnect(account),
329
351
  onWorkspaceSave: (workspace) => props.onWorkspaceSave(account, workspace),
352
+ onModelSave: (model) => props.onModelSave(account, model),
330
353
  onAgentPresetSave: (agentPreset) => props.onAgentPresetSave(account, agentPreset),
331
354
  onContextEnhancementSave: (config) => props.onContextEnhancementSave(account, config),
332
355
  onRequestRemove: () => props.onRequestRemove(account),
@@ -341,6 +364,7 @@ export function DingtalkSettingsTab({ rpcCall }) {
341
364
  const [model, setModel] = React.useState({
342
365
  phase: 'loading', bots: [], totals: EMPTY_TOTALS, revision: 0, error: null,
343
366
  agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG,
367
+ modelCatalog: EMPTY_MODEL_CATALOG,
344
368
  });
345
369
  const [provision, setProvision] = React.useState(null);
346
370
  const [busy, setBusy] = React.useState(false);
@@ -448,6 +472,7 @@ export function DingtalkSettingsTab({ rpcCall }) {
448
472
  revision: snapshot.revision,
449
473
  error: null,
450
474
  agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG,
475
+ modelCatalog: snapshot.modelCatalog ?? EMPTY_MODEL_CATALOG,
451
476
  });
452
477
  discardStaleFeedback(snapshot);
453
478
  if (restoreProvisioning && snapshot.provisioning) {
@@ -564,6 +589,7 @@ export function DingtalkSettingsTab({ rpcCall }) {
564
589
  revision: snapshot.revision,
565
590
  error: null,
566
591
  agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG,
592
+ modelCatalog: snapshot.modelCatalog ?? EMPTY_MODEL_CATALOG,
567
593
  });
568
594
  discardStaleFeedback(snapshot);
569
595
  }
@@ -705,6 +731,7 @@ export function DingtalkSettingsTab({ rpcCall }) {
705
731
  revision: snapshot.revision,
706
732
  error: null,
707
733
  agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG,
734
+ modelCatalog: snapshot.modelCatalog ?? EMPTY_MODEL_CATALOG,
708
735
  });
709
736
  discardStaleFeedback(snapshot);
710
737
  }
@@ -771,6 +798,7 @@ export function DingtalkSettingsTab({ rpcCall }) {
771
798
  revision: snapshot.revision,
772
799
  error: null,
773
800
  agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG,
801
+ modelCatalog: snapshot.modelCatalog ?? EMPTY_MODEL_CATALOG,
774
802
  });
775
803
  discardStaleFeedback(snapshot);
776
804
  }
@@ -797,6 +825,7 @@ export function DingtalkSettingsTab({ rpcCall }) {
797
825
  revision: snapshot.revision,
798
826
  error: null,
799
827
  agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG,
828
+ modelCatalog: snapshot.modelCatalog ?? EMPTY_MODEL_CATALOG,
800
829
  });
801
830
  discardStaleFeedback(snapshot);
802
831
  }
@@ -859,7 +888,9 @@ export function DingtalkSettingsTab({ rpcCall }) {
859
888
  })
860
889
  : null;
861
890
 
862
- return h(AgentPresetCatalogContext.Provider, {
891
+ return h(ModelCatalogContext.Provider, {
892
+ value: model.modelCatalog ?? EMPTY_MODEL_CATALOG,
893
+ }, h(AgentPresetCatalogContext.Provider, {
863
894
  value: model.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG,
864
895
  }, h('section', { className: 'ddt-page dim-channelPage', 'aria-label': '钉钉设置' },
865
896
  h(Heading, {
@@ -897,6 +928,9 @@ export function DingtalkSettingsTab({ rpcCall }) {
897
928
  removeTarget,
898
929
  onReconnect: (account) => void reconnect(account),
899
930
  onWorkspaceSave: saveWorkspace,
931
+ onModelSave: (account, selectedModel) => saveBotSetting(
932
+ account, 'model', DINGTALK_ENDPOINTS.setModel, { model: selectedModel },
933
+ ),
900
934
  onAgentPresetSave: (account, agentPreset) => saveBotSetting(
901
935
  account, 'preset', DINGTALK_ENDPOINTS.setAgentPreset, { agentPreset },
902
936
  ),
@@ -907,5 +941,5 @@ export function DingtalkSettingsTab({ rpcCall }) {
907
941
  onConfirmRemove: (account) => void remove(account),
908
942
  onCancelRemove: () => setRemoveTarget(null),
909
943
  })
910
- : null)));
944
+ : null))));
911
945
  }
@@ -7,6 +7,7 @@
7
7
  */
8
8
 
9
9
  import { normalizeAgentPresetCatalog, normalizeAgentPresetId } from "../../agent-preset.js";
10
+ import { normalizeModelCatalog, normalizeModelSelection, SET_MODEL_ENDPOINT } from "../../model-setting.js";
10
11
  import { normalizeLastMessageError } from "../../last-message-error.js";
11
12
  import { normalizeAccessPolicy } from "../../../../src/channels/shared/access-policy.mjs";
12
13
  import { normalizeContextEnhancementConfig } from "../../../../src/channels/shared/context-enhancement.mjs";
@@ -25,6 +26,7 @@ export const FEISHU_ENDPOINTS = Object.freeze({
25
26
  disconnectBot: "bot.disconnect",
26
27
  deleteBot: "bot.delete",
27
28
  setWorkspace: "bot.workspace.set",
29
+ setModel: SET_MODEL_ENDPOINT,
28
30
  setAgentPreset: "bot.preset.set",
29
31
  setContextEnhancement: "bot.context-enhancement.set",
30
32
  setAccessPolicy: "bot.access-policy.set",
@@ -207,6 +209,7 @@ export function normalizeBotConnection(value, fallbackBotId) {
207
209
  connected,
208
210
  configured: value.configured !== false,
209
211
  workspace: optionalString(value.workspace)?.slice(0, 4_096) ?? "",
212
+ model: normalizeModelSelection(value.model),
210
213
  agentPreset: normalizeAgentPresetId(value.agentPreset),
211
214
  contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
212
215
  ...(Object.hasOwn(value, "accessPolicy")
@@ -272,6 +275,7 @@ export function normalizeBotsSnapshot(value) {
272
275
  : undefined,
273
276
  error: normalizeError(value.error),
274
277
  agentPresetCatalog: normalizeAgentPresetCatalog(value.agentPresetCatalog),
278
+ modelCatalog: normalizeModelCatalog(value.modelCatalog),
275
279
  };
276
280
  }
277
281