@rezti/dsh-rez-suite 0.1.25 → 0.1.27

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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @rezti/dsh-rez-suite
2
2
 
3
- 雷泽插件的**唯一安装入口**。Odoo / 企微 / HA / TAPD / GSC / 工作区(老板三室 + 全员助理)都由这一包拉齐,不要再逐个 `plugin add`,**不要**再装 `@rezti/dsh-rez-boss-desk`。
3
+ 雷泽插件的**唯一安装入口**。Odoo / 企微 / HA / TAPD / GSC / 天眼查(仅老板) / 工作区(老板三室 + 全员助理)都由这一包拉齐,不要再逐个 `plugin add`,**不要**再装 `@rezti/dsh-rez-boss-desk`。
4
4
 
5
5
  设置里选身份后,左侧自己出现对应房间(全员三助理;老板另加搞钱/产品/运营),不必手动添加工作区。
6
6
 
package/lib/client.d.ts CHANGED
@@ -7300,6 +7300,9 @@ declare const zh: {
7300
7300
  readonly 'config.gsc': "Google Search Console";
7301
7301
  readonly 'config.gsc.siteUrl': "站点 URL";
7302
7302
  readonly 'config.gsc.key': "服务账号 JSON 或密钥文件路径";
7303
+ readonly 'config.tianyancha': "天眼查(法务助理 · 仅老板)";
7304
+ readonly 'config.tianyancha.url': "天眼查 MCP URL";
7305
+ readonly 'config.tianyancha.token': "OpenAPI Token";
7303
7306
  readonly 'config.fs': "本地文件 (fs-mcp-server)";
7304
7307
  readonly 'config.fs.root': "根目录";
7305
7308
  readonly 'config.sqlite': "SQLite (sqlite-mcp-server)";
@@ -7356,6 +7359,13 @@ declare const zh: {
7356
7359
  readonly 'weixin.listening': "通道在听:微信 → 网页「微信」会话(同一条,不另开窗口)→ 回微信。";
7357
7360
  readonly 'weixin.loggedIn': "已登录,通道未在听。点「重新连接」即可拉起,不必再扫码。";
7358
7361
  readonly 'weixin.loggedOut': "尚未登录。";
7362
+ readonly 'upgrade.label': "升级";
7363
+ readonly 'upgrade.current': "已最新";
7364
+ readonly 'upgrade.aria': "升级 ReZ-TI 插件";
7365
+ readonly 'upgrade.running': "升级中…";
7366
+ readonly 'upgrade.reloading': "正在重载";
7367
+ readonly 'upgrade.already': "已是 {version}";
7368
+ readonly 'upgrade.reloadTimeout': "升级完成,但网页还没重新连上。请刷新这一页。";
7359
7369
  };
7360
7370
  type RezKey = keyof typeof zh;
7361
7371
  //#endregion
@@ -7379,6 +7389,13 @@ declare module '@deepseek-ai/dsh-client-ui-slots' {
7379
7389
  children?: never;
7380
7390
  };
7381
7391
  };
7392
+ 'sidebar.footer.action': {
7393
+ kind: 'list';
7394
+ scope: 'root';
7395
+ owner: {
7396
+ wide: boolean;
7397
+ };
7398
+ };
7382
7399
  }
7383
7400
  }
7384
7401
  declare const inject: string[];
