@contextableai/clawg-ui 0.2.3 → 0.2.4
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/CHANGELOG.md +5 -0
- package/index.ts +2 -0
- package/package.json +1 -1
- package/src/http-handler.ts +32 -0
- package/src/tool-store.ts +20 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.2.4 (2026-02-06)
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
- Separate tool call events and text message events into distinct AG-UI runs — when text follows a tool call, the tool run is finished and a new run (with a unique runId) is started for the text messages
|
|
7
|
+
|
|
3
8
|
## 0.2.3 (2026-02-06)
|
|
4
9
|
|
|
5
10
|
### Fixed
|
package/index.ts
CHANGED
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
popToolCallId,
|
|
14
14
|
isClientTool,
|
|
15
15
|
setClientToolCalled,
|
|
16
|
+
setToolFiredInRun,
|
|
16
17
|
} from "./src/tool-store.js";
|
|
17
18
|
|
|
18
19
|
const plugin = {
|
|
@@ -50,6 +51,7 @@ const plugin = {
|
|
|
50
51
|
toolCallId,
|
|
51
52
|
toolCallName: event.toolName,
|
|
52
53
|
});
|
|
54
|
+
setToolFiredInRun(sk);
|
|
53
55
|
if (event.params && Object.keys(event.params).length > 0) {
|
|
54
56
|
console.log(`[clawg-ui] before_tool_call: emitting TOOL_CALL_ARGS, params=${JSON.stringify(event.params)}`);
|
|
55
57
|
writer({
|
package/package.json
CHANGED
package/src/http-handler.ts
CHANGED
|
@@ -12,6 +12,8 @@ import {
|
|
|
12
12
|
wasClientToolCalled,
|
|
13
13
|
clearClientToolCalled,
|
|
14
14
|
clearClientToolNames,
|
|
15
|
+
wasToolFiredInRun,
|
|
16
|
+
clearToolFiredInRun,
|
|
15
17
|
} from "./tool-store.js";
|
|
16
18
|
import { aguiChannelPlugin } from "./channel.js";
|
|
17
19
|
|
|
@@ -384,6 +386,31 @@ export function createAguiHttpHandler(api: OpenClawPluginApi) {
|
|
|
384
386
|
}
|
|
385
387
|
};
|
|
386
388
|
|
|
389
|
+
// If a tool call was emitted in the current run, finish that run and start
|
|
390
|
+
// a fresh one for text messages. This keeps tool events and text events in
|
|
391
|
+
// separate runs per the AG-UI protocol.
|
|
392
|
+
const splitRunIfToolFired = () => {
|
|
393
|
+
if (!wasToolFiredInRun(sessionKey)) {
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
396
|
+
// End the tool run
|
|
397
|
+
writeEvent({
|
|
398
|
+
type: EventType.RUN_FINISHED,
|
|
399
|
+
threadId,
|
|
400
|
+
runId: currentRunId,
|
|
401
|
+
});
|
|
402
|
+
// Start a new run for text messages
|
|
403
|
+
currentRunId = `clawg-ui-run-${randomUUID()}`;
|
|
404
|
+
currentMessageId = `msg-${randomUUID()}`;
|
|
405
|
+
messageStarted = false;
|
|
406
|
+
clearToolFiredInRun(sessionKey);
|
|
407
|
+
writeEvent({
|
|
408
|
+
type: EventType.RUN_STARTED,
|
|
409
|
+
threadId,
|
|
410
|
+
runId: currentRunId,
|
|
411
|
+
});
|
|
412
|
+
};
|
|
413
|
+
|
|
387
414
|
// Handle client disconnect
|
|
388
415
|
req.on("close", () => {
|
|
389
416
|
closed = true;
|
|
@@ -475,6 +502,8 @@ export function createAguiHttpHandler(api: OpenClawPluginApi) {
|
|
|
475
502
|
return false;
|
|
476
503
|
}
|
|
477
504
|
|
|
505
|
+
splitRunIfToolFired();
|
|
506
|
+
|
|
478
507
|
if (!messageStarted) {
|
|
479
508
|
messageStarted = true;
|
|
480
509
|
writeEvent({
|
|
@@ -501,6 +530,8 @@ export function createAguiHttpHandler(api: OpenClawPluginApi) {
|
|
|
501
530
|
const text = wasClientToolCalled(sessionKey) ? "" : payload.text?.trim();
|
|
502
531
|
|
|
503
532
|
if (text) {
|
|
533
|
+
splitRunIfToolFired();
|
|
534
|
+
|
|
504
535
|
if (!messageStarted) {
|
|
505
536
|
messageStarted = true;
|
|
506
537
|
writeEvent({
|
|
@@ -586,6 +617,7 @@ export function createAguiHttpHandler(api: OpenClawPluginApi) {
|
|
|
586
617
|
clearWriter(sessionKey);
|
|
587
618
|
clearClientToolCalled(sessionKey);
|
|
588
619
|
clearClientToolNames(sessionKey);
|
|
620
|
+
clearToolFiredInRun(sessionKey);
|
|
589
621
|
}
|
|
590
622
|
};
|
|
591
623
|
}
|
package/src/tool-store.ts
CHANGED
|
@@ -108,6 +108,26 @@ export function clearClientToolNames(sessionKey: string): void {
|
|
|
108
108
|
clientToolNames.delete(sessionKey);
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
+
// --- Tool-fired-in-run flag ---
|
|
112
|
+
// Tracks whether any tool call (server or client) was emitted in the current
|
|
113
|
+
// run. When a text message is about to be emitted and this flag is set, the
|
|
114
|
+
// http-handler splits into a new run so tool events and text events live in
|
|
115
|
+
// separate runs (per AG-UI protocol best practice).
|
|
116
|
+
|
|
117
|
+
const toolFiredInRunFlags = new Map<string, boolean>();
|
|
118
|
+
|
|
119
|
+
export function setToolFiredInRun(sessionKey: string): void {
|
|
120
|
+
toolFiredInRunFlags.set(sessionKey, true);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export function wasToolFiredInRun(sessionKey: string): boolean {
|
|
124
|
+
return toolFiredInRunFlags.get(sessionKey) ?? false;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export function clearToolFiredInRun(sessionKey: string): void {
|
|
128
|
+
toolFiredInRunFlags.delete(sessionKey);
|
|
129
|
+
}
|
|
130
|
+
|
|
111
131
|
// --- Client-tool-called flag ---
|
|
112
132
|
// Set when a client tool is invoked during a run so the dispatcher can
|
|
113
133
|
// suppress text output and end the run after the tool call events.
|