clawrelay 0.3.8 → 0.4.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clawrelay",
3
- "version": "0.3.8",
3
+ "version": "0.4.0",
4
4
  "description": "Channel relay plugin for OpenClaw — receives messages from an always-on relay proxy",
5
5
  "main": "src/index.ts",
6
6
  "type": "module",
@@ -69,7 +69,6 @@ export function createRelayInboundHandler(api: any) {
69
69
  logger.warn(`[clawrelay] Cannot send event ${event}: no client connId`);
70
70
  return;
71
71
  }
72
- logger.info(`[clawrelay] sendEventToClient: ${event} connId=${client.connId}`);
73
72
  context.broadcastToConnIds(event, payload, new Set([client.connId]));
74
73
  };
75
74
 
@@ -77,12 +76,12 @@ export function createRelayInboundHandler(api: any) {
77
76
  // Streaming mode: ack immediately, then send deltas via events
78
77
  respond(true, { messageId: message.messageId, streaming: true });
79
78
 
80
- const streamCallback = (text: string) => {
79
+ const onPartialText = (text: string) => {
81
80
  try {
82
81
  sendEventToClient('relay.stream.delta', {
83
82
  messageId: message.messageId,
84
83
  text,
85
- kind: 'deliver',
84
+ kind: 'partial',
86
85
  });
87
86
  } catch (err) {
88
87
  logger.debug(`[clawrelay] Failed to send stream delta: ${err}`);
@@ -95,7 +94,7 @@ export function createRelayInboundHandler(api: any) {
95
94
  account,
96
95
  config,
97
96
  log: logger,
98
- streamCallback,
97
+ onPartialText,
99
98
  });
100
99
 
101
100
  sendEventToClient('relay.stream.done', {
@@ -141,13 +140,6 @@ export function createRelayInboundHandler(api: any) {
141
140
 
142
141
  // --- Inbound message processing (extracted from channel.ts) ---
143
142
 
144
- function resolveSessionKey(message: RelayInboundMessage): string {
145
- if (message.chatType === 'direct') {
146
- return `relay:${message.platform}:dm:${message.senderId}`;
147
- }
148
- return `relay:${message.platform}:${message.guildId ?? 'unknown'}:${message.channelId}`;
149
- }
150
-
151
143
  function resolvePeerId(message: RelayInboundMessage): string {
152
144
  if (message.chatType === 'direct') {
153
145
  return `relay:${message.platform}:dm:${message.senderId}`;
@@ -160,9 +152,9 @@ async function processRelayMessage(params: {
160
152
  account: RelayAccount;
161
153
  config: any;
162
154
  log: any;
163
- streamCallback?: (text: string) => void;
155
+ onPartialText?: (text: string) => void;
164
156
  }): Promise<string> {
165
- const { message, account, config, log, streamCallback } = params;
157
+ const { message, account, config, log, onPartialText } = params;
166
158
 
167
159
  const core = getRelayRuntime();
168
160
  const peerId = resolvePeerId(message);
@@ -232,30 +224,37 @@ async function processRelayMessage(params: {
232
224
  },
233
225
  });
234
226
 
235
- // Dispatch reply — collect all deliver() calls into a single buffer
227
+ // Dispatch reply — collect final deliver() calls and stream partial text
236
228
  const parts: string[] = [];
237
- let deliverCount = 0;
238
229
 
239
230
  await core.channel.reply.dispatchReplyWithBufferedBlockDispatcher({
240
231
  ctx: ctxPayload,
241
232
  cfg: config,
242
233
  dispatcherOptions: {
243
- deliver: async (payload: { text?: string }, info?: { kind?: string }) => {
244
- deliverCount++;
234
+ deliver: async (payload: { text?: string }) => {
245
235
  const text = payload.text ?? '';
246
- log?.info(`[clawrelay] deliver #${deliverCount} kind=${info?.kind ?? 'unknown'} len=${text.length} preview="${text.slice(0, 80)}"`);
247
236
  if (text.trim()) {
248
237
  parts.push(text);
249
- streamCallback?.(text);
250
238
  }
251
239
  },
252
240
  onError: (err: unknown, info: { kind: string }) => {
253
241
  log?.error(`[clawrelay] ${info.kind} reply failed: ${String(err)}`);
254
242
  },
255
243
  },
244
+ // Stream progressive text via onPartialReply (fires as tokens arrive)
245
+ replyOptions: onPartialText
246
+ ? {
247
+ onPartialReply: (payload: { text?: string }) => {
248
+ const text = payload.text ?? '';
249
+ if (text.trim()) {
250
+ onPartialText(text);
251
+ }
252
+ },
253
+ }
254
+ : undefined,
256
255
  });
257
256
 
258
- log?.info(`[clawrelay] Processed message ${message.messageId} from ${message.senderName} (${deliverCount} delivers, ${parts.length} parts, total=${parts.join('\n').length} chars)`);
257
+ log?.info(`[clawrelay] Processed message ${message.messageId} from ${message.senderName}`);
259
258
 
260
259
  return parts.join('\n');
261
260
  }