@ondevplann/remotetype 0.1.3 → 0.2.1
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/bin/index.js +22 -10
- package/lib/config.js +2 -2
- package/lib/sanitize.js +6 -2
- package/package.json +1 -1
package/bin/index.js
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* RemoteType PC 客户端 CLI 入口。
|
|
6
6
|
*
|
|
7
7
|
* 子命令:
|
|
8
|
-
* remotetype serve
|
|
9
|
-
* remotetype serve --
|
|
8
|
+
* remotetype serve 启动守护进程(默认对齐模式:端到端加密 + 输入框实时对齐)
|
|
9
|
+
* remotetype serve --plain 兼容旧普通模式:只接收整句明文推送(无对齐)
|
|
10
10
|
* remotetype test "文本" 本地直接测试 Rust 注入,不走公网服务
|
|
11
11
|
* remotetype doctor 环境自检(平台/二进制/权限/网络)
|
|
12
12
|
* remotetype binary 打印解析到的 Rust 二进制路径
|
|
@@ -58,8 +58,8 @@ ${C.bold}用法${C.reset}
|
|
|
58
58
|
npx remotetype <command> [options]
|
|
59
59
|
|
|
60
60
|
${C.bold}命令${C.reset}
|
|
61
|
-
${C.cyan}serve${C.reset}
|
|
62
|
-
${C.cyan}serve --
|
|
61
|
+
${C.cyan}serve${C.reset} 启动守护进程:对齐模式(端到端加密,手机输入框与电脑实时对齐,含删除)
|
|
62
|
+
${C.cyan}serve --plain${C.reset} 兼容旧普通模式:只接收整句明文推送(/push 接口、外部脚本)
|
|
63
63
|
${C.cyan}test${C.reset} "<文本>" 本地测试:直接调用注入引擎,不连公网
|
|
64
64
|
${C.cyan}doctor${C.reset} 环境自检:平台支持 / 注入二进制 / 权限 / 网络
|
|
65
65
|
${C.cyan}binary${C.reset} 打印解析到的注入引擎路径
|
|
@@ -67,8 +67,9 @@ ${C.bold}命令${C.reset}
|
|
|
67
67
|
${C.bold}选项${C.reset}
|
|
68
68
|
--url <ws://...> 公网服务地址(默认 ${require('../lib/config').DEFAULT_SERVE_URL})
|
|
69
69
|
--client-id <id> 本机唯一标识,服务端按此路由(默认自动生成并持久化)
|
|
70
|
-
--align 对齐模式:只接受 RT1 加密信封,手机输入与电脑实时对齐
|
|
71
70
|
--key <KEY> 对齐模式配对 key(不传则自动生成强随机并打印;手机端输入同一 key)
|
|
71
|
+
--plain 切回旧普通模式:接收整句明文推送(无对齐、无加密)
|
|
72
|
+
--align (已默认开启,保留兼容;与 --plain 同给时 --plain 优先)
|
|
72
73
|
--token <TOKEN> 注册门禁 token(服务器设 RT_TOKEN 后两端都必须携带同一值)
|
|
73
74
|
--log-level <level> debug | info | warn | error(默认 info)
|
|
74
75
|
--max-queue <n> 本地消息队列上限(默认 100)
|
|
@@ -78,9 +79,9 @@ ${C.bold}选项${C.reset}
|
|
|
78
79
|
--version 显示版本
|
|
79
80
|
|
|
80
81
|
${C.bold}示例${C.reset}
|
|
81
|
-
npx remotetype serve --url ws://1.2.3.4:8790/ws
|
|
82
|
-
npx remotetype serve --
|
|
83
|
-
npx remotetype serve --
|
|
82
|
+
npx remotetype serve --url ws://1.2.3.4:8790/ws # 对齐模式,自动生成 key,复制到手机
|
|
83
|
+
npx remotetype serve --key MYKEY123 # 两端用同一个 key
|
|
84
|
+
npx remotetype serve --plain # 旧普通模式(接收 /push 整句推送)
|
|
84
85
|
npx remotetype test "你好,这是一条本地注入测试"
|
|
85
86
|
npx remotetype doctor
|
|
86
87
|
`);
|
|
@@ -273,8 +274,14 @@ async function cmdServe(cfg) {
|
|
|
273
274
|
}
|
|
274
275
|
|
|
275
276
|
// type:常规文本注入(serve 与 relay 共用,relay 的 text 是 diff 出的增量)
|
|
276
|
-
//
|
|
277
|
-
|
|
277
|
+
// 二次预处理:即便上游已过滤,这里仍是最后一道防线。
|
|
278
|
+
// 对齐模式保留纯空白:换行/空格是手机输入框的真实内容(IME 自动插入的
|
|
279
|
+
// 换行不该被判失败挂起整批计划),见 sanitize 的 keepWhitespace。
|
|
280
|
+
const isAlignSource = meta.source === 'align';
|
|
281
|
+
const cleaned = sanitize(item.text, {
|
|
282
|
+
maxLength: cfg.maxTextLength,
|
|
283
|
+
keepWhitespace: isAlignSource,
|
|
284
|
+
});
|
|
278
285
|
if (!cleaned.ok) {
|
|
279
286
|
logger.warn('文本预处理后丢弃', { reason: cleaned.reason, clientId: item.clientId });
|
|
280
287
|
if (meta.source === 'align' && item.seq !== undefined) failedAlignSeqs.add(item.seq);
|
|
@@ -288,6 +295,11 @@ async function cmdServe(cfg) {
|
|
|
288
295
|
});
|
|
289
296
|
return;
|
|
290
297
|
}
|
|
298
|
+
if (isAlignSource && cleaned.text.length === 0) {
|
|
299
|
+
// 整条只含不可见字符:无可注入内容,也不算失败——commit 仍会推进 mirror
|
|
300
|
+
logger.debug('对齐空操作(仅不可见字符),跳过注入', { seq: item.seq });
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
291
303
|
if (cleaned.truncated) {
|
|
292
304
|
logger.warn('文本超长已截断', {
|
|
293
305
|
originalLength: cleaned.originalLength,
|
package/lib/config.js
CHANGED
|
@@ -124,8 +124,8 @@ function loadConfig(flags = {}) {
|
|
|
124
124
|
requestTimeoutMs: num(flags.requestTimeoutMs ?? env.REMOTETYPE_REQUEST_TIMEOUT ?? file.requestTimeoutMs, 30000),
|
|
125
125
|
// 二进制
|
|
126
126
|
agentPath: flags.agent ?? env.REMOTETYPE_AGENT ?? file.agentPath ?? null,
|
|
127
|
-
//
|
|
128
|
-
align: flags.
|
|
127
|
+
// 对齐模式(serve 默认开启;--plain 切回旧普通模式,--align 保留兼容)
|
|
128
|
+
align: flags.plain === true ? false : true,
|
|
129
129
|
alignKey: flags.key ?? env.REMOTETYPE_KEY ?? file.alignKey ?? null,
|
|
130
130
|
// 注册门禁 token(服务器设 RT_TOKEN 后必须携带同一值才能注册)
|
|
131
131
|
token: flags.token ?? env.REMOTETYPE_TOKEN ?? env.RT_TOKEN ?? file.token ?? null,
|
package/lib/sanitize.js
CHANGED
|
@@ -32,10 +32,14 @@ function isInvisible(c) {
|
|
|
32
32
|
* @param {string} raw
|
|
33
33
|
* @param {object} [opts]
|
|
34
34
|
* @param {number} [opts.maxLength]
|
|
35
|
+
* @param {boolean} [opts.keepWhitespace] 保留纯空白文本(对齐模式用:
|
|
36
|
+
* 换行/空格是手机输入框的真实内容,整条空白不算「空文本」;
|
|
37
|
+
* 返回 ok:true 且 text 可能为空串,由调用方决定是否为无操作)
|
|
35
38
|
* @returns {{ok:boolean, text:string, reason?:string, truncated?:boolean, originalLength?:number}}
|
|
36
39
|
*/
|
|
37
40
|
function sanitize(raw, opts = {}) {
|
|
38
41
|
const maxLength = opts.maxLength ?? DEFAULT_MAX_LENGTH;
|
|
42
|
+
const keepWhitespace = opts.keepWhitespace === true;
|
|
39
43
|
|
|
40
44
|
if (typeof raw !== 'string') {
|
|
41
45
|
return { ok: false, text: '', reason: 'not_a_string' };
|
|
@@ -52,8 +56,8 @@ function sanitize(raw, opts = {}) {
|
|
|
52
56
|
// 2) 统一换行,避免 \r\n 造成目标程序出现多余字符
|
|
53
57
|
text = text.replace(/\r\n?/g, '\n');
|
|
54
58
|
|
|
55
|
-
// 3)
|
|
56
|
-
if (text.trim().length === 0) {
|
|
59
|
+
// 3) 空文本丢弃(keepWhitespace 时跳过:空白是对齐语义下的有效内容)
|
|
60
|
+
if (!keepWhitespace && text.trim().length === 0) {
|
|
57
61
|
return { ok: false, text: '', reason: 'empty_after_clean', originalLength };
|
|
58
62
|
}
|
|
59
63
|
|