@linxin666/dsh-remote-web-ui 0.2.6 → 0.2.8

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 (86) hide show
  1. package/README.i18n.yaml +2 -2
  2. package/README.md +8 -1
  3. package/README.zh.md +2 -1
  4. package/lib/client.js +55 -10
  5. package/lib/client.js.map +1 -1
  6. package/lib/index.js +12 -8
  7. package/lib/mobile.js +37 -18
  8. package/lib/mobile.js.map +1 -1
  9. package/lib/types/client/FenceNotice.d.ts +3 -2
  10. package/lib/types/client/FenceNotice.d.ts.map +1 -1
  11. package/lib/types/client/FooterRemoteEntry.js +1 -1
  12. package/lib/types/client/PluginSettingsCard.d.ts +1 -1
  13. package/lib/types/client/PluginSettingsCard.d.ts.map +1 -1
  14. package/lib/types/client/RemoteEntry.js +8 -8
  15. package/lib/types/client/RemotePanel.js +3 -3
  16. package/lib/types/client/RemoteSettingsCard.d.ts.map +1 -1
  17. package/lib/types/client/RemoteSettingsCard.js +2 -2
  18. package/lib/types/client/UpdateEntry.d.ts.map +1 -1
  19. package/lib/types/client/UpdateEntry.js +2 -2
  20. package/lib/types/client/UpdatePanel.js +1 -1
  21. package/lib/types/client/deep-link.js +1 -1
  22. package/lib/types/client/index.d.ts.map +1 -1
  23. package/lib/types/client/index.js +45 -23
  24. package/lib/types/client/pair-api.d.ts +6 -0
  25. package/lib/types/client/pair-api.d.ts.map +1 -1
  26. package/lib/types/client/pair-api.js +11 -0
  27. package/lib/types/client/remote-channel.d.ts +25 -0
  28. package/lib/types/client/remote-channel.d.ts.map +1 -1
  29. package/lib/types/client/remote-channel.js +24 -0
  30. package/lib/types/client/settings-form.d.ts.map +1 -1
  31. package/lib/types/client/update-api.d.ts.map +1 -1
  32. package/lib/types/gate.js +1 -1
  33. package/lib/types/index.js +15 -15
  34. package/lib/types/invariant.d.ts.map +1 -1
  35. package/lib/types/loopback-proxy.js +1 -1
  36. package/lib/types/mobile/PairRequiredView.js +1 -1
  37. package/lib/types/mobile/PairRequiredView.test.js +1 -1
  38. package/lib/types/mobile/api.js +1 -1
  39. package/lib/types/mobile/index.js +5 -5
  40. package/lib/types/mobile/markdown.test.js +1 -1
  41. package/lib/types/mobile/messages.d.ts.map +1 -1
  42. package/lib/types/mobile/messages.js +5 -3
  43. package/lib/types/mobile/messages.test.js +21 -1
  44. package/lib/types/mobile/mobile-theme.test.js +2 -2
  45. package/lib/types/mobile/mux.d.ts +7 -4
  46. package/lib/types/mobile/mux.d.ts.map +1 -1
  47. package/lib/types/mobile/mux.js +44 -16
  48. package/lib/types/mobile/mux.test.js +58 -1
  49. package/lib/types/mobile/rpc.d.ts.map +1 -1
  50. package/lib/types/mobile/theme-toggle.js +1 -1
  51. package/lib/types/mobile/views/App.js +7 -7
  52. package/lib/types/mobile/views/App.test.js +2 -2
  53. package/lib/types/mobile/views/ChatView.js +6 -6
  54. package/lib/types/mobile/views/ChatView.test.js +3 -3
  55. package/lib/types/mobile/views/SessionListView.js +3 -3
  56. package/lib/types/mobile/views/SessionListView.test.js +2 -2
  57. package/lib/types/mobile/views/WorkspaceView.js +3 -3
  58. package/lib/types/mobile/views/WorkspaceView.test.js +3 -3
  59. package/lib/types/mobile-api.d.ts +1 -1
  60. package/lib/types/mobile-api.d.ts.map +1 -1
  61. package/lib/types/mobile-api.js +2 -2
  62. package/lib/types/pairing-access.d.ts.map +1 -1
  63. package/lib/types/pairing.d.ts.map +1 -1
  64. package/lib/types/pairing.persist.test.js +2 -2
  65. package/lib/types/remote-api.js +6 -6
  66. package/lib/types/remote-methods.d.ts.map +1 -1
  67. package/lib/types/routes.d.ts +9 -7
  68. package/lib/types/routes.d.ts.map +1 -1
  69. package/lib/types/routes.js +8 -5
  70. package/lib/types/tunnel.d.ts.map +1 -1
  71. package/lib/types/update-routes.d.ts +2 -2
  72. package/lib/types/update-routes.d.ts.map +1 -1
  73. package/lib/types/update-routes.js +1 -1
  74. package/package.json +15 -12
  75. package/src/client/FenceNotice.tsx +3 -2
  76. package/src/client/RemoteEntry.tsx +3 -2
  77. package/src/client/UpdateEntry.tsx +1 -0
  78. package/src/client/index.ts +40 -15
  79. package/src/client/pair-api.ts +16 -0
  80. package/src/client/remote-channel.ts +42 -0
  81. package/src/index.ts +1 -1
  82. package/src/mobile/messages.test.ts +23 -0
  83. package/src/mobile/messages.ts +5 -3
  84. package/src/mobile/mux.test.ts +64 -0
  85. package/src/mobile/mux.ts +44 -17
  86. package/src/routes.ts +7 -2
