@privateclaw/privateclaw-relay 0.1.5 → 0.1.7
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/.env.example +3 -0
- package/README.md +1 -1
- package/dist/config.d.ts +3 -0
- package/dist/config.js +6 -0
- package/dist/config.js.map +1 -1
- package/dist/provider-setup.d.ts +3 -1
- package/dist/provider-setup.js +66 -24
- package/dist/provider-setup.js.map +1 -1
- package/dist/relay-cluster.js +102 -6
- package/dist/relay-cluster.js.map +1 -1
- package/dist/relay-server.d.ts +15 -0
- package/dist/relay-server.js +139 -15
- package/dist/relay-server.js.map +1 -1
- package/dist/web/chat/index.html +2 -2
- package/dist/web/scripts/chat.js +166 -4
- package/dist/web/scripts/i18n.js +15 -0
- package/dist/web/scripts/session-client.js +65 -0
- package/dist/web/styles.css +180 -0
- package/package.json +1 -1
package/dist/web/scripts/chat.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { applyTranslations, bindLocaleSelect, onLocaleChange, t } from "./i18n.js?v=
|
|
1
|
+
import { applyTranslations, bindLocaleSelect, onLocaleChange, t } from "./i18n.js?v=20260318-1";
|
|
2
2
|
import {
|
|
3
3
|
createIdentity,
|
|
4
4
|
decodeBase64,
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
inviteUsesNonDefaultRelay,
|
|
8
8
|
readFileAsAttachment,
|
|
9
9
|
} from "./protocol-web.js?v=20260316-1";
|
|
10
|
-
import { PrivateClawWebSessionClient } from "./session-client.js?v=
|
|
10
|
+
import { PrivateClawWebSessionClient } from "./session-client.js?v=20260318-1";
|
|
11
11
|
|
|
12
12
|
const MAX_INLINE_ATTACHMENT_BYTES = 5 * 1024 * 1024;
|
|
13
13
|
const QR_SCAN_MAX_DIMENSION = 1440;
|
|
@@ -60,6 +60,7 @@ const state = {
|
|
|
60
60
|
client: null,
|
|
61
61
|
invite: null,
|
|
62
62
|
messages: [],
|
|
63
|
+
expandedThinkingTraceIds: new Set(),
|
|
63
64
|
commands: [],
|
|
64
65
|
participants: [],
|
|
65
66
|
selectedAttachments: [],
|
|
@@ -582,6 +583,7 @@ function clearObjectUrls() {
|
|
|
582
583
|
function resetConversationState() {
|
|
583
584
|
clearObjectUrls();
|
|
584
585
|
state.messages = [];
|
|
586
|
+
state.expandedThinkingTraceIds.clear();
|
|
585
587
|
state.commands = [];
|
|
586
588
|
state.participants = [];
|
|
587
589
|
state.selectedAttachments = [];
|
|
@@ -749,6 +751,145 @@ function renderAttachments(attachments) {
|
|
|
749
751
|
return container;
|
|
750
752
|
}
|
|
751
753
|
|
|
754
|
+
function isThinkingTraceMessage(message) {
|
|
755
|
+
return typeof message?.thinkingStatus === "string";
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
function isThinkingTraceActive(message) {
|
|
759
|
+
return message?.thinkingStatus === "started" || message?.thinkingStatus === "streaming";
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
function createThinkingTraceBadge({ label, tone = "neutral" }) {
|
|
763
|
+
const badge = document.createElement("span");
|
|
764
|
+
badge.className = `thinking-trace-badge ${tone}`;
|
|
765
|
+
badge.textContent = label;
|
|
766
|
+
return badge;
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
function getThinkingTraceIcon(kind, { active = false, failed = false } = {}) {
|
|
770
|
+
if (failed || kind === "error") {
|
|
771
|
+
return "!";
|
|
772
|
+
}
|
|
773
|
+
if (active || kind === "thought") {
|
|
774
|
+
return "◎";
|
|
775
|
+
}
|
|
776
|
+
if (kind === "result") {
|
|
777
|
+
return "✓";
|
|
778
|
+
}
|
|
779
|
+
return "⚙";
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
function renderThinkingTraceEntry(entry) {
|
|
783
|
+
const card = document.createElement("div");
|
|
784
|
+
card.className = `thinking-trace-entry ${entry.kind || "thought"}`;
|
|
785
|
+
|
|
786
|
+
const header = document.createElement("div");
|
|
787
|
+
header.className = "thinking-trace-entry-header";
|
|
788
|
+
|
|
789
|
+
const icon = document.createElement("span");
|
|
790
|
+
icon.className = `thinking-trace-icon ${entry.kind || "thought"}`;
|
|
791
|
+
icon.textContent = getThinkingTraceIcon(entry.kind);
|
|
792
|
+
|
|
793
|
+
const title = document.createElement("strong");
|
|
794
|
+
title.textContent = entry.title || t("chat.thinkingTraceFallbackTitle");
|
|
795
|
+
|
|
796
|
+
header.append(icon, title);
|
|
797
|
+
if (entry.toolName) {
|
|
798
|
+
header.append(createThinkingTraceBadge({ label: entry.toolName, tone: "tool" }));
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
card.append(header);
|
|
802
|
+
if (typeof entry.text === "string" && entry.text.trim() !== "") {
|
|
803
|
+
const body = document.createElement("div");
|
|
804
|
+
body.className = "thinking-trace-entry-body";
|
|
805
|
+
body.append(renderRichText(entry.text));
|
|
806
|
+
card.append(body);
|
|
807
|
+
}
|
|
808
|
+
return card;
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
function renderThinkingTrace(message) {
|
|
812
|
+
const entries = Array.isArray(message.thinkingEntries) ? message.thinkingEntries : [];
|
|
813
|
+
const latestEntry = entries[entries.length - 1] || null;
|
|
814
|
+
const active = isThinkingTraceActive(message);
|
|
815
|
+
const failed = message.thinkingStatus === "failed";
|
|
816
|
+
const title = latestEntry?.title || t("chat.thinkingTraceFallbackTitle");
|
|
817
|
+
const previewSource =
|
|
818
|
+
(typeof message.thinkingSummary === "string" && message.thinkingSummary.trim()) ||
|
|
819
|
+
(typeof latestEntry?.text === "string" && latestEntry.text.trim()) ||
|
|
820
|
+
t("chat.pendingLabel");
|
|
821
|
+
|
|
822
|
+
const card = document.createElement(entries.length > 0 ? "details" : "div");
|
|
823
|
+
card.className = `thinking-trace-card${active ? " active" : ""}${failed ? " failed" : ""}`;
|
|
824
|
+
if (card instanceof HTMLDetailsElement) {
|
|
825
|
+
card.open = active && state.expandedThinkingTraceIds.has(message.id);
|
|
826
|
+
card.addEventListener("toggle", () => {
|
|
827
|
+
if (card.open && active) {
|
|
828
|
+
state.expandedThinkingTraceIds.add(message.id);
|
|
829
|
+
} else {
|
|
830
|
+
state.expandedThinkingTraceIds.delete(message.id);
|
|
831
|
+
}
|
|
832
|
+
});
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
const summary = document.createElement(entries.length > 0 ? "summary" : "div");
|
|
836
|
+
summary.className = "thinking-trace-summary";
|
|
837
|
+
|
|
838
|
+
const header = document.createElement("div");
|
|
839
|
+
header.className = "thinking-trace-header";
|
|
840
|
+
|
|
841
|
+
const headerMain = document.createElement("div");
|
|
842
|
+
headerMain.className = "thinking-trace-header-main";
|
|
843
|
+
|
|
844
|
+
const icon = document.createElement("span");
|
|
845
|
+
icon.className = `thinking-trace-icon ${failed ? "error" : latestEntry?.kind || "thought"}${active ? " active" : ""}`;
|
|
846
|
+
icon.textContent = getThinkingTraceIcon(latestEntry?.kind, { active, failed });
|
|
847
|
+
|
|
848
|
+
const heading = document.createElement("strong");
|
|
849
|
+
heading.textContent = title;
|
|
850
|
+
|
|
851
|
+
headerMain.append(icon, heading);
|
|
852
|
+
header.append(headerMain);
|
|
853
|
+
|
|
854
|
+
const badges = document.createElement("div");
|
|
855
|
+
badges.className = "thinking-trace-badges";
|
|
856
|
+
badges.append(
|
|
857
|
+
createThinkingTraceBadge({
|
|
858
|
+
label: active
|
|
859
|
+
? t("chat.thinkingTraceLive")
|
|
860
|
+
: failed
|
|
861
|
+
? t("chat.thinkingTraceFailed")
|
|
862
|
+
: t("chat.thinkingTraceDone"),
|
|
863
|
+
tone: failed ? "error" : active ? "live" : "done",
|
|
864
|
+
}),
|
|
865
|
+
);
|
|
866
|
+
if (latestEntry?.toolName) {
|
|
867
|
+
badges.append(createThinkingTraceBadge({ label: latestEntry.toolName, tone: "tool" }));
|
|
868
|
+
}
|
|
869
|
+
badges.append(createThinkingTraceBadge({
|
|
870
|
+
label: t("chat.thinkingTraceSteps", { count: String(entries.length) }),
|
|
871
|
+
}));
|
|
872
|
+
header.append(badges);
|
|
873
|
+
|
|
874
|
+
const preview = document.createElement("p");
|
|
875
|
+
preview.className = "thinking-trace-preview";
|
|
876
|
+
preview.textContent = previewSource;
|
|
877
|
+
|
|
878
|
+
summary.append(header, preview);
|
|
879
|
+
card.append(summary);
|
|
880
|
+
|
|
881
|
+
if (entries.length > 0) {
|
|
882
|
+
const history = document.createElement("div");
|
|
883
|
+
history.className = "thinking-trace-history";
|
|
884
|
+
for (const entry of entries) {
|
|
885
|
+
history.append(renderThinkingTraceEntry(entry));
|
|
886
|
+
}
|
|
887
|
+
card.append(history);
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
return card;
|
|
891
|
+
}
|
|
892
|
+
|
|
752
893
|
function upsertMessage(message) {
|
|
753
894
|
if (message.isPending && message.replyTo) {
|
|
754
895
|
const repliedIndex = state.messages.findIndex(
|
|
@@ -768,6 +909,14 @@ function upsertMessage(message) {
|
|
|
768
909
|
|
|
769
910
|
const existingIndex = state.messages.findIndex((item) => item.id === message.id);
|
|
770
911
|
if (existingIndex >= 0) {
|
|
912
|
+
if (isThinkingTraceMessage(message) && !isThinkingTraceActive(message) && !(message.thinkingEntries?.length > 0)) {
|
|
913
|
+
state.messages.splice(existingIndex, 1);
|
|
914
|
+
state.expandedThinkingTraceIds.delete(message.id);
|
|
915
|
+
return;
|
|
916
|
+
}
|
|
917
|
+
if (isThinkingTraceMessage(message) && !isThinkingTraceActive(message)) {
|
|
918
|
+
state.expandedThinkingTraceIds.delete(message.id);
|
|
919
|
+
}
|
|
771
920
|
const existingMessage = state.messages[existingIndex];
|
|
772
921
|
state.messages[existingIndex] = {
|
|
773
922
|
...message,
|
|
@@ -781,12 +930,17 @@ function upsertMessage(message) {
|
|
|
781
930
|
return;
|
|
782
931
|
}
|
|
783
932
|
|
|
933
|
+
if (isThinkingTraceMessage(message) && !isThinkingTraceActive(message) && !(message.thinkingEntries?.length > 0)) {
|
|
934
|
+
state.expandedThinkingTraceIds.delete(message.id);
|
|
935
|
+
return;
|
|
936
|
+
}
|
|
937
|
+
|
|
784
938
|
if (message.isPending) {
|
|
785
939
|
state.messages.push(message);
|
|
786
940
|
return;
|
|
787
941
|
}
|
|
788
942
|
|
|
789
|
-
if (message.replyTo) {
|
|
943
|
+
if (message.replyTo && !isThinkingTraceMessage(message)) {
|
|
790
944
|
const repliedIndex = state.messages.findIndex(
|
|
791
945
|
(item) => item.id === message.replyTo && item.sender === "user",
|
|
792
946
|
);
|
|
@@ -800,6 +954,9 @@ function upsertMessage(message) {
|
|
|
800
954
|
(item) => !(item.sender === "assistant" && item.isPending && item.replyTo === message.replyTo),
|
|
801
955
|
);
|
|
802
956
|
}
|
|
957
|
+
if (isThinkingTraceMessage(message) && !isThinkingTraceActive(message)) {
|
|
958
|
+
state.expandedThinkingTraceIds.delete(message.id);
|
|
959
|
+
}
|
|
803
960
|
state.messages.push(message);
|
|
804
961
|
}
|
|
805
962
|
|
|
@@ -822,6 +979,9 @@ function renderMessages() {
|
|
|
822
979
|
|
|
823
980
|
const bubble = document.createElement("div");
|
|
824
981
|
bubble.className = "message-bubble";
|
|
982
|
+
if (isThinkingTraceMessage(message)) {
|
|
983
|
+
bubble.classList.add("thinking-bubble");
|
|
984
|
+
}
|
|
825
985
|
|
|
826
986
|
const label = document.createElement("span");
|
|
827
987
|
label.className = "message-label";
|
|
@@ -838,7 +998,9 @@ function renderMessages() {
|
|
|
838
998
|
|
|
839
999
|
const body = document.createElement("div");
|
|
840
1000
|
body.className = "message-text";
|
|
841
|
-
if (message
|
|
1001
|
+
if (isThinkingTraceMessage(message)) {
|
|
1002
|
+
body.append(renderThinkingTrace(message));
|
|
1003
|
+
} else if (message.isPending && message.sender !== "user") {
|
|
842
1004
|
const pendingLabel = document.createElement("p");
|
|
843
1005
|
pendingLabel.textContent = t("chat.pendingLabel");
|
|
844
1006
|
body.append(pendingLabel, createPendingIndicator());
|
package/dist/web/scripts/i18n.js
CHANGED
|
@@ -261,6 +261,11 @@ const BUNDLES = {
|
|
|
261
261
|
youLabel: "You",
|
|
262
262
|
peerLabelFallback: "Participant",
|
|
263
263
|
pendingLabel: "Thinking…",
|
|
264
|
+
thinkingTraceFallbackTitle: "Thinking",
|
|
265
|
+
thinkingTraceLive: "Live",
|
|
266
|
+
thinkingTraceDone: "Done",
|
|
267
|
+
thinkingTraceFailed: "Failed",
|
|
268
|
+
thinkingTraceSteps: "{count} steps",
|
|
264
269
|
mutedLabel: "Bot muted",
|
|
265
270
|
commandSourceOpenclaw: "OpenClaw",
|
|
266
271
|
commandSourcePlugin: "Plugin",
|
|
@@ -527,6 +532,11 @@ const BUNDLES = {
|
|
|
527
532
|
youLabel: "你",
|
|
528
533
|
peerLabelFallback: "成员",
|
|
529
534
|
pendingLabel: "思考中…",
|
|
535
|
+
thinkingTraceFallbackTitle: "思考过程",
|
|
536
|
+
thinkingTraceLive: "进行中",
|
|
537
|
+
thinkingTraceDone: "已完成",
|
|
538
|
+
thinkingTraceFailed: "失败",
|
|
539
|
+
thinkingTraceSteps: "{count} 步",
|
|
530
540
|
mutedLabel: "机器人已静音",
|
|
531
541
|
commandSourceOpenclaw: "OpenClaw",
|
|
532
542
|
commandSourcePlugin: "插件",
|
|
@@ -793,6 +803,11 @@ const BUNDLES = {
|
|
|
793
803
|
youLabel: "你",
|
|
794
804
|
peerLabelFallback: "成員",
|
|
795
805
|
pendingLabel: "思考中…",
|
|
806
|
+
thinkingTraceFallbackTitle: "思考過程",
|
|
807
|
+
thinkingTraceLive: "進行中",
|
|
808
|
+
thinkingTraceDone: "已完成",
|
|
809
|
+
thinkingTraceFailed: "失敗",
|
|
810
|
+
thinkingTraceSteps: "{count} 步",
|
|
796
811
|
mutedLabel: "機器人已靜音",
|
|
797
812
|
commandSourceOpenclaw: "OpenClaw",
|
|
798
813
|
commandSourcePlugin: "外掛",
|
|
@@ -59,6 +59,52 @@ function parseParticipants(value) {
|
|
|
59
59
|
}));
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
+
function parseThinkingStatus(value) {
|
|
63
|
+
switch (value) {
|
|
64
|
+
case "started":
|
|
65
|
+
case "streaming":
|
|
66
|
+
case "completed":
|
|
67
|
+
case "failed":
|
|
68
|
+
return value;
|
|
69
|
+
default:
|
|
70
|
+
return "completed";
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function parseThinkingEntryKind(value) {
|
|
75
|
+
switch (value) {
|
|
76
|
+
case "thought":
|
|
77
|
+
case "action":
|
|
78
|
+
case "result":
|
|
79
|
+
case "error":
|
|
80
|
+
return value;
|
|
81
|
+
default:
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function parseThinkingEntries(value) {
|
|
87
|
+
if (!Array.isArray(value)) {
|
|
88
|
+
return [];
|
|
89
|
+
}
|
|
90
|
+
return value
|
|
91
|
+
.filter((item) => item && typeof item === "object")
|
|
92
|
+
.flatMap((item) => {
|
|
93
|
+
const kind = parseThinkingEntryKind(item.kind);
|
|
94
|
+
if (!kind) {
|
|
95
|
+
return [];
|
|
96
|
+
}
|
|
97
|
+
return [{
|
|
98
|
+
id: typeof item.id === "string" ? item.id : createMessageId("thinking-entry"),
|
|
99
|
+
kind,
|
|
100
|
+
title: typeof item.title === "string" ? item.title : "",
|
|
101
|
+
text: typeof item.text === "string" ? item.text : "",
|
|
102
|
+
sentAt: normalizeTimestamp(item.sentAt),
|
|
103
|
+
toolName: typeof item.toolName === "string" ? item.toolName : null,
|
|
104
|
+
}];
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
|
|
62
108
|
export class PrivateClawWebSessionClient extends EventTarget {
|
|
63
109
|
constructor(invite, { identity }) {
|
|
64
110
|
super();
|
|
@@ -263,6 +309,7 @@ export class PrivateClawWebSessionClient extends EventTarget {
|
|
|
263
309
|
appVersion: "privateclaw_web/0.1.0",
|
|
264
310
|
appId: this.identity.appId,
|
|
265
311
|
deviceLabel: "PrivateClaw Web",
|
|
312
|
+
supportsThinkingTrace: true,
|
|
266
313
|
...(this.identity.displayName ? { displayName: this.identity.displayName } : {}),
|
|
267
314
|
sentAt: new Date().toISOString(),
|
|
268
315
|
});
|
|
@@ -334,6 +381,23 @@ export class PrivateClawWebSessionClient extends EventTarget {
|
|
|
334
381
|
});
|
|
335
382
|
return;
|
|
336
383
|
}
|
|
384
|
+
case "thinking_message": {
|
|
385
|
+
this.#dispatch("message", {
|
|
386
|
+
message: {
|
|
387
|
+
id: typeof payload.messageId === "string" ? payload.messageId : this.#nextLocalMessageId(),
|
|
388
|
+
sender: "assistant",
|
|
389
|
+
text: "",
|
|
390
|
+
sentAt: normalizeTimestamp(payload.sentAt),
|
|
391
|
+
replyTo: typeof payload.replyTo === "string" ? payload.replyTo : null,
|
|
392
|
+
isPending: false,
|
|
393
|
+
attachments: [],
|
|
394
|
+
thinkingStatus: parseThinkingStatus(payload.status),
|
|
395
|
+
thinkingSummary: typeof payload.summary === "string" ? payload.summary : "",
|
|
396
|
+
thinkingEntries: parseThinkingEntries(payload.entries),
|
|
397
|
+
},
|
|
398
|
+
});
|
|
399
|
+
return;
|
|
400
|
+
}
|
|
337
401
|
case "participant_message": {
|
|
338
402
|
const senderAppId = typeof payload.senderAppId === "string" ? payload.senderAppId : "unknown-app";
|
|
339
403
|
this.#dispatch("message", {
|
|
@@ -429,6 +493,7 @@ export class PrivateClawWebSessionClient extends EventTarget {
|
|
|
429
493
|
appVersion: "privateclaw_web/0.1.0",
|
|
430
494
|
appId: this.identity.appId,
|
|
431
495
|
deviceLabel: "PrivateClaw Web",
|
|
496
|
+
supportsThinkingTrace: true,
|
|
432
497
|
...(this.identity.displayName ? { displayName: this.identity.displayName } : {}),
|
|
433
498
|
sentAt: new Date().toISOString(),
|
|
434
499
|
});
|
package/dist/web/styles.css
CHANGED
|
@@ -984,6 +984,11 @@ a:focus {
|
|
|
984
984
|
border-color: rgba(255, 127, 159, 0.28);
|
|
985
985
|
}
|
|
986
986
|
|
|
987
|
+
.message-bubble.thinking-bubble {
|
|
988
|
+
background: linear-gradient(180deg, rgba(143, 125, 255, 0.22), rgba(62, 217, 255, 0.08));
|
|
989
|
+
border-color: rgba(143, 125, 255, 0.24);
|
|
990
|
+
}
|
|
991
|
+
|
|
987
992
|
.message-text {
|
|
988
993
|
color: var(--text);
|
|
989
994
|
line-height: 1.6;
|
|
@@ -1020,6 +1025,181 @@ a:focus {
|
|
|
1020
1025
|
text-decoration: underline;
|
|
1021
1026
|
}
|
|
1022
1027
|
|
|
1028
|
+
.thinking-trace-card {
|
|
1029
|
+
border: 1px solid rgba(255, 255, 255, 0.08);
|
|
1030
|
+
border-radius: 18px;
|
|
1031
|
+
background: rgba(7, 12, 26, 0.28);
|
|
1032
|
+
padding: 12px;
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
details.thinking-trace-card > summary {
|
|
1036
|
+
list-style: none;
|
|
1037
|
+
cursor: pointer;
|
|
1038
|
+
}
|
|
1039
|
+
|
|
1040
|
+
details.thinking-trace-card > summary::-webkit-details-marker {
|
|
1041
|
+
display: none;
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
.thinking-trace-card.active {
|
|
1045
|
+
border-color: rgba(143, 125, 255, 0.3);
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1048
|
+
.thinking-trace-card.failed {
|
|
1049
|
+
border-color: rgba(255, 127, 159, 0.38);
|
|
1050
|
+
background: rgba(62, 10, 24, 0.26);
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
.thinking-trace-summary {
|
|
1054
|
+
display: flex;
|
|
1055
|
+
flex-direction: column;
|
|
1056
|
+
gap: 10px;
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
.thinking-trace-header {
|
|
1060
|
+
display: flex;
|
|
1061
|
+
align-items: flex-start;
|
|
1062
|
+
justify-content: space-between;
|
|
1063
|
+
gap: 12px;
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
.thinking-trace-header-main {
|
|
1067
|
+
min-width: 0;
|
|
1068
|
+
display: inline-flex;
|
|
1069
|
+
align-items: center;
|
|
1070
|
+
gap: 10px;
|
|
1071
|
+
}
|
|
1072
|
+
|
|
1073
|
+
.thinking-trace-header-main strong {
|
|
1074
|
+
font-size: 0.98rem;
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1077
|
+
.thinking-trace-icon {
|
|
1078
|
+
width: 26px;
|
|
1079
|
+
height: 26px;
|
|
1080
|
+
border-radius: 999px;
|
|
1081
|
+
display: inline-flex;
|
|
1082
|
+
align-items: center;
|
|
1083
|
+
justify-content: center;
|
|
1084
|
+
flex-shrink: 0;
|
|
1085
|
+
font-size: 0.92rem;
|
|
1086
|
+
background: rgba(255, 255, 255, 0.08);
|
|
1087
|
+
color: var(--text);
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1090
|
+
.thinking-trace-icon.thought,
|
|
1091
|
+
.thinking-trace-icon.active {
|
|
1092
|
+
background: rgba(143, 125, 255, 0.2);
|
|
1093
|
+
color: rgba(230, 224, 255, 0.96);
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
.thinking-trace-icon.active {
|
|
1097
|
+
animation: pulse 1.2s ease-in-out infinite;
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
.thinking-trace-icon.action {
|
|
1101
|
+
background: rgba(62, 217, 255, 0.18);
|
|
1102
|
+
color: rgba(204, 247, 255, 0.96);
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
.thinking-trace-icon.result {
|
|
1106
|
+
background: rgba(92, 255, 196, 0.18);
|
|
1107
|
+
color: rgba(218, 255, 241, 0.98);
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
.thinking-trace-icon.error {
|
|
1111
|
+
background: rgba(255, 127, 159, 0.22);
|
|
1112
|
+
color: rgba(255, 230, 237, 0.98);
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
.thinking-trace-preview {
|
|
1116
|
+
margin: 0;
|
|
1117
|
+
color: var(--text-muted);
|
|
1118
|
+
white-space: pre-wrap;
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1121
|
+
.thinking-trace-badges {
|
|
1122
|
+
display: flex;
|
|
1123
|
+
flex-wrap: wrap;
|
|
1124
|
+
justify-content: flex-end;
|
|
1125
|
+
gap: 8px;
|
|
1126
|
+
}
|
|
1127
|
+
|
|
1128
|
+
.thinking-trace-badge {
|
|
1129
|
+
display: inline-flex;
|
|
1130
|
+
align-items: center;
|
|
1131
|
+
gap: 6px;
|
|
1132
|
+
padding: 6px 10px;
|
|
1133
|
+
border-radius: 999px;
|
|
1134
|
+
background: rgba(255, 255, 255, 0.08);
|
|
1135
|
+
color: var(--text-muted);
|
|
1136
|
+
font-size: 0.82rem;
|
|
1137
|
+
font-weight: 600;
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1140
|
+
.thinking-trace-badge.live {
|
|
1141
|
+
background: rgba(143, 125, 255, 0.16);
|
|
1142
|
+
color: rgba(233, 228, 255, 0.96);
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1145
|
+
.thinking-trace-badge.done {
|
|
1146
|
+
background: rgba(92, 255, 196, 0.14);
|
|
1147
|
+
color: rgba(220, 255, 243, 0.98);
|
|
1148
|
+
}
|
|
1149
|
+
|
|
1150
|
+
.thinking-trace-badge.error {
|
|
1151
|
+
background: rgba(255, 127, 159, 0.18);
|
|
1152
|
+
color: rgba(255, 233, 239, 0.98);
|
|
1153
|
+
}
|
|
1154
|
+
|
|
1155
|
+
.thinking-trace-badge.tool {
|
|
1156
|
+
background: rgba(62, 217, 255, 0.16);
|
|
1157
|
+
color: rgba(208, 247, 255, 0.98);
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1160
|
+
.thinking-trace-history {
|
|
1161
|
+
margin-top: 12px;
|
|
1162
|
+
padding-top: 12px;
|
|
1163
|
+
border-top: 1px solid rgba(255, 255, 255, 0.08);
|
|
1164
|
+
display: flex;
|
|
1165
|
+
flex-direction: column;
|
|
1166
|
+
gap: 10px;
|
|
1167
|
+
}
|
|
1168
|
+
|
|
1169
|
+
.thinking-trace-entry {
|
|
1170
|
+
border-radius: 16px;
|
|
1171
|
+
padding: 12px;
|
|
1172
|
+
border: 1px solid rgba(255, 255, 255, 0.08);
|
|
1173
|
+
background: rgba(255, 255, 255, 0.04);
|
|
1174
|
+
}
|
|
1175
|
+
|
|
1176
|
+
.thinking-trace-entry.thought {
|
|
1177
|
+
border-color: rgba(143, 125, 255, 0.2);
|
|
1178
|
+
}
|
|
1179
|
+
|
|
1180
|
+
.thinking-trace-entry.action {
|
|
1181
|
+
border-color: rgba(62, 217, 255, 0.2);
|
|
1182
|
+
}
|
|
1183
|
+
|
|
1184
|
+
.thinking-trace-entry.result {
|
|
1185
|
+
border-color: rgba(92, 255, 196, 0.2);
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
.thinking-trace-entry.error {
|
|
1189
|
+
border-color: rgba(255, 127, 159, 0.24);
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1192
|
+
.thinking-trace-entry-header {
|
|
1193
|
+
display: flex;
|
|
1194
|
+
align-items: center;
|
|
1195
|
+
flex-wrap: wrap;
|
|
1196
|
+
gap: 10px;
|
|
1197
|
+
}
|
|
1198
|
+
|
|
1199
|
+
.thinking-trace-entry-body {
|
|
1200
|
+
margin-top: 8px;
|
|
1201
|
+
}
|
|
1202
|
+
|
|
1023
1203
|
.mermaid-card {
|
|
1024
1204
|
border: 1px solid var(--line);
|
|
1025
1205
|
border-radius: 16px;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@privateclaw/privateclaw-relay",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.7",
|
|
4
4
|
"description": "Blind WebSocket relay for PrivateClaw encrypted sessions with local CLI startup and optional Tailscale Funnel or Cloudflare Tunnel exposure",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|