dsh-remote-control 2.0.0 → 2.0.2
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/dist/bundle/client.cjs +31 -14
- package/dist/bundle/index.js +295 -93
- package/package.json +2 -2
package/dist/bundle/client.cjs
CHANGED
|
@@ -73,14 +73,20 @@ function pillLabel(status) {
|
|
|
73
73
|
if (paired > 0) {
|
|
74
74
|
const waiting = waitingCount(status);
|
|
75
75
|
if (waiting > 0) return { text: `\u7B49 ${waiting} \u4EF6\u4E8B`, tone: "wait" };
|
|
76
|
-
return { text: "\u5DF2\
|
|
76
|
+
return { text: "\u5DF2\u8FDE\u63A5", tone: "on" };
|
|
77
77
|
}
|
|
78
|
-
return { text: "\
|
|
78
|
+
if (pairingCount(status) > 0) return { text: "\u624B\u673A\u79BB\u7EBF", tone: "wait" };
|
|
79
|
+
return { text: "\u8FDC\u7A0B\u672A\u8FDE\u63A5", tone: "off" };
|
|
79
80
|
}
|
|
80
81
|
function waitingCount(status) {
|
|
81
82
|
const count = status?.waiting;
|
|
82
83
|
return typeof count === "number" && count > 0 ? Math.min(Math.floor(count), 99) : 0;
|
|
83
84
|
}
|
|
85
|
+
function pairingCount(status) {
|
|
86
|
+
const count = status?.pairings;
|
|
87
|
+
return typeof count === "number" ? count : 0;
|
|
88
|
+
}
|
|
89
|
+
var GUIDE_LINE = "\u6253\u5F00\u5C0F\u7A0B\u5E8F\u626B\u8FD9\u4E2A\u7801 \u8FDC\u7A0B\u63A7\u5236\u8FD9\u53F0\u7535\u8111";
|
|
84
90
|
function humanDuration(sec) {
|
|
85
91
|
const total = typeof sec === "number" && sec > 0 ? Math.floor(sec) : 0;
|
|
86
92
|
if (total < 60) return `${total} \u79D2`;
|
|
@@ -91,7 +97,7 @@ function waitingRow(status) {
|
|
|
91
97
|
const count = waitingCount(status);
|
|
92
98
|
if (count === 0) return "";
|
|
93
99
|
const oldest = typeof status?.waitingOldestSec === "number" ? status.waitingOldestSec : 0;
|
|
94
|
-
return `${count} \u4EF6${oldest > 0 ? ` \
|
|
100
|
+
return `${count} \u4EF6${oldest > 0 ? ` \u6700\u4E45 ${humanDuration(oldest)}` : ""}`.slice(0, 40);
|
|
95
101
|
}
|
|
96
102
|
function relayAddress(url) {
|
|
97
103
|
if (typeof url !== "string" || url.trim() === "") return "";
|
|
@@ -104,7 +110,7 @@ function relayRow(status) {
|
|
|
104
110
|
}
|
|
105
111
|
function relayStateRow(status) {
|
|
106
112
|
const relay = status?.relay;
|
|
107
|
-
if (relay === "online") return "\u5DF2\
|
|
113
|
+
if (relay === "online") return "\u5DF2\u5C31\u7EEA";
|
|
108
114
|
if (relay === "connecting") return "\u8FDE\u63A5\u4E2D";
|
|
109
115
|
if (relay === "offline") return "\u5DF2\u65AD\u5F00";
|
|
110
116
|
if (relay === "idle") return "\u672A\u542F\u52A8";
|
|
@@ -160,7 +166,10 @@ var CSS = `
|
|
|
160
166
|
.drc-value { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
|
|
161
167
|
.drc-qr { display: block; width: 200px; height: 200px; margin: 8px auto 0; image-rendering: pixelated; }
|
|
162
168
|
.drc-code { margin: 8px 0 0; text-align: center; font-weight: 600; font-size: 14px; letter-spacing: 2px; }
|
|
163
|
-
|
|
169
|
+
/* \u5F15\u5BFC\u884C\uFF1A\u6BD4 note \u91CD\u4E00\u6863\uFF08\u7B2C\u4E00\u6B21\u7528\u7684\u4EBA\u8981\u770B\u6E05\uFF09\uFF0C\u4F46\u4E0D\u52A0\u56FE\u6807\u4E0D\u52A0\u5E95\u8272\u2014\u2014
|
|
170
|
+
\u8FD9\u4E00\u5C4F\u7684\u4E3B\u89D2\u662F\u4E8C\u7EF4\u7801\uFF0C\u591A\u4E00\u4E2A\u8272\u5757\u5C31\u6210\u4E86\u63A8\u9500\u800C\u4E0D\u662F\u5F15\u5BFC\u3002 */
|
|
171
|
+
.drc-guide { margin: 8px 0 0; text-align: center; color: var(--dsw-alias-label-secondary, #5f6368); font-size: 12px; }
|
|
172
|
+
.drc-note { margin: 4px 0 0; text-align: center; color: var(--dsw-alias-label-tertiary); }
|
|
164
173
|
.drc-note[data-kind="failed"] { color: var(--dsw-alias-state-error-primary, #ff4d4f); }
|
|
165
174
|
`;
|
|
166
175
|
function isSlots(value) {
|
|
@@ -236,7 +245,7 @@ function buildPill(root, deps) {
|
|
|
236
245
|
let expiresInMs = 0;
|
|
237
246
|
let lastStatus;
|
|
238
247
|
let disposed = false;
|
|
239
|
-
const
|
|
248
|
+
const pairingNow = () => pairingCount(lastStatus);
|
|
240
249
|
const write = () => {
|
|
241
250
|
const next = pillLabel(lastStatus);
|
|
242
251
|
label.textContent = next.text;
|
|
@@ -258,7 +267,7 @@ function buildPill(root, deps) {
|
|
|
258
267
|
node.addEventListener("click", onClick);
|
|
259
268
|
return node;
|
|
260
269
|
};
|
|
261
|
-
const qrNote = () => expiresInMs > 0 ? `\u626B\u7801\u914D\u5BF9
|
|
270
|
+
const qrNote = () => expiresInMs > 0 ? `\u5FAE\u4FE1\u626B\u7801\u914D\u5BF9 ${secondsText(expiresInMs)}\u540E\u8FC7\u671F` : "\u914D\u5BF9\u7801\u5DF2\u8FC7\u671F \u70B9\u53F3\u4E0A\u89D2\u5237\u65B0\u91CD\u65B0\u751F\u6210";
|
|
262
271
|
const header = () => {
|
|
263
272
|
const head = doc.createElement("div");
|
|
264
273
|
head.className = "drc-head";
|
|
@@ -268,11 +277,16 @@ function buildPill(root, deps) {
|
|
|
268
277
|
head.appendChild(stateText);
|
|
269
278
|
const actions = doc.createElement("div");
|
|
270
279
|
actions.className = "drc-actions";
|
|
271
|
-
const action =
|
|
280
|
+
const action = pairingNow() > 0 ? { label: "\u9000\u51FA\u914D\u5BF9", run: requestUnpair } : { label: "\u5237\u65B0", run: requestPairing };
|
|
272
281
|
actions.appendChild(buttonOf(action.label, () => void action.run()));
|
|
273
282
|
head.appendChild(actions);
|
|
274
283
|
return head;
|
|
275
284
|
};
|
|
285
|
+
const offlineNote = () => {
|
|
286
|
+
if (!lastStatus) return null;
|
|
287
|
+
if (pillLabel(lastStatus).text !== "\u624B\u673A\u79BB\u7EBF") return null;
|
|
288
|
+
return text("p", "drc-note", "\u914D\u5BF9\u8FD8\u5728 \u5C0F\u7A0B\u5E8F\u56DE\u524D\u53F0\u4F1A\u81EA\u52A8\u91CD\u8FDE \u4E0D\u7528\u91CD\u65B0\u626B\u7801");
|
|
289
|
+
};
|
|
276
290
|
const infoRows = () => {
|
|
277
291
|
if (!lastStatus) return [];
|
|
278
292
|
const rows = [
|
|
@@ -295,24 +309,27 @@ function buildPill(root, deps) {
|
|
|
295
309
|
panel.replaceChildren();
|
|
296
310
|
panel.appendChild(header());
|
|
297
311
|
if (view.kind === "loading") {
|
|
298
|
-
panel.appendChild(text("p", "drc-note", "\u6B63\u5728\u751F\u6210\u914D\u5BF9\u7801
|
|
312
|
+
panel.appendChild(text("p", "drc-note", "\u6B63\u5728\u751F\u6210\u914D\u5BF9\u7801"));
|
|
299
313
|
} else if (view.kind === "qr") {
|
|
300
314
|
const image = doc.createElement("img");
|
|
301
315
|
image.className = "drc-qr";
|
|
302
316
|
image.setAttribute("alt", "\u914D\u5BF9\u4E8C\u7EF4\u7801");
|
|
303
317
|
image.src = view.imageSrc;
|
|
304
318
|
panel.appendChild(image);
|
|
319
|
+
panel.appendChild(text("p", "drc-guide", GUIDE_LINE));
|
|
305
320
|
panel.appendChild(text("p", "drc-code", view.token));
|
|
306
321
|
panel.appendChild(text("p", "drc-note", qrNote()));
|
|
307
322
|
} else if (view.kind === "unavailable" || view.kind === "failed") {
|
|
308
|
-
const
|
|
323
|
+
const note2 = view.kind === "unavailable" ? text("p", "drc-note", view.reason) : (() => {
|
|
309
324
|
const node = text("p", "drc-note", `\u914D\u5BF9\u8BF7\u6C42\u6CA1\u6210\u529F\uFF1A${view.detail}`);
|
|
310
325
|
node.setAttribute("data-kind", "failed");
|
|
311
326
|
return node;
|
|
312
327
|
})();
|
|
313
|
-
panel.appendChild(
|
|
328
|
+
panel.appendChild(note2);
|
|
314
329
|
}
|
|
315
330
|
for (const row of infoRows()) panel.appendChild(row);
|
|
331
|
+
const note = offlineNote();
|
|
332
|
+
if (note) panel.appendChild(note);
|
|
316
333
|
};
|
|
317
334
|
const closePanel = () => {
|
|
318
335
|
if (countTimer !== void 0) {
|
|
@@ -373,7 +390,7 @@ function buildPill(root, deps) {
|
|
|
373
390
|
warn("\u9000\u51FA\u914D\u5BF9\u8BF7\u6C42\u5931\u8D25\uFF08\u9762\u677F\u4F1A\u9760\u4E0B\u4E00\u6B21\u8F6E\u8BE2\u5BF9\u8D26\uFF09", error);
|
|
374
391
|
}
|
|
375
392
|
if (disposed || !panel) return;
|
|
376
|
-
if (lastStatus) lastStatus = { ...lastStatus, paired: 0 };
|
|
393
|
+
if (lastStatus) lastStatus = { ...lastStatus, paired: 0, pairings: 0 };
|
|
377
394
|
write();
|
|
378
395
|
view = { kind: "loading" };
|
|
379
396
|
paint();
|
|
@@ -388,7 +405,7 @@ function buildPill(root, deps) {
|
|
|
388
405
|
panel.tabIndex = -1;
|
|
389
406
|
root.appendChild(panel);
|
|
390
407
|
button.setAttribute("aria-expanded", "true");
|
|
391
|
-
if (
|
|
408
|
+
if (pairingNow() > 0) {
|
|
392
409
|
view = { kind: "info" };
|
|
393
410
|
paint();
|
|
394
411
|
} else {
|
|
@@ -430,7 +447,7 @@ function buildPill(root, deps) {
|
|
|
430
447
|
const body = await response.json?.();
|
|
431
448
|
if (!body || typeof body !== "object") return;
|
|
432
449
|
lastStatus = body;
|
|
433
|
-
if (view.kind === "qr" &&
|
|
450
|
+
if (view.kind === "qr" && pairingNow() > 0) {
|
|
434
451
|
view = { kind: "info" };
|
|
435
452
|
if (countTimer !== void 0) {
|
|
436
453
|
clearInterval(countTimer);
|
package/dist/bundle/index.js
CHANGED
|
@@ -7486,10 +7486,10 @@ var require_segments = __commonJS({
|
|
|
7486
7486
|
const segs = getSegmentsFromString(data, Utils.isKanjiModeEnabled());
|
|
7487
7487
|
const nodes = buildNodes(segs);
|
|
7488
7488
|
const graph = buildGraph(nodes, version2);
|
|
7489
|
-
const
|
|
7489
|
+
const path7 = dijkstra.find_path(graph.map, "start", "end");
|
|
7490
7490
|
const optimizedSegs = [];
|
|
7491
|
-
for (let i = 1; i <
|
|
7492
|
-
optimizedSegs.push(graph.table[
|
|
7491
|
+
for (let i = 1; i < path7.length - 1; i++) {
|
|
7492
|
+
optimizedSegs.push(graph.table[path7[i]].node);
|
|
7493
7493
|
}
|
|
7494
7494
|
return exports.fromArray(mergeSegments(optimizedSegs));
|
|
7495
7495
|
};
|
|
@@ -9925,7 +9925,7 @@ var require_utils2 = __commonJS({
|
|
|
9925
9925
|
// ../../node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/renderer/png.js
|
|
9926
9926
|
var require_png2 = __commonJS({
|
|
9927
9927
|
"../../node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/renderer/png.js"(exports) {
|
|
9928
|
-
var
|
|
9928
|
+
var fs2 = __require("fs");
|
|
9929
9929
|
var PNG = require_png().PNG;
|
|
9930
9930
|
var Utils = require_utils2();
|
|
9931
9931
|
exports.render = function render(qrData, options) {
|
|
@@ -9966,7 +9966,7 @@ var require_png2 = __commonJS({
|
|
|
9966
9966
|
});
|
|
9967
9967
|
png.pack();
|
|
9968
9968
|
};
|
|
9969
|
-
exports.renderToFile = function renderToFile(
|
|
9969
|
+
exports.renderToFile = function renderToFile(path7, qrData, options, cb) {
|
|
9970
9970
|
if (typeof cb === "undefined") {
|
|
9971
9971
|
cb = options;
|
|
9972
9972
|
options = void 0;
|
|
@@ -9977,7 +9977,7 @@ var require_png2 = __commonJS({
|
|
|
9977
9977
|
called = true;
|
|
9978
9978
|
cb.apply(null, args);
|
|
9979
9979
|
};
|
|
9980
|
-
const stream =
|
|
9980
|
+
const stream = fs2.createWriteStream(path7);
|
|
9981
9981
|
stream.on("error", done);
|
|
9982
9982
|
stream.on("close", done);
|
|
9983
9983
|
exports.renderToFileStream(stream, qrData, options);
|
|
@@ -10039,14 +10039,14 @@ var require_utf8 = __commonJS({
|
|
|
10039
10039
|
}
|
|
10040
10040
|
return output2;
|
|
10041
10041
|
};
|
|
10042
|
-
exports.renderToFile = function renderToFile(
|
|
10042
|
+
exports.renderToFile = function renderToFile(path7, qrData, options, cb) {
|
|
10043
10043
|
if (typeof cb === "undefined") {
|
|
10044
10044
|
cb = options;
|
|
10045
10045
|
options = void 0;
|
|
10046
10046
|
}
|
|
10047
|
-
const
|
|
10047
|
+
const fs2 = __require("fs");
|
|
10048
10048
|
const utf82 = exports.render(qrData, options);
|
|
10049
|
-
|
|
10049
|
+
fs2.writeFile(path7, utf82, cb);
|
|
10050
10050
|
};
|
|
10051
10051
|
}
|
|
10052
10052
|
});
|
|
@@ -10167,7 +10167,7 @@ var require_svg_tag = __commonJS({
|
|
|
10167
10167
|
return str;
|
|
10168
10168
|
}
|
|
10169
10169
|
function qrToPath(data, size, margin) {
|
|
10170
|
-
let
|
|
10170
|
+
let path7 = "";
|
|
10171
10171
|
let moveBy = 0;
|
|
10172
10172
|
let newRow = false;
|
|
10173
10173
|
let lineLength = 0;
|
|
@@ -10178,19 +10178,19 @@ var require_svg_tag = __commonJS({
|
|
|
10178
10178
|
if (data[i]) {
|
|
10179
10179
|
lineLength++;
|
|
10180
10180
|
if (!(i > 0 && col > 0 && data[i - 1])) {
|
|
10181
|
-
|
|
10181
|
+
path7 += newRow ? svgCmd("M", col + margin, 0.5 + row + margin) : svgCmd("m", moveBy, 0);
|
|
10182
10182
|
moveBy = 0;
|
|
10183
10183
|
newRow = false;
|
|
10184
10184
|
}
|
|
10185
10185
|
if (!(col + 1 < size && data[i + 1])) {
|
|
10186
|
-
|
|
10186
|
+
path7 += svgCmd("h", lineLength);
|
|
10187
10187
|
lineLength = 0;
|
|
10188
10188
|
}
|
|
10189
10189
|
} else {
|
|
10190
10190
|
moveBy++;
|
|
10191
10191
|
}
|
|
10192
10192
|
}
|
|
10193
|
-
return
|
|
10193
|
+
return path7;
|
|
10194
10194
|
}
|
|
10195
10195
|
exports.render = function render(qrData, options, cb) {
|
|
10196
10196
|
const opts = Utils.getOptions(options);
|
|
@@ -10198,10 +10198,10 @@ var require_svg_tag = __commonJS({
|
|
|
10198
10198
|
const data = qrData.modules.data;
|
|
10199
10199
|
const qrcodesize = size + opts.margin * 2;
|
|
10200
10200
|
const bg = !opts.color.light.a ? "" : "<path " + getColorAttrib(opts.color.light, "fill") + ' d="M0 0h' + qrcodesize + "v" + qrcodesize + 'H0z"/>';
|
|
10201
|
-
const
|
|
10201
|
+
const path7 = "<path " + getColorAttrib(opts.color.dark, "stroke") + ' d="' + qrToPath(data, size, opts.margin) + '"/>';
|
|
10202
10202
|
const viewBox = 'viewBox="0 0 ' + qrcodesize + " " + qrcodesize + '"';
|
|
10203
10203
|
const width = !opts.width ? "" : 'width="' + opts.width + '" height="' + opts.width + '" ';
|
|
10204
|
-
const svgTag = '<svg xmlns="http://www.w3.org/2000/svg" ' + width + viewBox + ' shape-rendering="crispEdges">' + bg +
|
|
10204
|
+
const svgTag = '<svg xmlns="http://www.w3.org/2000/svg" ' + width + viewBox + ' shape-rendering="crispEdges">' + bg + path7 + "</svg>\n";
|
|
10205
10205
|
if (typeof cb === "function") {
|
|
10206
10206
|
cb(null, svgTag);
|
|
10207
10207
|
}
|
|
@@ -10215,15 +10215,15 @@ var require_svg = __commonJS({
|
|
|
10215
10215
|
"../../node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/renderer/svg.js"(exports) {
|
|
10216
10216
|
var svgTagRenderer = require_svg_tag();
|
|
10217
10217
|
exports.render = svgTagRenderer.render;
|
|
10218
|
-
exports.renderToFile = function renderToFile(
|
|
10218
|
+
exports.renderToFile = function renderToFile(path7, qrData, options, cb) {
|
|
10219
10219
|
if (typeof cb === "undefined") {
|
|
10220
10220
|
cb = options;
|
|
10221
10221
|
options = void 0;
|
|
10222
10222
|
}
|
|
10223
|
-
const
|
|
10223
|
+
const fs2 = __require("fs");
|
|
10224
10224
|
const svgTag = exports.render(qrData, options);
|
|
10225
10225
|
const xmlStr = '<?xml version="1.0" encoding="utf-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">' + svgTag;
|
|
10226
|
-
|
|
10226
|
+
fs2.writeFile(path7, xmlStr, cb);
|
|
10227
10227
|
};
|
|
10228
10228
|
}
|
|
10229
10229
|
});
|
|
@@ -10381,8 +10381,8 @@ var require_server = __commonJS({
|
|
|
10381
10381
|
cb
|
|
10382
10382
|
};
|
|
10383
10383
|
}
|
|
10384
|
-
function getTypeFromFilename(
|
|
10385
|
-
return
|
|
10384
|
+
function getTypeFromFilename(path7) {
|
|
10385
|
+
return path7.slice((path7.lastIndexOf(".") - 1 >>> 0) + 2).toLowerCase();
|
|
10386
10386
|
}
|
|
10387
10387
|
function getRendererFromType(type) {
|
|
10388
10388
|
switch (type) {
|
|
@@ -10446,17 +10446,17 @@ var require_server = __commonJS({
|
|
|
10446
10446
|
const renderer = getRendererFromType(params.opts.type);
|
|
10447
10447
|
return render(renderer.renderToBuffer, text, params);
|
|
10448
10448
|
};
|
|
10449
|
-
exports.toFile = function toFile(
|
|
10450
|
-
if (typeof
|
|
10449
|
+
exports.toFile = function toFile(path7, text, opts, cb) {
|
|
10450
|
+
if (typeof path7 !== "string" || !(typeof text === "string" || typeof text === "object")) {
|
|
10451
10451
|
throw new Error("Invalid argument");
|
|
10452
10452
|
}
|
|
10453
10453
|
if (arguments.length < 3 && !canPromise()) {
|
|
10454
10454
|
throw new Error("Too few arguments provided");
|
|
10455
10455
|
}
|
|
10456
10456
|
const params = checkParams(text, opts, cb);
|
|
10457
|
-
const type = params.opts.type || getTypeFromFilename(
|
|
10457
|
+
const type = params.opts.type || getTypeFromFilename(path7);
|
|
10458
10458
|
const renderer = getRendererFromType(type);
|
|
10459
|
-
const renderToFile = renderer.renderToFile.bind(null,
|
|
10459
|
+
const renderToFile = renderer.renderToFile.bind(null, path7);
|
|
10460
10460
|
return render(renderToFile, text, params);
|
|
10461
10461
|
};
|
|
10462
10462
|
exports.toFileStream = function toFileStream(stream, text, opts) {
|
|
@@ -10538,6 +10538,22 @@ var init_mock_kernel = __esm({
|
|
|
10538
10538
|
if (found.state === "archived") return { ok: false, message: "\u4F1A\u8BDD\u5DF2\u5F52\u6863\uFF0C\u9700\u5148\u6062\u590D" };
|
|
10539
10539
|
this.running.add(sessionId);
|
|
10540
10540
|
this.emit({ kind: "run-state", sessionId, state: "running" });
|
|
10541
|
+
this.emit({
|
|
10542
|
+
kind: "todo",
|
|
10543
|
+
sessionId,
|
|
10544
|
+
todos: [
|
|
10545
|
+
{ content: "\u590D\u73B0\u7528\u6237\u62A5\u7684\u95EE\u9898", status: "completed" },
|
|
10546
|
+
{ content: "\u6539\u5B8C\u8DD1\u4E00\u904D\u672C\u5730\u5168\u94FE\u8DEF", status: "pending" }
|
|
10547
|
+
]
|
|
10548
|
+
});
|
|
10549
|
+
this.emit({
|
|
10550
|
+
kind: "todo",
|
|
10551
|
+
sessionId,
|
|
10552
|
+
todos: [
|
|
10553
|
+
{ content: "\u590D\u73B0\u7528\u6237\u62A5\u7684\u95EE\u9898", status: "completed" },
|
|
10554
|
+
{ content: "\u6539\u5B8C\u8DD1\u4E00\u904D\u672C\u5730\u5168\u94FE\u8DEF", status: "in_progress" }
|
|
10555
|
+
]
|
|
10556
|
+
});
|
|
10541
10557
|
if (this.options.autoApproval !== false && this.sink) {
|
|
10542
10558
|
const decision = await this.sink.approval({ sessionId, action: "bash echo", reason: "mock \u5BA1\u6279" });
|
|
10543
10559
|
this.emit({
|
|
@@ -10655,9 +10671,9 @@ var init_mock_kernel = __esm({
|
|
|
10655
10671
|
});
|
|
10656
10672
|
|
|
10657
10673
|
// src/index.ts
|
|
10658
|
-
import
|
|
10674
|
+
import path6 from "node:path";
|
|
10659
10675
|
|
|
10660
|
-
// ../../node_modules/.pnpm/dsh-remote-wire@1.
|
|
10676
|
+
// ../../node_modules/.pnpm/dsh-remote-wire@1.4.0/node_modules/dsh-remote-wire/dist/src/crypto/bytes.js
|
|
10661
10677
|
import { Buffer as Buffer2 } from "node:buffer";
|
|
10662
10678
|
var encoder = new TextEncoder();
|
|
10663
10679
|
var decoder = new TextDecoder("utf-8", { fatal: false });
|
|
@@ -10684,7 +10700,7 @@ function concat(parts) {
|
|
|
10684
10700
|
return out;
|
|
10685
10701
|
}
|
|
10686
10702
|
|
|
10687
|
-
// ../../node_modules/.pnpm/dsh-remote-wire@1.
|
|
10703
|
+
// ../../node_modules/.pnpm/dsh-remote-wire@1.4.0/node_modules/dsh-remote-wire/dist/src/crypto/keys.js
|
|
10688
10704
|
import { createHash, randomBytes } from "node:crypto";
|
|
10689
10705
|
var KDF_NAMESPACE = "dsh-rc/v1";
|
|
10690
10706
|
var UNIT_SEPARATOR = 31;
|
|
@@ -10714,7 +10730,7 @@ function randomNonce() {
|
|
|
10714
10730
|
return new Uint8Array(randomBytes(NONCE_BYTES));
|
|
10715
10731
|
}
|
|
10716
10732
|
|
|
10717
|
-
// ../../node_modules/.pnpm/dsh-remote-wire@1.
|
|
10733
|
+
// ../../node_modules/.pnpm/dsh-remote-wire@1.4.0/node_modules/dsh-remote-wire/dist/src/crypto/record.js
|
|
10718
10734
|
var import_tweetnacl = __toESM(require_nacl_fast(), 1);
|
|
10719
10735
|
var MAC_BYTES = 16;
|
|
10720
10736
|
var MIN_RECORD_BYTES = NONCE_BYTES + MAC_BYTES;
|
|
@@ -10747,7 +10763,7 @@ function open(key, record2) {
|
|
|
10747
10763
|
}
|
|
10748
10764
|
}
|
|
10749
10765
|
|
|
10750
|
-
// ../../node_modules/.pnpm/dsh-remote-wire@1.
|
|
10766
|
+
// ../../node_modules/.pnpm/dsh-remote-wire@1.4.0/node_modules/dsh-remote-wire/dist/src/identity/pairing.js
|
|
10751
10767
|
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
10752
10768
|
var URI_PREFIX = "dshr:";
|
|
10753
10769
|
var TOKEN_RE = /^\d{6}$/;
|
|
@@ -11593,10 +11609,10 @@ function mergeDefs(...defs) {
|
|
|
11593
11609
|
function cloneDef(schema) {
|
|
11594
11610
|
return mergeDefs(schema._zod.def);
|
|
11595
11611
|
}
|
|
11596
|
-
function getElementAtPath(obj,
|
|
11597
|
-
if (!
|
|
11612
|
+
function getElementAtPath(obj, path7) {
|
|
11613
|
+
if (!path7)
|
|
11598
11614
|
return obj;
|
|
11599
|
-
return
|
|
11615
|
+
return path7.reduce((acc, key) => acc?.[key], obj);
|
|
11600
11616
|
}
|
|
11601
11617
|
function promiseAllObject(promisesObj) {
|
|
11602
11618
|
const keys = Object.keys(promisesObj);
|
|
@@ -11936,11 +11952,11 @@ function explicitlyAborted(x, startIndex = 0) {
|
|
|
11936
11952
|
}
|
|
11937
11953
|
return false;
|
|
11938
11954
|
}
|
|
11939
|
-
function prefixIssues(
|
|
11955
|
+
function prefixIssues(path7, issues) {
|
|
11940
11956
|
return issues.map((iss) => {
|
|
11941
11957
|
var _a3;
|
|
11942
11958
|
(_a3 = iss).path ?? (_a3.path = []);
|
|
11943
|
-
iss.path.unshift(
|
|
11959
|
+
iss.path.unshift(path7);
|
|
11944
11960
|
return iss;
|
|
11945
11961
|
});
|
|
11946
11962
|
}
|
|
@@ -12390,16 +12406,16 @@ function flattenError(error62, mapper = (issue2) => issue2.message) {
|
|
|
12390
12406
|
}
|
|
12391
12407
|
function formatError(error62, mapper = (issue2) => issue2.message) {
|
|
12392
12408
|
const fieldErrors = { _errors: [] };
|
|
12393
|
-
const processError = (error63,
|
|
12409
|
+
const processError = (error63, path7 = []) => {
|
|
12394
12410
|
for (const issue2 of error63.issues) {
|
|
12395
12411
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
12396
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
12412
|
+
issue2.errors.map((issues) => processError({ issues }, [...path7, ...issue2.path]));
|
|
12397
12413
|
} else if (issue2.code === "invalid_key") {
|
|
12398
|
-
processError({ issues: issue2.issues }, [...
|
|
12414
|
+
processError({ issues: issue2.issues }, [...path7, ...issue2.path]);
|
|
12399
12415
|
} else if (issue2.code === "invalid_element") {
|
|
12400
|
-
processError({ issues: issue2.issues }, [...
|
|
12416
|
+
processError({ issues: issue2.issues }, [...path7, ...issue2.path]);
|
|
12401
12417
|
} else {
|
|
12402
|
-
const fullpath = [...
|
|
12418
|
+
const fullpath = [...path7, ...issue2.path];
|
|
12403
12419
|
if (fullpath.length === 0) {
|
|
12404
12420
|
fieldErrors._errors.push(mapper(issue2));
|
|
12405
12421
|
} else {
|
|
@@ -12438,17 +12454,17 @@ function formatError(error62, mapper = (issue2) => issue2.message) {
|
|
|
12438
12454
|
}
|
|
12439
12455
|
function treeifyError(error62, mapper = (issue2) => issue2.message) {
|
|
12440
12456
|
const result2 = { errors: [] };
|
|
12441
|
-
const processError = (error63,
|
|
12457
|
+
const processError = (error63, path7 = []) => {
|
|
12442
12458
|
var _a3;
|
|
12443
12459
|
for (const issue2 of error63.issues) {
|
|
12444
12460
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
12445
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
12461
|
+
issue2.errors.map((issues) => processError({ issues }, [...path7, ...issue2.path]));
|
|
12446
12462
|
} else if (issue2.code === "invalid_key") {
|
|
12447
|
-
processError({ issues: issue2.issues }, [...
|
|
12463
|
+
processError({ issues: issue2.issues }, [...path7, ...issue2.path]);
|
|
12448
12464
|
} else if (issue2.code === "invalid_element") {
|
|
12449
|
-
processError({ issues: issue2.issues }, [...
|
|
12465
|
+
processError({ issues: issue2.issues }, [...path7, ...issue2.path]);
|
|
12450
12466
|
} else {
|
|
12451
|
-
const fullpath = [...
|
|
12467
|
+
const fullpath = [...path7, ...issue2.path];
|
|
12452
12468
|
if (fullpath.length === 0) {
|
|
12453
12469
|
result2.errors.push(mapper(issue2));
|
|
12454
12470
|
continue;
|
|
@@ -12487,8 +12503,8 @@ function treeifyError(error62, mapper = (issue2) => issue2.message) {
|
|
|
12487
12503
|
}
|
|
12488
12504
|
function toDotPath(_path) {
|
|
12489
12505
|
const segs = [];
|
|
12490
|
-
const
|
|
12491
|
-
for (const seg of
|
|
12506
|
+
const path7 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
12507
|
+
for (const seg of path7) {
|
|
12492
12508
|
if (typeof seg === "number")
|
|
12493
12509
|
segs.push(`[${seg}]`);
|
|
12494
12510
|
else if (typeof seg === "symbol")
|
|
@@ -29590,13 +29606,13 @@ function resolveRef(ref, ctx) {
|
|
|
29590
29606
|
if (!ref.startsWith("#")) {
|
|
29591
29607
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
29592
29608
|
}
|
|
29593
|
-
const
|
|
29594
|
-
if (
|
|
29609
|
+
const path7 = ref.slice(1).split("/").filter(Boolean);
|
|
29610
|
+
if (path7.length === 0) {
|
|
29595
29611
|
return ctx.rootSchema;
|
|
29596
29612
|
}
|
|
29597
29613
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
29598
|
-
if (
|
|
29599
|
-
const key =
|
|
29614
|
+
if (path7[0] === defsKey) {
|
|
29615
|
+
const key = path7[1] === void 0 ? void 0 : decodeJSONPointerSegment(path7[1]);
|
|
29600
29616
|
if (!key || !ctx.defs[key]) {
|
|
29601
29617
|
throw new Error(`Reference not found: ${ref}`);
|
|
29602
29618
|
}
|
|
@@ -30445,7 +30461,7 @@ function date4(params) {
|
|
|
30445
30461
|
return _coercedDate(ZodDate, params);
|
|
30446
30462
|
}
|
|
30447
30463
|
|
|
30448
|
-
// ../../node_modules/.pnpm/dsh-remote-wire@1.
|
|
30464
|
+
// ../../node_modules/.pnpm/dsh-remote-wire@1.4.0/node_modules/dsh-remote-wire/dist/src/wire/frames.js
|
|
30449
30465
|
var PAIRING_TOKEN_RE = /^\d{6}$/;
|
|
30450
30466
|
var nonEmpty = external_exports.string().min(1);
|
|
30451
30467
|
var pairingToken = external_exports.string().regex(PAIRING_TOKEN_RE);
|
|
@@ -30604,7 +30620,7 @@ function parseRelayFrameText(raw) {
|
|
|
30604
30620
|
}
|
|
30605
30621
|
}
|
|
30606
30622
|
|
|
30607
|
-
// ../../node_modules/.pnpm/dsh-remote-wire@1.
|
|
30623
|
+
// ../../node_modules/.pnpm/dsh-remote-wire@1.4.0/node_modules/dsh-remote-wire/dist/src/wire/payloads.js
|
|
30608
30624
|
var SESSION_STATES = [
|
|
30609
30625
|
"idle",
|
|
30610
30626
|
"running",
|
|
@@ -30711,6 +30727,16 @@ var evRunState = external_exports.object({
|
|
|
30711
30727
|
state: external_exports.enum(["running", "idle"]),
|
|
30712
30728
|
detail: external_exports.string().optional()
|
|
30713
30729
|
});
|
|
30730
|
+
var todoItem = external_exports.object({
|
|
30731
|
+
/** 待办正文。内核侧不限长,协议侧截到 200 字(面板高度有限,超长的部分看不见)。 */
|
|
30732
|
+
content: external_exports.string(),
|
|
30733
|
+
status: external_exports.enum(["pending", "in_progress", "completed"])
|
|
30734
|
+
});
|
|
30735
|
+
var evTodo = external_exports.object({
|
|
30736
|
+
t: external_exports.literal("ev.todo"),
|
|
30737
|
+
sessionId: nonEmpty2.optional(),
|
|
30738
|
+
todos: external_exports.array(todoItem)
|
|
30739
|
+
});
|
|
30714
30740
|
var evKeepAwakeState = external_exports.object({
|
|
30715
30741
|
t: external_exports.literal("ev.keep_awake_state"),
|
|
30716
30742
|
enabled: external_exports.boolean(),
|
|
@@ -30762,17 +30788,34 @@ var evPayload = external_exports.discriminatedUnion("t", [
|
|
|
30762
30788
|
evQuestionRequest,
|
|
30763
30789
|
evQuestionResolved,
|
|
30764
30790
|
evRunState,
|
|
30791
|
+
evTodo,
|
|
30765
30792
|
evKeepAwakeState,
|
|
30766
30793
|
evModel,
|
|
30767
30794
|
evResult,
|
|
30768
30795
|
evSessionHistory
|
|
30769
30796
|
]);
|
|
30797
|
+
var imageAttachment = external_exports.object({
|
|
30798
|
+
/** 落盘用的文件名(mp 侧生成,形如 `img-<ms>-<n>.jpg`;主机侧还会再收敛一次字符集)。 */
|
|
30799
|
+
name: nonEmpty2,
|
|
30800
|
+
mediaType: external_exports.literal("image/jpeg"),
|
|
30801
|
+
/** base64 字节,**不带** `data:` 前缀。 */
|
|
30802
|
+
data: nonEmpty2,
|
|
30803
|
+
/** 压缩后的像素尺寸,主机写旁车元数据用(排错时对得上)。 */
|
|
30804
|
+
width: external_exports.number().int().positive().optional(),
|
|
30805
|
+
height: external_exports.number().int().positive().optional()
|
|
30806
|
+
});
|
|
30770
30807
|
var cmdSendPrompt = external_exports.object({
|
|
30771
30808
|
t: external_exports.literal("cmd.send_prompt"),
|
|
30772
30809
|
cmdId: nonEmpty2,
|
|
30773
30810
|
/** DSH 会话 id,不是配对通道 id。 */
|
|
30774
30811
|
sessionId: nonEmpty2,
|
|
30775
|
-
text: external_exports.string()
|
|
30812
|
+
text: external_exports.string(),
|
|
30813
|
+
/**
|
|
30814
|
+
* 随消息的图片附件。**可选**:老版本手机不带这个字段,老主机看到也不认
|
|
30815
|
+
* (zod 默认 strip 未知键,而 text 照旧)——所以这是向后兼容的增补,不升协议版本。
|
|
30816
|
+
* 上限 4 张:再多对"看清楚这张图"没有帮助,只是把帧撑爆。
|
|
30817
|
+
*/
|
|
30818
|
+
images: external_exports.array(imageAttachment).max(4).optional()
|
|
30776
30819
|
});
|
|
30777
30820
|
var answerItem = external_exports.object({
|
|
30778
30821
|
questionId: nonEmpty2,
|
|
@@ -30855,13 +30898,14 @@ var PAYLOAD_TYPES = {
|
|
|
30855
30898
|
evQuestionRequest: "ev.question_request",
|
|
30856
30899
|
evQuestionResolved: "ev.question_resolved",
|
|
30857
30900
|
evRunState: "ev.run_state",
|
|
30901
|
+
evTodo: "ev.todo",
|
|
30858
30902
|
evKeepAwakeState: "ev.keep_awake_state",
|
|
30859
30903
|
evModel: "ev.model",
|
|
30860
30904
|
evResult: "ev.result",
|
|
30861
30905
|
evSessionHistory: "ev.session_history"
|
|
30862
30906
|
};
|
|
30863
30907
|
|
|
30864
|
-
// ../../node_modules/.pnpm/dsh-remote-wire@1.
|
|
30908
|
+
// ../../node_modules/.pnpm/dsh-remote-wire@1.4.0/node_modules/dsh-remote-wire/dist/src/wire/outbound.js
|
|
30865
30909
|
function sessionChanged(sessions, reason) {
|
|
30866
30910
|
return { t: PAYLOAD_TYPES.evSessionChanged, sessions, ...reason === void 0 ? {} : { reason } };
|
|
30867
30911
|
}
|
|
@@ -30886,6 +30930,9 @@ function questionResolved(args) {
|
|
|
30886
30930
|
function runState(args) {
|
|
30887
30931
|
return { t: PAYLOAD_TYPES.evRunState, ...args };
|
|
30888
30932
|
}
|
|
30933
|
+
function todoList(args) {
|
|
30934
|
+
return { t: PAYLOAD_TYPES.evTodo, ...args };
|
|
30935
|
+
}
|
|
30889
30936
|
function keepAwakeState(args) {
|
|
30890
30937
|
return { t: PAYLOAD_TYPES.evKeepAwakeState, ...args };
|
|
30891
30938
|
}
|
|
@@ -30920,7 +30967,7 @@ function sessionHistory(args) {
|
|
|
30920
30967
|
};
|
|
30921
30968
|
}
|
|
30922
30969
|
|
|
30923
|
-
// ../../node_modules/.pnpm/dsh-remote-wire@1.
|
|
30970
|
+
// ../../node_modules/.pnpm/dsh-remote-wire@1.4.0/node_modules/dsh-remote-wire/dist/src/platform/sleep.js
|
|
30924
30971
|
function detectBackend(platform) {
|
|
30925
30972
|
if (platform === "darwin")
|
|
30926
30973
|
return "caffeinate";
|
|
@@ -30961,6 +31008,81 @@ function buildSleepCommand(platform, ownerPid, keepDisplay = false) {
|
|
|
30961
31008
|
// src/core/runtime.ts
|
|
30962
31009
|
import { randomUUID } from "node:crypto";
|
|
30963
31010
|
|
|
31011
|
+
// src/shell/uploads.ts
|
|
31012
|
+
import fs from "node:fs";
|
|
31013
|
+
import path from "node:path";
|
|
31014
|
+
function safeSegment(raw, fallback, maxLen = 96) {
|
|
31015
|
+
const cleaned = String(raw || "").replace(/[^A-Za-z0-9._-]+/g, "_").replace(/^[._-]+/, "").slice(0, maxLen).replace(/[._-]+$/, "");
|
|
31016
|
+
return cleaned === "" ? fallback : cleaned;
|
|
31017
|
+
}
|
|
31018
|
+
function decodeBase64(data) {
|
|
31019
|
+
if (!/^[A-Za-z0-9+/=\s]+$/.test(data)) return null;
|
|
31020
|
+
const buf = Buffer.from(data, "base64");
|
|
31021
|
+
return buf.length > 0 ? buf : null;
|
|
31022
|
+
}
|
|
31023
|
+
function looksLikeJpeg(buf) {
|
|
31024
|
+
return buf.length > 3 && buf[0] === 255 && buf[1] === 216 && buf[2] === 255;
|
|
31025
|
+
}
|
|
31026
|
+
function saveImageAttachments(options) {
|
|
31027
|
+
const maxCount = options.maxCount ?? 4;
|
|
31028
|
+
const maxBytes = options.maxBytesPerImage ?? 4 * 1024 * 1024;
|
|
31029
|
+
const images = options.images || [];
|
|
31030
|
+
if (images.length === 0) return { ok: true, saved: [], dir: options.dir };
|
|
31031
|
+
if (images.length > maxCount) {
|
|
31032
|
+
return { ok: false, message: `\u4E00\u6B21\u6700\u591A\u5E26 ${maxCount} \u5F20\u56FE\u7247\uFF0C\u6536\u5230 ${images.length} \u5F20` };
|
|
31033
|
+
}
|
|
31034
|
+
const decoded = [];
|
|
31035
|
+
for (const [i, img] of images.entries()) {
|
|
31036
|
+
if (img.mediaType !== "image/jpeg") {
|
|
31037
|
+
return { ok: false, message: `\u7B2C ${i + 1} \u5F20\u4E0D\u662F jpeg\uFF08${img.mediaType || "\u7A7A"}\uFF09\uFF0C\u4E3B\u673A\u53EA\u6536 jpeg` };
|
|
31038
|
+
}
|
|
31039
|
+
const buf = decodeBase64(img.data);
|
|
31040
|
+
if (!buf) return { ok: false, message: `\u7B2C ${i + 1} \u5F20\u7684\u89E3\u7801\u5931\u8D25\uFF08\u4E0D\u662F\u5408\u6CD5 base64\uFF09` };
|
|
31041
|
+
if (buf.length > maxBytes) {
|
|
31042
|
+
return {
|
|
31043
|
+
ok: false,
|
|
31044
|
+
message: `\u7B2C ${i + 1} \u5F20\u6709 ${Math.round(buf.length / 1024)}KB\uFF0C\u8D85\u8FC7\u5355\u5F20\u4E0A\u9650 ${Math.round(maxBytes / 1024)}KB`
|
|
31045
|
+
};
|
|
31046
|
+
}
|
|
31047
|
+
if (!looksLikeJpeg(buf)) {
|
|
31048
|
+
return { ok: false, message: `\u7B2C ${i + 1} \u5F20\u7684\u5185\u5BB9\u4E0D\u662F jpeg\uFF08\u6587\u4EF6\u5934\u5BF9\u4E0D\u4E0A\uFF09` };
|
|
31049
|
+
}
|
|
31050
|
+
decoded.push({ img, buf });
|
|
31051
|
+
}
|
|
31052
|
+
const sessionDir = path.join(options.dir, safeSegment(options.sessionId, "session"));
|
|
31053
|
+
const written = [];
|
|
31054
|
+
try {
|
|
31055
|
+
fs.mkdirSync(sessionDir, { recursive: true });
|
|
31056
|
+
for (const [i, one] of decoded.entries()) {
|
|
31057
|
+
const base = safeSegment(one.img.name, `img-${i + 1}.jpg`).replace(/\.jpg$/i, "") + ".jpg";
|
|
31058
|
+
let name = base;
|
|
31059
|
+
let n = 1;
|
|
31060
|
+
while (fs.existsSync(path.join(sessionDir, name))) {
|
|
31061
|
+
name = base.replace(/\.jpg$/, `-${++n}.jpg`);
|
|
31062
|
+
}
|
|
31063
|
+
const file2 = path.join(sessionDir, name);
|
|
31064
|
+
fs.writeFileSync(file2, one.buf, { mode: 384 });
|
|
31065
|
+
written.push({ name, path: file2, bytes: one.buf.length });
|
|
31066
|
+
}
|
|
31067
|
+
} catch (error62) {
|
|
31068
|
+
return {
|
|
31069
|
+
ok: false,
|
|
31070
|
+
message: `\u56FE\u7247\u843D\u76D8\u5931\u8D25\uFF1A${String(error62?.message ?? error62).slice(0, 160)}`
|
|
31071
|
+
};
|
|
31072
|
+
}
|
|
31073
|
+
return { ok: true, saved: written, dir: sessionDir };
|
|
31074
|
+
}
|
|
31075
|
+
function appendImageNote(text, saved) {
|
|
31076
|
+
if (saved.length === 0) return text;
|
|
31077
|
+
const lines = saved.map((img, i) => `${i + 1}. ${img.path}`);
|
|
31078
|
+
const note = `
|
|
31079
|
+
|
|
31080
|
+
[\u56FE\u7247\u9644\u4EF6 ${saved.length} \u5F20\uFF0C\u5DF2\u5B58\u5230\u672C\u673A]
|
|
31081
|
+
${lines.join("\n")}`;
|
|
31082
|
+
const head = String(text || "");
|
|
31083
|
+
return head === "" ? note.replace(/^\n\n/, "") : head + note;
|
|
31084
|
+
}
|
|
31085
|
+
|
|
30964
31086
|
// src/core/window.ts
|
|
30965
31087
|
var DEFAULT_WINDOW_OPTIONS = {
|
|
30966
31088
|
windowMs: 120,
|
|
@@ -31131,7 +31253,11 @@ var DEFAULTS = {
|
|
|
31131
31253
|
listingRefreshMs: 15e3,
|
|
31132
31254
|
approvalTimeoutMs: 18e4,
|
|
31133
31255
|
questionTimeoutMs: 3e5,
|
|
31134
|
-
unarchiveOnPrompt: true
|
|
31256
|
+
unarchiveOnPrompt: true,
|
|
31257
|
+
// 图片附件:默认**不收**(uploadDir 空 = 拒收)。要放开必须在插件配置里显式
|
|
31258
|
+
// 给一个目录——落盘是往用户磁盘写文件,不该由库默认值悄悄代劳。
|
|
31259
|
+
uploadDir: "",
|
|
31260
|
+
maxImageBytes: 4 * 1024 * 1024
|
|
31135
31261
|
};
|
|
31136
31262
|
var LISTING_LIMIT = 100;
|
|
31137
31263
|
var HISTORY_LIMIT = 40;
|
|
@@ -31218,7 +31344,32 @@ var HostRuntime = class {
|
|
|
31218
31344
|
return;
|
|
31219
31345
|
}
|
|
31220
31346
|
}
|
|
31221
|
-
|
|
31347
|
+
let text = cmd.text;
|
|
31348
|
+
const images = Array.isArray(cmd.images) ? cmd.images : [];
|
|
31349
|
+
if (images.length > 0) {
|
|
31350
|
+
if (!this.options.uploadDir) {
|
|
31351
|
+
reply(false, { message: "\u8FD9\u53F0\u4E3B\u673A\u6CA1\u914D\u56FE\u7247\u843D\u76D8\u76EE\u5F55\uFF08uploadDir\uFF09\uFF0C\u6536\u4E0D\u4E86\u56FE\u7247\u9644\u4EF6" });
|
|
31352
|
+
return;
|
|
31353
|
+
}
|
|
31354
|
+
const saved = saveImageAttachments({
|
|
31355
|
+
images,
|
|
31356
|
+
dir: this.options.uploadDir,
|
|
31357
|
+
sessionId: cmd.sessionId,
|
|
31358
|
+
maxBytesPerImage: this.options.maxImageBytes
|
|
31359
|
+
});
|
|
31360
|
+
if (!saved.ok) {
|
|
31361
|
+
reply(false, { message: saved.message });
|
|
31362
|
+
return;
|
|
31363
|
+
}
|
|
31364
|
+
this.options.log?.("\u56FE\u7247\u9644\u4EF6\u843D\u76D8", {
|
|
31365
|
+
sessionId: cmd.sessionId,
|
|
31366
|
+
images: saved.saved.length,
|
|
31367
|
+
bytes: saved.saved.reduce((sum, img) => sum + img.bytes, 0),
|
|
31368
|
+
dir: saved.dir
|
|
31369
|
+
});
|
|
31370
|
+
text = appendImageNote(text, saved.saved);
|
|
31371
|
+
}
|
|
31372
|
+
const sent = await this.kernel.sendPrompt(cmd.sessionId, text);
|
|
31222
31373
|
reply(sent.ok, sent.message ? { message: sent.message } : {});
|
|
31223
31374
|
if (sent.ok) {
|
|
31224
31375
|
this.sleep.markActive();
|
|
@@ -31356,6 +31507,11 @@ var HostRuntime = class {
|
|
|
31356
31507
|
if (event.state === "running") this.sleep.markActive();
|
|
31357
31508
|
void this.pushSessions("run-state");
|
|
31358
31509
|
return;
|
|
31510
|
+
case "todo":
|
|
31511
|
+
this.window.flushSession(event.sessionId);
|
|
31512
|
+
this.broadcast(todoList({ todos: event.todos, sessionId: event.sessionId }));
|
|
31513
|
+
this.sleep.markActive();
|
|
31514
|
+
return;
|
|
31359
31515
|
case "title":
|
|
31360
31516
|
void this.pushSessions("title");
|
|
31361
31517
|
return;
|
|
@@ -31567,9 +31723,11 @@ var HostRuntime = class {
|
|
|
31567
31723
|
* 再补一帧 `ev.run_state` 兜住"手机上装的是老版小程序"这一档。
|
|
31568
31724
|
*
|
|
31569
31725
|
* 为什么要两条而不是一条:`ev.permission_resolved` / `ev.question_resolved` 是按
|
|
31570
|
-
* `requestId`
|
|
31571
|
-
*
|
|
31572
|
-
*
|
|
31726
|
+
* `requestId` 收单的(一次答完不会误收别的会话、别的请求那张卡),这是**正路**——
|
|
31727
|
+
* mp 1.0.1 起就认这两帧(`pages/chat/chat.js` 的 `_onPermissionResolved` /
|
|
31728
|
+
* `_onQuestionResolved`)。而 `ev.run_state` 是它从第一版就认的粗粒度信号
|
|
31729
|
+
* (整会话两张卡一起收),发它只为兜住 **1.0.1 以前**的安装存量——那一档小程序
|
|
31730
|
+
* 的分发是一串 `if (p.t === …)`,认不出来的 `t` 静默忽略。
|
|
31573
31731
|
* (`pages/chat/chat.js` 的 `_onRunState` 同时清 `pendingPermission` 与 `pendingQuestion`,
|
|
31574
31732
|
* 并停掉那条还在走的本地倒数)。所以两条都发:新版手机收到精确帧就精收一张,
|
|
31575
31733
|
* 老版手机靠 `run_state` 也能当场收卡,不用等用户重新上传小程序。
|
|
@@ -32782,8 +32940,18 @@ function createServicesKernel(services, options) {
|
|
|
32782
32940
|
return { ok: false, message: `sessionController.commands \u4E0A\u6CA1\u6709 create()\uFF08\u6210\u5458\uFF1A${shapeOf(commands)}\uFF09` };
|
|
32783
32941
|
}
|
|
32784
32942
|
try {
|
|
32943
|
+
let cwd = String(options.newSessionCwd ?? "").trim();
|
|
32944
|
+
if (!cwd) {
|
|
32945
|
+
try {
|
|
32946
|
+
const newest = (await listSessions(1))[0];
|
|
32947
|
+
cwd = String(newest?.summary?.workspace ?? "").trim();
|
|
32948
|
+
} catch {
|
|
32949
|
+
}
|
|
32950
|
+
}
|
|
32951
|
+
const request = cwd === "" ? {} : { cwd };
|
|
32952
|
+
if (cwd === "") log("new session without explicit cwd; host default applies", {});
|
|
32785
32953
|
const made = await withTimeout(
|
|
32786
|
-
Promise.resolve(create.call(commands,
|
|
32954
|
+
Promise.resolve(create.call(commands, request)),
|
|
32787
32955
|
options.createTimeoutMs ?? CREATE_TIMEOUT_DEFAULT
|
|
32788
32956
|
);
|
|
32789
32957
|
const id = typeof made?.sessionId === "string" ? made.sessionId : "";
|
|
@@ -33218,12 +33386,6 @@ function createServicesKernel(services, options) {
|
|
|
33218
33386
|
modelFace: modelFaceSummary(),
|
|
33219
33387
|
workspaceRegistry: typeof services.workspaceRegistry === "object",
|
|
33220
33388
|
userQuestions: typeof services.userQuestions === "object",
|
|
33221
|
-
// 这个键**已经不生效**了:提问现在跟审批一样是 waterfall 参与者,两端同弹、
|
|
33222
|
-
// 谁先答谁算,不再有"接管/取代桌面"这回事(那条 `registerProvider` 单提供者
|
|
33223
|
-
// 路线在这一代宿主上根本不存在)。这里照实把配置值报出来,真正的状态看
|
|
33224
|
-
// `questionsFace`。(删键要动 config.ts/index.ts,那两棵树此刻有并行会话在飞的改动。)
|
|
33225
|
-
takeOverQuestions: options.takeOverQuestions === true,
|
|
33226
|
-
takeOverQuestionsInert: options.takeOverQuestions === true,
|
|
33227
33389
|
archivedSessions: archivedIds().size,
|
|
33228
33390
|
hasOn: typeof services.on === "function",
|
|
33229
33391
|
// 真机排错的第一现场:内核到底发了哪些事件类型、其中哪些我们没认。
|
|
@@ -33258,7 +33420,10 @@ var MAPPED_SESSION_EVENTS = /* @__PURE__ */ new Set([
|
|
|
33258
33420
|
"turn/end",
|
|
33259
33421
|
"session/title",
|
|
33260
33422
|
"approval/asked",
|
|
33261
|
-
"approval/decided"
|
|
33423
|
+
"approval/decided",
|
|
33424
|
+
// 内核的 todo/write 在真机的 eventTypes 里(status.json 的 unmappedEventTypes 曾一直记着它),
|
|
33425
|
+
// 但没人转发到手机——于是手机上一整轮"现在在干什么"都是空白。2026-10-05 补上。
|
|
33426
|
+
"todo/write"
|
|
33262
33427
|
]);
|
|
33263
33428
|
function sessionEventKernelEvents(input2) {
|
|
33264
33429
|
const { sessionId, type, data } = input2;
|
|
@@ -33305,6 +33470,21 @@ function sessionEventKernelEvents(input2) {
|
|
|
33305
33470
|
}
|
|
33306
33471
|
];
|
|
33307
33472
|
}
|
|
33473
|
+
case "todo/write": {
|
|
33474
|
+
const raw = Array.isArray(data.todos) ? data.todos : [];
|
|
33475
|
+
const todos = [];
|
|
33476
|
+
for (const item of raw) {
|
|
33477
|
+
if (todos.length >= 50) break;
|
|
33478
|
+
const content = typeof item?.content === "string" ? item.content.trim() : "";
|
|
33479
|
+
if (!content) continue;
|
|
33480
|
+
const status = item?.status;
|
|
33481
|
+
todos.push({
|
|
33482
|
+
content: content.slice(0, 200),
|
|
33483
|
+
status: status === "in_progress" || status === "completed" || status === "pending" ? status : "pending"
|
|
33484
|
+
});
|
|
33485
|
+
}
|
|
33486
|
+
return [{ kind: "todo", sessionId, todos }];
|
|
33487
|
+
}
|
|
33308
33488
|
case "tool/result": {
|
|
33309
33489
|
const message = data.message;
|
|
33310
33490
|
const callId = data.callId ?? message?.toolCallId ?? message?.source?.callId ?? "";
|
|
@@ -33576,7 +33756,7 @@ function createOneShotTimers(clock) {
|
|
|
33576
33756
|
|
|
33577
33757
|
// src/shell/status.ts
|
|
33578
33758
|
import { mkdirSync, renameSync, writeFileSync } from "node:fs";
|
|
33579
|
-
import
|
|
33759
|
+
import path2 from "node:path";
|
|
33580
33760
|
var StatusFile = class {
|
|
33581
33761
|
constructor(file2, clock, refreshMs = 3e3) {
|
|
33582
33762
|
this.file = file2;
|
|
@@ -33590,7 +33770,7 @@ var StatusFile = class {
|
|
|
33590
33770
|
write(snapshot) {
|
|
33591
33771
|
if (!this.file) return;
|
|
33592
33772
|
try {
|
|
33593
|
-
mkdirSync(
|
|
33773
|
+
mkdirSync(path2.dirname(this.file), { recursive: true });
|
|
33594
33774
|
const tmp = `${this.file}.tmp-${process.pid}`;
|
|
33595
33775
|
writeFileSync(
|
|
33596
33776
|
tmp,
|
|
@@ -33633,7 +33813,7 @@ var StatusFile = class {
|
|
|
33633
33813
|
// src/shell/host-id.ts
|
|
33634
33814
|
import { randomBytes as randomBytes4 } from "node:crypto";
|
|
33635
33815
|
import { chmodSync, mkdirSync as mkdirSync2, readFileSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
33636
|
-
import
|
|
33816
|
+
import path3 from "node:path";
|
|
33637
33817
|
var HOST_ID = /^[A-Za-z0-9][A-Za-z0-9_.-]{0,63}$/;
|
|
33638
33818
|
function newHostId() {
|
|
33639
33819
|
return `drc-${randomBytes4(6).toString("hex")}`;
|
|
@@ -33641,7 +33821,7 @@ function newHostId() {
|
|
|
33641
33821
|
function resolveHostId(dir, configured) {
|
|
33642
33822
|
if (configured) return configured;
|
|
33643
33823
|
if (!dir) return newHostId();
|
|
33644
|
-
const file2 =
|
|
33824
|
+
const file2 = path3.join(dir, "host-id");
|
|
33645
33825
|
let existing;
|
|
33646
33826
|
try {
|
|
33647
33827
|
existing = readFileSync(file2, "utf8").trim();
|
|
@@ -33673,7 +33853,7 @@ function resolveHostId(dir, configured) {
|
|
|
33673
33853
|
// src/shell/pair-store.ts
|
|
33674
33854
|
import { chmodSync as chmodSync2, mkdirSync as mkdirSync3, readFileSync as readFileSync2, renameSync as renameSync2, unlinkSync, writeFileSync as writeFileSync3 } from "node:fs";
|
|
33675
33855
|
import { createHash as createHash2 } from "node:crypto";
|
|
33676
|
-
import
|
|
33856
|
+
import path4 from "node:path";
|
|
33677
33857
|
var storedConversationSchema = external_exports.object({
|
|
33678
33858
|
id: external_exports.string().min(1),
|
|
33679
33859
|
/** 配对 PSK(base64)。两把方向密钥在恢复时由它现派生,不落盘。 */
|
|
@@ -33691,14 +33871,14 @@ var storeSchema = external_exports.object({
|
|
|
33691
33871
|
savedAt: external_exports.number().finite().nonnegative(),
|
|
33692
33872
|
conversations: external_exports.array(storedConversationSchema)
|
|
33693
33873
|
});
|
|
33694
|
-
function
|
|
33874
|
+
function safeSegment2(hostId) {
|
|
33695
33875
|
const cleaned = hostId.replace(/[^A-Za-z0-9._-]/g, "_").slice(0, 48);
|
|
33696
33876
|
const tag = createHash2("sha256").update(hostId).digest("hex").slice(0, 8);
|
|
33697
33877
|
return `${cleaned || "host"}-${tag}`;
|
|
33698
33878
|
}
|
|
33699
33879
|
function defaultPairStoreFile(statusFile, hostId) {
|
|
33700
33880
|
if (!statusFile) return "";
|
|
33701
|
-
return
|
|
33881
|
+
return path4.join(path4.dirname(statusFile), `conversations-${safeSegment2(hostId)}.json`);
|
|
33702
33882
|
}
|
|
33703
33883
|
var PairStore = class {
|
|
33704
33884
|
constructor(options) {
|
|
@@ -33768,7 +33948,7 @@ var PairStore = class {
|
|
|
33768
33948
|
const body = JSON.stringify({ version: 1, hostId, savedAt: now, conversations }) + "\n";
|
|
33769
33949
|
const tmp = `${file2}.tmp-${process.pid}`;
|
|
33770
33950
|
try {
|
|
33771
|
-
mkdirSync3(
|
|
33951
|
+
mkdirSync3(path4.dirname(file2), { recursive: true });
|
|
33772
33952
|
writeFileSync3(tmp, body, { encoding: "utf8", mode: 384 });
|
|
33773
33953
|
chmodSync2(tmp, 384);
|
|
33774
33954
|
renameSync2(tmp, file2);
|
|
@@ -33797,7 +33977,7 @@ function safeJsonParse(raw) {
|
|
|
33797
33977
|
|
|
33798
33978
|
// src/shell/config.ts
|
|
33799
33979
|
import { homedir } from "node:os";
|
|
33800
|
-
import
|
|
33980
|
+
import path5 from "node:path";
|
|
33801
33981
|
var DEFAULT_CONFIG = {
|
|
33802
33982
|
enabled: true,
|
|
33803
33983
|
serverUrl: "ws://127.0.0.1:8787",
|
|
@@ -33807,12 +33987,11 @@ var DEFAULT_CONFIG = {
|
|
|
33807
33987
|
hostLabel: "dsh-host",
|
|
33808
33988
|
keepAwake: { enabled: true, idleReleaseSec: 300, keepDisplay: false },
|
|
33809
33989
|
mockBridge: false,
|
|
33810
|
-
statusFile:
|
|
33990
|
+
statusFile: path5.join(homedir(), ".dsh", "dsh-remote-control", "status.json"),
|
|
33811
33991
|
unarchiveOnPrompt: true,
|
|
33812
33992
|
pairOnStartSec: 0,
|
|
33813
33993
|
pairTtlMs: 12e4,
|
|
33814
33994
|
carrierGraceMs: 5e3,
|
|
33815
|
-
takeOverQuestions: false,
|
|
33816
33995
|
approvalTimeoutSec: 180,
|
|
33817
33996
|
listingRefreshSec: 15,
|
|
33818
33997
|
conversationIdleTtlSec: 86400,
|
|
@@ -33820,6 +33999,10 @@ var DEFAULT_CONFIG = {
|
|
|
33820
33999
|
restoredIdleTtlSec: 604800,
|
|
33821
34000
|
// 密钥簿落盘:默认跟着 statusFile 走(见 `resolvePairStoreFile`)。
|
|
33822
34001
|
pairStoreFile: "",
|
|
34002
|
+
// 图片附件落盘:默认 status.json 同目录的 uploads/(见 `resolveUploadDir`)。
|
|
34003
|
+
uploadDir: "",
|
|
34004
|
+
maxImageBytes: 4 * 1024 * 1024,
|
|
34005
|
+
newSessionCwd: "",
|
|
33823
34006
|
// 配对的唯一入口。关掉它 = 这台主机**没有**配对入口(`/drc pair` 与文本二维码都在
|
|
33824
34007
|
// 2026-10-03 删掉了),所以 index.ts 会把它记成一条 warn 而不是安静地什么都不做。
|
|
33825
34008
|
pill: { enabled: true }
|
|
@@ -33831,7 +34014,17 @@ function resolvePairStoreFile(config2, hostId) {
|
|
|
33831
34014
|
if (!configured) return defaultPairStoreFile(config2.statusFile, hostId);
|
|
33832
34015
|
if (configured.startsWith("/")) return configured;
|
|
33833
34016
|
if (!config2.statusFile) return configured;
|
|
33834
|
-
return
|
|
34017
|
+
return path5.join(path5.dirname(config2.statusFile), configured);
|
|
34018
|
+
}
|
|
34019
|
+
function resolveUploadDir(config2) {
|
|
34020
|
+
const configured = config2.uploadDir.trim();
|
|
34021
|
+
if (!configured) {
|
|
34022
|
+
const base = config2.statusFile ? path5.dirname(config2.statusFile) : path5.join(homedir(), ".dsh", "dsh-remote-control");
|
|
34023
|
+
return path5.join(base, "uploads");
|
|
34024
|
+
}
|
|
34025
|
+
if (configured.startsWith("/")) return configured;
|
|
34026
|
+
if (!config2.statusFile) return configured;
|
|
34027
|
+
return path5.join(path5.dirname(config2.statusFile), configured);
|
|
33835
34028
|
}
|
|
33836
34029
|
var loopback = /^wss?:\/\/(localhost|127\.0\.0\.1|\[::1\])(:|\/|$)/;
|
|
33837
34030
|
var wsUrl = /^wss?:\/\/.+/;
|
|
@@ -33860,7 +34053,7 @@ function readConfig(injected, env = process.env) {
|
|
|
33860
34053
|
if (fromEnv("DRC_PAIR_ON_START_SEC")) merged.pairOnStartSec = envSeconds(env.DRC_PAIR_ON_START_SEC);
|
|
33861
34054
|
if (fromEnv("DRC_PILL")) merged.pill.enabled = envFlag(env.DRC_PILL, merged.pill.enabled);
|
|
33862
34055
|
if (fromEnv("DRC_MOCK_BRIDGE") === "1") merged.mockBridge = true;
|
|
33863
|
-
if (fromEnv("
|
|
34056
|
+
if (fromEnv("DRC_NEW_SESSION_CWD")) merged.newSessionCwd = env.DRC_NEW_SESSION_CWD;
|
|
33864
34057
|
if (merged.hostTokenEnv) merged.hostToken = env[merged.hostTokenEnv] ?? merged.hostToken;
|
|
33865
34058
|
return merged;
|
|
33866
34059
|
}
|
|
@@ -33935,13 +34128,6 @@ function validateConfig(config2) {
|
|
|
33935
34128
|
if (!config2.statusFile) {
|
|
33936
34129
|
problems.push({ level: "warn", field: "statusFile", message: "\u4E3A\u7A7A\u5C06\u5173\u95ED\u72B6\u6001\u5FEB\u7167\uFF1BGUI \u5BBF\u4E3B\u91CC\u8FD9\u662F\u552F\u4E00\u7684\u6392\u9519\u5165\u53E3" });
|
|
33937
34130
|
}
|
|
33938
|
-
if (config2.takeOverQuestions) {
|
|
33939
|
-
problems.push({
|
|
33940
|
-
level: "warn",
|
|
33941
|
-
field: "takeOverQuestions",
|
|
33942
|
-
message: "\u63D0\u95EE\u63A5\u7BA1\u4F1A**\u53D6\u4EE3\u684C\u9762 UI \u7684\u63D0\u95EE\u80FD\u529B**\uFF08ctx.userQuestions \u53EA\u5141\u8BB8\u4E00\u4E2A\u6D3B\u8DC3 provider\uFF09\uFF1B\u624B\u673A\u7AEF\u4E0D\u5728\u7EBF\u65F6\u63D0\u95EE\u4F1A\u76F4\u63A5\u5931\u8D25"
|
|
33943
|
-
});
|
|
33944
|
-
}
|
|
33945
34131
|
return problems;
|
|
33946
34132
|
}
|
|
33947
34133
|
function redact(value) {
|
|
@@ -34098,6 +34284,7 @@ function pillStatusHandler(deps) {
|
|
|
34098
34284
|
json2(response, 200, {
|
|
34099
34285
|
relay: status.relay,
|
|
34100
34286
|
paired: status.paired,
|
|
34287
|
+
pairings: status.pairings,
|
|
34101
34288
|
serverUrl: status.serverUrl,
|
|
34102
34289
|
version: status.version,
|
|
34103
34290
|
waiting: status.waiting,
|
|
@@ -34261,7 +34448,7 @@ function startPill(ctx, deps) {
|
|
|
34261
34448
|
}
|
|
34262
34449
|
|
|
34263
34450
|
// src/version.ts
|
|
34264
|
-
var PLUGIN_VERSION = true ? "2.0.
|
|
34451
|
+
var PLUGIN_VERSION = true ? "2.0.2" : "dev";
|
|
34265
34452
|
|
|
34266
34453
|
// src/index.ts
|
|
34267
34454
|
var SERVICE_NAMES = [
|
|
@@ -34317,7 +34504,7 @@ function applyInner(ctx, injected) {
|
|
|
34317
34504
|
const clock = systemClock;
|
|
34318
34505
|
const oneShot = createOneShotTimers(clock);
|
|
34319
34506
|
const status = new StatusFile(config2.statusFile, clock);
|
|
34320
|
-
const hostId = resolveHostId(config2.statusFile ?
|
|
34507
|
+
const hostId = resolveHostId(config2.statusFile ? path6.dirname(config2.statusFile) : "", config2.hostId);
|
|
34321
34508
|
const log = (message, fields = {}) => {
|
|
34322
34509
|
try {
|
|
34323
34510
|
process.stdout.write(
|
|
@@ -34441,6 +34628,8 @@ function applyInner(ctx, injected) {
|
|
|
34441
34628
|
runtime = new HostRuntime(port, transport, sleep, clock, {
|
|
34442
34629
|
listingRefreshMs: config2.listingRefreshSec * 1e3,
|
|
34443
34630
|
unarchiveOnPrompt: config2.unarchiveOnPrompt,
|
|
34631
|
+
uploadDir: resolveUploadDir(config2),
|
|
34632
|
+
maxImageBytes: config2.maxImageBytes,
|
|
34444
34633
|
approvalTimeoutMs: config2.approvalTimeoutSec * 1e3,
|
|
34445
34634
|
log: (message, fields) => log(message, fields)
|
|
34446
34635
|
});
|
|
@@ -34571,12 +34760,14 @@ function applyInner(ctx, injected) {
|
|
|
34571
34760
|
function currentPairing() {
|
|
34572
34761
|
const shown = active.pairing;
|
|
34573
34762
|
if (!shown) return null;
|
|
34574
|
-
|
|
34575
|
-
|
|
34763
|
+
const slot = slots.resolveFor(shown.token);
|
|
34764
|
+
if (!slot) return null;
|
|
34765
|
+
return { qr: shown.qr, token: shown.token, expiresAt: slot.expiresAt };
|
|
34576
34766
|
}
|
|
34577
34767
|
function ensureFreshPairing() {
|
|
34578
34768
|
const fresh = currentPairing() ?? createPairing();
|
|
34579
34769
|
if (!fresh) return null;
|
|
34770
|
+
if (fresh.expiresAt <= Date.now()) return createPairing();
|
|
34580
34771
|
return { qr: fresh.qr, token: fresh.token, expiresAt: fresh.expiresAt };
|
|
34581
34772
|
}
|
|
34582
34773
|
function pillStatus() {
|
|
@@ -34584,6 +34775,11 @@ function applyInner(ctx, injected) {
|
|
|
34584
34775
|
return {
|
|
34585
34776
|
relay: relay ? relayState() : "idle",
|
|
34586
34777
|
paired: relay?.clientCount ?? 0,
|
|
34778
|
+
// 配对簿里几条会话 = 配对还在不在。为什么必须与 paired 分开:pair-store 之后
|
|
34779
|
+
// 配对按 D3 长存、落盘,手机退后台只是 socket 断——只用 clientCount 回答 配没配上,
|
|
34780
|
+
// 用户把小程序放进后台的每一分钟,桌面那颗 pill 都会说 未配对,点开还会烧一张
|
|
34781
|
+
// 不需要的新码(2026-10-04 用户报的误解)。
|
|
34782
|
+
pairings: relay?.conversationCount ?? 0,
|
|
34587
34783
|
serverUrl: config2.serverUrl,
|
|
34588
34784
|
version: PLUGIN_VERSION,
|
|
34589
34785
|
waiting: waiting.count,
|
|
@@ -34625,7 +34821,13 @@ function applyInner(ctx, injected) {
|
|
|
34625
34821
|
return;
|
|
34626
34822
|
}
|
|
34627
34823
|
decided = true;
|
|
34628
|
-
start(
|
|
34824
|
+
start(
|
|
34825
|
+
createServicesKernel(collected, {
|
|
34826
|
+
log,
|
|
34827
|
+
clock,
|
|
34828
|
+
newSessionCwd: config2.newSessionCwd
|
|
34829
|
+
})
|
|
34830
|
+
);
|
|
34629
34831
|
return;
|
|
34630
34832
|
}
|
|
34631
34833
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-remote-control",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.2",
|
|
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,7 +53,7 @@
|
|
|
53
53
|
"provenance": true
|
|
54
54
|
},
|
|
55
55
|
"dependencies": {
|
|
56
|
-
"dsh-remote-wire": "^1.
|
|
56
|
+
"dsh-remote-wire": "^1.4.0",
|
|
57
57
|
"qrcode": "^1.5.4",
|
|
58
58
|
"tweetnacl": "^1.0.3",
|
|
59
59
|
"ws": "^8.18.0",
|