@privateclaw/privateclaw-relay 0.1.6 → 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.
@@ -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
  });
@@ -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.6",
3
+ "version": "0.1.8",
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",