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

推荐订阅源

博客园 - 三生石上(FineUI控件)
T
Threat Research - Cisco Blogs
月光博客
月光博客
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
爱范儿
爱范儿
Hugging Face - Blog
Hugging Face - Blog
腾讯CDC
云风的 BLOG
云风的 BLOG
D
Docker
罗磊的独立博客
U
Unit 42
博客园 - 聂微东
人人都是产品经理
人人都是产品经理
P
Proofpoint News Feed
博客园 - Franky
Apple Machine Learning Research
Apple Machine Learning Research
MyScale Blog
MyScale Blog
B
Blog RSS Feed
美团技术团队
J
Java Code Geeks
S
Securelist
Cyberwarzone
Cyberwarzone
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
NISL@THU
NISL@THU
Security Latest
Security Latest
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Recorded Future
Recorded Future
Hacker News - Newest:
Hacker News - Newest: "LLM"
L
LINUX DO - 热门话题
Recent Announcements
Recent Announcements
Last Week in AI
Last Week in AI
A
About on SuperTechFans
MongoDB | Blog
MongoDB | Blog
Spread Privacy
Spread Privacy
T
Tenable Blog
I
Intezer
N
News | PayPal Newsroom
大猫的无限游戏
大猫的无限游戏
A
Arctic Wolf
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
V
V2EX - 技术
S
Schneier on Security
S
SegmentFault 最新的问题
Latest news
Latest news
宝玉的分享
宝玉的分享
V
Visual Studio Blog
V
V2EX
T
Tor Project blog
C
Comments on: Blog

Recent Commits to openclaw:main

