mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 07:30:43 +00:00
fix(cli): keep empty agent replies silent
* fix(cli): keep empty agent replies silent * fix(commands): preserve empty gateway status summaries --------- Co-authored-by: Peter Steinberger <steipete@steipete-macstudio.local> Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
This commit is contained in:
committed by
GitHub
parent
c7bbb3f9af
commit
95cee64ca6
@@ -20,6 +20,7 @@ Docs: https://docs.openclaw.ai
|
||||
### Fixes
|
||||
|
||||
- Agents/sessions: keep delayed `sessions_send` A2A replies alive after soft wait-window timeouts, while preserving terminal run timeouts and avoiding stale target replies in requester sessions. Fixes #76443. Thanks @ryswork1993 and @vincentkoc.
|
||||
- CLI/sessions: keep intentional empty agent replies silent after tool-delivered channel output, instead of surfacing a misleading "No reply from agent." fallback. Thanks @vincentkoc.
|
||||
- Config/doctor: cap `.clobbered.*` forensic snapshots per config path and serialize snapshot writes so repeated `doctor --fix` recovery loops cannot flood the config directory. Fixes #76454; carries forward #65649. Thanks @JUSTICEESSIELP, @rsnow, and @vincentkoc.
|
||||
- Feishu: suppress duplicate text when replies send native voice media while preserving captions for ordinary audio files and falling back to text plus attachment links when voice uploads fail.
|
||||
- Feishu: keep packaged Feishu startup from bundling the Lark SDK's ESM `__dirname` path by loading the SDK as a plugin-local runtime dependency. Fixes #76291 and #76494. (#76392) Thanks @zqchris.
|
||||
|
||||
@@ -350,7 +350,6 @@ export async function deliverAgentCommandResult(params: {
|
||||
}
|
||||
|
||||
if (!payloads || payloads.length === 0) {
|
||||
runtime.log("No reply from agent.");
|
||||
return { payloads: [], meta: resultMeta };
|
||||
}
|
||||
|
||||
|
||||
@@ -147,6 +147,42 @@ describe("agentCliCommand", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("stays silent when the gateway returns an intentional empty reply", async () => {
|
||||
await withTempStore(async () => {
|
||||
callGateway.mockResolvedValue({
|
||||
runId: "idem-1",
|
||||
status: "ok",
|
||||
summary: "completed",
|
||||
result: {
|
||||
payloads: [],
|
||||
meta: { stub: true },
|
||||
},
|
||||
});
|
||||
|
||||
await agentCliCommand({ message: "hi", to: "+1555" }, runtime);
|
||||
|
||||
expect(runtime.log).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
it("logs non-ok gateway summaries when payloads are empty", async () => {
|
||||
await withTempStore(async () => {
|
||||
callGateway.mockResolvedValue({
|
||||
runId: "idem-1",
|
||||
status: "timeout",
|
||||
summary: "aborted",
|
||||
result: {
|
||||
payloads: [],
|
||||
meta: { aborted: true },
|
||||
},
|
||||
});
|
||||
|
||||
await agentCliCommand({ message: "hi", to: "+1555" }, runtime);
|
||||
|
||||
expect(runtime.log).toHaveBeenCalledWith("aborted");
|
||||
});
|
||||
});
|
||||
|
||||
it("passes model overrides through gateway requests", async () => {
|
||||
await withTempStore(async () => {
|
||||
mockGatewaySuccessReply();
|
||||
|
||||
@@ -201,7 +201,9 @@ async function agentViaGatewayCommand(opts: AgentCliOpts, runtime: RuntimeEnv) {
|
||||
const payloads = result?.payloads ?? [];
|
||||
|
||||
if (payloads.length === 0) {
|
||||
runtime.log(response?.summary ? response.summary : "No reply from agent.");
|
||||
if (response?.status !== "ok") {
|
||||
runtime.log(response?.summary ? response.summary : "No reply from agent.");
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
@@ -378,6 +378,16 @@ describe("agentCommand ACP runtime routing", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("keeps no-reply ACP turns silent", async () => {
|
||||
await withAcpSessionEnv(async () => {
|
||||
const { assistantEvents, logLines } = await runAcpTurnWithAssistantEvents(["NO_REPLY"]);
|
||||
|
||||
expect(assistantEvents.map((event) => event.text).filter(Boolean)).toEqual([]);
|
||||
expect(logLines.some((line) => line.includes("NO_REPLY"))).toBe(false);
|
||||
expect(logLines).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
it("fails closed for ACP-shaped session keys missing ACP metadata", async () => {
|
||||
await withTempHome(async (home) => {
|
||||
const storePath = path.join(home, "sessions.json");
|
||||
|
||||
@@ -200,6 +200,21 @@ describe("deliverAgentCommandResult", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("stays silent for intentional empty payloads", async () => {
|
||||
const runtime = createRuntime();
|
||||
|
||||
await runDelivery({
|
||||
opts: {
|
||||
message: "hello",
|
||||
},
|
||||
runtime,
|
||||
payloads: [],
|
||||
});
|
||||
|
||||
expect(runtime.log).not.toHaveBeenCalled();
|
||||
expect(mocks.deliverOutboundPayloads).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("uses runContext turn source over stale session last route", async () => {
|
||||
await runDelivery({
|
||||
opts: {
|
||||
|
||||
Reference in New Issue
Block a user