@aiyiran/myclaw 1.1.137 → 1.1.138
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/assets/myclaw-inject.js +206 -0
- package/package.json +1 -1
package/assets/myclaw-inject.js
CHANGED
|
@@ -784,6 +784,211 @@ btn.addEventListener("click", function () {
|
|
|
784
784
|
});
|
|
785
785
|
}
|
|
786
786
|
|
|
787
|
+
// ═══ 7.5 右下角"新会话"按钮(支持中文命名) ═══
|
|
788
|
+
//
|
|
789
|
+
// 实现思路(复用原生机制,避免重写会话切换逻辑):
|
|
790
|
+
// 1. 点击我们的按钮 → 弹框输入中文名
|
|
791
|
+
// 2. 程序点击 openclaw 原生"新会话"按钮(藏在 openclaw-app 的 shadow DOM 里),
|
|
792
|
+
// 由它负责"创建 + 无刷新切换"——这套逻辑(zH/BH)是模块私有的,外部无法直接调用
|
|
793
|
+
// 3. 轮询 openclaw-app.sessionKey,等它从旧值变为新会话的 key
|
|
794
|
+
// 4. 通过 openclaw-app.client(WebSocket RPC)发 sessions.patch 把 label 改成中文名
|
|
795
|
+
// 服务端 patch 后会广播 sessions.changed,前端订阅会自动刷新侧栏显示,无需手动刷新
|
|
796
|
+
|
|
797
|
+
var newSessionOpen = false;
|
|
798
|
+
|
|
799
|
+
// 获取 openclaw 根组件(上面挂着 WebSocket client 和 sessionKey)
|
|
800
|
+
function getOpenclawApp() {
|
|
801
|
+
return document.querySelector("openclaw-app");
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
// 在 shadow DOM(含嵌套)里深度查找元素
|
|
805
|
+
function deepQuerySelector(root, selector) {
|
|
806
|
+
if (!root) return null;
|
|
807
|
+
var direct = root.querySelector ? root.querySelector(selector) : null;
|
|
808
|
+
if (direct) return direct;
|
|
809
|
+
var all = root.querySelectorAll ? root.querySelectorAll("*") : [];
|
|
810
|
+
for (var i = 0; i < all.length; i++) {
|
|
811
|
+
if (all[i].shadowRoot) {
|
|
812
|
+
var found = deepQuerySelector(all[i].shadowRoot, selector);
|
|
813
|
+
if (found) return found;
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
return null;
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
// 找到原生"新会话"按钮(先 light DOM,再 app 的 shadow DOM 深搜)
|
|
820
|
+
function findNativeNewSessionBtn() {
|
|
821
|
+
var sel = ".sidebar-new-session";
|
|
822
|
+
var el = document.querySelector(sel);
|
|
823
|
+
if (el) return el;
|
|
824
|
+
var app = getOpenclawApp();
|
|
825
|
+
if (app && app.shadowRoot) {
|
|
826
|
+
return deepQuerySelector(app.shadowRoot, sel);
|
|
827
|
+
}
|
|
828
|
+
return null;
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
// 从 sessionKey 解析 agentId(格式 agent:NAME:...),非 agent 会话返回 null
|
|
832
|
+
function deriveAgentId(sessionKey) {
|
|
833
|
+
if (typeof sessionKey === "string" && sessionKey.indexOf("agent:") === 0) {
|
|
834
|
+
var parts = sessionKey.split(":");
|
|
835
|
+
if (parts.length >= 2 && parts[1]) return parts[1];
|
|
836
|
+
}
|
|
837
|
+
return null;
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
// 轮询等待 sessionKey 变化(原生按钮创建+切换后,key 会变成新会话)
|
|
841
|
+
function waitForSessionChange(app, prevKey, timeoutMs) {
|
|
842
|
+
return new Promise(function (resolve) {
|
|
843
|
+
var start = Date.now();
|
|
844
|
+
(function poll() {
|
|
845
|
+
if (app.sessionKey && app.sessionKey !== prevKey) { resolve(app.sessionKey); return; }
|
|
846
|
+
if (Date.now() - start > timeoutMs) { resolve(null); return; }
|
|
847
|
+
setTimeout(poll, 80);
|
|
848
|
+
})();
|
|
849
|
+
});
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
// 创建一个带中文名的新会话
|
|
853
|
+
function createNamedSession(label) {
|
|
854
|
+
var app = getOpenclawApp();
|
|
855
|
+
if (!app) { showToast("未找到 openclaw 应用", "error"); return; }
|
|
856
|
+
if (!app.client) { showToast("网关未连接", "error"); return; }
|
|
857
|
+
|
|
858
|
+
var nativeBtn = findNativeNewSessionBtn();
|
|
859
|
+
if (!nativeBtn) { showToast("未找到原生新会话按钮", "error"); return; }
|
|
860
|
+
if (nativeBtn.disabled) { showToast("当前无法新建(有进行中的任务?)", "error"); return; }
|
|
861
|
+
|
|
862
|
+
var prevKey = app.sessionKey;
|
|
863
|
+
showToast("正在创建:" + label);
|
|
864
|
+
|
|
865
|
+
// 由原生按钮负责创建 + 切换
|
|
866
|
+
nativeBtn.click();
|
|
867
|
+
|
|
868
|
+
waitForSessionChange(app, prevKey, 8000).then(function (newKey) {
|
|
869
|
+
if (!newKey) { showToast("新会话创建超时", "error"); return; }
|
|
870
|
+
// 改名
|
|
871
|
+
var params = { key: newKey, label: label };
|
|
872
|
+
var agentId = deriveAgentId(newKey);
|
|
873
|
+
if (agentId) params.agentId = agentId;
|
|
874
|
+
app.client.request("sessions.patch", params).then(function () {
|
|
875
|
+
showToast("已创建:" + label, "success");
|
|
876
|
+
console.log("[myclaw-newsession] 创建并命名成功:", newKey, label);
|
|
877
|
+
}).catch(function (err) {
|
|
878
|
+
showToast("改名失败:" + (err && err.message ? err.message : err), "error");
|
|
879
|
+
console.error("[myclaw-newsession] sessions.patch 失败:", err);
|
|
880
|
+
});
|
|
881
|
+
});
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
function createNewSessionButton() {
|
|
885
|
+
if (document.querySelector("#myclaw-newsession-btn")) return;
|
|
886
|
+
|
|
887
|
+
var btn = document.createElement("div");
|
|
888
|
+
btn.id = "myclaw-newsession-btn";
|
|
889
|
+
btn.style.cssText = [
|
|
890
|
+
"position: fixed",
|
|
891
|
+
"bottom: 8px",
|
|
892
|
+
"right: 335px",
|
|
893
|
+
"padding: 3px 10px",
|
|
894
|
+
"background: rgba(139, 92, 246, 0.85)",
|
|
895
|
+
"color: #fff",
|
|
896
|
+
"font-size: 11px",
|
|
897
|
+
"font-weight: bold",
|
|
898
|
+
"font-family: monospace",
|
|
899
|
+
"border-radius: 4px",
|
|
900
|
+
"z-index: 99999",
|
|
901
|
+
"user-select: none",
|
|
902
|
+
"cursor: pointer",
|
|
903
|
+
"transition: all 0.2s",
|
|
904
|
+
"letter-spacing: 0.5px",
|
|
905
|
+
].join(";");
|
|
906
|
+
btn.textContent = "🆕 新会话";
|
|
907
|
+
btn.title = "创建新会话(可中文命名)";
|
|
908
|
+
|
|
909
|
+
btn.onmouseenter = function () { btn.style.background = "rgba(124, 58, 237, 1)"; btn.style.transform = "scale(1.05)"; };
|
|
910
|
+
btn.onmouseleave = function () { btn.style.background = "rgba(139, 92, 246, 0.85)"; btn.style.transform = "scale(1)"; };
|
|
911
|
+
btn.onclick = function (e) {
|
|
912
|
+
e.stopPropagation();
|
|
913
|
+
if (newSessionOpen) { closeNewSessionModal(); } else { openNewSessionModal(); }
|
|
914
|
+
};
|
|
915
|
+
|
|
916
|
+
document.body.appendChild(btn);
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
function closeNewSessionModal() {
|
|
920
|
+
newSessionOpen = false;
|
|
921
|
+
var m = document.querySelector("#myclaw-newsession-modal");
|
|
922
|
+
if (m) m.remove();
|
|
923
|
+
}
|
|
924
|
+
|
|
925
|
+
function openNewSessionModal() {
|
|
926
|
+
if (document.querySelector("#myclaw-newsession-modal")) return;
|
|
927
|
+
newSessionOpen = true;
|
|
928
|
+
|
|
929
|
+
var overlay = document.createElement("div");
|
|
930
|
+
overlay.id = "myclaw-newsession-modal";
|
|
931
|
+
overlay.style.cssText = [
|
|
932
|
+
"position: fixed", "top: 0", "left: 0", "width: 100vw", "height: 100vh",
|
|
933
|
+
"background: rgba(0,0,0,0.4)", "z-index: 99998",
|
|
934
|
+
"display: flex", "align-items: center", "justify-content: center",
|
|
935
|
+
"animation: myclaw-fade-in 0.15s ease",
|
|
936
|
+
].join(";");
|
|
937
|
+
overlay.onclick = function (e) { if (e.target === overlay) closeNewSessionModal(); };
|
|
938
|
+
|
|
939
|
+
var box = document.createElement("div");
|
|
940
|
+
box.style.cssText = "width:360px;background:#1e1e2e;border-radius:8px;overflow:hidden;box-shadow:0 8px 32px rgba(0,0,0,0.5);";
|
|
941
|
+
|
|
942
|
+
var header = document.createElement("div");
|
|
943
|
+
header.style.cssText = "display:flex;align-items:center;justify-content:space-between;padding:10px 14px;background:#2d2d3f;color:#cdd6f4;font-size:13px;font-family:monospace;user-select:none;";
|
|
944
|
+
header.innerHTML = "<span>🆕 新会话</span>";
|
|
945
|
+
var closeBtn = document.createElement("span");
|
|
946
|
+
closeBtn.textContent = "✕";
|
|
947
|
+
closeBtn.style.cssText = "cursor:pointer;padding:2px 6px;border-radius:3px;font-size:14px;transition:background 0.15s;";
|
|
948
|
+
closeBtn.onmouseenter = function () { closeBtn.style.background = "rgba(255,255,255,0.1)"; };
|
|
949
|
+
closeBtn.onmouseleave = function () { closeBtn.style.background = "none"; };
|
|
950
|
+
closeBtn.onclick = function () { closeNewSessionModal(); };
|
|
951
|
+
header.appendChild(closeBtn);
|
|
952
|
+
|
|
953
|
+
var body = document.createElement("div");
|
|
954
|
+
body.style.cssText = "padding:16px;display:flex;flex-direction:column;gap:10px;";
|
|
955
|
+
|
|
956
|
+
var desc = document.createElement("div");
|
|
957
|
+
desc.textContent = "给新会话起个名字(支持中文),点击后自动创建并切换";
|
|
958
|
+
desc.style.cssText = "font-size:11px;color:#888;font-family:monospace;";
|
|
959
|
+
body.appendChild(desc);
|
|
960
|
+
|
|
961
|
+
var input = document.createElement("input");
|
|
962
|
+
input.type = "text";
|
|
963
|
+
input.placeholder = "如:期末复习计划";
|
|
964
|
+
input.style.cssText = "padding:8px 10px;background:#252536;border:1px solid #3d3d5c;border-radius:4px;color:#cdd6f4;font-size:13px;font-family:monospace;outline:none;";
|
|
965
|
+
input.onfocus = function () { input.style.borderColor = "#8b5cf6"; };
|
|
966
|
+
input.onblur = function () { input.style.borderColor = "#3d3d5c"; };
|
|
967
|
+
body.appendChild(input);
|
|
968
|
+
|
|
969
|
+
var submitBtn = document.createElement("button");
|
|
970
|
+
submitBtn.textContent = "创建";
|
|
971
|
+
submitBtn.style.cssText = "padding:8px 16px;background:#8b5cf6;border:none;border-radius:4px;color:#fff;font-size:12px;font-family:monospace;cursor:pointer;transition:opacity 0.15s;";
|
|
972
|
+
submitBtn.onmouseenter = function () { submitBtn.style.opacity = "0.8"; };
|
|
973
|
+
submitBtn.onmouseleave = function () { submitBtn.style.opacity = "1"; };
|
|
974
|
+
|
|
975
|
+
function doSubmit() {
|
|
976
|
+
var val = input.value.trim();
|
|
977
|
+
if (!val) { input.style.borderColor = "#ff4444"; input.focus(); return; }
|
|
978
|
+
closeNewSessionModal();
|
|
979
|
+
createNamedSession(val);
|
|
980
|
+
}
|
|
981
|
+
submitBtn.onclick = doSubmit;
|
|
982
|
+
input.onkeydown = function (e) { if (e.key === "Enter") doSubmit(); };
|
|
983
|
+
body.appendChild(submitBtn);
|
|
984
|
+
|
|
985
|
+
box.appendChild(header);
|
|
986
|
+
box.appendChild(body);
|
|
987
|
+
overlay.appendChild(box);
|
|
988
|
+
document.body.appendChild(overlay);
|
|
989
|
+
setTimeout(function () { input.focus(); }, 100);
|
|
990
|
+
}
|
|
991
|
+
|
|
787
992
|
// ═══ 8. 右下角"命令"按钮 ═══
|
|
788
993
|
|
|
789
994
|
var commandOpen = false;
|
|
@@ -1566,6 +1771,7 @@ btn.addEventListener("click", function () {
|
|
|
1566
1771
|
createDocButton();
|
|
1567
1772
|
createCmdButton();
|
|
1568
1773
|
createCommandButton();
|
|
1774
|
+
createNewSessionButton();
|
|
1569
1775
|
injectStyles();
|
|
1570
1776
|
|
|
1571
1777
|
// 初始化 VoiceInput SDK
|