dsh-remote-control 2.0.2 → 2.0.4

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/cordis.patch.yml CHANGED
@@ -12,7 +12,6 @@
12
12
  hostTokenEnv: DRC_HOST_TOKEN
13
13
  hostLabel: dsh-host
14
14
  unarchiveOnPrompt: true
15
- takeOverQuestions: false
16
15
  listingRefreshSec: 15
17
16
  approvalTimeoutSec: 180
18
17
  keepAwake:
@@ -11,11 +11,20 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
11
11
  if (typeof require !== "undefined") return require.apply(this, arguments);
12
12
  throw Error('Dynamic require of "' + x + '" is not supported');
13
13
  });
14
- var __esm = (fn, res) => function __init() {
15
- return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
14
+ var __esm = (fn, res, err) => function __init() {
15
+ if (err) throw err[0];
16
+ try {
17
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
18
+ } catch (e) {
19
+ throw err = [e], e;
20
+ }
16
21
  };
17
22
  var __commonJS = (cb, mod) => function __require2() {
18
- return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
23
+ try {
24
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
25
+ } catch (e) {
26
+ throw mod = 0, e;
27
+ }
19
28
  };
20
29
  var __export = (target, all) => {
21
30
  for (var name in all)
@@ -10500,7 +10509,17 @@ function defaultHistory(sessionId) {
10500
10509
  },
10501
10510
  { kind: "delta", sessionId, messageId: "mock_h3", text: "\u7ED3\u6784\u6E05\u695A\u4E86\u3002", role: "assistant", done: true },
10502
10511
  { kind: "delta", sessionId, messageId: "mock_h4", text: "\u518D\u8DD1\u4E00\u904D\u6D4B\u8BD5", role: "user", done: true },
10503
- { kind: "delta", sessionId, messageId: "mock_h5", text: "\u6D4B\u8BD5\u5168\u8FC7\u3002", role: "assistant", done: true }
10512
+ { kind: "delta", sessionId, messageId: "mock_h5", text: "\u6D4B\u8BD5\u5168\u8FC7\u3002", role: "assistant", done: true },
10513
+ // 2026-10-05 补:待办快照也进历史页(wire 1.5.0)。放在最后——一页里最后一条
10514
+ // 就是那一页截止时的清单,本地全链路要真的走到这条路径,而不是只在单测里摆帧。
10515
+ {
10516
+ kind: "todo",
10517
+ sessionId,
10518
+ todos: [
10519
+ { content: "\u590D\u73B0\u7528\u6237\u62A5\u7684\u95EE\u9898", status: "completed" },
10520
+ { content: "\u6539\u5B8C\u8DD1\u4E00\u904D\u672C\u5730\u5168\u94FE\u8DEF", status: "in_progress" }
10521
+ ]
10522
+ }
10504
10523
  ];
10505
10524
  }
