mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 07:10:43 +00:00
fix(daemon): harden launchd restart handoff (#71409)
This commit is contained in:
@@ -81,6 +81,7 @@ Docs: https://docs.openclaw.ai
|
||||
### Fixes
|
||||
|
||||
- Discord/cron: deliver text-only isolated cron and heartbeat announce output from the canonical final assistant text once, avoiding duplicate Discord posts when streamed block payloads and the final answer contain the same content. Fixes #71406. Thanks @alexgross21.
|
||||
- macOS Gateway: wait for launchd to reload the exited Gateway LaunchAgent before bootstrapping repair fallback, preventing config-triggered restarts from leaving the service not loaded. Fixes #45178. Thanks @vincentkoc.
|
||||
- Control UI/WebChat: hide heartbeat prompts, `HEARTBEAT_OK` acknowledgments, and internal-only runtime context turns from visible chat history while leaving the underlying transcript intact. Fixes #71381. Thanks @gerald1950ggg-ai.
|
||||
- Control UI/chat: keep optimistic user and assistant tail messages visible when a final history refresh briefly returns an older snapshot, preventing message cards from flash-disappearing until the next refresh. Fixes #71371. Thanks @WolvenRA.
|
||||
- Talk/TTS: resolve configured extension speech providers from the active runtime registry before provider-list discovery, so Talk mode no longer rejects valid plugin speech providers as unsupported.
|
||||
|
||||
@@ -63,6 +63,11 @@ describe("scheduleDetachedLaunchdRestartHandoff", () => {
|
||||
|
||||
const [, args] = spawnMock.mock.calls[0] as [string, string[]];
|
||||
expect(args[7]).toBe("ai.openclaw.gateway");
|
||||
expect(args[1]).toContain('if launchctl print "$service_target" >/dev/null 2>&1; then');
|
||||
expect(args[1]).toContain("reason=launchd-auto-reload");
|
||||
expect(args[1]).toContain("print_retry_count=$((print_retry_count - 1))");
|
||||
expect(args[1]).toContain("sleep 0.2");
|
||||
expect(args[1]).toContain('if launchctl bootstrap "$domain" "$plist_path"; then');
|
||||
expect(args[1]).toContain('if launchctl start "$label"; then');
|
||||
expect(args[1]).not.toContain('basename "$service_target"');
|
||||
});
|
||||
|
||||
@@ -22,6 +22,9 @@ export type LaunchdRestartTarget = {
|
||||
serviceTarget: string;
|
||||
};
|
||||
|
||||
const START_AFTER_EXIT_PRINT_RETRY_COUNT = 15;
|
||||
const START_AFTER_EXIT_PRINT_RETRY_DELAY_SECONDS = 0.2;
|
||||
|
||||
function assertValidLaunchAgentLabel(label: string): string {
|
||||
const trimmed = label.trim();
|
||||
if (!/^[A-Za-z0-9._-]+$/.test(trimmed)) {
|
||||
@@ -116,28 +119,36 @@ exit "$status"
|
||||
`;
|
||||
}
|
||||
|
||||
const verifyLaunchdReload = `print_retry_count="${START_AFTER_EXIT_PRINT_RETRY_COUNT}"
|
||||
while [ "$print_retry_count" -gt 0 ]; do
|
||||
if launchctl print "$service_target" >/dev/null 2>&1; then
|
||||
printf '[%s] openclaw restart done source=launchd-handoff mode=${mode} reason=launchd-auto-reload\\n' "$(date -u +%FT%TZ)" >&2
|
||||
exit 0
|
||||
fi
|
||||
print_retry_count=$((print_retry_count - 1))
|
||||
sleep ${START_AFTER_EXIT_PRINT_RETRY_DELAY_SECONDS}
|
||||
done
|
||||
`;
|
||||
|
||||
// Restart is explicit operator intent; undo any previous `launchctl disable`.
|
||||
return `service_target="$1"
|
||||
domain="$2"
|
||||
plist_path="$3"
|
||||
${waitForCallerPid}
|
||||
${verifyLaunchdReload}
|
||||
status=0
|
||||
launchctl enable "$service_target"
|
||||
if launchctl start "$label"; then
|
||||
status=0
|
||||
else
|
||||
status=$?
|
||||
if launchctl bootstrap "$domain" "$plist_path"; then
|
||||
if launchctl start "$label"; then
|
||||
status=0
|
||||
else
|
||||
launchctl kickstart -k "$service_target"
|
||||
status=$?
|
||||
fi
|
||||
if launchctl bootstrap "$domain" "$plist_path"; then
|
||||
if launchctl start "$label"; then
|
||||
status=0
|
||||
else
|
||||
launchctl kickstart -k "$service_target"
|
||||
status=$?
|
||||
fi
|
||||
else
|
||||
status=$?
|
||||
launchctl kickstart -k "$service_target"
|
||||
status=$?
|
||||
fi
|
||||
if [ "$status" -eq 0 ]; then
|
||||
printf '[%s] openclaw restart done source=launchd-handoff mode=${mode}\\n' "$(date -u +%FT%TZ)" >&2
|
||||
|
||||
Reference in New Issue
Block a user