
















@@ -1712,7 +1712,7 @@ describe("dispatchReplyFromConfig", () => {
17121712expect(dispatcher.sendFinalReply).toHaveBeenCalledWith(notice);
17131713});
171417141715-it("renders plain-text plan updates without generic working statuses when verbose is enabled", async () => {
1715+it("renders the first plan update as a status notice without generic working statuses", async () => {
17161716setNoAbort();
17171717const cfg = {
17181718 ...emptyConfig,
@@ -1748,10 +1748,45 @@ describe("dispatchReplyFromConfig", () => {
1748174817491749await dispatchReplyFromConfig({ ctx, cfg, dispatcher, replyResolver });
175017501751-expect(firstToolResultPayload(dispatcher)?.text).toBe(
1752-"Inspect code, patch it, run tests.\n\n1. Inspect code\n2. Patch code\n3. Run tests",
1753-);
1751+expect(firstToolResultPayload(dispatcher)).toMatchObject({
1752+text: "1. Inspect code\n2. Patch code\n3. Run tests",
1753+isStatusNotice: true,
1754+});
1755+expect(dispatcher.sendToolResult).toHaveBeenCalledTimes(1);
1756+expect(dispatcher.sendFinalReply).toHaveBeenCalledWith({ text: "done" });
1757+});
1758+1759+it("sends only one plan status notice per reply run", async () => {
1760+setNoAbort();
1761+const dispatcher = createDispatcher();
1762+const ctx = buildTestCtx({
1763+Provider: "telegram",
1764+ChatType: "direct",
1765+});
1766+1767+const replyResolver = async (
1768+_ctx: MsgContext,
1769+opts?: GetReplyOptions,
1770+_cfg?: OpenClawConfig,
1771+) => {
1772+await opts?.onPlanUpdate?.({
1773+phase: "update",
1774+steps: ["Inspect code"],
1775+});
1776+await opts?.onPlanUpdate?.({
1777+phase: "update",
1778+steps: ["Inspect code", "Patch code"],
1779+});
1780+return { text: "done" } satisfies ReplyPayload;
1781+};
1782+1783+await dispatchReplyFromConfig({ ctx, cfg: emptyConfig, dispatcher, replyResolver });
1784+17541785expect(dispatcher.sendToolResult).toHaveBeenCalledTimes(1);
1786+expect(firstToolResultPayload(dispatcher)).toMatchObject({
1787+text: "1. Inspect code",
1788+isStatusNotice: true,
1789+});
17551790expect(dispatcher.sendFinalReply).toHaveBeenCalledWith({ text: "done" });
17561791});
17571792@@ -1832,7 +1867,7 @@ describe("dispatchReplyFromConfig", () => {
18321867expect(dispatcher.sendFinalReply).toHaveBeenCalledWith({ text: "done" });
18331868});
183418691835-it("suppresses plan and working-status progress when session verbose is off", async () => {
1870+it("keeps plan notices when session verbose is off but suppresses working statuses", async () => {
18361871setNoAbort();
18371872sessionStoreMocks.currentEntry = {
18381873verboseLevel: "off",
@@ -1877,7 +1912,11 @@ describe("dispatchReplyFromConfig", () => {
1877191218781913await dispatchReplyFromConfig({ ctx, cfg, dispatcher, replyResolver });
187919141880-expect(dispatcher.sendToolResult).not.toHaveBeenCalled();
1915+expect(firstToolResultPayload(dispatcher)).toMatchObject({
1916+text: "1. Inspect code\n2. Patch code\n3. Run tests",
1917+isStatusNotice: true,
1918+});
1919+expect(dispatcher.sendToolResult).toHaveBeenCalledTimes(1);
18811920expect(dispatcher.sendFinalReply).toHaveBeenCalledWith({ text: "done" });
18821921});
18831922@@ -1915,6 +1954,11 @@ describe("dispatchReplyFromConfig", () => {
19151954explanation: "Inspect code, patch it, run tests.",
19161955steps: ["Inspect code", "Patch code", "Run tests"],
19171956});
1957+await opts?.onApprovalEvent?.({
1958+phase: "requested",
1959+status: "pending",
1960+command: "pnpm test",
1961+});
19181962return { text: "done" } satisfies ReplyPayload;
19191963};
19201964@@ -1926,7 +1970,10 @@ describe("dispatchReplyFromConfig", () => {
19261970);
19271971expect(sessionStoreMocks.loadSessionStore).not.toHaveBeenCalled();
19281972expect(sessionStoreMocks.resolveSessionStoreEntry).not.toHaveBeenCalled();
1929-expect(dispatcher.sendToolResult).not.toHaveBeenCalled();
1973+expect(firstToolResultPayload(dispatcher)).toMatchObject({
1974+text: "1. Inspect code\n2. Patch code\n3. Run tests",
1975+isStatusNotice: true,
1976+});
19301977expect(dispatcher.sendFinalReply).toHaveBeenCalledWith({ text: "done" });
19311978});
19321979@@ -2218,7 +2265,7 @@ describe("dispatchReplyFromConfig", () => {
22182265expect(dispatcher.sendFinalReply).toHaveBeenCalledWith({ text: "done" });
22192266});
222022672221-it("delivers plan progress without generic working status when verbose overrides preview suppression", async () => {
2268+it("delivers plan status when verbose overrides preview suppression", async () => {
22222269setNoAbort();
22232270sessionStoreMocks.currentEntry = {
22242271verboseLevel: "on",
@@ -2258,7 +2305,8 @@ describe("dispatchReplyFromConfig", () => {
22582305});
2259230622602307expect(dispatcher.sendToolResult).toHaveBeenNthCalledWith(1, {
2261-text: "Inspect code.\n\n1. Patch code",
2308+text: "1. Patch code",
2309+isStatusNotice: true,
22622310});
22632311expect(dispatcher.sendToolResult).toHaveBeenCalledTimes(1);
22642312expect(dispatcher.sendFinalReply).toHaveBeenCalledWith({ text: "done" });
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。