10506
10525
  function createMockKernel(options) {
@@ -10673,7 +10692,7 @@ var init_mock_kernel = __esm({
10673
10692
  // src/index.ts
10674
10693
  import path6 from "node:path";
10675
10694
 
10676
- // ../../node_modules/.pnpm/dsh-remote-wire@1.4.0/node_modules/dsh-remote-wire/dist/src/crypto/bytes.js
10695
+ // ../../node_modules/.pnpm/dsh-remote-wire@1.5.0/node_modules/dsh-remote-wire/dist/src/crypto/bytes.js
10677
10696
  import { Buffer as Buffer2 } from "node:buffer";
10678
10697
  var encoder = new TextEncoder();
10679
10698
  var decoder = new TextDecoder("utf-8", { fatal: false });
@@ -10700,7 +10719,7 @@ function concat(parts) {
10700
10719
  return out;
10701
10720
  }
10702
10721
 
10703
- // ../../node_modules/.pnpm/dsh-remote-wire@1.4.0/node_modules/dsh-remote-wire/dist/src/crypto/keys.js
10722
+ // ../../node_modules/.pnpm/dsh-remote-wire@1.5.0/node_modules/dsh-remote-wire/dist/src/crypto/keys.js
10704
10723
  import { createHash, randomBytes } from "node:crypto";
10705
10724
  var KDF_NAMESPACE = "dsh-rc/v1";
10706
10725
  var UNIT_SEPARATOR = 31;
@@ -10730,7 +10749,7 @@ function randomNonce() {
10730
10749
  return new Uint8Array(randomBytes(NONCE_BYTES));
10731
10750
  }
10732
10751
 
10733
- // ../../node_modules/.pnpm/dsh-remote-wire@1.4.0/node_modules/dsh-remote-wire/dist/src/crypto/record.js
10752
+ // ../../node_modules/.pnpm/dsh-remote-wire@1.5.0/node_modules/dsh-remote-wire/dist/src/crypto/record.js
10734
10753
  var import_tweetnacl = __toESM(require_nacl_fast(), 1);
10735
10754
  var MAC_BYTES = 16;
10736
10755
  var MIN_RECORD_BYTES = NONCE_BYTES + MAC_BYTES;
@@ -10763,7 +10782,7 @@ function open(key, record2) {
10763
10782
  }
10764
10783
  }
10765
10784
 
10766
- // ../../node_modules/.pnpm/dsh-remote-wire@1.4.0/node_modules/dsh-remote-wire/dist/src/identity/pairing.js
10785
+ // ../../node_modules/.pnpm/dsh-remote-wire@1.5.0/node_modules/dsh-remote-wire/dist/src/identity/pairing.js
10767
10786
  import { randomBytes as randomBytes2 } from "node:crypto";
10768
10787
  var URI_PREFIX = "dshr:";
10769
10788
  var TOKEN_RE = /^\d{6}$/;
@@ -30461,7 +30480,7 @@ function date4(params) {
30461
30480
  return _coercedDate(ZodDate, params);
30462
30481
  }
30463
30482
 
30464
- // ../../node_modules/.pnpm/dsh-remote-wire@1.4.0/node_modules/dsh-remote-wire/dist/src/wire/frames.js
30483
+ // ../../node_modules/.pnpm/dsh-remote-wire@1.5.0/node_modules/dsh-remote-wire/dist/src/wire/frames.js
30465
30484
  var PAIRING_TOKEN_RE = /^\d{6}$/;
30466
30485
  var nonEmpty = external_exports.string().min(1);
30467
30486
  var pairingToken = external_exports.string().regex(PAIRING_TOKEN_RE);
@@ -30620,7 +30639,7 @@ function parseRelayFrameText(raw) {
30620
30639
  }
30621
30640
  }
30622
30641
 
30623
- // ../../node_modules/.pnpm/dsh-remote-wire@1.4.0/node_modules/dsh-remote-wire/dist/src/wire/payloads.js
30642
+ // ../../node_modules/.pnpm/dsh-remote-wire@1.5.0/node_modules/dsh-remote-wire/dist/src/wire/payloads.js
30624
30643
  var SESSION_STATES = [
30625
30644
  "idle",
30626
30645
  "running",
@@ -30770,7 +30789,7 @@ var evResult = external_exports.object({
30770
30789
  message: external_exports.string().optional(),
30771
30790
  data: external_exports.record(external_exports.string(), external_exports.unknown()).optional()
30772
30791
  });
30773
- var historyItem = external_exports.discriminatedUnion("t", [evMessageDelta, evToolEvent]);
30792
+ var historyItem = external_exports.discriminatedUnion("t", [evMessageDelta, evToolEvent, evTodo]);
30774
30793
  var evSessionHistory = external_exports.object({
30775
30794
  t: external_exports.literal("ev.session_history"),
30776
30795
  sessionId: nonEmpty2,
@@ -30905,7 +30924,7 @@ var PAYLOAD_TYPES = {
30905
30924
  evSessionHistory: "ev.session_history"
30906
30925
  };
30907
30926
 
30908
- // ../../node_modules/.pnpm/dsh-remote-wire@1.4.0/node_modules/dsh-remote-wire/dist/src/wire/outbound.js
30927
+ // ../../node_modules/.pnpm/dsh-remote-wire@1.5.0/node_modules/dsh-remote-wire/dist/src/wire/outbound.js
30909
30928
  function sessionChanged(sessions, reason) {
30910
30929
  return { t: PAYLOAD_TYPES.evSessionChanged, sessions, ...reason === void 0 ? {} : { reason } };
30911
30930
  }
@@ -30967,7 +30986,7 @@ function sessionHistory(args) {
30967
30986
  };
30968
30987
  }
30969
30988
 
30970
- // ../../node_modules/.pnpm/dsh-remote-wire@1.4.0/node_modules/dsh-remote-wire/dist/src/platform/sleep.js
30989
+ // ../../node_modules/.pnpm/dsh-remote-wire@1.5.0/node_modules/dsh-remote-wire/dist/src/platform/sleep.js
30971
30990
  function detectBackend(platform) {
30972
30991
  if (platform === "darwin")
30973
30992
  return "caffeinate";
@@ -31780,6 +31799,9 @@ function historyWireItem(event) {
31780
31799
  ...event.role === void 0 ? {} : { role: event.role }
31781
31800
  });
31782
31801
  }
31802
+ if (event.kind === "todo") {
31803
+ return todoList({ todos: event.todos });
31804
+ }
31783
31805
  if (event.kind === "tool") {
31784
31806
  return toolEvent({
31785
31807
  callId: event.callId,
@@ -32230,6 +32252,8 @@ import { randomBytes as randomBytes3 } from "node:crypto";
32230
32252
  var BACKOFF_MIN_MS = 1e3;
32231
32253
  var BACKOFF_MAX_MS = 3e4;
32232
32254
  var HANDSHAKE_TIMEOUT_MS = 1e4;
32255
+ var PROBE_INTERVAL_MS = 2e4;
32256
+ var PROBE_TIMEOUT_MS = 1e4;
32233
32257
  var VOIDED_MAX = 256;
32234
32258
  var RelayClient = class {
32235
32259
  constructor(options) {
@@ -32251,6 +32275,10 @@ var RelayClient = class {
32251
32275
  stopped = false;
32252
32276
  reconnectTimer;
32253
32277
  handshakeTimer;
32278
+ /** 存活探针的下一次提问(自重启的 setTimeout 链,见 {@link startProbe})。 */
32279
+ probeTimer;
32280
+ /** 已提问、还没等到 pong 的那个定时器;undefined = 当前没有待答的问题。 */
32281
+ pongDeadline;
32254
32282
  /** 连续解不开的会话:解不开说明这端已经没有对应密钥,留着它只会让手机永远转圈。 */
32255
32283
  undecryptable = /* @__PURE__ */ new Map();
32256
32284
  /** 已经向中继声明过的 convId(防重复 `session-leave`);有上界,见 {@link VOIDED_MAX}。 */
@@ -32326,6 +32354,7 @@ var RelayClient = class {
32326
32354
  });
32327
32355
  });
32328
32356
  socket.on("message", (raw) => this.onFrame(String(raw)));
32357
+ this.startProbe(socket);
32329
32358
  socket.on("close", (code, reason) => {
32330
32359
  this.options.clock.clearTimeout(timeout);
32331
32360
  this.emitState("offline", `\u8FDE\u63A5\u5173\u95ED ${code} ${reason ? reason.toString() : ""}`.trim());
@@ -32496,6 +32525,7 @@ var RelayClient = class {
32496
32525
  });
32497
32526
  return;
32498
32527
  case "pong":
32528
+ this.clearPongDeadline();
32499
32529
  return;
32500
32530
  case "enc":
32501
32531
  case "enc-batch":
@@ -32559,6 +32589,7 @@ var RelayClient = class {
32559
32589
  this.options.clock.clearTimeout(this.handshakeTimer);
32560
32590
  this.handshakeTimer = void 0;
32561
32591
  }
32592
+ this.stopProbe();
32562
32593
  if (!socket) return;
32563
32594
  socket.removeAllListeners();
32564
32595
  socket.on("error", () => {
@@ -32568,6 +32599,49 @@ var RelayClient = class {
32568
32599
  } catch {
32569
32600
  }
32570
32601
  }
32602
+ // ── 存活探针 ────────────────────────────────────────────────────────
32603
+ /**
32604
+ * 每隔 `probeIntervalMs` 问中继一句 `ping`,并给答复留 `probeTimeoutMs`。
32605
+ *
32606
+ * 用**自重启的 setTimeout 链**而不是 setInterval:时钟接口只有 setTimeout
32607
+ * (见 `Clock`),而且链式写法天然带上"上一轮还没答就下一轮"的语义——
32608
+ * 超时判死之后这条链也跟着 socket 一起被 closeSocket 收掉。
32609
+ *
32610
+ * `ping`/`pong` 是协议里本来就有的一对应用帧(中继无条件回 pong),
32611
+ * 所以这一跳不需要动线协议;不直接用 ws 协议层 ping 是因为那一条在
32612
+ * Node 的 ws 里由库自动应答,两端都"看得见"却都不留痕,排障时查不到。
32613
+ */
32614
+ startProbe(socket) {
32615
+ this.stopProbe();
32616
+ const interval = this.options.probeIntervalMs ?? PROBE_INTERVAL_MS;
32617
+ const timeout = this.options.probeTimeoutMs ?? PROBE_TIMEOUT_MS;
32618
+ const ask = () => {
32619
+ if (this.stopped || this.socket !== socket) return;
32620
+ if (socket.readyState === import_websocket.default.OPEN) {
32621
+ this.raw({ t: "ping", ts: this.options.clock.now() });
32622
+ this.clearPongDeadline();
32623
+ this.pongDeadline = this.options.clock.setTimeout(() => {
32624
+ this.options.log("relay probe timeout", { waitedMs: timeout });
32625
+ socket.terminate();
32626
+ }, timeout);
32627
+ }
32628
+ this.probeTimer = this.options.clock.setTimeout(ask, interval);
32629
+ };
32630
+ this.probeTimer = this.options.clock.setTimeout(ask, interval);
32631
+ }
32632
+ stopProbe() {
32633
+ if (this.probeTimer !== void 0) {
32634
+ this.options.clock.clearTimeout(this.probeTimer);
32635
+ this.probeTimer = void 0;
32636
+ }
32637
+ this.clearPongDeadline();
32638
+ }
32639
+ clearPongDeadline() {
32640
+ if (this.pongDeadline !== void 0) {
32641
+ this.options.clock.clearTimeout(this.pongDeadline);
32642
+ this.pongDeadline = void 0;
32643
+ }
32644
+ }
32571
32645
  emitState(relay, problem) {
32572
32646
  this.options.onState({
32573
32647
  relay,
@@ -34448,7 +34522,7 @@ function startPill(ctx, deps) {
34448
34522
  }
34449
34523
 
34450
34524
  // src/version.ts
34451
- var PLUGIN_VERSION = true ? "2.0.2" : "dev";
34525
+ var PLUGIN_VERSION = true ? "2.0.4" : "dev";
34452
34526
 
34453
34527
  // src/index.ts
34454
34528
  var SERVICE_NAMES = [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-remote-control",
3
- "version": "2.0.2",
3
+ "version": "2.0.4",
4
4
  "description": "DSH Remote Control host plugin: pairs a running DeepSeek Harness with the DRC relay so a WeChat Mini Program can send prompts, watch streamed output, and answer approvals. Payload-level E2E encryption; the relay never sees plaintext. Pairing is one click on the status-bar pill (three same-origin routes + a browser half).",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -53,19 +53,19 @@
53
53
  "provenance": true
54
54
  },
55
55
  "dependencies": {
56
- "dsh-remote-wire": "^1.4.0",
56
+ "dsh-remote-wire": "^1.5.0",
57
57
  "qrcode": "^1.5.4",
58
58
  "tweetnacl": "^1.0.3",
59
59
  "ws": "^8.18.0",
60
60
  "zod": "^4.6.5"
61
61
  },
62
62
  "devDependencies": {
63
- "@types/node": "^22.9.0",
63
+ "@types/node": "^26.6.3",
64
64
  "@types/qrcode": "^1.5.5",
65
65
  "@types/ws": "^8.5.12",
66
- "esbuild": "^0.27.7",
66
+ "esbuild": "^0.28.2",
67
67
  "prettier": "^3.3.3",
68
- "typescript": "^5.6.3"
68
+ "typescript": "^7.0.2"
69
69
  },
70
70
  "scripts": {
71
71
  "clean": "node --input-type=module -e \"import { rmSync } from 'node:fs'; rmSync('dist', { recursive: true, force: true })\"",