package/lib/index.js CHANGED
@@ -14,7 +14,7 @@ import http, { request } from "node:http";
14
14
  import { connect } from "node:net";
15
15
  import { Tunnel, bin, install } from "cloudflared";
16
16
  import { spawn } from "node:child_process";
17
- //#region ../../node_modules/.pnpm/@deepseek-ai+dsh-settings@0.1.0-rc.8_@deepseek-ai+cordis@4.0.1_@deepseek-ai+dsh-brand@0_7616943ecf171cb97db9e2088de3356f/node_modules/@deepseek-ai/dsh-settings/lib/index.js
17
+ //#region ../../node_modules/.pnpm/@deepseek-ai+dsh-settings@0.1.1-rc.2_@deepseek-ai+cordis@4.0.1_@deepseek-ai+dsh-brand@0_02aaf429ec98c58247037e2222c17a8f/node_modules/@deepseek-ai/dsh-settings/lib/index.js
18
18
  /**
19
19
  * Structural secret redaction for settings values. `role('secret')` fields are
20
20
  * removed from a value before it crosses a wire boundary; a sidecar records
@@ -975,7 +975,8 @@ var PairingEventsStream = class {
975
975
  * @returns the exact routes to register on webServer.
976
976
  */
977
977
  function makeRoutes(deps) {
978
- const { service, lanAddresses } = deps;
978
+ const { service, lanAddresses, requirePairingForLan = true } = deps;
979
+ const pairingRequired = () => typeof requirePairingForLan === "function" ? requirePairingForLan() : requirePairingForLan;
979
980
  const events = new PairingEventsStream(service);
980
981
  /** Loopback-only fence: the desktop panel's control endpoints. */
981
982
  const loopbackFence = (req) => isTrustedApiRequest(req, []);
@@ -1182,14 +1183,16 @@ function makeRoutes(deps) {
1182
1183
  const paired = deviceId !== void 0 && service.hasDevice(deviceId);
1183
1184
  const snapshot = service.snapshot();
1184
1185
  const { devices: _devices, ...rest } = snapshot;
1186
+ const visible = paired ? rest : {
1187
+ phase: snapshot.phase,
1188
+ lanAvailable: snapshot.lanAvailable,
1189
+ lanAddresses: snapshot.lanAddresses
1190
+ };
1185
1191
  writeJson(res, 200, {
1186
1192
  ok: true,
1187
1193
  paired,
1188
- ...paired ? rest : {
1189
- phase: snapshot.phase,
1190
- lanAvailable: snapshot.lanAvailable,
1191
- lanAddresses: snapshot.lanAddresses
1192
- }
1194
+ requirePairingForLan: pairingRequired(),
1195
+ ...visible
1193
1196
  });
1194
1197
  };
1195
1198
  const handleEvents = (req, res) => {
@@ -3184,7 +3187,8 @@ function applyImpl(ctx, config) {
3184
3187
  const routes = [
3185
3188
  ...makeRoutes({
3186
3189
  service,
3187
- lanAddresses
3190
+ lanAddresses,
3191
+ requirePairingForLan: () => resolve().requirePairingForLan
3188
3192
  }),
3189
3193
  ...makeMobileRoutes(),
3190
3194
  ...apiProxy !== void 0 ? makeMobileApiRoutes({
package/lib/mobile.js CHANGED
@@ -11962,7 +11962,7 @@ function superRefine(fn, params) {
11962
11962
  return /* @__PURE__ */ _superRefine(fn, params);
11963
11963
  }
11964
11964
  //#endregion
11965
- //#region ../../node_modules/.pnpm/@deepseek-ai+dsh-host-apiproxy@0.1.0-rc.8_87e50522ee3e6c004ae77f9049f48ed1/node_modules/@deepseek-ai/dsh-host-apiproxy/lib/types/api/rpc.schema.js
11965
+ //#region ../../node_modules/.pnpm/@deepseek-ai+dsh-host-apiproxy@0.1.1-rc.2_73bb34f881f3291b26a2607af4c34648/node_modules/@deepseek-ai/dsh-host-apiproxy/lib/types/api/rpc.schema.js
11966
11966
  /**
11967
11967
  * Message-layer zod schemas: the four wire full forms + error body +
11968
11968
  * carrier receipt. The payload slot is unknown in the full-form schemas — business payloads
@@ -12271,7 +12271,7 @@ union([object({ accepted: literal(true) }), object({
12271
12271
  reason: union([literal("not-pending"), literal("bad-response")])
12272
12272
  })]);
12273
12273
  //#endregion
12274
- //#region ../../node_modules/.pnpm/@deepseek-ai+dsh-host-apiproxy@0.1.0-rc.8_87e50522ee3e6c004ae77f9049f48ed1/node_modules/@deepseek-ai/dsh-host-apiproxy/lib/types/api/session-search.js
12274
+ //#region ../../node_modules/.pnpm/@deepseek-ai+dsh-host-apiproxy@0.1.1-rc.2_73bb34f881f3291b26a2607af4c34648/node_modules/@deepseek-ai/dsh-host-apiproxy/lib/types/api/session-search.js
12275
12275
  /**
12276
12276
  * Return the longest prefix containing at most `maximum` Unicode code points.
12277
12277
  * @param value - text to bound.
@@ -12289,7 +12289,7 @@ function truncateUnicodeCodePoints(value, maximum) {
12289
12289
  return value;
12290
12290
  }
12291
12291
  //#endregion
12292
- //#region ../../node_modules/.pnpm/@deepseek-ai+dsh-host-apiproxy@0.1.0-rc.8_87e50522ee3e6c004ae77f9049f48ed1/node_modules/@deepseek-ai/dsh-host-apiproxy/lib/types/api/sessions.schema.js
12292
+ //#region ../../node_modules/.pnpm/@deepseek-ai+dsh-host-apiproxy@0.1.1-rc.2_73bb34f881f3291b26a2607af4c34648/node_modules/@deepseek-ai/dsh-host-apiproxy/lib/types/api/sessions.schema.js
12293
12293
  /**
12294
12294
  * sessions domain zod schemas (names derived from map keys: sessionListRequestSchema /
12295
12295
  * sessionListValueSchema). SessionEvent passthrough = strict envelope (type/seq/time) + wide
@@ -12526,7 +12526,7 @@ object({ accepted: literal(true) });
12526
12526
  object({ sessionId: sessionIdSchema });
12527
12527
  object({ accepted: literal(true) });
12528
12528
  //#endregion
12529
- //#region ../../node_modules/.pnpm/@deepseek-ai+dsh-host-apiproxy@0.1.0-rc.8_87e50522ee3e6c004ae77f9049f48ed1/node_modules/@deepseek-ai/dsh-host-apiproxy/lib/types/api/approvals.schema.js
12529
+ //#region ../../node_modules/.pnpm/@deepseek-ai+dsh-host-apiproxy@0.1.1-rc.2_73bb34f881f3291b26a2607af4c34648/node_modules/@deepseek-ai/dsh-host-apiproxy/lib/types/api/approvals.schema.js
12530
12530
  /**
12531
12531
  * approvals domain zod schemas (respond is a client-response; the payload schema serves
12532
12532
  * the /api/respond endpoint's second parse after routing via the pending table).
@@ -12560,7 +12560,7 @@ const taskViewSchema = object({
12560
12560
  finishedAt: number().int().nonnegative().optional()
12561
12561
  });
12562
12562
  //#endregion
12563
- //#region ../../node_modules/.pnpm/@deepseek-ai+dsh-host-apiproxy@0.1.0-rc.8_87e50522ee3e6c004ae77f9049f48ed1/node_modules/@deepseek-ai/dsh-host-apiproxy/lib/types/api/workspace.schema.js
12563
+ //#region ../../node_modules/.pnpm/@deepseek-ai+dsh-host-apiproxy@0.1.1-rc.2_73bb34f881f3291b26a2607af4c34648/node_modules/@deepseek-ai/dsh-host-apiproxy/lib/types/api/workspace.schema.js
12564
12564
  /**
12565
12565
  * workspace domain zod schemas (names derived from map keys). The
12566
12566
  * WorkspaceId brand cast lives in sessions.schema (see the note there) and
@@ -12606,7 +12606,7 @@ object({ workspace: workspaceViewSchema });
12606
12606
  object({ sessionId: sessionIdSchema });
12607
12607
  object({ archivedSessionIds: array(sessionIdSchema) });
12608
12608
  //#endregion
12609
- //#region ../../node_modules/.pnpm/@deepseek-ai+dsh-host-apiproxy@0.1.0-rc.8_87e50522ee3e6c004ae77f9049f48ed1/node_modules/@deepseek-ai/dsh-host-apiproxy/lib/types/api/events.schema.js
12609
+ //#region ../../node_modules/.pnpm/@deepseek-ai+dsh-host-apiproxy@0.1.1-rc.2_73bb34f881f3291b26a2607af4c34648/node_modules/@deepseek-ai/dsh-host-apiproxy/lib/types/api/events.schema.js
12610
12610
  /**
12611
12611
  * events domain zod schemas: MuxFrame / HostFrame unions (discriminatedUnion('type')).
12612
12612
  * A frame is the payload slot of the ServerRequest full form; the SessionEvent inside
@@ -12770,6 +12770,8 @@ function browserSource(url) {
12770
12770
  }
12771
12771
  const DEFAULT_POLL_INTERVAL_MS = 3e3;
12772
12772
  const DEFAULT_STALL_THRESHOLD_MS = 12e3;
12773
+ const LIVE_SSE_STALL_MULTIPLIER = 3;
12774
+ const MAX_POLL_BACKOFF_MS = 6e4;
12773
12775
  /**
12774
12776
  * Stall-check granularity: the single scheduler tick runs at least this
12775
12777
  * often so fallback arms within a second of the stall threshold passing,
@@ -12800,8 +12802,8 @@ var MuxClient = class {
12800
12802
  lastDataAt = 0;
12801
12803
  /**
12802
12804
  * Whether the SSE channel has ever delivered a frame in this stream (a
12803
- * delivered frame proves the tunnel forwards SSE; silence alone then means
12804
- * the agent idle, not a dead channel — only an onerror re-arms fallback).
12805
+ * delivered frame proves the tunnel can forward SSE; sustained silence may
12806
+ * still mean a suspended mobile tunnel, so polling re-arms after 3 windows).
12805
12807
  */
12806
12808
  sseAlive = false;
12807
12809
  /** Per-session highest event seq already emitted, for poll dedup. */
@@ -12811,6 +12813,8 @@ var MuxClient = class {
12811
12813
  polling = false;
12812
12814
  /** Epoch ms of the next due poll while polling (kept on the same tick timer). */
12813
12815
  nextPollAt = 0;
12816
+ /** Adaptive delay: productive polls reset it; empty/error polls add one base interval up to one minute. */
12817
+ pollDelayMs;
12814
12818
  /**
12815
12819
  * @param url - the mobile events endpoint (browser-relative).
12816
12820
  * @param options - seams.
@@ -12820,6 +12824,7 @@ var MuxClient = class {
12820
12824
  this.sourceFactory = options.sourceFactory ?? browserSource;
12821
12825
  this.pollLatest = options.pollLatest ?? ((sessionId) => history(sessionId, void 0, DEFAULT_POLL_PAGE_SIZE));
12822
12826
  this.pollIntervalMs = options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
12827
+ this.pollDelayMs = this.pollIntervalMs;
12823
12828
  this.stallThresholdMs = options.stallThresholdMs ?? DEFAULT_STALL_THRESHOLD_MS;
12824
12829
  this.now = options.now ?? (() => Date.now());
12825
12830
  }
@@ -12857,7 +12862,7 @@ var MuxClient = class {
12857
12862
  this.stopPolling();
12858
12863
  return;
12859
12864
  }
12860
- if (!this.polling && !this.stopped && !this.sseAlive && this.now() - this.lastDataAt > this.stallThresholdMs) this.startPolling();
12865
+ if (!this.polling && !this.stopped && this.isSseStalled()) this.startPolling();
12861
12866
  }
12862
12867
  connect() {
12863
12868
  this.sseAlive = false;
@@ -12899,22 +12904,28 @@ var MuxClient = class {
12899
12904
  if (this.observeSessionId === void 0) return;
12900
12905
  if (this.polling) {
12901
12906
  if (this.now() >= this.nextPollAt) {
12902
- this.nextPollAt = this.now() + this.pollIntervalMs;
12907
+ this.nextPollAt = Number.POSITIVE_INFINITY;
12903
12908
  this.pollTick();
12904
12909
  }
12905
12910
  return;
12906
12911
  }
12907
- if (this.sseAlive) return;
12908
- if (this.now() - this.lastDataAt > this.stallThresholdMs) this.startPolling();
12912
+ if (this.isSseStalled()) this.startPolling();
12913
+ }
12914
+ isSseStalled() {
12915
+ const windowMs = this.sseAlive ? this.stallThresholdMs * LIVE_SSE_STALL_MULTIPLIER : this.stallThresholdMs;
12916
+ return this.now() - this.lastDataAt > windowMs;
12909
12917
  }
12910
12918
  startPolling() {
12911
12919
  if (this.polling || this.stopped) return;
12912
12920
  this.polling = true;
12913
- this.nextPollAt = this.now() + this.pollIntervalMs;
12921
+ this.pollDelayMs = this.pollIntervalMs;
12922
+ this.nextPollAt = Number.POSITIVE_INFINITY;
12914
12923
  this.pollTick();
12915
12924
  }
12916
12925
  stopPolling() {
12917
12926
  this.polling = false;
12927
+ this.pollDelayMs = this.pollIntervalMs;
12928
+ this.nextPollAt = 0;
12918
12929
  }
12919
12930
  /**
12920
12931
  * Fetch the latest history page for the observed session and re-emit any
@@ -12927,14 +12938,19 @@ var MuxClient = class {
12927
12938
  this.stopPolling();
12928
12939
  return;
12929
12940
  }
12941
+ let emitted = 0;
12930
12942
  try {
12931
12943
  const page = await this.pollLatest(sessionId);
12932
12944
  let maxSeq = this.pollWatermark.get(sessionId) ?? -1;
12933
- for (const entry of page.events) {
12945
+ const ordered = [...page.events].sort((left, right) => {
12946
+ return (typeof left.event?.seq === "number" ? left.event.seq : -1) - (typeof right.event?.seq === "number" ? right.event.seq : -1);
12947
+ });
12948
+ for (const entry of ordered) {
12934
12949
  const event = entry.event;
12935
12950
  const seq = typeof event?.seq === "number" ? event.seq : -1;
12936
12951
  if (seq <= maxSeq) continue;
12937
12952
  maxSeq = seq;
12953
+ emitted += 1;
12938
12954
  this.emit({
12939
12955
  type: "session/event",
12940
12956
  sessionId,
@@ -12942,7 +12958,11 @@ var MuxClient = class {
12942
12958
  });
12943
12959
  }
12944
12960
  this.pollWatermark.set(sessionId, maxSeq);
12945
- } catch {}
12961
+ } catch {} finally {
12962
+ if (emitted > 0) this.pollDelayMs = this.pollIntervalMs;
12963
+ else this.pollDelayMs = Math.min(MAX_POLL_BACKOFF_MS, this.pollDelayMs + this.pollIntervalMs);
12964
+ if (this.polling && this.observeSessionId === sessionId) this.nextPollAt = this.now() + this.pollDelayMs;
12965
+ }
12946
12966
  }
12947
12967
  handleMessage(data) {
12948
12968
  if (typeof data !== "string" || data === "") return;
@@ -13405,7 +13425,6 @@ function applyTurnEnd(state, event) {
13405
13425
  ...message,
13406
13426
  ...wasPending ? { pending: false } : {},
13407
13427
  ...failed ? { failed: true } : {},
13408
- seq: Math.max(message.seq, event.seq),
13409
13428
  time: event.time
13410
13429
  });
13411
13430
  }
@@ -13474,12 +13493,12 @@ function snapshotOf(state) {
13474
13493
  for (let index = 1; index < out.length; index += 1) {
13475
13494
  const prev = out[index - 1];
13476
13495
  const current = out[index];
13477
- if (prev.seq > current.seq || prev.seq === current.seq && prev.id >= current.id) {
13496
+ if (prev.seq > current.seq) {
13478
13497
  ordered = false;
13479
13498
  break;
13480
13499
  }
13481
13500
  }
13482
- return ordered ? out : out.sort((a, b) => a.seq - b.seq || (a.id < b.id ? -1 : 1));
13501
+ return ordered ? out : out.sort((a, b) => a.seq - b.seq);
13483
13502
  }
13484
13503
  //#endregion
13485
13504
  //#region src/mobile/markdown.ts