























@@ -298,6 +298,44 @@ describe("runEmbeddedPiAgent incomplete-turn safety", () => {
298298);
299299});
300300301+it("returns NO_REPLY without retrying reasoning-only assistant turns when silence is allowed", async () => {
302+mockedClassifyFailoverReason.mockReturnValue(null);
303+mockedRunEmbeddedAttempt.mockResolvedValueOnce(
304+makeAttemptResult({
305+assistantTexts: [],
306+lastAssistant: {
307+role: "assistant",
308+stopReason: "end_turn",
309+provider: "openai-codex",
310+model: "gpt-5.5",
311+content: [
312+{
313+type: "thinking",
314+thinking: "internal reasoning",
315+thinkingSignature: JSON.stringify({ id: "rs_silent_group", type: "reasoning" }),
316+},
317+],
318+} as unknown as EmbeddedRunAttemptResult["lastAssistant"],
319+}),
320+);
321+322+const result = await runEmbeddedPiAgent({
323+ ...overflowBaseRunParams,
324+allowEmptyAssistantReplyAsSilent: true,
325+provider: "openai-codex",
326+model: "gpt-5.5",
327+runId: "run-reasoning-only-silent",
328+});
329+330+expect(mockedRunEmbeddedAttempt).toHaveBeenCalledTimes(1);
331+expect(mockedLog.warn).not.toHaveBeenCalledWith(
332+expect.stringContaining("reasoning-only assistant turn detected"),
333+);
334+expect(result.payloads).toEqual([{ text: "NO_REPLY" }]);
335+expect(result.meta.terminalReplyKind).toBe("silent-empty");
336+expect(result.meta.livenessState).toBe("working");
337+});
338+301339it("does not retry or warn on reasoning-only turns when a messaging tool already delivered", async () => {
302340mockedClassifyFailoverReason.mockReturnValue(null);
303341mockedRunEmbeddedAttempt.mockResolvedValueOnce(
@@ -1184,6 +1222,44 @@ describe("runEmbeddedPiAgent incomplete-turn safety", () => {
11841222).toBe(false);
11851223});
118612241225+it("treats reasoning-only assistant turns as silent only when the caller allows it", () => {
1226+const attempt = makeAttemptResult({
1227+assistantTexts: [],
1228+lastAssistant: {
1229+role: "assistant",
1230+stopReason: "end_turn",
1231+provider: "openai-codex",
1232+model: "gpt-5.5",
1233+content: [
1234+{
1235+type: "thinking",
1236+thinking: "internal reasoning",
1237+thinkingSignature: JSON.stringify({ id: "rs_silent_helper", type: "reasoning" }),
1238+},
1239+],
1240+} as unknown as EmbeddedRunAttemptResult["lastAssistant"],
1241+});
1242+1243+expect(
1244+shouldTreatEmptyAssistantReplyAsSilent({
1245+allowEmptyAssistantReplyAsSilent: true,
1246+payloadCount: 0,
1247+aborted: false,
1248+timedOut: false,
1249+ attempt,
1250+}),
1251+).toBe(true);
1252+expect(
1253+shouldTreatEmptyAssistantReplyAsSilent({
1254+allowEmptyAssistantReplyAsSilent: false,
1255+payloadCount: 0,
1256+aborted: false,
1257+timedOut: false,
1258+ attempt,
1259+}),
1260+).toBe(false);
1261+});
1262+11871263it("does not treat error or side-effect empty turns as silent", () => {
11881264const errorAttempt = makeAttemptResult({
11891265assistantTexts: [],
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。