mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-06 14:12:53 +00:00
* codex: honor verbose in group dispatch * codex: address group verbose review findings Record the final local review pass for the group /verbose PR. Codex review against origin/main completed clean after tightening the shared group progress gate, keeping public plugin hook types stable, preserving ACP hidden tool boundaries, and adding regressions for live verbose gating and progress-callback suppression. * codex: require explicit group verbose progress Normal group tool/progress summaries now require an explicit session verbose override instead of inherited agent verbose defaults. This addresses the PR review concern that existing verboseDefault configurations could expose group progress after upgrade. DMs and forum-topic behavior continue to use the effective verbose state, while normal groups use the live explicit session verbose state set by /verbose on|full|off. * codex: document Slack group verbose caveat * fix(channels): simplify verbose progress gating * docs(changelog): note verbose channel fix * fix(channels): preserve quiet default for group progress * fix(channels): keep verbose error policy dynamic * fix(channels): default verbose progress off everywhere * fix(channels): keep followup verbose default quiet * fix(channels): latch visible tool-error progress * fix(channels): track failed verbose progress events * fix(channels): latch delivered tool errors * fix(channels): prevent progress opt-out bypass * fix(channels): isolate followup error warning state * fix(channels): keep full verbose followup warnings * fix(channels): latch tool errors after visible progress * fix(channels): require visible followup failure progress * fix(channels): refresh followup verbose state * fix(channels): honor live verbose for error details * test(channels): expect live verbose off warning mode * fix(channels): preserve static tool error suppression semantics * fix(channels): bypass acp for colon verbose commands * fix(channels): narrow dynamic tool warning override * fix(channels): gate compaction notices on live verbose * fix(channels): suppress quiet followup compaction callbacks * fix(channels): suppress tts for hidden tool summaries --------- Co-authored-by: Peter Steinberger <steipete@gmail.com>
288 lines
8.0 KiB
TypeScript
288 lines
8.0 KiB
TypeScript
import { beforeEach, describe, expect, it } from "vitest";
|
|
import type { OpenClawConfig } from "../../config/config.js";
|
|
import { setActivePluginRegistry } from "../../plugins/runtime.js";
|
|
import {
|
|
createChannelTestPluginBase,
|
|
createTestRegistry,
|
|
} from "../../test-utils/channel-plugins.js";
|
|
import { shouldBypassAcpDispatchForCommand } from "./dispatch-acp-command-bypass.js";
|
|
import { buildTestCtx } from "./test-ctx.js";
|
|
|
|
describe("shouldBypassAcpDispatchForCommand", () => {
|
|
beforeEach(() => {
|
|
setActivePluginRegistry(createTestRegistry([]));
|
|
});
|
|
|
|
it("returns false for plain-text ACP turns", () => {
|
|
const ctx = buildTestCtx({
|
|
Provider: "discord",
|
|
Surface: "discord",
|
|
BodyForCommands: "write a test",
|
|
BodyForAgent: "write a test",
|
|
});
|
|
|
|
expect(shouldBypassAcpDispatchForCommand(ctx, {} as OpenClawConfig)).toBe(false);
|
|
});
|
|
|
|
it("returns true for ACP slash commands", () => {
|
|
const ctx = buildTestCtx({
|
|
Provider: "discord",
|
|
Surface: "discord",
|
|
CommandBody: "/acp cancel",
|
|
BodyForCommands: "/acp cancel",
|
|
BodyForAgent: "/acp cancel",
|
|
});
|
|
|
|
expect(shouldBypassAcpDispatchForCommand(ctx, {} as OpenClawConfig)).toBe(true);
|
|
});
|
|
|
|
it("returns true for native ACP slash commands", () => {
|
|
const ctx = buildTestCtx({
|
|
Provider: "discord",
|
|
Surface: "discord",
|
|
CommandSource: "native",
|
|
CommandBody: "/acp close",
|
|
BodyForCommands: "/acp close",
|
|
BodyForAgent: "/acp close",
|
|
});
|
|
|
|
expect(shouldBypassAcpDispatchForCommand(ctx, {} as OpenClawConfig)).toBe(true);
|
|
});
|
|
|
|
it("returns false for ACP slash commands addressed to another bot", () => {
|
|
const ctx = buildTestCtx({
|
|
Provider: "discord",
|
|
Surface: "discord",
|
|
CommandBody: "/acp@otherbot cancel",
|
|
BodyForCommands: "/acp@otherbot cancel",
|
|
BodyForAgent: "/acp@otherbot cancel",
|
|
});
|
|
|
|
expect(shouldBypassAcpDispatchForCommand(ctx, {} as OpenClawConfig)).toBe(false);
|
|
});
|
|
|
|
it("returns true for local status commands", () => {
|
|
const ctx = buildTestCtx({
|
|
Provider: "discord",
|
|
Surface: "discord",
|
|
CommandBody: "/status",
|
|
BodyForCommands: "/status",
|
|
BodyForAgent: "/status",
|
|
});
|
|
|
|
expect(shouldBypassAcpDispatchForCommand(ctx, {} as OpenClawConfig)).toBe(true);
|
|
});
|
|
|
|
it("returns true for local unfocus commands", () => {
|
|
const ctx = buildTestCtx({
|
|
Provider: "discord",
|
|
Surface: "discord",
|
|
CommandBody: "/unfocus",
|
|
BodyForCommands: "/unfocus",
|
|
BodyForAgent: "/unfocus",
|
|
});
|
|
|
|
expect(shouldBypassAcpDispatchForCommand(ctx, {} as OpenClawConfig)).toBe(true);
|
|
});
|
|
|
|
it("returns true for local verbose commands", () => {
|
|
const ctx = buildTestCtx({
|
|
Provider: "discord",
|
|
Surface: "discord",
|
|
CommandBody: "/verbose on",
|
|
BodyForCommands: "/verbose on",
|
|
BodyForAgent: "/verbose on",
|
|
});
|
|
|
|
expect(shouldBypassAcpDispatchForCommand(ctx, {} as OpenClawConfig)).toBe(true);
|
|
});
|
|
|
|
it("returns true for local verbose alias commands", () => {
|
|
const ctx = buildTestCtx({
|
|
Provider: "discord",
|
|
Surface: "discord",
|
|
CommandBody: "/v off",
|
|
BodyForCommands: "/v off",
|
|
BodyForAgent: "/v off",
|
|
});
|
|
|
|
expect(shouldBypassAcpDispatchForCommand(ctx, {} as OpenClawConfig)).toBe(true);
|
|
});
|
|
|
|
it.each(["/verbose:on", "/v:off", "/verbose:"])(
|
|
"returns true for colon-form local verbose command %s",
|
|
(command) => {
|
|
const ctx = buildTestCtx({
|
|
Provider: "discord",
|
|
Surface: "discord",
|
|
CommandBody: command,
|
|
BodyForCommands: command,
|
|
BodyForAgent: command,
|
|
});
|
|
|
|
expect(shouldBypassAcpDispatchForCommand(ctx, {} as OpenClawConfig)).toBe(true);
|
|
},
|
|
);
|
|
|
|
it("returns true for ACP reset-tail slash commands", () => {
|
|
const ctx = buildTestCtx({
|
|
Provider: "discord",
|
|
Surface: "discord",
|
|
CommandSource: "native",
|
|
CommandBody: "/new continue with deployment",
|
|
BodyForCommands: "/new continue with deployment",
|
|
BodyForAgent: "/new continue with deployment",
|
|
});
|
|
|
|
expect(shouldBypassAcpDispatchForCommand(ctx, {} as OpenClawConfig)).toBe(true);
|
|
});
|
|
|
|
it("returns true for bare ACP reset slash commands", () => {
|
|
const ctx = buildTestCtx({
|
|
Provider: "discord",
|
|
Surface: "discord",
|
|
CommandBody: "/reset",
|
|
BodyForCommands: "/reset",
|
|
BodyForAgent: "/reset",
|
|
});
|
|
|
|
expect(shouldBypassAcpDispatchForCommand(ctx, {} as OpenClawConfig)).toBe(true);
|
|
});
|
|
|
|
it("returns false for unrelated slash commands when text commands are disabled", () => {
|
|
const ctx = buildTestCtx({
|
|
Provider: "discord",
|
|
Surface: "discord",
|
|
CommandBody: "/foo cancel",
|
|
BodyForCommands: "/foo cancel",
|
|
BodyForAgent: "/foo cancel",
|
|
CommandSource: "text",
|
|
});
|
|
const cfg = {
|
|
commands: {
|
|
text: false,
|
|
},
|
|
} as OpenClawConfig;
|
|
|
|
expect(shouldBypassAcpDispatchForCommand(ctx, cfg)).toBe(false);
|
|
});
|
|
|
|
it("returns true for ACP slash commands when text commands are disabled", () => {
|
|
const ctx = buildTestCtx({
|
|
Provider: "discord",
|
|
Surface: "discord",
|
|
CommandBody: "/acp cancel",
|
|
BodyForCommands: "/acp cancel",
|
|
BodyForAgent: "/acp cancel",
|
|
CommandSource: "text",
|
|
});
|
|
const cfg = {
|
|
commands: {
|
|
text: false,
|
|
},
|
|
} as OpenClawConfig;
|
|
|
|
expect(shouldBypassAcpDispatchForCommand(ctx, cfg)).toBe(true);
|
|
});
|
|
|
|
it("returns false for local status commands when text commands are disabled on text-native surfaces", () => {
|
|
setActivePluginRegistry(
|
|
createTestRegistry([
|
|
{
|
|
pluginId: "discord",
|
|
plugin: createChannelTestPluginBase({
|
|
id: "discord",
|
|
capabilities: { nativeCommands: true, chatTypes: ["direct"] },
|
|
}),
|
|
source: "test",
|
|
},
|
|
]),
|
|
);
|
|
|
|
const ctx = buildTestCtx({
|
|
Provider: "discord",
|
|
Surface: "discord",
|
|
CommandBody: "/status",
|
|
BodyForCommands: "/status",
|
|
BodyForAgent: "/status",
|
|
CommandSource: "text",
|
|
});
|
|
const cfg = {
|
|
commands: {
|
|
text: false,
|
|
},
|
|
} as OpenClawConfig;
|
|
|
|
expect(shouldBypassAcpDispatchForCommand(ctx, cfg)).toBe(false);
|
|
});
|
|
|
|
it("returns true for native local status commands when text commands are disabled", () => {
|
|
const ctx = buildTestCtx({
|
|
Provider: "discord",
|
|
Surface: "discord",
|
|
CommandBody: "/status",
|
|
BodyForCommands: "/status",
|
|
BodyForAgent: "/status",
|
|
CommandSource: "native",
|
|
});
|
|
const cfg = {
|
|
commands: {
|
|
text: false,
|
|
},
|
|
} as OpenClawConfig;
|
|
|
|
expect(shouldBypassAcpDispatchForCommand(ctx, cfg)).toBe(true);
|
|
});
|
|
|
|
it("returns false for unauthorized bang-prefixed commands", () => {
|
|
const ctx = buildTestCtx({
|
|
Provider: "discord",
|
|
Surface: "discord",
|
|
CommandBody: "!poll",
|
|
BodyForCommands: "!poll",
|
|
BodyForAgent: "!poll",
|
|
CommandAuthorized: false,
|
|
});
|
|
|
|
expect(shouldBypassAcpDispatchForCommand(ctx, {} as OpenClawConfig)).toBe(false);
|
|
});
|
|
|
|
it("returns false for bang-prefixed commands when text commands are disabled", () => {
|
|
const ctx = buildTestCtx({
|
|
Provider: "discord",
|
|
Surface: "discord",
|
|
CommandBody: "!poll",
|
|
BodyForCommands: "!poll",
|
|
BodyForAgent: "!poll",
|
|
CommandAuthorized: true,
|
|
CommandSource: "text",
|
|
});
|
|
const cfg = {
|
|
commands: {
|
|
text: false,
|
|
},
|
|
} as OpenClawConfig;
|
|
|
|
expect(shouldBypassAcpDispatchForCommand(ctx, cfg)).toBe(false);
|
|
});
|
|
|
|
it("returns true for authorized bang-prefixed commands when text commands are enabled", () => {
|
|
const ctx = buildTestCtx({
|
|
Provider: "discord",
|
|
Surface: "discord",
|
|
CommandBody: "!poll",
|
|
BodyForCommands: "!poll",
|
|
BodyForAgent: "!poll",
|
|
CommandAuthorized: true,
|
|
CommandSource: "text",
|
|
});
|
|
const cfg = {
|
|
commands: {
|
|
bash: true,
|
|
},
|
|
} as OpenClawConfig;
|
|
|
|
expect(shouldBypassAcpDispatchForCommand(ctx, cfg)).toBe(true);
|
|
});
|
|
});
|