@xmanrui/dsh-im 4.31.0 → 4.32.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.
@@ -4,6 +4,10 @@ dsh-im 发布可选客户端服务 `dshImClient`,供同一 DSH 客户端中的
4
4
 
5
5
  The optional `dshImClient` service exposes the existing IM management panel to a shell in the same DSH client. Settings → IM bots remains available by default. No migration or new configuration is required. The host-side `dshIm` delivery service is separate.
6
6
 
7
+ 支持插件详情操作按钮的 DSH 中,dsh-im 详情页提供「打开 IM机器人」按钮,在主区域打开同一管理面板;「返回插件详情」返回该插件。此入口依赖可选的 `layout`、`pluginNavigation` 服务及 `plugins.detail.actions` 槽位,旧版 DSH 仍可通过设置入口访问。
8
+
9
+ On DSH versions with plugin detail actions, **Open IM bots** opens the same management panel in the main area, with **Back to plugin details** returning to this plugin. This entry uses the optional `layout` and `pluginNavigation` services and the `plugins.detail.actions` slot. Older DSH versions retain the Settings entry.
10
+
7
11
  ```ts
8
12
  interface DshImClient {
9
13
  readonly version: 1;
package/lib/client.js CHANGED
@@ -590,14 +590,14 @@ async function callManagementRpc(connection, channel7, method, payload, signal)
590
590
  }
591
591
 
592
592
  // plugin-src/client/index.js
593
- var React37 = __toESM(require("react"), 1);
593
+ var React38 = __toESM(require("react"), 1);
594
594
 
595
595
  // package.json
596
596
  var package_default = {
597
597
  name: "@xmanrui/dsh-im",
598
- version: "4.31.0",
598
+ version: "4.32.0",
599
599
  icon: "./assets/logo-plugin-message-link-gradient.webp",
600
- description: "\u628A\u5341\u4E8C\u79CD IM \u6E20\u9053\u548C\u516C\u7F51 AI Office \u63A5\u5165\u672C\u673A DeepSeek Harness\u3002 Connect twelve IM channels and a public AI Office to a local DeepSeek Harness.",
600
+ description: "\u628A\u5FAE\u4FE1\u3001\u98DE\u4E66\u3001\u4F01\u5FAE\u3001\u9489\u9489\u3001QQ\u3001Telegram\u3001WhatsApp\u3001Slack\u3001Discord\u3001Matrix\u63A5\u5165DSH\u3002 Connect Telegram, WhatsApp, Slack, Discord, Matrix, WeChat, Feishu, WeCom, DingTalk, and QQ to DSH.",
601
601
  keywords: [
602
602
  "deepseek-harness",
603
603
  "dsh",
@@ -711,13 +711,15 @@ var package_default = {
711
711
  exports: {
712
712
  ".": "./lib/index.js",
713
713
  "./client": "./lib/client.js",
714
- "./package.json": "./package.json"
714
+ "./package.json": "./package.json",
715
+ "./locale/*.json": "./locale/*.json"
715
716
  },
716
717
  files: [
717
718
  "assets",
718
719
  "bin",
719
720
  "cordis.patch.yml",
720
721
  "lib",
722
+ "locale/*.json",
721
723
  "plugin-src",
722
724
  "scripts/verify-interface-language.mjs",
723
725
  "scripts/verify-injected-context.mjs",
@@ -1255,6 +1257,8 @@ var EN = Object.freeze({
1255
1257
  "\u65E0\u9700\u5B89\u88C5\u7B2C\u4E09\u65B9\u670D\u52A1\uFF1B\u8BF7\u6309\u6307\u5F15\u6388\u4E88 macOS Messages \u8BBF\u95EE\u6743\u9650\u3002": "No third-party service is required; follow the guide to grant macOS Messages access.",
1256
1258
  "macOS Messages \u6743\u9650": "macOS Messages permissions",
1257
1259
  "IM\u673A\u5668\u4EBA": "IM bots",
1260
+ "\u6253\u5F00 IM\u673A\u5668\u4EBA": "Open IM bots",
1261
+ "\u8FD4\u56DE\u63D2\u4EF6\u8BE6\u60C5": "Back to plugin details",
1258
1262
  "IM\u673A\u5668\u4EBA\u8BBE\u7F6E": "IM bot settings",
1259
1263
  "IM \u9762\u677F\u52A0\u8F7D\u5931\u8D25": "Could not load the IM panel",
1260
1264
  "\u66F4\u591A\u673A\u5668\u4EBA\u8BBE\u7F6E": "More bot settings",
@@ -19236,6 +19240,15 @@ function replacePageLocation(url, location = globalThis.location) {
19236
19240
  // plugin-src/client/styles.js
19237
19241
  var IM_STYLE_ID = "xmanrui-dsh-im-settings";
19238
19242
  var CSS15 = String.raw`