perf(agents): avoid full setup registry for runtime aliases fix(agents): prevent embedded runtime shadowing fix(outbound): route source replies through configured channels refactor(cron): split tool and doctor repair helpers perf: reduce tui refresh work feat: default exec shell snapshots fix(ui): keep chat usable during session loading fix(cron): guard flat atMs canonicalization refactor(cron): keep runtime on canonical sqlite rows fix(codex): restore bounded recovery continuity · openclaw/openclaw@827ceb5 refactor: clean up ACP package metadata and helpers (#88659) · openclaw/openclaw@7b78941 fix(discord): ping mention-bearing final replies · openclaw/openclaw@a5d8f09 fix(telegram): preserve usage footer for tool-only replies · openclaw/openclaw@8f941ea fix(agents): avoid alias setup load for matching refs · openclaw/openclaw@b334e7e chore(ui): translate thinking default label fix(agents): preserve runtime tools in lean mode (#88381) fix(messages): use best-effort for implicit tool-only source replies … docs: raise bulk PR close threshold · openclaw/openclaw@66775c0 feat: add exec shell snapshot cache · openclaw/openclaw@c389839 fix: use typed tui empty session defaults · openclaw/openclaw@50c6519 perf: speed up tui session refresh · openclaw/openclaw@18dc6e5 fix(ci): align agent thinking default surfaces · openclaw/openclaw@9a4b631 docs: require live batch issue verification · openclaw/openclaw@832b648 ci(release): extend QA runtime parity timeout · openclaw/openclaw@d689893 ci: stabilize Testbox changed checks · openclaw/openclaw@d1bec46 fix(agents): report stale session locks without cleanup · openclaw/openclaw@7ca7712 fix(gateway): reject stale lifecycle session updates · openclaw/openclaw@fb7e217 docs(agents): require typed presentation actions · openclaw/openclaw@88c99dd fix(models): keep auth login out of main config · openclaw/openclaw@1bfae9d fix: guard stale lifecycle snapshots (#88583) fix(gateway): reject pre-reset run lifecycle events from clobbering r… · openclaw/openclaw@613f51a fix: apply ACP spawn model defaults · openclaw/openclaw@ff22b1e fix(agents): accept disabled thinking params fix(gateway): expose agent thinking defaults · openclaw/openclaw@f8f5259 ci: use normal node_modules for Blacksmith Testbox · openclaw/openclaw@d99934a fix(agents): inherit subagent thinking defaults fix(plugins): scope tool callbacks during materialization · openclaw/openclaw@643633c fix(plugins): remove redundant proxy assertion · openclaw/openclaw@82a0ba8 fix(agents): keep async media starts nonterminal · openclaw/openclaw@3ebbf9a fix(plugins): preserve wrapped tool descriptors · openclaw/openclaw@f62a22c fix(codex): let async media coexist with terminal batches fix(plugins): delegate wrapped tool properties · openclaw/openclaw@d99c824 fix(codex): clear completed dynamic tool release blockers fix(gateway): enforce OpenAI tool_choice contracts feat: add MCP code-mode namespace (#88636) fix(agents): avoid synthetic tool results during parallel races · openclaw/openclaw@44c65de fix(e2e): show plugins docker sweep progress · openclaw/openclaw@0833c68 docs: require gh comment drafts · openclaw/openclaw@f2ace9f docs: require codex source citations · openclaw/openclaw@036acbd fix(agents): release session lock on manual abort · openclaw/openclaw@95890fe docs: clarify autoreview refactor follow-up · openclaw/openclaw@a7075f3 fix(agents): scope timeout cooldowns by model · openclaw/openclaw@582fea9 test(discord): drive application id retry timer · openclaw/openclaw@d927e73 docs: strengthen review dependency inspection rules refactor: expand acp core package (#88618) · openclaw/openclaw@7dea283 fix(doctor): diagnose malformed provider catalogs · openclaw/openclaw@cc29005 fix(agents): normalize prefixed Anthropic model ids (#88587) · openclaw/openclaw@826b378 chore: bump OpenClaw version to 2026.5.31 · openclaw/openclaw@0d17623 feat(codex): add portable Codex command pickers (#82224) fix(tui): preserve pending local runs during session sync (#87959) · openclaw/openclaw@5a0e677 docs: clarify inline code comments · openclaw/openclaw@85beee6 fix(auto-reply): warn on substantive private message-tool finals · openclaw/openclaw@75e0053 fix(tui): use middle truncation for paths and commands in tool displa… · openclaw/openclaw@81b9da0 fix(webchat): suppress stale active session rows (#87962) · openclaw/openclaw@e452d16 fix(tui): skip history reload when final event has displayable output… · openclaw/openclaw@9a1b95c test(discord): isolate timer-sensitive request tests · openclaw/openclaw@5dc4531 fix(e2e): heartbeat resource-sampled docker lanes fix(auth): coerce persisted device auth tokens refactor: unify subagent handoffs into agent steering queue fix(tasks): reclaim ACP zombie runs blocking gateway restart (#88281) · openclaw/openclaw@02c7b5b test(release): wait for bundled runtime commands · openclaw/openclaw@100dd79 fix(hooks): isolate slug-generator auth failures · openclaw/openclaw@318cae1 docs: require issue summaries in agent replies · openclaw/openclaw@17c8602 docs: clarify agent workflow rules refactor(openai): confine legacy codex repair to doctor · openclaw/openclaw@7423e9c fix(auto-reply): honor per-model thinking params · openclaw/openclaw@2f7e6ec refactor(cron): keep legacy notify migration in doctor · openclaw/openclaw@b222b5f fix(exec): allow predicate shell builtins in allowlist mode · openclaw/openclaw@2fe019c test(voice-call): drive Twilio stream failure timers · openclaw/openclaw@657a668 fix(diagnostics): surface Bonjour state in support exports · openclaw/openclaw@c797f02 perf(cli): narrow gateway dispatch startup · openclaw/openclaw@32c0279 docs: tighten refactor storage policy · openclaw/openclaw@44512b5 docs: require PR review transparency · openclaw/openclaw@f1fc204 docs: clarify runtime migration boundary fix(agents): preserve reasoning replay from model metadata · openclaw/openclaw@cf315dd test(release): harden beta validation gates fix(exec): allow known safe shell builtins in allowlist mode · openclaw/openclaw@fee4e52 docs: explain per-agent model params refactor: move plugin state stores to sqlite (#88609) fix: preserve discord policy close narrowing · openclaw/openclaw@fd88f34 fix: queue subagent completion handoffs (#88613) docs(codex): clarify first-party plugin marketplaces · openclaw/openclaw@729712d docs: tighten env surface policy · openclaw/openclaw@97a97ad docs: tighten config surface policy · openclaw/openclaw@2e25400 fix(devices): refresh paired device last-seen metadata · openclaw/openclaw@703fae1 fix(agents): classify expired thinking signatures (#88340) · openclaw/openclaw@fdf8ddd fix(browser): document stable tab references (#88393) · openclaw/openclaw@3a88142 fix(discord): log gateway websocket close details · openclaw/openclaw@94b1427 chore(lint): trim remaining suppressions · openclaw/openclaw@f83886c test(release): stabilize beta validation after rebase
fix(macos): prevent duplicate menu bar icons · openclaw/openclaw@e18099b
afalk42 · 2026-05-31 · via Recent Commits to openclaw:main

@@ -39,6 +39,48 @@ enum ControlChannelError: Error, LocalizedError {

3939

}

4040

}

414142+

struct ControlChannelStateDebouncer {

43+

private let interval: TimeInterval

44+

private var lastAppliedAt: Date

45+46+

init(interval: TimeInterval = 0.5, lastAppliedAt: Date = .distantPast) {

47+

self.interval = interval

48+

self.lastAppliedAt = lastAppliedAt

49+

}

50+51+

mutating func delayBeforeApplying(

52+

currentState: ControlChannel.ConnectionState,

53+

newState: ControlChannel.ConnectionState,

54+

now: Date) -> TimeInterval?

55+

{

56+

if Self.isTerminal(currentState) || Self.isTerminal(newState) {

57+

self.lastAppliedAt = now

58+

return nil

59+

}

60+61+

let elapsed = now.timeIntervalSince(self.lastAppliedAt)

62+

guard elapsed < self.interval else {

63+

self.lastAppliedAt = now

64+

return nil

65+

}

66+67+

return self.interval - max(0, elapsed)

68+

}

69+70+

mutating func recordDeferredApply(at date: Date) {

71+

self.lastAppliedAt = date

72+

}

73+74+

private static func isTerminal(_ state: ControlChannel.ConnectionState) -> Bool {

75+

switch state {

76+

case .connected, .disconnected:

77+

true

78+

case .connecting, .degraded:

79+

false

80+

}

81+

}

82+

}

