dsh-pocket 2.10.4 → 2.10.6

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/client/client.js CHANGED
@@ -1796,6 +1796,35 @@ function mobileApply(ctx) {
1796
1796
  );
1797
1797
  return startFileGuard(readFile);
1798
1798
  }, "dsh-mobile-nav: file open guard + copy button + hide add-workspace (issue #17)");
1799
+ ctx.effect(() => {
1800
+ if (!narrow.matches) return () => {
1801
+ };
1802
+ const PHRASES = ["加载提供方目录失败", "Settings are unavailable in this browser"];
1803
+ const NOTICE = "手机上不支持模型设置,请去电脑端修改设置";
1804
+ const findDeepest = (el) => {
1805
+ let deepest = el;
1806
+ for (const child of el.querySelectorAll("*")) {
1807
+ if (PHRASES.some((p) => (child.textContent ?? "").includes(p))) deepest = child;
1808
+ }
1809
+ return deepest;
1810
+ };
1811
+ const patch = () => {
1812
+ for (const el of document.querySelectorAll("body *")) {
1813
+ const t = el.textContent ?? "";
1814
+ if (!PHRASES.some((p) => t.includes(p))) continue;
1815
+ if (el.dataset?.dshpModelNotice === "1") continue;
1816
+ const target = findDeepest(el);
1817
+ target.textContent = NOTICE;
1818
+ target.dataset.dshpModelNotice = "1";
1819
+ }
1820
+ };
1821
+ const observer = new MutationObserver(patch);
1822
+ observer.observe(document.body, { childList: true, subtree: true, characterData: true });
1823
+ patch();
1824
+ return () => {
1825
+ observer.disconnect();
1826
+ };
1827
+ }, "dsh-mobile-nav: replace model-settings load error with mobile hint");
1799
1828
  ctx.slots.inject("conversation.session.header.actions", () => ctx.slots.register({
1800
1829
  name: "conversation.session.header.actions",
1801
1830
  id: "mobile-nav-toggle",
@@ -299,6 +299,38 @@ export function mobileApply(ctx): void {
299
299
  return startFileGuard(readFile)
300
300
  }, 'dsh-mobile-nav: file open guard + copy button + hide add-workspace (issue #17)')
301
301
 
302
+ // 手机上模型 / 提供方设置加载失败:上游 dsh-web 会渲染「加载提供方目录失败 /
303
+ // Settings are unavailable in this browser」。这条文案不是 dsh-pocket 的,但手机侧
304
+ // 本就不支持改模型设置,原报错只会吓到用户。窄屏下用 MutationObserver 就地把该报错
305
+ // 文本替换成「去电脑端修改」的引导提示(仅手机,桌面端不受影响)。
306
+ ctx.effect(() => {
307
+ if (!narrow.matches) return () => {}
308
+ const PHRASES = ['加载提供方目录失败', 'Settings are unavailable in this browser']
309
+ const NOTICE = '手机上不支持模型设置,请去电脑端修改设置'
310
+ // 取包含报错文案的最深节点,避免把外层大容器整块清掉。
311
+ const findDeepest = (el: Element): Element => {
312
+ let deepest = el
313
+ for (const child of el.querySelectorAll('*')) {
314
+ if (PHRASES.some((p) => (child.textContent ?? '').includes(p))) deepest = child
315
+ }
316
+ return deepest
317
+ }
318
+ const patch = (): void => {
319
+ for (const el of document.querySelectorAll('body *')) {
320
+ const t = el.textContent ?? ''
321
+ if (!PHRASES.some((p) => t.includes(p))) continue
322
+ if ((el as HTMLElement).dataset?.dshpModelNotice === '1') continue
323
+ const target = findDeepest(el)
324
+ target.textContent = NOTICE
325
+ ;(target as HTMLElement).dataset.dshpModelNotice = '1'
326
+ }
327
+ }
328
+ const observer = new MutationObserver(patch)
329
+ observer.observe(document.body, { childList: true, subtree: true, characterData: true })
330
+ patch()
331
+ return () => observer.disconnect()
332
+ }, 'dsh-mobile-nav: replace model-settings load error with mobile hint')
333
+
302
334
 
303
335
  ctx.slots.inject('conversation.session.header.actions', () => ctx.slots.register({
304
336
  name: 'conversation.session.header.actions',
package/lib/web-rpc.js CHANGED
@@ -201,15 +201,24 @@ async function pocketHttpBridge(req, res, fetchHandler, maxBodyBytes) {
201
201
  function mountPocketWebRoute(ctx, { channel, handler, log }) {
202
202
  const webServer = ctx?.webServer;
203
203
  if (!webServer || typeof webServer.register !== 'function') return null;
204
- const requestRejection = ctx?.connection?.requestRejection;
204
+ // 必须持有 connection 本体并以**方法形式**调用 requestRejection(issue #117):
205
+ // dsh 的 HostConnectionService.requestRejection 是类方法,内部读 this.trustedHosts /
206
+ // this.browserAuth。先把方法抽成裸函数(`const fn = ctx.connection.requestRejection`)
207
+ // 再调用会丢失 this → TypeError → 被下面的 catch 兜底成 403,于是**任何**请求
208
+ // (本机、带会话 cookie 的浏览器、移动端)都被判 forbidden,设置页 status RPC 全挂
209
+ // (用户可见症状:局域网区块一直显示「代理未就绪…」,公网隧道开启报 403)。
210
+ // dsh 自己的 /api 路由也是以方法形式调用的(见 client-connection 的 register());
211
+ // 本仓库 lib/index.js 处理 authenticatedUrl 时同样用 fn.call(ctx.connection, ...) 绑定。
212
+ // 等价写法:requestRejection.call(ctx.connection, req)(issue #117 报告者的建议)。
213
+ const connection = ctx?.connection;
205
214
  const fetchHandler = pocketFetchHandler(channel, handler, log);
206
215
  const route = {
207
216
  kind: 'prefix',
208
217
  path: channel,
209
218
  handler: async (req, res) => {
210
219
  let rejection;
211
- if (typeof requestRejection === 'function') {
212
- try { rejection = requestRejection(req); } catch { rejection = 403; }
220
+ if (typeof connection?.requestRejection === 'function') {
221
+ try { rejection = connection.requestRejection(req); } catch { rejection = 403; }
213
222
  } else if (!isTrustedLoopbackRequest(req)) {
214
223
  rejection = 403;
215
224
  }
package/package.json CHANGED
@@ -24,7 +24,8 @@
24
24
  "scripts": {
25
25
  "build:client": "node client/build.mjs",
26
26
  "release": "semantic-release",
27
- "test": "node --test --test-timeout=30000 \"test/*.test.js\""
27
+ "test": "node --test --test-timeout=30000 \"test/*.test.js\"",
28
+ "test:local": "node --test --test-timeout=300000 \"test/local/*.test.js\""
28
29
  },
29
30
  "dependencies": {
30
31
  "qrcode": "^1.5.4",
@@ -80,5 +81,5 @@
80
81
  "access": "public",
81
82
  "registry": "https://registry.npmjs.org/"
82
83
  },
83
- "version": "2.10.4"
84
+ "version": "2.10.6"
84
85
  }