19243
+ .dim-pluginOpen { display: inline-flex; align-items: center; justify-content: center; min-height: 36px; padding: 7px 14px; border: 1px solid var(--dsw-alias-border-l2, #dfe1e5); border-radius: 8px; color: var(--dsw-alias-label-primary, #1f2329); background: var(--dsw-alias-bg-layer-1, #fff); font: inherit; font-size: 13px; line-height: 20px; cursor: pointer; }
19244
+ .dim-pluginOpen:hover { background: var(--dsw-alias-interactive-bg-hover, #f7f8fa); }
19245
+ .dim-pluginOpen:focus-visible, .dim-pluginBack:focus-visible { outline: 2px solid var(--dsw-alias-state-business-primary, #3370ff); outline-offset: 3px; }
19246
+ .dim-pluginPage { height: 100%; min-height: 0; overflow: auto; box-sizing: border-box; padding: 24px clamp(16px, 4vw, 48px) 32px; color: var(--dsw-alias-label-primary, #1f2329); }
19247
+ .dim-pluginPageContent { max-width: 1080px; margin: 0 auto; }
19248
+ .dim-pluginBack { display: inline-flex; align-items: center; gap: 8px; min-height: 36px; margin: 0 0 24px; padding: 6px 8px; border: 0; border-radius: 8px; color: var(--dsw-alias-label-secondary, #646a73); background: transparent; font: inherit; font-size: 13px; line-height: 20px; cursor: pointer; }
19249
+ .dim-pluginBack:hover { color: var(--dsw-alias-label-primary, #1f2329); background: var(--dsw-alias-interactive-bg-hover, #f7f8fa); }
19250
+ .dim-pluginBack > span { font-size: 22px; line-height: 20px; }
19251
+ @media (pointer: coarse) { .dim-pluginOpen, .dim-pluginBack { min-height: 44px; } }
19239
19252
  .dim-connectionDiagnostic { min-width: 0; width: 100%; color: var(--dsw-alias-label-secondary, #646a73); overflow-wrap: anywhere; font-size: 13px; line-height: 1.6; }
19240
19253
  .dim-connectionDiagnostic[data-warning="true"] { color: var(--dsw-alias-state-warn-primary, #d97706); }
19241
19254
  .dim-connectionDiagnostic p { margin: 4px 0; }
@@ -20823,6 +20836,66 @@ var IMPanelErrorBoundary = class extends React36.Component {
20823
20836
  }
20824
20837
  };
20825
20838
 
20839
+ // plugin-src/client/plugin-page.js
20840
+ var React37 = __toESM(require("react"), 1);
20841
+ var IM_MAIN_PANEL_ID = "xmanrui-dsh-im";
20842
+ var h3 = React37.createElement;
20843
+ function OpenImAction({ subject, packageName, onOpen, t }) {
20844
+ if (subject?.kind !== "bundle" && subject?.kind !== "row") return null;
20845
+ if (subject.pkg?.name !== packageName) return null;
20846
+ if (subject.kind === "row" && subject.row?.moduleName !== packageName) return null;
20847
+ return h3("button", {
20848
+ type: "button",
20849
+ className: "dim-pluginOpen",
20850
+ onClick: onOpen
20851
+ }, t("\u6253\u5F00 IM\u673A\u5668\u4EBA"));
20852
+ }
20853
+ function ImPluginPage({ renderPanel, onBack, t }) {
20854
+ return h3(
20855
+ "div",
20856
+ { className: "dim-pluginPage" },
20857
+ h3(
20858
+ "div",
20859
+ { className: "dim-pluginPageContent" },
20860
+ h3(
20861
+ "button",
20862
+ { type: "button", className: "dim-pluginBack", onClick: onBack },
20863
+ h3("span", { "aria-hidden": true }, "\u2039"),
20864
+ t("\u8FD4\u56DE\u63D2\u4EF6\u8BE6\u60C5")
20865
+ ),
20866
+ renderPanel()
20867
+ )
20868
+ );
20869
+ }
20870
+ function installImPluginPage(ctx, { packageName, renderPanel }) {
20871
+ if (typeof ctx.inject !== "function") return;
20872
+ ctx.inject(["layout", "pluginNavigation"], (pageCtx) => pageCtx.slots.inject("main", () => {
20873
+ const unregisterPage = pageCtx.slots.register({
20874
+ name: "main",
20875
+ key: IM_MAIN_PANEL_ID,
20876
+ locale: IM_LOCALE_NAMESPACE,
20877
+ inject: () => ({
20878
+ renderPanel,
20879
+ onBack: () => pageCtx.pluginNavigation.openBundle(packageName)
20880
+ })
20881
+ }, ImPluginPage);
20882
+ const stopActions = pageCtx.slots.inject("plugins.detail.actions", () => pageCtx.slots.register({
20883
+ name: "plugins.detail.actions",
20884
+ id: "xmanrui-dsh-im-open",
20885
+ order: 20,
20886
+ locale: IM_LOCALE_NAMESPACE,
20887
+ inject: () => ({
20888
+ packageName,
20889
+ onOpen: () => pageCtx.layout.selectPanel(IM_MAIN_PANEL_ID)
20890
+ })
20891
+ }, OpenImAction));
20892
+ return () => {
20893
+ stopActions();
20894
+ unregisterPage();
20895
+ };
20896
+ }));
20897
+ }
20898
+
20826
20899
  // plugin-src/client/index.js
20827
20900
  var name = "im-settings";
20828
20901
  var inject = ["slots", "connection", "locale", "workspaces"];
@@ -20997,28 +21070,28 @@ function IMSettingsTab({
20997
21070
  browserLocation = globalThis.location,
20998
21071
  navigateToRecoveryUrl = replacePageLocation
20999
21072
  }) {
21000
- const [selected, setSelected] = React37.useState(() => preferredSectionId === GLOBAL_SETTINGS_TAB_ID || CHANNELS.some((channel7) => channel7.id === preferredSectionId) ? preferredSectionId : "weixin");
21001
- const [loopbackRecovery, setLoopbackRecovery] = React37.useState(null);
21002
- const [runningVersion, setRunningVersion] = React37.useState(IM_PLUGIN_VERSION);
21003
- const [deliverySettings, setDeliverySettings] = React37.useState(null);
21073
+ const [selected, setSelected] = React38.useState(() => preferredSectionId === GLOBAL_SETTINGS_TAB_ID || CHANNELS.some((channel7) => channel7.id === preferredSectionId) ? preferredSectionId : "weixin");
21074
+ const [loopbackRecovery, setLoopbackRecovery] = React38.useState(null);
21075
+ const [runningVersion, setRunningVersion] = React38.useState(IM_PLUGIN_VERSION);
21076
+ const [deliverySettings, setDeliverySettings] = React38.useState(null);
21004
21077
  const emailEnabled = useEmailChannelEnabled(emailRpcCall);
21005
- const visibleChannels = React37.useMemo(
21078
+ const visibleChannels = React38.useMemo(
21006
21079
  () => CHANNELS.filter((channel7) => channel7.id !== "email" || emailEnabled),
21007
21080
  [emailEnabled]
21008
21081
  );
21009
- const githubTooltipId = React37.useId();
21010
- const generalSettingsTooltipId = React37.useId();
21082
+ const githubTooltipId = React38.useId();
21083
+ const generalSettingsTooltipId = React38.useId();
21011
21084
  const globalSettingsSelected = selected === GLOBAL_SETTINGS_TAB_ID;
21012
21085
  const active = visibleChannels.find((channel7) => channel7.id === selected) ?? visibleChannels[0];
21013
21086
  const activeTabId = globalSettingsSelected ? "dim-general-settings-trigger" : `dim-tab-${active.id}`;
21014
21087
  const activePanelId = globalSettingsSelected ? `dim-panel-${GLOBAL_SETTINGS_TAB_ID}` : `dim-panel-${active.id}`;
21015
- const reportLoopbackRecovery = React37.useCallback((recovery) => {
21088
+ const reportLoopbackRecovery = React38.useCallback((recovery) => {
21016
21089
  setLoopbackRecovery((current) => current?.url === recovery.url ? current : recovery);
21017
21090
  }, []);
21018
- const reportUpdateStatus = React37.useCallback((snapshot) => {
21091
+ const reportUpdateStatus = React38.useCallback((snapshot) => {
21019
21092
  setRunningVersion(snapshot.runningVersion);
21020
21093
  }, []);
21021
- const rpcCalls = React37.useMemo(() => createLoopbackAwareRpcCalls({
21094
+ const rpcCalls = React38.useMemo(() => createLoopbackAwareRpcCalls({
21022
21095
  dingtalkRpcCall,
21023
21096
  discordRpcCall,
21024
21097
  feishuRpcCall,
@@ -21060,7 +21133,7 @@ function IMSettingsTab({
21060
21133
  weixinRpcCall,
21061
21134
  whatsappRpcCall
21062
21135
  ]);
21063
- const botSettingsContext = React37.useMemo(() => Object.freeze({
21136
+ const botSettingsContext = React38.useMemo(() => Object.freeze({
21064
21137
  openBotSettings: setDeliverySettings
21065
21138
  }), []);
21066
21139
  return h2(
@@ -21284,7 +21357,7 @@ function apply(ctx) {
21284
21357
  };
21285
21358
  const localeSnapshot = () => ctx.locale.getLocale?.()?.active ?? "";
21286
21359
  function IMPanel({ preferredSectionId }) {
21287
- React37.useSyncExternalStore(subscribeLocale, localeSnapshot, localeSnapshot);
21360
+ React38.useSyncExternalStore(subscribeLocale, localeSnapshot, localeSnapshot);
21288
21361
  return h2(
21289
21362
  IMPanelErrorBoundary,
21290
21363
  null,
@@ -21294,6 +21367,7 @@ function apply(ctx) {
21294
21367
  const buildPanelElement = (props = {}) => h2(IMPanel, {
21295
21368
  preferredSectionId: props.preferredSectionId
21296
21369
  });
21370
+ installImPluginPage(ctx, { packageName: package_default.name, renderPanel: buildPanelElement });
21297
21371
  ctx.effect(() => {
21298
21372
  let disposed = false;
21299
21373
  let stopSettings = null;