mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-29 17:35:13 +00:00
fix(channels): pass allowBootstrap from channel-selection so in-agent message tool resolves channels in --local processes (#85022)
Summary: - The branch passes `allowBootstrap: true` through outbound channel selection, preserves bundled-plugin resolution before bootstrap, adds focused regression tests, and documents the fix in the changelog. - Reproducibility: yes. source inspection gives a high-confidence reproduction path: current main omits `allow ... run the live current-main failure, but the supplied after-fix terminal proof exercises the implicated path. Automerge notes: - PR branch already contained follow-up commit before automerge: test(channels): cover bootstrap channel selection - PR branch already contained follow-up commit before automerge: fix(channels): avoid unnecessary bootstrap during message sends - PR branch already contained follow-up commit before automerge: fix(channels): pass allowBootstrap from channel-selection so in-agent… Validation: - ClawSweeper review passed for head44099a80e8. - Required merge gates passed before the squash merge. Prepared head SHA:44099a80e8Review: https://github.com/openclaw/openclaw/pull/85022#issuecomment-4510333662 Co-authored-by: Kaspre <kaspre@gmail.com> Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com> Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com> Approved-by: takhoffman Co-authored-by: takhoffman <781889+takhoffman@users.noreply.github.com>
This commit is contained in:
@@ -34,6 +34,7 @@ Docs: https://docs.openclaw.ai
|
||||
- Auto-reply/ACP: wait for same-channel block reply delivery before starting tool work, while still honoring ACP dispatch aborts so stopped turns do not wait on slow channel sends. (#83722) Thanks @IWhatsskill.
|
||||
- Codex/ACP: mark required child-run completions that only report progress, omit a final deliverable, or fail requester delivery as blocked while preserving real final reports. (#85110) Thanks @IWhatsskill.
|
||||
- Channels: treat bare abort messages such as `stop`, `abort`, and `wait` as immediate control commands in inbound debounce paths so stop requests are not delayed behind pending message coalescing. (#83348) Thanks @IWhatsskill.
|
||||
- Channels/message tool: resolve configured external channel plugins during in-agent channel selection, so `openclaw agent --local` message-tool sends no longer report an available channel as unavailable. (#85022) Thanks @Kaspre.
|
||||
- Agents/subagents: surface blocked child-run completions as errors instead of successful subagent finishes. (#80886) Thanks @TurboTheTurtle.
|
||||
- Agents/Pi: treat accepted embedded `sessions_spawn` child-session handoffs as terminal progress so parent turns no longer report false non-deliverable failures. (#85054) Thanks @samzong.
|
||||
- WhatsApp: update Baileys to `7.0.0-rc13` and drop the obsolete logger type patch.
|
||||
|
||||
@@ -121,6 +121,22 @@ describe("outbound channel resolution", () => {
|
||||
expect(resolveRuntimePluginRegistryMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("returns a bundled plugin without bootstrapping", async () => {
|
||||
const plugin = { id: "alpha" };
|
||||
getLoadedChannelPluginMock.mockReturnValue(undefined);
|
||||
getChannelPluginMock.mockReturnValue(plugin);
|
||||
const channelResolution = await importChannelResolution("bundled-plugin");
|
||||
|
||||
expect(
|
||||
channelResolution.resolveOutboundChannelPlugin({
|
||||
channel: "alpha",
|
||||
cfg: {} as never,
|
||||
allowBootstrap: true,
|
||||
}),
|
||||
).toBe(plugin);
|
||||
expect(resolveRuntimePluginRegistryMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("falls back to the active registry when getChannelPlugin misses", async () => {
|
||||
const plugin = { id: "alpha" };
|
||||
getChannelPluginMock.mockReturnValue(undefined);
|
||||
|
||||
@@ -192,8 +192,13 @@ export function resolveOutboundChannelPlugin(params: {
|
||||
return directCurrent;
|
||||
}
|
||||
|
||||
const bundledCurrent = resolve();
|
||||
if (bundledCurrent) {
|
||||
return bundledCurrent;
|
||||
}
|
||||
|
||||
if (params.allowBootstrap !== true) {
|
||||
return resolve();
|
||||
return undefined;
|
||||
}
|
||||
|
||||
maybeBootstrapChannelPlugin({ channel: normalized, cfg: params.cfg });
|
||||
|
||||
@@ -245,6 +245,36 @@ describe("resolveMessageChannelSelection", () => {
|
||||
verify?.(setupResult as never);
|
||||
});
|
||||
|
||||
it("allows bootstrap while checking explicit and fallback channels", async () => {
|
||||
const cfg = {} as never;
|
||||
mocks.resolveOutboundChannelPlugin.mockImplementation(({ channel }: { channel: string }) =>
|
||||
channel === "beta" ? { id: "beta" } : undefined,
|
||||
);
|
||||
|
||||
await expect(
|
||||
expectResolvedSelection({
|
||||
cfg,
|
||||
channel: "alpha",
|
||||
fallbackChannel: "beta",
|
||||
}),
|
||||
).resolves.toEqual({
|
||||
channel: "beta",
|
||||
configured: [],
|
||||
source: "tool-context-fallback",
|
||||
});
|
||||
|
||||
expect(mocks.resolveOutboundChannelPlugin).toHaveBeenNthCalledWith(1, {
|
||||
channel: "alpha",
|
||||
cfg,
|
||||
allowBootstrap: true,
|
||||
});
|
||||
expect(mocks.resolveOutboundChannelPlugin).toHaveBeenNthCalledWith(2, {
|
||||
channel: "beta",
|
||||
cfg,
|
||||
allowBootstrap: true,
|
||||
});
|
||||
});
|
||||
|
||||
it.each([
|
||||
{
|
||||
params: { cfg: {} as never, channel: "channel:C123", fallbackChannel: "not-a-channel" },
|
||||
|
||||
@@ -49,9 +49,19 @@ function resolveAvailableKnownChannel(params: {
|
||||
if (!normalized) {
|
||||
return undefined;
|
||||
}
|
||||
// Pass `allowBootstrap: true` so the in-agent message tool path can resolve
|
||||
// outbound channels in processes where external channel adapters have not
|
||||
// been eagerly loaded (e.g. `openclaw agent --local`). Already-loaded and
|
||||
// bundled plugins still resolve through side-effect-free fast paths first.
|
||||
// Without the bootstrap fallback, official external channels can surface as
|
||||
// the recurring "Channel is unavailable" error on `--local`-routed
|
||||
// dispatches that the CLI send-path could deliver to.
|
||||
// Adjacent to #77254 (cron-announce / final-reply paths); this closes the
|
||||
// remaining in-agent caller in the same family.
|
||||
return resolveOutboundChannelPlugin({
|
||||
channel: normalized,
|
||||
cfg: params.cfg,
|
||||
allowBootstrap: true,
|
||||
})
|
||||
? normalized
|
||||
: undefined;
|
||||
|
||||
Reference in New Issue
Block a user