83+4284

@MainActor

4385

@Observable

4486

final class ControlChannel {

@@ -85,6 +127,46 @@ final class ControlChannel {

85127

private var recoveryTask: Task<Void, Never>?

86128

private var lastRecoveryAt: Date?

87129130+

// Coalesce rapid connecting/degraded oscillations so SwiftUI does not churn

131+

// MenuBarExtra status items while the gateway connection is unstable.

132+

private var pendingStateTask: Task<Void, Never>?

133+

private var stateDebouncer = ControlChannelStateDebouncer()

134+135+

private func setStateThrottled(_ newState: ConnectionState) {

136+

let now = Date()

137+

if let delay = self.stateDebouncer.delayBeforeApplying(

138+

currentState: self.state,

139+

newState: newState,

140+

now: now)

141+

{

142+

self.pendingStateTask?.cancel()

143+

self.pendingStateTask = Task { [weak self] in

144+

try? await Task.sleep(nanoseconds: Self.nanoseconds(for: delay))

145+

guard let self, !Task.isCancelled else { return }

146+

self.pendingStateTask = nil

147+

self.stateDebouncer.recordDeferredApply(at: Date())

148+

self.applyState(newState)

149+

}

150+

return

151+

}

152+153+

self.cancelPendingStateTask()

154+

self.applyState(newState)

155+

}

156+157+

private func cancelPendingStateTask() {

158+

self.pendingStateTask?.cancel()

159+

self.pendingStateTask = nil

160+

}

161+162+

private func applyState(_ newState: ConnectionState) {

163+

self.state = newState

164+

}

165+166+

private static func nanoseconds(for interval: TimeInterval) -> UInt64 {

167+

UInt64(max(0, interval) * 1_000_000_000)

168+

}

169+88170

private init() {

89171

self.startEventStream()

90172

}

@@ -105,32 +187,32 @@ final class ControlChannel {

105187

self.logger.info(

106188

"control channel configure mode=remote " +

107189

"target=\(target, privacy: .public) identitySet=\(idSet, privacy: .public)")

108-

self.state = .connecting

190+

self.setStateThrottled(.connecting)

109191

_ = try await GatewayEndpointStore.shared.ensureRemoteControlTunnel()

110192

await self.refreshEndpoint(reason: "configure")

111193

} catch {

112-

self.state = .degraded(error.localizedDescription)

194+

self.setStateThrottled(.degraded(error.localizedDescription))

113195

throw error

114196

}

115197

}

116198

}

117199118200

func refreshEndpoint(reason: String) async {

119201

self.logger.info("control channel refresh endpoint reason=\(reason, privacy: .public)")

120-

self.state = .connecting

202+

self.setStateThrottled(.connecting)

121203

do {

122204

try await self.establishGatewayConnection()

123-

self.state = .connected

205+

self.setStateThrottled(.connected)

124206

PresenceReporter.shared.sendImmediate(reason: "connect")

125207

} catch {

126208

let message = self.friendlyGatewayMessage(error)

127-

self.state = .degraded(message)

209+

self.setStateThrottled(.degraded(message))

128210

}

129211

}

130212131213

func disconnect() async {

132214

await GatewayConnection.shared.shutdown()

133-

self.state = .disconnected

215+

self.setStateThrottled(.disconnected)

134216

self.lastPingMs = nil

135217

self.authSourceLabel = nil

136218

}

@@ -146,11 +228,11 @@ final class ControlChannel {

146228

let payload = try await self.request(method: "health", params: params, timeoutMs: timeoutMs)

147229

let ms = Date().timeIntervalSince(start) * 1000

148230

self.lastPingMs = ms

149-

self.state = .connected

231+

self.setStateThrottled(.connected)

150232

return payload

151233

} catch {

152234

let message = self.friendlyGatewayMessage(error)

153-

self.state = .degraded(message)

235+

self.setStateThrottled(.degraded(message))

154236

throw ControlChannelError.badResponse(message)

155237

}

156238

}

@@ -173,11 +255,11 @@ final class ControlChannel {

173255

method: method,

174256

params: rawParams,

175257

timeoutMs: timeoutMs)

176-

self.state = .connected

258+

self.setStateThrottled(.connected)

177259

return data

178260

} catch {

179261

let message = self.friendlyGatewayMessage(error)

180-

self.state = .degraded(message)

262+

self.setStateThrottled(.degraded(message))

181263

throw ControlChannelError.badResponse(message)

182264

}

183265

}

@@ -386,9 +468,9 @@ final class ControlChannel {

386468

NotificationCenter.default.post(name: .controlHeartbeat, object: data)

387469

}

388470

case let .event(evt) where evt.event == "shutdown":

389-

self.state = .degraded("gateway shutdown")

471+

self.setStateThrottled(.degraded("gateway shutdown"))

390472

case .snapshot:

391-

self.state = .connected

473+

self.setStateThrottled(.connected)

392474

default:

393475

break

394476

}