@newbase-clawchat/openclaw-clawchat 2026.4.15 → 2026.4.21
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 +1 -1
- package/src/api-client.ts +2 -2
- package/src/login.runtime.ts +1 -1
- package/src/reply-dispatcher.ts +24 -12
- package/src/tools.ts +1 -1
package/package.json
CHANGED
package/src/api-client.ts
CHANGED
|
@@ -32,7 +32,7 @@ export interface OpenclawClawlingApiClient {
|
|
|
32
32
|
*/
|
|
33
33
|
agentsConnect(params: {
|
|
34
34
|
/** The invite code entered by the operator. */
|
|
35
|
-
|
|
35
|
+
code: string;
|
|
36
36
|
/** Platform the agent is attaching from (e.g. "openclaw"). */
|
|
37
37
|
platform: string;
|
|
38
38
|
/** Agent type tag (e.g. "bot"). */
|
|
@@ -179,7 +179,7 @@ export function createOpenclawClawlingApiClient(opts: ApiClientOptions): Opencla
|
|
|
179
179
|
},
|
|
180
180
|
);
|
|
181
181
|
},
|
|
182
|
-
async agentsConnect({ inviteCode, platform, type }): Promise<AgentConnectResult> {
|
|
182
|
+
async agentsConnect({ code: inviteCode, platform, type }): Promise<AgentConnectResult> {
|
|
183
183
|
if (!inviteCode?.trim()) {
|
|
184
184
|
throw new ClawlingApiError("validation", "agentsConnect: inviteCode is required");
|
|
185
185
|
}
|
package/src/login.runtime.ts
CHANGED
|
@@ -94,7 +94,7 @@ export async function runOpenclawClawlingLogin(params: LoginParams): Promise<voi
|
|
|
94
94
|
let result;
|
|
95
95
|
try {
|
|
96
96
|
result = await apiClient.agentsConnect({
|
|
97
|
-
inviteCode,
|
|
97
|
+
code: inviteCode,
|
|
98
98
|
platform: AGENTS_CONNECT_PLATFORM,
|
|
99
99
|
type: AGENTS_CONNECT_TYPE,
|
|
100
100
|
});
|
package/src/reply-dispatcher.ts
CHANGED
|
@@ -58,17 +58,20 @@ type StreamingReplyHooks = {
|
|
|
58
58
|
* Reply dispatcher for openclaw-clawchat.
|
|
59
59
|
*
|
|
60
60
|
* Streaming mode (`account.replyMode === "stream"`, no replyCtx):
|
|
61
|
-
* 1. `onReplyStart`
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
61
|
+
* 1. `onReplyStart` just resets accumulators. It does NOT open the session
|
|
62
|
+
* yet — that would leave a ghost `message.created + done` bubble if the
|
|
63
|
+
* run produces nothing (e.g., agent not configured, send-policy denied).
|
|
64
|
+
* 2. On first real content (deliver block/tool or partial/reasoning
|
|
65
|
+
* snapshot), `queueStreamSnapshot` lazily opens the session, which emits
|
|
66
|
+
* `message.created` plus the first `message.add`.
|
|
67
|
+
* 3. Subsequent snapshots/deltas emit `message.add` frames (chunked by
|
|
66
68
|
* `stream.flushIntervalMs` + `stream.minChunkChars`).
|
|
67
|
-
*
|
|
69
|
+
* 4. On run end (`onIdle`), the session flushes pending buffer, emits
|
|
68
70
|
* `message.done`, then the merged full text plus any accumulated
|
|
69
71
|
* media is emitted as a separate `message.send` / `message.reply` —
|
|
70
72
|
* mirroring the clawling-channel v1 pattern where streaming `agent`
|
|
71
|
-
* events are followed by a consolidated `chat` final.
|
|
73
|
+
* events are followed by a consolidated `chat` final. Empty runs emit
|
|
74
|
+
* nothing at all (no created/done/reply) — they only log a skip line.
|
|
72
75
|
*
|
|
73
76
|
* Static mode or replyCtx: bypass streaming and emit one `message.send` /
|
|
74
77
|
* `message.reply` per deliver with text + media.
|
|
@@ -133,10 +136,14 @@ export function createOpenclawClawlingReplyDispatcher(options: ReplyDispatcherOp
|
|
|
133
136
|
const openSessionIfNeeded = () => {
|
|
134
137
|
if (!streamingEnabled || streamingSession || streamCreatedEmitted) return;
|
|
135
138
|
streamCreatedEmitted = true;
|
|
136
|
-
//
|
|
137
|
-
//
|
|
138
|
-
//
|
|
139
|
-
|
|
139
|
+
// Mint a fresh agent-side message_id at `message.created` time. All
|
|
140
|
+
// subsequent `message.add` / `message.done` / `message.reply` frames for
|
|
141
|
+
// this stream reuse it. Once the stream finalizes (done or reply), this
|
|
142
|
+
// id is retired — the next inbound turn spawns a new dispatcher instance
|
|
143
|
+
// which mints its own id. The inbound user message_id lives on
|
|
144
|
+
// `replyTo.msgId`; keeping the two distinct avoids the agent's reply
|
|
145
|
+
// frames shadowing the user turn they answer.
|
|
146
|
+
streamingMessageId = `${account.userId}-stream-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
140
147
|
streamingSession = openBufferedStreamingSession({
|
|
141
148
|
client,
|
|
142
149
|
routing,
|
|
@@ -269,6 +276,12 @@ export function createOpenclawClawlingReplyDispatcher(options: ReplyDispatcherOp
|
|
|
269
276
|
// If `onReplyStart` fires again during the same dispatcher instance
|
|
270
277
|
// (e.g. typing controller re-entry), we must NOT tear down the stream
|
|
271
278
|
// session — that would cause a second `message.created`.
|
|
279
|
+
//
|
|
280
|
+
// We deliberately do NOT open the streaming session here. Opening it
|
|
281
|
+
// eagerly would emit `message.created` even for runs that ultimately
|
|
282
|
+
// produce nothing (unknown agent, send-policy denied, etc.), leaving a
|
|
283
|
+
// ghost empty bubble. The session opens lazily via queueStreamSnapshot
|
|
284
|
+
// on the first real content.
|
|
272
285
|
if (!streamCreatedEmitted) {
|
|
273
286
|
streamText = "";
|
|
274
287
|
reasoningText = "";
|
|
@@ -277,7 +290,6 @@ export function createOpenclawClawlingReplyDispatcher(options: ReplyDispatcherOp
|
|
|
277
290
|
streamingClosed = false;
|
|
278
291
|
runDone = false;
|
|
279
292
|
}
|
|
280
|
-
if (streamingEnabled) openSessionIfNeeded();
|
|
281
293
|
},
|
|
282
294
|
deliver: async (payload: ReplyPayload, info?: { kind: "tool" | "block" | "final" }) => {
|
|
283
295
|
const text = payload.text ?? "";
|
package/src/tools.ts
CHANGED
|
@@ -123,7 +123,7 @@ export function registerOpenclawClawlingTools(api: OpenClawPluginApi): void {
|
|
|
123
123
|
});
|
|
124
124
|
return jsonResponse({
|
|
125
125
|
ok: true,
|
|
126
|
-
message: "ClawChat activated successfully.
|
|
126
|
+
message: "✅ ClawChat activated successfully.",
|
|
127
127
|
});
|
|
128
128
|
} catch (err) {
|
|
129
129
|
if (err instanceof ClawlingApiError) return apiError(err);
|