package/lib/client.js CHANGED
@@ -4,7 +4,7 @@ window.__ModuleLoader__.load({
4
4
  var module = { exports: {} };
5
5
  var exports = module.exports;
6
6
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
7
- (function(){var id="dsh-rez-suite-css";if(typeof document==="undefined"||document.getElementById(id))return;var s=document.createElement("style");s.id=id;s.textContent=".LOjPTW_shell {\n flex-direction: column;\n gap: 12px;\n min-width: 0;\n display: flex;\n}\n\n.LOjPTW_card {\n border: 1px solid var(--dsw-alias-border-l2);\n background: var(--dsw-alias-bg-layer-3);\n border-radius: 12px;\n list-style: none;\n transition: border-color .16s, background .16s;\n}\n\n.LOjPTW_card:hover {\n border-color: var(--dsw-alias-label-dimmed);\n}\n\n.LOjPTW_cardOpen {\n background: var(--dsw-alias-bg-layer-2);\n border-color: var(--dsw-alias-label-dimmed);\n}\n\n.LOjPTW_header {\n appearance: none;\n width: 100%;\n font: inherit;\n color: inherit;\n text-align: left;\n cursor: pointer;\n background: none;\n border: 0;\n border-radius: 12px;\n align-items: center;\n gap: 12px;\n padding: 14px 16px;\n display: flex;\n}\n\n.LOjPTW_header:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: -2px;\n}\n\n.LOjPTW_headText {\n flex-direction: column;\n flex: 1;\n gap: 4px;\n min-width: 0;\n display: flex;\n}\n\n.LOjPTW_name {\n color: var(--dsw-alias-label-primary);\n font-size: 15px;\n font-weight: 600;\n line-height: 1.4;\n}\n\n.LOjPTW_description {\n color: var(--dsw-alias-label-tertiary);\n font-size: 13px;\n line-height: 1.5;\n}\n\n.LOjPTW_chevron {\n color: var(--dsw-alias-label-tertiary);\n flex: none;\n transition: transform .16s;\n}\n\n.LOjPTW_chevronOpen {\n transform: rotate(180deg);\n}\n\n.LOjPTW_body {\n border-top: 1px solid var(--dsw-alias-border-l2);\n margin: 0 16px 12px;\n padding-top: 8px;\n}\n\n.LOjPTW_tabBar {\n border-bottom: 1px solid var(--dsw-alias-border-l1);\n flex: none;\n gap: 2px;\n display: flex;\n}\n\n.LOjPTW_tab {\n color: var(--dsw-alias-label-secondary);\n cursor: pointer;\n background: none;\n border: none;\n border-bottom: 2px solid #0000;\n border-radius: 6px 6px 0 0;\n padding: 7px 14px;\n font-size: 13px;\n}\n\n.LOjPTW_tab:hover {\n color: var(--dsw-alias-label-primary);\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.LOjPTW_tab[data-active] {\n color: var(--dsw-alias-label-primary);\n border-bottom-color: var(--dsw-alias-state-business-primary);\n font-weight: 600;\n}\n\n.LOjPTW_tabBody {\n flex-direction: column;\n gap: 12px;\n min-width: 0;\n padding: 12px 0 4px;\n display: flex;\n}\n\n.LOjPTW_section {\n border: 1px solid var(--dsw-alias-border-l1);\n background: var(--dsw-alias-bg-layer-1, var(--dsw-alias-bg-base));\n border-radius: 10px;\n flex-direction: column;\n gap: 8px;\n padding: 12px;\n display: flex;\n}\n\n.LOjPTW_sectionTitle {\n color: var(--dsw-alias-label-primary);\n margin: 0;\n font-size: 13px;\n font-weight: 600;\n}\n\n.LOjPTW_field {\n flex-direction: column;\n align-items: stretch;\n gap: 4px;\n display: flex;\n}\n\n.LOjPTW_label {\n color: var(--dsw-alias-label-secondary);\n font-size: 12.5px;\n}\n\n.LOjPTW_input, .LOjPTW_select {\n color: var(--dsw-alias-label-primary);\n background: var(--dsw-specific-input-major, var(--dsw-alias-bg-layer-3));\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 8px;\n outline: none;\n padding: 6px 8px;\n font-size: 13px;\n}\n\n.LOjPTW_checkbox {\n justify-self: start;\n width: 15px;\n height: 15px;\n}\n\n.LOjPTW_toolbar {\n flex-wrap: wrap;\n flex: none;\n align-items: center;\n gap: 8px;\n display: flex;\n}\n\n.LOjPTW_button {\n border: 1px solid var(--dsw-alias-border-l2);\n background: var(--dsw-specific-input-major, var(--dsw-alias-bg-layer-3));\n color: var(--dsw-alias-label-primary);\n cursor: pointer;\n border-radius: 8px;\n padding: 7px 12px;\n font-size: 13px;\n}\n\n.LOjPTW_button:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.LOjPTW_button:disabled {\n opacity: .4;\n cursor: default;\n}\n\n.LOjPTW_primaryButton {\n background: var(--dsw-alias-label-primary);\n border-color: var(--dsw-alias-label-primary);\n color: var(--dsw-alias-bg-layer-3);\n}\n\n.LOjPTW_dangerButton {\n background: var(--dsw-alias-state-danger, #c62828);\n border-color: var(--dsw-alias-state-danger, #c62828);\n color: #fff;\n}\n\n.LOjPTW_qr {\n background: #fff;\n border-radius: 8px;\n width: 200px;\n height: 200px;\n margin: 8px 0;\n display: block;\n}\n\n.LOjPTW_message {\n color: var(--dsw-alias-label-secondary);\n margin: 0;\n font-size: 12.5px;\n line-height: 1.5;\n}\n\n.LOjPTW_error {\n color: var(--dsw-alias-state-danger, #c62828);\n}\n\n.LOjPTW_tableWrap {\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 10px;\n overflow: auto;\n}\n\n.LOjPTW_table {\n border-collapse: collapse;\n width: 100%;\n font-size: 12.5px;\n}\n\n.LOjPTW_table th {\n z-index: 1;\n text-align: left;\n background: var(--dsw-alias-bg-layer-2, var(--dsw-alias-bg-layer-1));\n padding: 8px 10px;\n position: sticky;\n top: 0;\n}\n\n.LOjPTW_table td {\n border-top: 1px solid var(--dsw-alias-border-l1);\n vertical-align: top;\n padding: 8px 10px;\n}\n\n.LOjPTW_badge {\n border-radius: 999px;\n padding: 2px 8px;\n font-size: 11px;\n display: inline-block;\n}\n\n.LOjPTW_badgeOk {\n color: #229a55;\n background: #229a5524;\n}\n\n.LOjPTW_badgeFail {\n color: #c62828;\n background: #c6282824;\n}\n\n.LOjPTW_cards {\n grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));\n gap: 8px;\n display: grid;\n}\n\n.LOjPTW_stat {\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 10px;\n padding: 10px;\n}\n\n.LOjPTW_cardLabel {\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n}\n\n.LOjPTW_cardValue {\n color: var(--dsw-alias-label-primary);\n font-size: 15px;\n font-weight: 600;\n}\n";document.head.appendChild(s);})();
7
+ (function(){var id="dsh-rez-suite-css";if(typeof document==="undefined"||document.getElementById(id))return;var s=document.createElement("style");s.id=id;s.textContent=".LOjPTW_shell {\n flex-direction: column;\n gap: 12px;\n min-width: 0;\n display: flex;\n}\n\n.LOjPTW_card {\n border: 1px solid var(--dsw-alias-border-l2);\n background: var(--dsw-alias-bg-layer-3);\n border-radius: 12px;\n list-style: none;\n transition: border-color .16s, background .16s;\n}\n\n.LOjPTW_card:hover {\n border-color: var(--dsw-alias-label-dimmed);\n}\n\n.LOjPTW_cardOpen {\n background: var(--dsw-alias-bg-layer-2);\n border-color: var(--dsw-alias-label-dimmed);\n}\n\n.LOjPTW_header {\n appearance: none;\n width: 100%;\n font: inherit;\n color: inherit;\n text-align: left;\n cursor: pointer;\n background: none;\n border: 0;\n border-radius: 12px;\n align-items: center;\n gap: 12px;\n padding: 14px 16px;\n display: flex;\n}\n\n.LOjPTW_header:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: -2px;\n}\n\n.LOjPTW_headText {\n flex-direction: column;\n flex: 1;\n gap: 4px;\n min-width: 0;\n display: flex;\n}\n\n.LOjPTW_name {\n color: var(--dsw-alias-label-primary);\n font-size: 15px;\n font-weight: 600;\n line-height: 1.4;\n}\n\n.LOjPTW_description {\n color: var(--dsw-alias-label-tertiary);\n font-size: 13px;\n line-height: 1.5;\n}\n\n.LOjPTW_chevron {\n color: var(--dsw-alias-label-tertiary);\n flex: none;\n transition: transform .16s;\n}\n\n.LOjPTW_chevronOpen {\n transform: rotate(180deg);\n}\n\n.LOjPTW_body {\n border-top: 1px solid var(--dsw-alias-border-l2);\n margin: 0 16px 12px;\n padding-top: 8px;\n}\n\n.LOjPTW_tabBar {\n border-bottom: 1px solid var(--dsw-alias-border-l1);\n flex: none;\n gap: 2px;\n display: flex;\n}\n\n.LOjPTW_tab {\n color: var(--dsw-alias-label-secondary);\n cursor: pointer;\n background: none;\n border: none;\n border-bottom: 2px solid #0000;\n border-radius: 6px 6px 0 0;\n padding: 7px 14px;\n font-size: 13px;\n}\n\n.LOjPTW_tab:hover {\n color: var(--dsw-alias-label-primary);\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.LOjPTW_tab[data-active] {\n color: var(--dsw-alias-label-primary);\n border-bottom-color: var(--dsw-alias-state-business-primary);\n font-weight: 600;\n}\n\n.LOjPTW_tabBody {\n flex-direction: column;\n gap: 12px;\n min-width: 0;\n padding: 12px 0 4px;\n display: flex;\n}\n\n.LOjPTW_section {\n border: 1px solid var(--dsw-alias-border-l1);\n background: var(--dsw-alias-bg-layer-1, var(--dsw-alias-bg-base));\n border-radius: 10px;\n flex-direction: column;\n gap: 8px;\n padding: 12px;\n display: flex;\n}\n\n.LOjPTW_sectionTitle {\n color: var(--dsw-alias-label-primary);\n margin: 0;\n font-size: 13px;\n font-weight: 600;\n}\n\n.LOjPTW_field {\n flex-direction: column;\n align-items: stretch;\n gap: 4px;\n display: flex;\n}\n\n.LOjPTW_label {\n color: var(--dsw-alias-label-secondary);\n font-size: 12.5px;\n}\n\n.LOjPTW_input, .LOjPTW_select {\n color: var(--dsw-alias-label-primary);\n background: var(--dsw-specific-input-major, var(--dsw-alias-bg-layer-3));\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 8px;\n outline: none;\n padding: 6px 8px;\n font-size: 13px;\n}\n\n.LOjPTW_checkbox {\n justify-self: start;\n width: 15px;\n height: 15px;\n}\n\n.LOjPTW_toolbar {\n flex-wrap: wrap;\n flex: none;\n align-items: center;\n gap: 8px;\n display: flex;\n}\n\n.LOjPTW_button {\n border: 1px solid var(--dsw-alias-border-l2);\n background: var(--dsw-specific-input-major, var(--dsw-alias-bg-layer-3));\n color: var(--dsw-alias-label-primary);\n cursor: pointer;\n border-radius: 8px;\n padding: 7px 12px;\n font-size: 13px;\n}\n\n.LOjPTW_button:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.LOjPTW_button:disabled {\n opacity: .4;\n cursor: default;\n}\n\n.LOjPTW_primaryButton {\n background: var(--dsw-alias-label-primary);\n border-color: var(--dsw-alias-label-primary);\n color: var(--dsw-alias-bg-layer-3);\n}\n\n.LOjPTW_dangerButton {\n background: var(--dsw-alias-state-danger, #c62828);\n border-color: var(--dsw-alias-state-danger, #c62828);\n color: #fff;\n}\n\n.LOjPTW_qr {\n background: #fff;\n border-radius: 8px;\n width: 200px;\n height: 200px;\n margin: 8px 0;\n display: block;\n}\n\n.LOjPTW_message {\n color: var(--dsw-alias-label-secondary);\n margin: 0;\n font-size: 12.5px;\n line-height: 1.5;\n}\n\n.LOjPTW_error {\n color: var(--dsw-alias-state-danger, #c62828);\n}\n\n.LOjPTW_tableWrap {\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 10px;\n overflow: auto;\n}\n\n.LOjPTW_table {\n border-collapse: collapse;\n width: 100%;\n font-size: 12.5px;\n}\n\n.LOjPTW_table th {\n z-index: 1;\n text-align: left;\n background: var(--dsw-alias-bg-layer-2, var(--dsw-alias-bg-layer-1));\n padding: 8px 10px;\n position: sticky;\n top: 0;\n}\n\n.LOjPTW_table td {\n border-top: 1px solid var(--dsw-alias-border-l1);\n vertical-align: top;\n padding: 8px 10px;\n}\n\n.LOjPTW_badge {\n border-radius: 999px;\n padding: 2px 8px;\n font-size: 11px;\n display: inline-block;\n}\n\n.LOjPTW_badgeOk {\n color: #229a55;\n background: #229a5524;\n}\n\n.LOjPTW_badgeFail {\n color: #c62828;\n background: #c6282824;\n}\n\n.LOjPTW_cards {\n grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));\n gap: 8px;\n display: grid;\n}\n\n.LOjPTW_stat {\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 10px;\n padding: 10px;\n}\n\n.LOjPTW_cardLabel {\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n}\n\n.LOjPTW_cardValue {\n color: var(--dsw-alias-label-primary);\n font-size: 15px;\n font-weight: 600;\n}\n\n.LOjPTW_upgradeLayer {\n flex: none;\n align-items: center;\n width: 100%;\n height: 42px;\n margin: 8px 0 0;\n display: flex;\n position: relative;\n}\n\n.LOjPTW_upgradeLayerRail {\n width: 36px;\n height: 36px;\n margin: 0;\n}\n\n.LOjPTW_upgradeButton {\n width: calc(100% + 4px);\n height: 42px;\n color: var(--dsw-alias-label-primary);\n cursor: pointer;\n background: none;\n border: none;\n border-radius: 12px;\n align-items: center;\n gap: 8px;\n margin: 0 -2px;\n padding: 0 10px 0 8px;\n font-family: inherit;\n font-size: 14px;\n display: inline-flex;\n overflow: hidden;\n}\n\n.LOjPTW_upgradeButton:hover, .LOjPTW_upgradeButton[data-outdated] {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.LOjPTW_upgradeButton:disabled {\n cursor: progress;\n opacity: .72;\n}\n\n.LOjPTW_upgradeButton:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: -2px;\n}\n\n.LOjPTW_upgradeLayerRail .LOjPTW_upgradeButton {\n border-radius: 50%;\n justify-content: center;\n gap: 0;\n width: 36px;\n height: 36px;\n padding: 0;\n}\n\n.LOjPTW_upgradeLabel {\n text-overflow: ellipsis;\n white-space: nowrap;\n min-width: 0;\n overflow: hidden;\n}\n\n.LOjPTW_upgradeMeta {\n color: var(--dsw-alias-label-tertiary);\n font-variant-numeric: tabular-nums;\n flex: none;\n margin-left: auto;\n font-size: 12px;\n line-height: 16px;\n}\n\n.LOjPTW_upgradeDot {\n background: var(--dsw-alias-brand-primary);\n border-radius: 50%;\n flex: none;\n width: 7px;\n height: 7px;\n}\n";document.head.appendChild(s);})();
8
8
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
9
9
  let react = require("react");
10
10
  let react_jsx_runtime = require("react/jsx-runtime");
@@ -61,6 +61,9 @@ const zh = {
61
61
  "config.gsc": "Google Search Console",
62
62
  "config.gsc.siteUrl": "站点 URL",
63
63
  "config.gsc.key": "服务账号 JSON 或密钥文件路径",
64
+ "config.tianyancha": "天眼查(法务助理 · 仅老板)",
65
+ "config.tianyancha.url": "天眼查 MCP URL",
66
+ "config.tianyancha.token": "OpenAPI Token",
64
67
  "config.fs": "本地文件 (fs-mcp-server)",
65
68
  "config.fs.root": "根目录",
66
69
  "config.sqlite": "SQLite (sqlite-mcp-server)",
@@ -116,7 +119,14 @@ const zh = {
116
119
  "weixin.qrAlt": "微信登录二维码",
117
120
  "weixin.listening": "通道在听:微信 → 网页「微信」会话(同一条,不另开窗口)→ 回微信。",
118
121
  "weixin.loggedIn": "已登录,通道未在听。点「重新连接」即可拉起,不必再扫码。",
119
- "weixin.loggedOut": "尚未登录。"
122
+ "weixin.loggedOut": "尚未登录。",
123
+ "upgrade.label": "升级",
124
+ "upgrade.current": "已最新",
125
+ "upgrade.aria": "升级 ReZ-TI 插件",
126
+ "upgrade.running": "升级中…",
127
+ "upgrade.reloading": "正在重载",
128
+ "upgrade.already": "已是 {version}",
129
+ "upgrade.reloadTimeout": "升级完成,但网页还没重新连上。请刷新这一页。"
120
130
  };
121
131
  const en = {
122
132
  "entry.label": "Rez",
@@ -167,6 +177,9 @@ const en = {
167
177
  "config.gsc": "Google Search Console",
168
178
  "config.gsc.siteUrl": "Site URL",
169
179
  "config.gsc.key": "Service-account JSON or key file path",
180
+ "config.tianyancha": "Tianyancha (Legal assistant, boss only)",
181
+ "config.tianyancha.url": "Tianyancha MCP URL",
182
+ "config.tianyancha.token": "OpenAPI token",
170
183
  "config.fs": "Local files (fs-mcp-server)",
171
184
  "config.fs.root": "Root directory",
172
185
  "config.sqlite": "SQLite (sqlite-mcp-server)",
@@ -222,7 +235,14 @@ const en = {
222
235
  "weixin.qrAlt": "WeChat login QR",
223
236
  "weixin.listening": "Channel is live: WeChat → the WeChat folder session on the left → WeChat.",
224
237
  "weixin.loggedIn": "Logged in, listener idle. Click Reconnect — no need to scan again.",
225
- "weixin.loggedOut": "Not logged in."
238
+ "weixin.loggedOut": "Not logged in.",
239
+ "upgrade.label": "Upgrade",
240
+ "upgrade.current": "Up to date",
241
+ "upgrade.aria": "Upgrade the ReZ-TI plugin",
242
+ "upgrade.running": "Updating…",
243
+ "upgrade.reloading": "Reloading",
244
+ "upgrade.already": "Already {version}",
245
+ "upgrade.reloadTimeout": "Update finished, but the page did not reconnect. Refresh this tab."
226
246
  };
227
247
  /** Minimal {name} interpolator shared by the panel helpers. */
228
248
  function t(dict, key, values) {
@@ -239,7 +259,8 @@ const REZ_API = {
239
259
  audit: "/api/dsh-rez-suite/audit",
240
260
  auditReset: "/api/dsh-rez-suite/audit/reset",
241
261
  weixin: "/api/dsh-rez-suite/weixin",
242
- weixinVerify: "/api/dsh-rez-suite/weixin/verify"
262
+ weixinVerify: "/api/dsh-rez-suite/weixin/verify",
263
+ update: "/api/dsh-rez-suite/update"
243
264
  };
244
265
  //#endregion
245
266
  //#region src/client/api.ts
@@ -301,6 +322,12 @@ var RezApi = class {
301
322
  async weixinLogout() {
302
323
  return readJson(await fetch(REZ_API.weixin, { method: "DELETE" }));
303
324
  }
325
+ async updateStatus() {
326
+ return readJson(await fetch(REZ_API.update));
327
+ }
328
+ async applyUpdate() {
329
+ return readJson(await fetch(REZ_API.update, { method: "POST" }));
330
+ }
304
331
  };
305
332
  //#endregion
306
333
  //#region src/client/panel/helpers.ts
@@ -355,7 +382,13 @@ var panel_module_default = {
355
382
  "tabBody": "LOjPTW_tabBody",
356
383
  "table": "LOjPTW_table",
357
384
  "tableWrap": "LOjPTW_tableWrap",
358
- "toolbar": "LOjPTW_toolbar"
385
+ "toolbar": "LOjPTW_toolbar",
386
+ "upgradeButton": "LOjPTW_upgradeButton",
387
+ "upgradeDot": "LOjPTW_upgradeDot",
388
+ "upgradeLabel": "LOjPTW_upgradeLabel",
389
+ "upgradeLayer": "LOjPTW_upgradeLayer",
390
+ "upgradeLayerRail": "LOjPTW_upgradeLayerRail",
391
+ "upgradeMeta": "LOjPTW_upgradeMeta"
359
392
  };
360
393
  //#endregion
361
394
  //#region src/client/panel/AuditTab.tsx
@@ -554,7 +587,8 @@ const EMPTY_SECRETS = {
554
587
  wechat: "",
555
588
  homeassistant: "",
556
589
  tapd: "",
557
- gsc: ""
590
+ gsc: "",
591
+ tianyancha: ""
558
592
  };
559
593
  function Field({ label, children }) {
560
594
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -718,6 +752,10 @@ function ConfigTab({ api }) {
718
752
  gsc: {
719
753
  ...config.connections.gsc,
720
754
  secret: secrets.gsc || void 0
755
+ },
756
+ tianyancha: {
757
+ ...config.connections.tianyancha,
758
+ secret: secrets.tianyancha || void 0
721
759
  }
722
760
  }
723
761
  };
@@ -923,6 +961,25 @@ function ConfigTab({ api }) {
923
961
  },
924
962
  secretLabel: tt("config.gsc.key")
925
963
  }),
964
+ config.role === "boss" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(McpSection, {
965
+ title: tt("config.tianyancha"),
966
+ row: config.connections.tianyancha,
967
+ secret: secrets.tianyancha,
968
+ onEnabled: (enabled) => {
969
+ patchConnection("tianyancha", { enabled });
970
+ },
971
+ onUrl: (url) => {
972
+ patchConnection("tianyancha", { url });
973
+ },
974
+ onSecret: (value) => {
975
+ setSecrets((prev) => ({
976
+ ...prev,
977
+ tianyancha: value
978
+ }));
979
+ },
980
+ urlLabel: tt("config.tianyancha.url"),
981
+ secretLabel: tt("config.tianyancha.token")
982
+ }),
926
983
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Section, {
927
984
  title: tt("config.billing"),
928
985
  children: [
@@ -1333,6 +1390,109 @@ function RezPluginCard() {
1333
1390
  });
1334
1391
  }
1335
1392
  //#endregion
1393
+ //#region src/client/upgrade-button.tsx
1394
+ /**
1395
+ * Sidebar footer action: upgrade @rezti/dsh-rez-suite without a terminal.
1396
+ * Host code still needs a process respawn; the button does that after pnpm add.
1397
+ */
1398
+ function UpgradeIcon() {
1399
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
1400
+ width: "16",
1401
+ height: "16",
1402
+ viewBox: "0 0 16 16",
1403
+ "aria-hidden": "true",
1404
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
1405
+ d: "M8 12.5V4.8M8 4.8 4.8 8M8 4.8 11.2 8M3 13.2h10",
1406
+ fill: "none",
1407
+ stroke: "currentColor",
1408
+ strokeWidth: "1.4",
1409
+ strokeLinecap: "round",
1410
+ strokeLinejoin: "round"
1411
+ })
1412
+ });
1413
+ }
1414
+ async function waitUntilHostBack(api, timeoutMs = 6e4) {
1415
+ const deadline = Date.now() + timeoutMs;
1416
+ await new Promise((resolve) => setTimeout(resolve, 800));
1417
+ while (Date.now() < deadline) try {
1418
+ await api.updateStatus();
1419
+ return;
1420
+ } catch {
1421
+ await new Promise((resolve) => setTimeout(resolve, 700));
1422
+ }
1423
+ throw new Error(tt("upgrade.reloadTimeout"));
1424
+ }
1425
+ function UpgradeButton({ wide }) {
1426
+ const api = (0, react.useMemo)(() => new RezApi(), []);
1427
+ const [info, setInfo] = (0, react.useState)();
1428
+ const [busy, setBusy] = (0, react.useState)(false);
1429
+ const [note, setNote] = (0, react.useState)("");
1430
+ (0, react.useEffect)(() => {
1431
+ let cancelled = false;
1432
+ api.updateStatus().then((value) => {
1433
+ if (!cancelled) setInfo(value);
1434
+ }).catch((error) => {
1435
+ if (!cancelled) setNote(error instanceof Error ? error.message : String(error));
1436
+ });
1437
+ return () => {
1438
+ cancelled = true;
1439
+ };
1440
+ }, [api]);
1441
+ const label = busy ? tt("upgrade.running") : info?.outdated === true ? tt("upgrade.label") : tt("upgrade.current");
1442
+ const meta = note !== "" ? note : info === void 0 ? "" : info.outdated ? info.latest : info.installed;
1443
+ async function onClick() {
1444
+ if (busy) return;
1445
+ setBusy(true);
1446
+ setNote("");
1447
+ try {
1448
+ const snapshot = info ?? await api.updateStatus();
1449
+ setInfo(snapshot);
1450
+ if (!snapshot.outdated) {
1451
+ setNote(tt("upgrade.already", { version: snapshot.installed }));
1452
+ return;
1453
+ }
1454
+ const result = await api.applyUpdate();
1455
+ setInfo(result);
1456
+ if (result.restarting) {
1457
+ setNote(tt("upgrade.reloading"));
1458
+ await waitUntilHostBack(api);
1459
+ window.location.reload();
1460
+ return;
1461
+ }
1462
+ setNote(tt("upgrade.already", { version: result.installed }));
1463
+ } catch (error) {
1464
+ setNote(error instanceof Error ? error.message : String(error));
1465
+ } finally {
1466
+ setBusy(false);
1467
+ }
1468
+ }
1469
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1470
+ className: wide ? panel_module_default.upgradeLayer : `${panel_module_default.upgradeLayer} ${panel_module_default.upgradeLayerRail}`,
1471
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
1472
+ type: "button",
1473
+ className: panel_module_default.upgradeButton,
1474
+ "data-outdated": info?.outdated === true ? "" : void 0,
1475
+ "aria-label": tt("upgrade.aria"),
1476
+ disabled: busy,
1477
+ onClick: () => {
1478
+ onClick();
1479
+ },
1480
+ children: [
1481
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(UpgradeIcon, {}),
1482
+ wide && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1483
+ className: panel_module_default.upgradeLabel,
1484
+ children: label
1485
+ }),
1486
+ wide && meta !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1487
+ className: panel_module_default.upgradeMeta,
1488
+ children: meta
1489
+ }),
1490
+ !wide && info?.outdated === true && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: panel_module_default.upgradeDot })
1491
+ ]
1492
+ })
1493
+ });
1494
+ }
1495
+ //#endregion
1336
1496
  //#region src/client/index.ts
1337
1497
  const NS = "dsh-rez-suite";
1338
1498
  const inject = ["slots", "locale"];
@@ -1354,6 +1514,13 @@ function apply(ctx) {
1354
1514
  label: () => t("settings.title"),
1355
1515
  locale: NS
1356
1516
  }, RezSettingsPage));
1517
+ ctx.slots.inject("sidebar.footer.action", () => ctx.slots.register({
1518
+ name: "sidebar.footer.action",
1519
+ id: "rez-upgrade",
1520
+ order: 10,
1521
+ label: () => t("upgrade.label"),
1522
+ locale: NS
1523
+ }, UpgradeButton));
1357
1524
  }
1358
1525
  //#endregion
1359
1526
  exports.apply = apply;
package/lib/index.d.ts CHANGED
@@ -1730,6 +1730,10 @@ interface RezConnections {
1730
1730
  enabled: boolean;
1731
1731
  siteUrl: string;
1732
1732
  };
1733
+ tianyancha: {
1734
+ enabled: boolean;
1735
+ url: string;
1736
+ };
1733
1737
  }
1734
1738
  /** Full plugin configuration persisted under ~/.dsh/dsh-rez-suite.json. */
1735
1739
  interface RezConfig {