@rethinkingstudio/clawpilot 1.1.15-beta.1 → 1.1.15-beta.2

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.
@@ -3,6 +3,7 @@ import { OpenClawGatewayClient } from "./gateway-client.js";
3
3
  import { handleLocalCommand } from "../commands/local-handlers.js";
4
4
  import { handleProviderCommand } from "../commands/provider-handlers.js";
5
5
  import { getServicePlatform } from "../platform/service-manager.js";
6
+ import { uploadAssistantAttachments } from "../media/assistant-attachments.js";
6
7
  import { homedir } from "os";
7
8
  import { join } from "path";
8
9
  import { mkdir, writeFile } from "fs/promises";
@@ -105,15 +106,15 @@ export async function runRelayManager(opts: RelayManagerOptions): Promise<boolea
105
106
  },
106
107
 
107
108
  onEvent: (event, payload) => {
108
- // On chat final, fetch history to get actual content (OpenClaw 2026.3.2+
109
- // no longer includes message content in the chat final event payload).
110
- // This mirrors what the macOS 2026.3.2 client does.
109
+ // On chat final, fetch history to get actual content + extract media attachments.
110
+ // OpenClaw 2026.3.2+ no longer includes message content in chat final payload.
111
111
  if (event === "chat") {
112
112
  const p = payload as { state?: string; sessionKey?: string; runId?: string; message?: unknown };
113
113
  if (p?.state === "final" && p?.sessionKey) {
114
114
  const sessionKey = p.sessionKey;
115
115
  const runId = p.runId;
116
- type HistoryResponse = { messages?: Array<{ role: string; content?: Array<{ type: string; text?: string }> }> };
116
+ type ContentBlock = { type: string; text?: string; source?: { type?: string; media_type?: string; data?: string; path?: string } };
117
+ type HistoryResponse = { messages?: Array<{ role: string; content?: ContentBlock[] }> };
117
118
  const fetchHistory = () =>
118
119
  gatewayClient!.request<HistoryResponse>("chat.history", { sessionKey, limit: 10 });
119
120
  const extractText = (h: HistoryResponse | undefined) => {
@@ -129,10 +130,28 @@ export async function runRelayManager(opts: RelayManagerOptions): Promise<boolea
129
130
  await new Promise((resolve) => setTimeout(resolve, 600));
130
131
  const retryHistory = await fetchHistory();
131
132
  text = extractText(retryHistory);
133
+ history = retryHistory;
132
134
  }
133
135
  if (text) {
134
136
  (p as Record<string, unknown>).message = { content: [{ type: "text", text }] };
135
137
  }
138
+
139
+ // Upload any media blocks found in the history
140
+ try {
141
+ const attachments = await uploadAssistantAttachments(
142
+ history ?? {},
143
+ opts.relayServerUrl,
144
+ opts.gatewayId,
145
+ opts.relaySecret
146
+ );
147
+ if (attachments.length > 0) {
148
+ (p as Record<string, unknown>).attachments = attachments;
149
+ console.log(`[relay] chat final: injected ${attachments.length} attachment(s) runId=${runId}`);
150
+ }
151
+ } catch (mediaErr) {
152
+ console.error(`[relay] media upload error (non-fatal): ${mediaErr}`);
153
+ }
154
+
136
155
  console.log(`[relay] chat final (history fetched): runId=${runId} textLength=${text?.length ?? 0}`);
137
156
  send({ type: "event", event, payload });
138
157
  })
@@ -140,7 +159,7 @@ export async function runRelayManager(opts: RelayManagerOptions): Promise<boolea
140
159
  console.error(`[relay] chat.history fetch failed: ${err}`);
141
160
  send({ type: "event", event, payload });
142
161
  });
143
- return; // will send after history fetch
162
+ return; // will send after history fetch + media upload
144
163
  }
145
164
  }
146
165
  send({ type: "event", event, payload });
@@ -1,18 +0,0 @@
1
- import { WebSocket } from "ws";
2
- /**
3
- * Proxies WebSocket frames between the relay server (via relayWs) and the
4
- * local OpenClaw Gateway (via a new direct WebSocket connection).
5
- *
6
- * All frames are forwarded as raw bytes — no parsing of OpenClaw protocol.
7
- */
8
- export declare class SessionProxy {
9
- private readonly sessionId;
10
- private readonly relayWs;
11
- private readonly gatewayUrl;
12
- private gwWs;
13
- private closed;
14
- constructor(sessionId: string, relayWs: WebSocket, gatewayUrl: string);
15
- start(): Promise<void>;
16
- forwardToGateway(base64Data: string): void;
17
- close(): void;
18
- }
@@ -1,75 +0,0 @@
1
- import { WebSocket } from "ws";
2
- /**
3
- * Proxies WebSocket frames between the relay server (via relayWs) and the
4
- * local OpenClaw Gateway (via a new direct WebSocket connection).
5
- *
6
- * All frames are forwarded as raw bytes — no parsing of OpenClaw protocol.
7
- */
8
- export class SessionProxy {
9
- sessionId;
10
- relayWs;
11
- gatewayUrl;
12
- gwWs = null;
13
- closed = false;
14
- constructor(sessionId, relayWs, gatewayUrl) {
15
- this.sessionId = sessionId;
16
- this.relayWs = relayWs;
17
- this.gatewayUrl = gatewayUrl;
18
- }
19
- async start() {
20
- return new Promise((resolve, reject) => {
21
- const gw = new WebSocket(this.gatewayUrl);
22
- this.gwWs = gw;
23
- const timeout = setTimeout(() => {
24
- gw.terminate();
25
- reject(new Error(`Timeout connecting to gateway at ${this.gatewayUrl}`));
26
- }, 10_000);
27
- gw.on("open", () => {
28
- clearTimeout(timeout);
29
- resolve();
30
- });
31
- gw.on("error", (err) => {
32
- clearTimeout(timeout);
33
- if (!this.closed)
34
- reject(err);
35
- });
36
- // Gateway → relay server
37
- gw.on("message", (raw) => {
38
- if (this.relayWs.readyState !== WebSocket.OPEN)
39
- return;
40
- const data = raw instanceof Buffer ? raw : Buffer.from(raw);
41
- const msg = {
42
- ctrl: "DATA",
43
- sessionId: this.sessionId,
44
- data: data.toString("base64"),
45
- };
46
- this.relayWs.send(JSON.stringify(msg));
47
- });
48
- gw.on("close", () => {
49
- if (!this.closed) {
50
- this.closed = true;
51
- // Notify relay server that session is done
52
- if (this.relayWs.readyState === WebSocket.OPEN) {
53
- const msg = {
54
- ctrl: "SESSION_CLOSE",
55
- sessionId: this.sessionId,
56
- };
57
- this.relayWs.send(JSON.stringify(msg));
58
- }
59
- }
60
- });
61
- });
62
- }
63
- // Called when DATA arrives from the relay server for this session
64
- forwardToGateway(base64Data) {
65
- if (!this.gwWs || this.gwWs.readyState !== WebSocket.OPEN)
66
- return;
67
- const buf = Buffer.from(base64Data, "base64");
68
- this.gwWs.send(buf);
69
- }
70
- close() {
71
- this.closed = true;
72
- this.gwWs?.close();
73
- }
74
- }
75
- //# sourceMappingURL=session-proxy.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"session-proxy.js","sourceRoot":"","sources":["../../src/relay/session-proxy.ts"],"names":[],"mappings":"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"}