@tunnelbox/hermes 0.1.7 → 0.1.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.
- package/dist/index.mjs +107 -3
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -114,6 +114,7 @@ var zh_CN_default = {
|
|
|
114
114
|
"index.error.pairTimeout": "\u7B49\u5F85\u914D\u5BF9\u7801\u8D85\u65F6\uFF08\u4E2D\u7EE7\u672A\u54CD\u5E94\uFF09",
|
|
115
115
|
"index.log.claimed": "\u5DF2\u7ED1\u5B9A\u5230\u624B\u673A\u8D26\u53F7\uFF0C\u4E4B\u540E\u624B\u673A\u4ECE\u300C\u6211\u7684\u7535\u8111\u300D\u76F4\u63A5\u8FDE\u63A5\uFF0C\u65E0\u9700\u518D\u626B\u7801",
|
|
116
116
|
"index.log.connectedRelay": "\u5DF2\u8FDE\u63A5\u4E2D\u7EE7 {url}",
|
|
117
|
+
"index.log.loaded": "tunnelbox opencode \u63D2\u4EF6\u5DF2\u542F\u52A8\uFF08v{version}\uFF09",
|
|
117
118
|
"index.log.disconnected": "\u4E0E\u4E2D\u7EE7\u65AD\u5F00\uFF0C\u6B63\u5728\u81EA\u52A8\u91CD\u8FDE\u2026",
|
|
118
119
|
"index.log.exit": "\u5DF2\u9000\u51FA",
|
|
119
120
|
"index.log.pairCode": "\u751F\u6210\u914D\u5BF9\u7801: {code}",
|
|
@@ -275,6 +276,7 @@ var zh_TW_default = {
|
|
|
275
276
|
"index.error.pairTimeout": "\u7B49\u5F85\u914D\u5C0D\u78BC\u903E\u6642\uFF08\u4E2D\u7E7C\u672A\u56DE\u61C9\uFF09",
|
|
276
277
|
"index.log.claimed": "\u5DF2\u7D81\u5B9A\u5230\u624B\u6A5F\u5E33\u865F\uFF0C\u4E4B\u5F8C\u624B\u6A5F\u76F4\u63A5\u5F9E\u300C\u6211\u7684\u96FB\u8166\u300D\u9023\u63A5\uFF0C\u4E0D\u9700\u518D\u6383\u78BC",
|
|
277
278
|
"index.log.connectedRelay": "\u5DF2\u9023\u63A5\u4E2D\u7E7C {url}",
|
|
279
|
+
"index.log.loaded": "tunnelbox opencode \u5916\u639B\u5DF2\u555F\u52D5\uFF08v{version}\uFF09",
|
|
278
280
|
"index.log.disconnected": "\u8207\u4E2D\u7E7C\u65B7\u7DDA\uFF0C\u6B63\u5728\u81EA\u52D5\u91CD\u9023\u2026",
|
|
279
281
|
"index.log.exit": "\u5DF2\u9000\u51FA",
|
|
280
282
|
"index.log.pairCode": "\u7522\u751F\u914D\u5C0D\u78BC: {code}",
|
|
@@ -436,6 +438,7 @@ var en_US_default = {
|
|
|
436
438
|
"index.error.pairTimeout": "Timed out waiting for a pairing code (the relay did not respond)",
|
|
437
439
|
"index.log.claimed": "Bound to your phone account. From now on the phone connects directly from My Computers; no need to scan again",
|
|
438
440
|
"index.log.connectedRelay": "Connected to relay {url}",
|
|
441
|
+
"index.log.loaded": "tunnelbox opencode plugin started (v{version})",
|
|
439
442
|
"index.log.disconnected": "Disconnected from relay, reconnecting automatically\u2026",
|
|
440
443
|
"index.log.exit": "Exited",
|
|
441
444
|
"index.log.pairCode": "Generated pairing code: {code}",
|
|
@@ -597,6 +600,7 @@ var ja_JP_default = {
|
|
|
597
600
|
"index.error.pairTimeout": "\u30DA\u30A2\u30EA\u30F3\u30B0\u30B3\u30FC\u30C9\u306E\u53D6\u5F97\u304C\u30BF\u30A4\u30E0\u30A2\u30A6\u30C8\u3057\u307E\u3057\u305F\uFF08\u30EA\u30EC\u30FC\u304C\u5FDC\u7B54\u3057\u307E\u305B\u3093\uFF09",
|
|
598
601
|
"index.log.claimed": "\u30B9\u30DE\u30DB\u306E\u30A2\u30AB\u30A6\u30F3\u30C8\u306B\u7D10\u4ED8\u3051\u307E\u3057\u305F\u3002\u4EE5\u964D\u306F\u300C\u30DE\u30A4 PC\u300D\u304B\u3089\u76F4\u63A5\u63A5\u7D9A\u3055\u308C\u308B\u305F\u3081\u3001\u518D\u30B9\u30AD\u30E3\u30F3\u306F\u4E0D\u8981\u3067\u3059",
|
|
599
602
|
"index.log.connectedRelay": "\u30EA\u30EC\u30FC\u306B\u63A5\u7D9A\u3057\u307E\u3057\u305F {url}",
|
|
603
|
+
"index.log.loaded": "tunnelbox opencode \u30D7\u30E9\u30B0\u30A4\u30F3\u3092\u8D77\u52D5\u3057\u307E\u3057\u305F\uFF08v{version}\uFF09",
|
|
600
604
|
"index.log.disconnected": "\u30EA\u30EC\u30FC\u304B\u3089\u5207\u65AD\u3001\u81EA\u52D5\u7684\u306B\u518D\u63A5\u7D9A\u3057\u3066\u3044\u307E\u3059\u2026",
|
|
601
605
|
"index.log.exit": "\u7D42\u4E86\u3057\u307E\u3057\u305F",
|
|
602
606
|
"index.log.pairCode": "\u30DA\u30A2\u30EA\u30F3\u30B0\u30B3\u30FC\u30C9\u3092\u751F\u6210: {code}",
|
|
@@ -758,6 +762,7 @@ var ko_KR_default = {
|
|
|
758
762
|
"index.error.pairTimeout": "\uD398\uC5B4\uB9C1 \uCF54\uB4DC \uB300\uAE30 \uC2DC\uAC04 \uCD08\uACFC(\uB9B4\uB808\uC774\uAC00 \uC751\uB2F5\uD558\uC9C0 \uC54A\uC74C)",
|
|
759
763
|
"index.log.claimed": "\uD734\uB300\uD3F0 \uACC4\uC815\uC5D0 \uC5F0\uACB0\uB418\uC5C8\uC2B5\uB2C8\uB2E4. \uC774\uC81C \uD734\uB300\uD3F0\uC740 \u300C\uB0B4 PC\u300D\uC5D0\uC11C \uC9C1\uC811 \uC5F0\uACB0\uD558\uBA70 \uB2E4\uC2DC \uC2A4\uCE94\uD560 \uD544\uC694\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4",
|
|
760
764
|
"index.log.connectedRelay": "\uB9B4\uB808\uC774\uC5D0 \uC5F0\uACB0\uB428 {url}",
|
|
765
|
+
"index.log.loaded": "tunnelbox opencode \uD50C\uB7EC\uADF8\uC778\uC744 \uC2DC\uC791\uD588\uC2B5\uB2C8\uB2E4\uFF08v{version}\uFF09",
|
|
761
766
|
"index.log.disconnected": "\uB9B4\uB808\uC774 \uC5F0\uACB0\uC774 \uB04A\uACA8 \uC790\uB3D9\uC73C\uB85C \uC7AC\uC5F0\uACB0 \uC911\u2026",
|
|
762
767
|
"index.log.exit": "\uC885\uB8CC\uB428",
|
|
763
768
|
"index.log.pairCode": "\uD398\uC5B4\uB9C1 \uCF54\uB4DC \uC0DD\uC131: {code}",
|
|
@@ -919,6 +924,7 @@ var fr_FR_default = {
|
|
|
919
924
|
"index.error.pairTimeout": "D\xE9lai d'attente du code d'appairage d\xE9pass\xE9 (le relais ne r\xE9pond pas)",
|
|
920
925
|
"index.log.claimed": "Li\xE9 \xE0 votre compte t\xE9l\xE9phone. Le t\xE9l\xE9phone se connecte d\xE9sormais directement depuis \xAB Mes PC \xBB ; plus besoin de scanner",
|
|
921
926
|
"index.log.connectedRelay": "Connect\xE9 au relais {url}",
|
|
927
|
+
"index.log.loaded": "Plugin tunnelbox opencode d\xE9marr\xE9 (v{version})",
|
|
922
928
|
"index.log.disconnected": "D\xE9connect\xE9 du relais, reconnexion automatique\u2026",
|
|
923
929
|
"index.log.exit": "Arr\xEAt\xE9",
|
|
924
930
|
"index.log.pairCode": "Code d'appairage g\xE9n\xE9r\xE9 : {code}",
|
|
@@ -1080,6 +1086,7 @@ var de_DE_default = {
|
|
|
1080
1086
|
"index.error.pairTimeout": "Zeit\xFCberschreitung beim Warten auf einen Pairing-Code (Relay antwortet nicht)",
|
|
1081
1087
|
"index.log.claimed": "An Ihr Telefonkonto gebunden. Das Telefon verbindet sich nun direkt \xFCber \u201CMeine PCs\u201D; kein erneutes Scannen n\xF6tig",
|
|
1082
1088
|
"index.log.connectedRelay": "Mit Relay verbunden {url}",
|
|
1089
|
+
"index.log.loaded": "tunnelbox-opencode-Plugin gestartet (v{version})",
|
|
1083
1090
|
"index.log.disconnected": "Vom Relay getrennt, verbinde automatisch neu\u2026",
|
|
1084
1091
|
"index.log.exit": "Beendet",
|
|
1085
1092
|
"index.log.pairCode": "Pairing-Code erzeugt: {code}",
|
|
@@ -1241,6 +1248,7 @@ var es_ES_default = {
|
|
|
1241
1248
|
"index.error.pairTimeout": "Tiempo de espera agotado al obtener el c\xF3digo de emparejamiento (el relay no responde)",
|
|
1242
1249
|
"index.log.claimed": "Vinculado a su cuenta de tel\xE9fono. El tel\xE9fono se conecta ahora directamente desde \xABMis PC\xBB; no hace falta volver a escanear",
|
|
1243
1250
|
"index.log.connectedRelay": "Conectado al relay {url}",
|
|
1251
|
+
"index.log.loaded": "Plugin tunnelbox opencode iniciado (v{version})",
|
|
1244
1252
|
"index.log.disconnected": "Desconectado del relay, reconectando autom\xE1ticamente\u2026",
|
|
1245
1253
|
"index.log.exit": "Salido",
|
|
1246
1254
|
"index.log.pairCode": "C\xF3digo de emparejamiento generado: {code}",
|
|
@@ -1550,6 +1558,102 @@ async function printPairing(code, type, name, lang) {
|
|
|
1550
1558
|
console.log(" " + tt("qr.fileWritten", { path: file }));
|
|
1551
1559
|
console.log("");
|
|
1552
1560
|
}
|
|
1561
|
+
var DEFAULT_PAGE_SIZE = 50;
|
|
1562
|
+
var MAX_PART_TEXT = 16e3;
|
|
1563
|
+
var MAX_PART_ARGS = 4e3;
|
|
1564
|
+
var MAX_PAGE_BYTES = 15e5;
|
|
1565
|
+
function capStr(s, max) {
|
|
1566
|
+
if (s.length <= max) return s;
|
|
1567
|
+
return `${s.slice(0, max)}\u2026`;
|
|
1568
|
+
}
|
|
1569
|
+
function capMessage(m) {
|
|
1570
|
+
let parts;
|
|
1571
|
+
for (let i = 0; i < m.parts.length; i++) {
|
|
1572
|
+
const p = m.parts[i];
|
|
1573
|
+
const nText = typeof p.text === "string" && p.text.length > MAX_PART_TEXT ? capStr(p.text, MAX_PART_TEXT) : p.text;
|
|
1574
|
+
const nDelta = typeof p.delta === "string" && p.delta.length > MAX_PART_TEXT ? capStr(p.delta, MAX_PART_TEXT) : p.delta;
|
|
1575
|
+
const nArgs = typeof p.args === "string" && p.args.length > MAX_PART_ARGS ? capStr(p.args, MAX_PART_ARGS) : p.args;
|
|
1576
|
+
if (nText !== p.text || nDelta !== p.delta || nArgs !== p.args) {
|
|
1577
|
+
if (!parts) parts = m.parts.slice(0, i);
|
|
1578
|
+
parts.push({ ...p, text: nText, delta: nDelta, args: nArgs });
|
|
1579
|
+
} else if (parts) {
|
|
1580
|
+
parts.push(p);
|
|
1581
|
+
}
|
|
1582
|
+
}
|
|
1583
|
+
return parts ? { ...m, parts } : m;
|
|
1584
|
+
}
|
|
1585
|
+
function capMessages(messages) {
|
|
1586
|
+
let changed = false;
|
|
1587
|
+
const out = messages.map((m) => {
|
|
1588
|
+
const c = capMessage(m);
|
|
1589
|
+
if (c !== m) changed = true;
|
|
1590
|
+
return c;
|
|
1591
|
+
});
|
|
1592
|
+
return changed ? out : messages;
|
|
1593
|
+
}
|
|
1594
|
+
function byteLength(messages) {
|
|
1595
|
+
try {
|
|
1596
|
+
return JSON.stringify(messages).length;
|
|
1597
|
+
} catch {
|
|
1598
|
+
return messages.length * MAX_PART_TEXT * 2;
|
|
1599
|
+
}
|
|
1600
|
+
}
|
|
1601
|
+
function sliceWindow(full, query = {}) {
|
|
1602
|
+
const limit = Math.max(1, query.limit ?? DEFAULT_PAGE_SIZE);
|
|
1603
|
+
const maxBytes = query.maxBytes ?? MAX_PAGE_BYTES;
|
|
1604
|
+
let end = full.length;
|
|
1605
|
+
if (query.before !== void 0 && query.before !== "") {
|
|
1606
|
+
const idx = full.findIndex((m) => m.id === query.before);
|
|
1607
|
+
if (idx >= 0) end = idx;
|
|
1608
|
+
}
|
|
1609
|
+
let start2 = Math.max(0, end - limit);
|
|
1610
|
+
let messages = full.slice(start2, end);
|
|
1611
|
+
while (messages.length > 1) {
|
|
1612
|
+
const capped = capMessages(messages);
|
|
1613
|
+
if (byteLength(capped) <= maxBytes) {
|
|
1614
|
+
messages = capped;
|
|
1615
|
+
break;
|
|
1616
|
+
}
|
|
1617
|
+
start2++;
|
|
1618
|
+
messages = full.slice(start2, end);
|
|
1619
|
+
}
|
|
1620
|
+
return { messages: capMessages(messages), hasMore: start2 > 0 };
|
|
1621
|
+
}
|
|
1622
|
+
var MessagesCache = class {
|
|
1623
|
+
ttlMs;
|
|
1624
|
+
maxEntries;
|
|
1625
|
+
store = /* @__PURE__ */ new Map();
|
|
1626
|
+
constructor(ttlMs = 2e3, maxEntries = 64) {
|
|
1627
|
+
this.ttlMs = ttlMs;
|
|
1628
|
+
this.maxEntries = maxEntries;
|
|
1629
|
+
}
|
|
1630
|
+
/** 命中且未过 TTL 时返回完整列表副本;否则 undefined。 */
|
|
1631
|
+
get(sessionID, now = Date.now()) {
|
|
1632
|
+
const e = this.store.get(sessionID);
|
|
1633
|
+
if (!e) return void 0;
|
|
1634
|
+
if (now - e.at > this.ttlMs) {
|
|
1635
|
+
this.store.delete(sessionID);
|
|
1636
|
+
return void 0;
|
|
1637
|
+
}
|
|
1638
|
+
return e.full;
|
|
1639
|
+
}
|
|
1640
|
+
put(sessionID, full) {
|
|
1641
|
+
if (this.store.size >= this.maxEntries && !this.store.has(sessionID)) {
|
|
1642
|
+
const oldest = this.store.keys().next().value;
|
|
1643
|
+
if (oldest !== void 0) this.store.delete(oldest);
|
|
1644
|
+
}
|
|
1645
|
+
this.store.set(sessionID, { full, at: Date.now() });
|
|
1646
|
+
}
|
|
1647
|
+
/** 会话内容变化(流式部件/状态/删除等)时调用,立即失效快照。 */
|
|
1648
|
+
invalidate(sessionID) {
|
|
1649
|
+
this.store.delete(sessionID);
|
|
1650
|
+
}
|
|
1651
|
+
/** 适配器重连/整体失效(如清除全部快照)。 */
|
|
1652
|
+
clear() {
|
|
1653
|
+
this.store.clear();
|
|
1654
|
+
}
|
|
1655
|
+
};
|
|
1656
|
+
var messagesCache = new MessagesCache();
|
|
1553
1657
|
|
|
1554
1658
|
// src/bridge.ts
|
|
1555
1659
|
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
@@ -1889,7 +1993,7 @@ async function removeSession(sessionID) {
|
|
|
1889
1993
|
}
|
|
1890
1994
|
|
|
1891
1995
|
// src/bridge.ts
|
|
1892
|
-
var VERSION = "0.1.0";
|
|
1996
|
+
var VERSION = true ? "0.1.8" : "0.0.0-dev";
|
|
1893
1997
|
var AGENT_TYPE = "hermes";
|
|
1894
1998
|
var HermesBridge = class {
|
|
1895
1999
|
constructor(cfg) {
|
|
@@ -2057,9 +2161,9 @@ var HermesBridge = class {
|
|
|
2057
2161
|
});
|
|
2058
2162
|
}
|
|
2059
2163
|
async sessionMessages(env) {
|
|
2060
|
-
const { sessionID } = env.payload;
|
|
2164
|
+
const { sessionID, before, limit } = env.payload;
|
|
2061
2165
|
const messages = exists(sessionID) ? await readHistory(sessionID) : [];
|
|
2062
|
-
this.reply(env, "messages", { sessionID, messages });
|
|
2166
|
+
this.reply(env, "messages", { sessionID, ...sliceWindow(messages, { before, limit }) });
|
|
2063
2167
|
}
|
|
2064
2168
|
async sessionPrompt(env) {
|
|
2065
2169
|
const payload = env.payload;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tunnelbox/hermes",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.8",
|
|
4
4
|
"description": "tunnelbox 的 Hermes 适配器(B 类,CLI oneshot 桥接):手机远程驱动本机 Hermes Agent(hermes chat -Q -q + --resume 续聊,会话/流式/中止/删除;headless 无手机审批)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.mjs",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"qrcode": "^1.5.3"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
|
-
"@tunnelbox/core": "0.1.
|
|
37
|
+
"@tunnelbox/core": "0.1.8",
|
|
38
38
|
"@types/node": "^22.0.0",
|
|
39
39
|
"@types/qrcode": "^1.5.5",
|
|
40
40
|
"esbuild": "^0.24.0",
|