mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 08:00:42 +00:00
fix(gateway): surface clean channel exits
This commit is contained in:
@@ -28,6 +28,7 @@ Docs: https://docs.openclaw.ai
|
||||
### Fixes
|
||||
|
||||
- CLI/status: show skipped fast-path memory checks as `not checked` and report active custom memory plugin runtime status from `status --json --all` without requiring built-in `agents.defaults.memorySearch`, so plugins such as memory-lancedb-pro and memory-cms no longer look unavailable when their own runtime is healthy. Fixes #56968. Thanks @Tony-ooo and @aderius.
|
||||
- Gateway/channels: record and log unexpected clean channel monitor exits so channels that return without throwing no longer appear stopped with no error. Fixes #73099. Thanks @balaji1968-kingler.
|
||||
- Memory/LanceDB: let embedding config use provider-backed auth profiles, environment credentials, or provider config without a separate plugin `embedding.apiKey`, so OAuth-capable embedding providers can power auto-recall/capture. Fixes #68950. Thanks @malshaalan-ai.
|
||||
- Plugins/hooks: time out never-settling `agent_end` observation hooks after 30 seconds and log the plugin failure, so hung embedding endpoints no longer leave memory capture silently pending forever. Fixes #65544. Thanks @ghoc0099.
|
||||
- Gateway/config: serve runtime config schemas from the current plugin metadata snapshot and generated bundled channel schema metadata instead of rebuilding plugin channel config modules on every `config.get`/`config.schema`, preventing idle plugin-discovery CPU churn after upgrades. Fixes #73088. Thanks @sleitor and @geovansb.
|
||||
|
||||
@@ -186,11 +186,47 @@ describe("server-channels auto restart", () => {
|
||||
const account = snapshot.channelAccounts.discord?.[DEFAULT_ACCOUNT_ID];
|
||||
expect(account?.running).toBe(false);
|
||||
expect(account?.reconnectAttempts).toBe(11);
|
||||
expect(account?.lastError).toBe("channel exited without an error");
|
||||
|
||||
await vi.advanceTimersByTimeAsync(200);
|
||||
expect(startAccount).toHaveBeenCalledTimes(11);
|
||||
});
|
||||
|
||||
it("records a clean channel monitor exit before auto-restart", async () => {
|
||||
const startAccount = vi.fn(async () => {});
|
||||
installTestRegistry(createTestPlugin({ startAccount }));
|
||||
const manager = createManager();
|
||||
|
||||
await manager.startChannels();
|
||||
await vi.advanceTimersByTimeAsync(0);
|
||||
|
||||
const snapshot = manager.getRuntimeSnapshot();
|
||||
const account = snapshot.channelAccounts.discord?.[DEFAULT_ACCOUNT_ID];
|
||||
expect(startAccount).toHaveBeenCalled();
|
||||
expect(account?.running).toBe(false);
|
||||
expect(account?.restartPending).toBe(true);
|
||||
expect(account?.lastError).toBe("channel exited without an error");
|
||||
});
|
||||
|
||||
it("does not record a clean-exit error for manual abort stops", async () => {
|
||||
const startAccount = vi.fn(
|
||||
async ({ abortSignal }: { abortSignal: AbortSignal }) =>
|
||||
await new Promise<void>((resolve) => {
|
||||
abortSignal.addEventListener("abort", () => resolve(), { once: true });
|
||||
}),
|
||||
);
|
||||
installTestRegistry(createTestPlugin({ startAccount }));
|
||||
const manager = createManager();
|
||||
|
||||
await manager.startChannels();
|
||||
await manager.stopChannel("discord", DEFAULT_ACCOUNT_ID);
|
||||
|
||||
const snapshot = manager.getRuntimeSnapshot();
|
||||
const account = snapshot.channelAccounts.discord?.[DEFAULT_ACCOUNT_ID];
|
||||
expect(account?.running).toBe(false);
|
||||
expect(account?.lastError).toBeNull();
|
||||
});
|
||||
|
||||
it("does not auto-restart after manual stop during backoff", async () => {
|
||||
const startAccount = vi.fn(async () => {});
|
||||
installTestRegistry(
|
||||
|
||||
@@ -509,6 +509,14 @@ export function createChannelManager(opts: ChannelManagerOptions): ChannelManage
|
||||
),
|
||||
);
|
||||
const trackedPromise = task
|
||||
.then(() => {
|
||||
if (abort.signal.aborted || manuallyStopped.has(rKey)) {
|
||||
return;
|
||||
}
|
||||
const message = "channel exited without an error";
|
||||
setRuntime(channelId, id, { accountId: id, lastError: message });
|
||||
log.error?.(`[${id}] ${message}`);
|
||||
})
|
||||
.catch((err) => {
|
||||
const message = formatErrorMessage(err);
|
||||
setRuntime(channelId, id, { accountId: id, lastError: message });
|
||||
|
||||
Reference in New Issue
Block a user