mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-07 18:42:25 +00:00
Keep command text in progress drafts (#93711)
* Keep command text in progress drafts * test(channels): align successful progress drafts --------- Co-authored-by: Vincent Koc <25068+vincentkoc@users.noreply.github.com>
This commit is contained in:
@@ -3057,8 +3057,8 @@ describe("processDiscordMessage draft streaming", () => {
|
||||
await runProcessDiscordMessage(ctx);
|
||||
|
||||
const lastUpdate = draftStream.update.mock.calls.at(-1)?.[0];
|
||||
expect(lastUpdate).toContain("completed");
|
||||
expect(lastUpdate).not.toContain("install dependencies");
|
||||
expect(lastUpdate).toContain("install dependencies");
|
||||
expect(lastUpdate).not.toContain("completed");
|
||||
});
|
||||
|
||||
it("drops later tool warning finals after progress preview final replies", async () => {
|
||||
|
||||
@@ -134,7 +134,7 @@ describe("buildSlackProgressDraftBlocks", () => {
|
||||
],
|
||||
});
|
||||
|
||||
expectLegacyLineBlock(blocks?.[1], "• *Exec*", "command finished · completed");
|
||||
expectLegacyLineBlock(blocks?.[1], "• *Exec*", "command finished");
|
||||
expectLegacyLineBlock(blocks?.[2], "• *Exec*", "command failed · exit 1");
|
||||
});
|
||||
|
||||
@@ -243,7 +243,7 @@ describe("native Slack progress stream chunks", () => {
|
||||
}),
|
||||
).toEqual([
|
||||
planUpdate("Shelling..."),
|
||||
taskUpdate("exec_1", "Exec — command finished · completed", "complete"),
|
||||
taskUpdate("exec_1", "Exec — command finished", "complete"),
|
||||
taskUpdate("exec_2", "Exec — command failed · exit 1", "error"),
|
||||
]);
|
||||
});
|
||||
|
||||
@@ -59,7 +59,12 @@ function compactChunkText(value: string): string {
|
||||
}
|
||||
|
||||
function lineDetailParts(line: ChannelProgressDraftLine): string[] {
|
||||
return [line.detail, line.status && !line.detail?.includes(line.status) ? line.status : undefined]
|
||||
return [
|
||||
line.detail,
|
||||
line.status && line.status !== "completed" && !line.detail?.includes(line.status)
|
||||
? line.status
|
||||
: undefined,
|
||||
]
|
||||
.map((part) => part?.trim())
|
||||
.filter((part): part is string => Boolean(part));
|
||||
}
|
||||
|
||||
@@ -2625,10 +2625,10 @@ describe("dispatchTelegramMessage draft streaming", () => {
|
||||
});
|
||||
|
||||
const lastUpdate = answerDraftStream.updatePreview.mock.calls.at(-1)?.[0];
|
||||
expect(lastUpdate?.text).toContain("completed");
|
||||
expect(lastUpdate?.text).toContain("install dependencies");
|
||||
expect(lastUpdate?.text).not.toContain("completed");
|
||||
expect(lastUpdate?.richMessage).toEqual({
|
||||
html: "<b>Shelling</b><br><b>🛠️ Exec</b> <code>install dependencies</code> <i>completed</i>",
|
||||
html: "<b>Shelling</b><br><b>🛠️ Exec</b> <code>install dependencies</code>",
|
||||
skip_entity_detection: true,
|
||||
});
|
||||
});
|
||||
|
||||
@@ -458,7 +458,7 @@ function renderTelegramProgressLine(line: ChannelProgressDraftCompositorLine): s
|
||||
parts.push(renderTelegramProgressStringLine(text));
|
||||
}
|
||||
}
|
||||
if (line.status && line.status !== line.detail) {
|
||||
if (line.status && line.status !== "completed" && line.status !== line.detail) {
|
||||
parts.push(`<i>${escapeTelegramProgressHtml(line.status)}</i>`);
|
||||
}
|
||||
return parts.join(" ");
|
||||
|
||||
@@ -2,6 +2,44 @@ import { describe, expect, it } from "vitest";
|
||||
import { buildChannelProgressDraftLine } from "./streaming.js";
|
||||
|
||||
describe("buildChannelProgressDraftLine", () => {
|
||||
it("omits generic completed status from successful command output with title", () => {
|
||||
const line = buildChannelProgressDraftLine(
|
||||
{
|
||||
event: "command-output",
|
||||
toolCallId: "exec-1",
|
||||
phase: "end",
|
||||
title: "pwd",
|
||||
name: "exec",
|
||||
exitCode: 0,
|
||||
},
|
||||
{ commandText: "raw" },
|
||||
);
|
||||
|
||||
expect(line).toMatchObject({
|
||||
kind: "command-output",
|
||||
id: "exec-1",
|
||||
text: "🛠️ pwd",
|
||||
detail: "pwd",
|
||||
status: "completed",
|
||||
});
|
||||
});
|
||||
|
||||
it("uses the tool label when successful command output has no title", () => {
|
||||
const line = buildChannelProgressDraftLine({
|
||||
event: "command-output",
|
||||
phase: "end",
|
||||
name: "exec",
|
||||
exitCode: 0,
|
||||
});
|
||||
|
||||
expect(line).toMatchObject({
|
||||
kind: "command-output",
|
||||
text: "🛠️ Exec",
|
||||
status: "completed",
|
||||
});
|
||||
expect(line?.detail).toBeUndefined();
|
||||
});
|
||||
|
||||
it("keeps command status and title in raw command progress lines", () => {
|
||||
const line = buildChannelProgressDraftLine(
|
||||
{
|
||||
|
||||
@@ -443,6 +443,9 @@ function buildCommandOutputProgressLine(
|
||||
if (!line || !status) {
|
||||
return line;
|
||||
}
|
||||
if (status === "completed") {
|
||||
return line;
|
||||
}
|
||||
if (!line.detail || line.detail === status) {
|
||||
const statusLine = {
|
||||
...line,
|
||||
@@ -1055,11 +1058,14 @@ function getProgressDraftLineText(line: string | ChannelProgressDraftLine): stri
|
||||
const label = line.label.trim();
|
||||
const detail = line.detail?.trim();
|
||||
const status = line.status?.trim();
|
||||
const displayStatus = status === "completed" ? undefined : status;
|
||||
if (detail) {
|
||||
const compactCommandLine =
|
||||
line.toolName === "exec" || line.toolName === "bash" || line.toolName === "shell";
|
||||
if (line.kind === "command-output" && status && detail !== status) {
|
||||
const outputDetail = detail.startsWith(`${status};`) ? detail : `${status}; ${detail}`;
|
||||
if (line.kind === "command-output" && displayStatus && detail !== displayStatus) {
|
||||
const outputDetail = detail.startsWith(`${displayStatus};`)
|
||||
? detail
|
||||
: `${displayStatus}; ${detail}`;
|
||||
if (compactCommandLine) {
|
||||
return `${prefix}${outputDetail}`;
|
||||
}
|
||||
@@ -1070,11 +1076,11 @@ function getProgressDraftLineText(line: string | ChannelProgressDraftLine): stri
|
||||
}
|
||||
return `${prefix}${detail}`;
|
||||
}
|
||||
if (status) {
|
||||
if (displayStatus) {
|
||||
if (label) {
|
||||
return `${prefix}${label}: ${status}`;
|
||||
return `${prefix}${label}: ${displayStatus}`;
|
||||
}
|
||||
return `${prefix}${status}`;
|
||||
return `${prefix}${displayStatus}`;
|
||||
}
|
||||
const text = line.text.trim();
|
||||
if (!icon && text && text !== label) {
|
||||
|
||||
@@ -601,10 +601,16 @@ describe("channel-streaming", () => {
|
||||
expect(updated[0]).toMatchObject({
|
||||
id: "tool:call-1-output",
|
||||
kind: "command-output",
|
||||
status: "completed",
|
||||
detail: "install dependencies",
|
||||
text: "🛠️ completed; install dependencies",
|
||||
status: "completed",
|
||||
text: "🛠️ install dependencies",
|
||||
});
|
||||
expect(
|
||||
formatChannelProgressDraftText({
|
||||
lines: updated,
|
||||
entry: { streaming: { progress: { label: false } } },
|
||||
}),
|
||||
).toBe("🛠️ install dependencies");
|
||||
|
||||
const recoveredItemLine = buildChannelProgressDraftLine({
|
||||
event: "item",
|
||||
@@ -634,9 +640,9 @@ describe("channel-streaming", () => {
|
||||
{
|
||||
id: "command-2",
|
||||
kind: "command-output",
|
||||
status: "completed",
|
||||
detail: "install dependencies failed",
|
||||
text: "🛠️ completed; install dependencies failed",
|
||||
status: "completed",
|
||||
text: "🛠️ install dependencies failed",
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user