terminal-bridge-setup 3.3.5 → 3.3.6

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.
@@ -846,6 +846,19 @@ async function yrSqlSetViaCDP(tabId, sql, reqId, skipNew = false) {
846
846
  await new Promise(resolve => attachDebugger(tabId) ?? resolve());
847
847
  await new Promise(r => setTimeout(r, 400)); // 等 Network.enable 完成
848
848
  }
849
+ // 把 Yearning 标签页带到前台:后台标签页的 Vue/monaco 渲染被 rAF 节流,
850
+ // 新建查询 tab 点了也不渲染 → SQL 会被追加到已有编辑器后面(严重 bug,实测)
851
+ try {
852
+ const yrTab = await chrome.tabs.get(tabId);
853
+ if (!yrTab.active) {
854
+ await chrome.tabs.update(tabId, { active: true });
855
+ if (yrTab.windowId != null) await chrome.windows.update(yrTab.windowId, { focused: true });
856
+ await sleepMs(500); // 等页面从节流中恢复渲染
857
+ console.log("[bg] Yearning 标签页已带到前台(原为后台)");
858
+ }
859
+ } catch (err) {
860
+ console.warn("[bg] 激活 Yearning 标签页失败(继续注入):", err?.message);
861
+ }
849
862
  // 新建 SQL 窗口:避免把 SQL 注入用户正在使用的已有编辑器。
850
863
  // 编排模式(代理已显式建过 tab 并选好库)由 skipNew 跳过。
851
864
  if (!skipNew) {
@@ -853,6 +866,18 @@ async function yrSqlSetViaCDP(tabId, sql, reqId, skipNew = false) {
853
866
  if (!newWin || !newWin.ok) {
854
867
  console.warn("[bg] 新建 SQL 窗口失败(继续在当前编辑器注入):", newWin?.error);
855
868
  }
869
+ // 安全护栏:新建失败且现有编辑器非空时绝不注入——宁可失败也不能把 SQL
870
+ // 追加到用户已有语句后面(后台节流场景实测踩过)
871
+ const cur = await sendFrameMessage(tabId, { type: "yr-sql-get" }, 0);
872
+ if (cur?.ok && (cur.sql || "").trim().length > 0) {
873
+ sendToBridge({
874
+ type: "yr-result", reqId, tabId, ok: false,
875
+ error: "editor-not-empty",
876
+ message: "新建查询 tab 未生效且当前编辑器已有内容,为避免把 SQL 追加到你现有语句后面已中止。请切到 Yearning 页面确认后重试(或先清空/关闭已有 SQL tab)。",
877
+ editorText: (cur.sql || "").slice(0, 120),
878
+ });
879
+ return;
880
+ }
856
881
  }
857
882
  // 前置校验:数据库未选择时 Yearning 查询必报错,提前失败给明确提示
858
883
  const meta = await sendFrameMessage(tabId, { type: "yr-meta" }, 0);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "manifest_version": 3,
3
3
  "name": "JumpServer 终端桥接",
4
- "version": "3.3.5",
4
+ "version": "3.3.6",
5
5
  "description": "终端桥接:JumpServer / Arthas / Yearning,让 Agent 能通过浏览器执行命令、收结果与查数据",
6
6
  "key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtsnqR6PcFUueZwYria79tVbstvjk+tM7PpvIXILm5xbd6bAdjDIhzg3lsnKioVfvxjfvT+s6vJsiOYa9ojVZyJMFc5m/05TYqr770ovYwQmz0e88fmiy6dUoSulbtKvBCSLbN6OOL7u+ul8ixLZ/HautxSmou/eNgAFPmhE+4UueE7wfCqcgMYvjLvEzlqTVumMW+5LKw9YsRk6WhHPghY1a3MVUn3eQOWXBtQTEUy3wBM3v4wHxLwDeinVOR4f/P87IlUNo84C5DeimoFit0qCj3K04hS8MIYCLCYZc3v9ftRJDJBkAoah6Eaqj7JajbS3KvLR1ctOYfDhubgmURQIDAQAB",
7
7
  "permissions": ["debugger", "tabs", "alarms", "webNavigation", "nativeMessaging", "scripting", "downloads", "storage"],
@@ -619,6 +619,25 @@ function detectTerminalType(text) {
619
619
  }
620
620
 
621
621
  // 插件上报的 ws-recv 帧
622
+ // OrcaTerm(腾讯云 TKE 容器终端等)用 JSON 文本帧包裹终端流:
623
+ // {"type":"data","data":"<带 ANSI 的真实终端明文>","sessionId":"..."}
624
+ // 且一帧内可能拼接多个 JSON 对象。解包取 data 字段;其他类型帧(心跳等)丢弃。
625
+ function extractOrcaTermData(text) {
626
+ if (typeof text !== "string" || text.indexOf('{"type"') === -1) return text;
627
+ let out = "";
628
+ let buf = "";
629
+ for (const ch of text) {
630
+ buf += ch;
631
+ if (ch !== "}") continue;
632
+ try {
633
+ const obj = JSON.parse(buf);
634
+ buf = "";
635
+ if (obj && obj.type === "data" && typeof obj.data === "string") out += obj.data;
636
+ } catch { /* 还没凑齐一个完整 JSON,继续累积 */ }
637
+ }
638
+ return out;
639
+ }
640
+
622
641
  function handleWsRecv(payload) {
623
642
  const data = payload && payload.data;
624
643
  const opcode = payload && payload.opcode;
@@ -647,6 +666,9 @@ function handleWsRecv(payload) {
647
666
  text = typeof data === "string" ? data : String(data);
648
667
  }
649
668
 
669
+ // OrcaTerm JSON 包裹帧解包(koko 无此包裹,indexOf 快速跳过零开销)
670
+ text = extractOrcaTermData(text);
671
+
650
672
  // 给当前 pending(同时只会有一个)喂帧,按 prompt 锚点状态机处理
651
673
  for (const [reqId, entry] of pending) {
652
674
  entry.buffer += text;
@@ -1062,7 +1084,10 @@ wss.on("connection", (ws, req) => {
1062
1084
  // 防止 tap 页面(Yearning JSON 帧)污染终端命令的输出配对。
1063
1085
  broadcastTap(msg.payload);
1064
1086
  const frameUrl = (msg.payload && msg.payload.url) || "";
1065
- const isTerminalUrl = !frameUrl || /\/koko\/ws|connectArthas/i.test(frameUrl);
1087
+ // 终端白名单:koko(JumpServer)/ Arthas / 腾讯云 OrcaTerm(TKE 容器终端,
1088
+ // JSON 文本帧由 extractOrcaTermData 解包)。空 URL 也接受(attach 前建立的
1089
+ // 连接拿不到 webSocketCreated,帧没有 url)
1090
+ const isTerminalUrl = !frameUrl || /\/koko\/ws|connectArthas|orcaterm/i.test(frameUrl);
1066
1091
  if (isTerminalUrl) handleWsRecv(msg.payload);
1067
1092
  return;
1068
1093
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "terminal-bridge-setup",
3
- "version": "3.3.5",
3
+ "version": "3.3.6",
4
4
  "description": "一次性安装器:释放终端桥接(JumpServer / Arthas / Yearning)的本地代理 + Chrome 插件,并注册 native messaging host。让 Agent 能通过浏览器 xterm 终端执行命令并拿回输出。",
5
5
  "license": "MIT",
6
6
  "author": "encorearon",