惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

The GitHub Blog
The GitHub Blog
A
About on SuperTechFans
The Cloudflare Blog
G
Google Developers Blog
博客园_首页
Martin Fowler
Martin Fowler
Apple Machine Learning Research
Apple Machine Learning Research
L
LangChain Blog
D
Docker
C
Check Point Blog
T
Tailwind CSS Blog
博客园 - 司徒正美
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Hugging Face - Blog
Hugging Face - Blog
Microsoft Security Blog
Microsoft Security Blog
V
V2EX
博客园 - 叶小钗
T
The Blog of Author Tim Ferriss
酷 壳 – CoolShell
酷 壳 – CoolShell
IT之家
IT之家
M
MIT News - Artificial intelligence
Microsoft Azure Blog
Microsoft Azure Blog
博客园 - 【当耐特】
GbyAI
GbyAI

Recent Commits to openclaw:main

test: merge chat side-result checks · openclaw/openclaw@ddd2c2a test: merge cron history checks · openclaw/openclaw@f7eb746 test: merge responsive navigation shell checks · openclaw/openclaw@c2e4b47 docs(changelog): add codex oauth fixes · openclaw/openclaw@628e6cd test: merge navigation routing cases · openclaw/openclaw@5d8cecb Tests: mock channel registry bundled fallback · openclaw/openclaw@2b08233 Secrets: avoid broad web search discovery for single plugin config · openclaw/openclaw@a464f59 test: merge config view browser checks · openclaw/openclaw@20cf511 fix(status): align oauth health with runtime · openclaw/openclaw@eed7116 feat: add macOS screen snapshots for monitor preview (#67954) thanks … · openclaw/openclaw@f377db1 fix: report shared auth scopes in hello-ok (#67810) thanks @BunsDev · openclaw/openclaw@0b6c39b Auto-reply: avoid eager bundled route fallback · openclaw/openclaw@3ea1bf4 Tests: narrow session binding contract setup · openclaw/openclaw@54e4e16 fix(macOS): enable undo/redo in webchat composer text input (#34962) · openclaw/openclaw@00951dc Tests: speed up channel setup promotion · openclaw/openclaw@82b529a Docs: refresh agent instructions · openclaw/openclaw@5775fe2 fix(auth): serialize OAuth refresh across agents to fix #26322 (#67876) · openclaw/openclaw@8e79080 test: allow ollama public surface boundary test · openclaw/openclaw@7d4f1a6 Docs: add test performance guardrails · openclaw/openclaw@89706d3 Tests: restore context-engine usage proof · openclaw/openclaw@e4c4f95 Tests: slim context engine runtime coverage · openclaw/openclaw@74c198f ci: retry failed custom checkouts · openclaw/openclaw@0ee5baf test: trim duplicate provider auth onboarding cases · openclaw/openclaw@1ffc02e matrix: fix sessions_spawn --thread subagent session spawning (#67643) · openclaw/openclaw@1ce2596 test: reduce auth choice fixture churn · openclaw/openclaw@857b9cd test: mock health status config boundaries · openclaw/openclaw@9d5ab4a test: mock onboard config io boundary · openclaw/openclaw@299694d test: mock legacy state plugin boundaries · openclaw/openclaw@2713089 test: mock channel install boundaries · openclaw/openclaw@b945248 test: mock doctor preview channel boundaries · openclaw/openclaw@b1a3ad4
fix(agents): accept silent no-reply turns · openclaw/open...
steipete · 2026-04-23 · via Recent Commits to openclaw:main
Original file line numberDiff line numberDiff line change

@@ -22,6 +22,7 @@ Docs: https://docs.openclaw.ai

2222

- Gateway/restart: preserve group and channel chat context when resuming an agent turn after a Gateway restart, so continuation replies keep the same prompt, routing, and tool-status behavior as the original conversation.

2323

- Gateway/pairing: shared-secret loopback CLI clients now silently auto-approve `metadata-upgrade` pairing (platform / device family refresh) instead of being disconnected with `1008 pairing required`. This matches the scope-upgrade and role-upgrade behavior added in #69431 and unblocks non-interactive CLI automation when a paired-device record has a stale platform string (e.g. device key replicated across hosts, install migrated between OSes, or platform-string format changed between OpenClaw versions). Browser / Control-UI clients keep the existing approval-required flow for metadata changes.

2424

- Gateway/pairing: treat any forwarded-header evidence (`Forwarded`, `X-Forwarded-*`, or `X-Real-IP`) as proxied WebSocket traffic before pairing locality checks, so reverse-proxy topologies cannot use the loopback shared-secret helper auto-pairing path.

25+

- Agents/OpenAI: treat exact `NO_REPLY` assistant output as a deliberate silent reply in embedded runs, so GPT-5.4 turns with signed reasoning plus a silent final no longer surface a false incomplete-turn error.

2526

- Gateway/pairing webchat: render `/pair qr` replies as structured media instead of raw markdown text, preserve inline reply threading and silent-control handling on media replies, avoid persisting sensitive QR images into transcript history, and keep local webchat media embedding behind internal-only trust markers. (#70047) Thanks @BunsDev.

2627

- Codex harness: default app-server runs to unchained local execution, so OpenAI heartbeats can use network and shell tools without stalling behind native Codex approvals or the workspace-write sandbox.

2728

- Codex harness: apply the GPT-5 behavior and heartbeat prompt overlay to native Codex app-server runs, so `codex/gpt-5.x` sessions get the same follow-through, tool-use, and proactive heartbeat guidance as OpenAI GPT-5 runs.

Original file line numberDiff line numberDiff line change

@@ -23,6 +23,7 @@ import {

2323

resolveEmptyResponseRetryInstruction,

2424

resolvePlanningOnlyRetryLimit,

2525

resolvePlanningOnlyRetryInstruction,

26+

resolveIncompleteTurnPayloadText,

2627

resolveReasoningOnlyRetryInstruction,

2728

STRICT_AGENTIC_BLOCKED_TEXT,

2829

resolveReplayInvalidFlag,

@@ -732,6 +733,34 @@ describe("runEmbeddedPiAgent incomplete-turn safety", () => {

732733

expect(retryInstruction).toBe(REASONING_ONLY_RETRY_INSTRUCTION);

733734

});

734735
736+

it("treats exact NO_REPLY as a deliberate silent assistant reply", () => {

737+

const incompleteTurnText = resolveIncompleteTurnPayloadText({

738+

payloadCount: 0,

739+

aborted: false,

740+

timedOut: false,

741+

attempt: makeAttemptResult({

742+

assistantTexts: ["NO_REPLY"],

743+

lastAssistant: {

744+

role: "assistant",

745+

stopReason: "stop",

746+

provider: "openai",

747+

model: "gpt-5.4",

748+

content: [

749+

{

750+

type: "thinking",

751+

thinking: "internal reasoning",

752+

thinkingSignature: JSON.stringify({ id: "rs_no_reply", type: "reasoning" }),

753+

},

754+

{ type: "text", text: "" },

755+

{ type: "text", text: "NO_REPLY" },

756+

],

757+

} as unknown as EmbeddedRunAttemptResult["lastAssistant"],

758+

}),

759+

});

760+
761+

expect(incompleteTurnText).toBeNull();

762+

});

763+
735764

it("does not retry reasoning-only GPT turns after side effects", () => {

736765

const retryInstruction = resolveReasoningOnlyRetryInstruction({

737766

provider: "openai",

Original file line numberDiff line numberDiff line change

@@ -1,4 +1,5 @@

11

import type { AgentMessage } from "@mariozechner/pi-agent-core";

2+

import { isSilentReplyPayloadText, SILENT_REPLY_TOKEN } from "../../../auto-reply/tokens.js";

23

import type { EmbeddedPiExecutionContract } from "../../../config/types.agent-defaults.js";

34

import { normalizeLowercaseStringOrEmpty } from "../../../shared/string-coerce.js";

45

import { isStrictAgenticSupportedProviderModel } from "../../execution-contract.js";

@@ -173,6 +174,10 @@ export function resolveIncompleteTurnPayloadText(params: {

173174

return null;

174175

}

175176
177+

if (hasOnlySilentAssistantReply(params.attempt.assistantTexts)) {

178+

return null;

179+

}

180+
176181

const stopReason = params.attempt.lastAssistant?.stopReason;

177182

const incompleteTerminalAssistant = isIncompleteTerminalAssistantTurn({

178183

hasAssistantVisibleText: params.payloadCount > 0,

@@ -199,6 +204,14 @@ export function resolveIncompleteTurnPayloadText(params: {

199204

: "⚠️ Agent couldn't generate a response. Please try again.";

200205

}

201206
207+

function hasOnlySilentAssistantReply(assistantTexts: readonly string[]): boolean {

208+

const nonEmptyTexts = assistantTexts.filter((text) => text.trim().length > 0);

209+

return (

210+

nonEmptyTexts.length > 0 &&

211+

nonEmptyTexts.every((text) => isSilentReplyPayloadText(text, SILENT_REPLY_TOKEN))

212+

);

213+

}

214+
202215

export function resolveReplayInvalidFlag(params: {

203216

attempt: RunLivenessAttempt;

204217

incompleteTurnText?: string | null;