mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-23 03:18:11 +00:00
fix: recover telegram polling after runner stop (#26447) (thanks @theclawdaddy)
This commit is contained in:
@@ -14,6 +14,7 @@ Docs: https://docs.openclaw.ai
|
||||
### Fixes
|
||||
|
||||
- Agents/Subagents delivery: refactor subagent completion announce dispatch into an explicit queue/direct/fallback state machine, recover outbound channel-plugin resolution in cold/stale plugin-registry states across announce/message/gateway send paths, finalize cleanup bookkeeping when announce flow rejects, and treat Telegram sends without `message_id` as delivery failures (instead of false-success `"unknown"` IDs). (#26867, #25961, #26803, #25069, #26741) Thanks @SmithLabsLLC and @docaohieu2808.
|
||||
- Telegram/Polling: keep the polling monitor alive when the grammY runner stops unexpectedly under an active gateway abort lifecycle, auto-restarting with backoff instead of exiting silently. (#26447) Thanks @theclawdaddy.
|
||||
- Slack/Session threads: prevent oversized parent-session inheritance from silently bricking new thread sessions, surface embedded context-overflow empty-result failures to users, and add configurable `session.parentForkMaxTokens` (default `100000`, `0` disables). (#26912) Thanks @markshields-tl.
|
||||
- Security/Signal: enforce DM/group authorization before reaction-only notification enqueue so unauthorized senders can no longer inject Signal reaction system events under `dmPolicy`/`groupPolicy`; reaction notifications now require channel access checks first. This ships in the next npm release (`2026.2.25`). Thanks @tdjackey for reporting.
|
||||
- Security/Discord + Slack reactions: enforce DM policy/allowlist authorization before reaction-event system enqueue in direct messages; Discord reaction handling now also honors DM/group-DM enablement and guild `groupPolicy` channel gating to keep reaction ingress aligned with normal message preflight. This ships in the next npm release (`2026.2.25`). Thanks @tdjackey for reporting.
|
||||
|
||||
@@ -45,6 +45,7 @@ vi.mock("../../commands/agent.js", () => ({
|
||||
|
||||
vi.mock("../../config/config.js", () => ({
|
||||
loadConfig: () => mocks.loadConfigReturn,
|
||||
STATE_DIR: "/tmp/openclaw-test-state",
|
||||
}));
|
||||
|
||||
vi.mock("../../agents/agent-scope.js", () => ({
|
||||
|
||||
@@ -229,6 +229,30 @@ describe("monitorTelegramProvider (grammY)", () => {
|
||||
expect(runSpy).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it("restarts polling when runner stops unexpectedly under active abort signal", async () => {
|
||||
const abort = new AbortController();
|
||||
runSpy
|
||||
.mockImplementationOnce(() => ({
|
||||
task: () => Promise.resolve(),
|
||||
stop: vi.fn(),
|
||||
isRunning: (): boolean => false,
|
||||
}))
|
||||
.mockImplementationOnce(() => ({
|
||||
task: () => {
|
||||
abort.abort();
|
||||
return Promise.resolve();
|
||||
},
|
||||
stop: vi.fn(),
|
||||
isRunning: (): boolean => false,
|
||||
}));
|
||||
|
||||
await monitorTelegramProvider({ token: "tok", abortSignal: abort.signal });
|
||||
|
||||
expect(computeBackoff).toHaveBeenCalled();
|
||||
expect(sleepWithAbort).toHaveBeenCalled();
|
||||
expect(runSpy).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it("deletes webhook before starting polling", async () => {
|
||||
const order: string[] = [];
|
||||
api.deleteWebhook.mockReset();
|
||||
|
||||
@@ -45,10 +45,8 @@ export function createTelegramRunnerOptions(cfg: OpenClawConfig): RunOptions<unk
|
||||
},
|
||||
// Suppress grammY getUpdates stack traces; we log concise errors ourselves.
|
||||
silent: true,
|
||||
// Retry transient failures before surfacing errors. Use a generous
|
||||
// window so the runner survives prolonged outages (e.g. scheduled
|
||||
// internet downtime) without the outer loop needing to restart it.
|
||||
maxRetryTime: 60 * 60 * 1000,
|
||||
// Retry transient failures for a limited window before surfacing errors.
|
||||
maxRetryTime: 5 * 60 * 1000,
|
||||
retryInterval: "exponential",
|
||||
},
|
||||
};
|
||||
@@ -279,7 +277,7 @@ export async function monitorTelegramProvider(opts: MonitorTelegramOpts = {}) {
|
||||
try {
|
||||
// runner.task() returns a promise that resolves when the runner stops
|
||||
await runner.task();
|
||||
if (opts.abortSignal?.aborted) {
|
||||
if ((!opts.abortSignal || opts.abortSignal.aborted) && !forceRestarted) {
|
||||
return;
|
||||
}
|
||||
// The runner stopped on its own. This can happen when grammY's
|
||||
|
||||
Reference in New Issue
Block a user