mirror of
https://github.com/moltbot/moltbot.git
synced 2026-03-07 22:44:16 +00:00
fix(slack): land #29032 /agentstatus alias from @maloqab
Land contributor PR #29032 by @maloqab with Slack native alias docs, integration tests, and changelog entry. Co-authored-by: maloqab <mitebaloqab@gmail.com>
This commit is contained in:
@@ -19,6 +19,7 @@ Docs: https://docs.openclaw.ai
|
||||
- CLI/Install: add an npm-link fallback to fix CLI startup `Permission denied` failures (`exit 127`) on affected installs. (#17151) Thanks @sskyu and @vincentkoc.
|
||||
- Agents/Ollama: demote empty-discovery logging from `warn` to `debug` to reduce noisy warnings in normal edge-case discovery flows. (#26379) Thanks @byungsker.
|
||||
- Install/npm: fix npm global install deprecation warnings. (#28318) Thanks @vincentkoc.
|
||||
- Slack/Native commands: register Slack native status as `/agentstatus` (Slack-reserved `/status`) so manifest slash command registration stays valid while text `/status` still works. Landed from contributor PR #29032 by @maloqab. Thanks @maloqab.
|
||||
- Android/Nodes reliability: reject `facing=both` when `deviceId` is set to avoid mislabeled duplicate captures, allow notification `open`/`reply` on non-clearable entries while still gating dismiss, trigger listener rebind before notification actions, and scale invoke-result ack timeout to invoke budget for large clip payloads. (#28260) Thanks @obviyus.
|
||||
- Android/Camera clip: remove `camera.clip` HTTP-upload fallback to base64 so clip transport is deterministic and fail-loud, and reject non-positive `maxWidth` values so invalid inputs fall back to the safe resize default. (#28229) Thanks @obviyus.
|
||||
- Android/Gateway canvas capability refresh: send `node.canvas.capability.refresh` with object `params` (`{}`) from Android node runtime so gateway object-schema validation accepts refresh retries and A2UI host recovery works after scoped capability expiry. (#28413) Thanks @obviyus.
|
||||
|
||||
@@ -208,7 +208,8 @@ For actions/directory reads, user token can be preferred when configured. For wr
|
||||
|
||||
- Native command auto-mode is **off** for Slack (`commands.native: "auto"` does not enable Slack native commands).
|
||||
- Enable native Slack command handlers with `channels.slack.commands.native: true` (or global `commands.native: true`).
|
||||
- When native commands are enabled, register matching slash commands in Slack (`/<command>` names).
|
||||
- When native commands are enabled, register matching slash commands in Slack (`/<command>` names), with one exception:
|
||||
- register `/agentstatus` for the status command (Slack reserves `/status`)
|
||||
- If native commands are not enabled, you can run a single configured slash command via `channels.slack.slashCommand`.
|
||||
- Native arg menus now adapt their rendering strategy:
|
||||
- up to 5 options: button blocks
|
||||
|
||||
@@ -219,3 +219,4 @@ Notes:
|
||||
- Telegram: `telegram:slash:<userId>` (targets the chat session via `CommandTargetSessionKey`)
|
||||
- **`/stop`** targets the active chat session so it can abort the current run.
|
||||
- **Slack:** `channels.slack.slashCommand` is still supported for a single `/openclaw`-style command. If you enable `commands.native`, you must create one Slack slash command per built-in command (same names as `/help`). Command argument menus for Slack are delivered as ephemeral Block Kit buttons.
|
||||
- Slack native exception: register `/agentstatus` (not `/status`) because Slack reserves `/status`. Text `/status` still works in Slack messages.
|
||||
|
||||
@@ -109,6 +109,17 @@ describe("commands registry", () => {
|
||||
expect(findCommandByNativeName("tts", "discord")).toBeUndefined();
|
||||
});
|
||||
|
||||
it("renames status to agentstatus for slack", () => {
|
||||
const native = listNativeCommandSpecsForConfig(
|
||||
{ commands: { native: true } },
|
||||
{ provider: "slack" },
|
||||
);
|
||||
expect(native.find((spec) => spec.name === "agentstatus")).toBeTruthy();
|
||||
expect(native.find((spec) => spec.name === "status")).toBeFalsy();
|
||||
expect(findCommandByNativeName("agentstatus", "slack")?.key).toBe("status");
|
||||
expect(findCommandByNativeName("status", "slack")).toBeUndefined();
|
||||
});
|
||||
|
||||
it("keeps discord native command specs within slash-command limits", () => {
|
||||
const native = listNativeCommandSpecsForConfig(
|
||||
{ commands: { native: true } },
|
||||
|
||||
@@ -123,6 +123,11 @@ const NATIVE_NAME_OVERRIDES: Record<string, Record<string, string>> = {
|
||||
discord: {
|
||||
tts: "voice",
|
||||
},
|
||||
slack: {
|
||||
// Slack reserves /status — registering it returns "invalid name"
|
||||
// and invalidates the entire slash_commands manifest array.
|
||||
status: "agentstatus",
|
||||
},
|
||||
};
|
||||
|
||||
function resolveNativeName(command: ChatCommandDefinition, provider?: string): string | undefined {
|
||||
|
||||
@@ -8,6 +8,7 @@ vi.mock("../../auto-reply/commands-registry.js", () => {
|
||||
const reportExternalCommand = { key: "reportexternal", nativeName: "reportexternal" };
|
||||
const reportLongCommand = { key: "reportlong", nativeName: "reportlong" };
|
||||
const unsafeConfirmCommand = { key: "unsafeconfirm", nativeName: "unsafeconfirm" };
|
||||
const statusAliasCommand = { key: "status", nativeName: "status" };
|
||||
const periodArg = { name: "period", description: "period" };
|
||||
const baseReportPeriodChoices = [
|
||||
{ value: "day", label: "day" },
|
||||
@@ -73,6 +74,9 @@ vi.mock("../../auto-reply/commands-registry.js", () => {
|
||||
if (normalized === "unsafeconfirm") {
|
||||
return unsafeConfirmCommand;
|
||||
}
|
||||
if (normalized === "agentstatus") {
|
||||
return statusAliasCommand;
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
listNativeCommandSpecsForConfig: () => [
|
||||
@@ -112,6 +116,12 @@ vi.mock("../../auto-reply/commands-registry.js", () => {
|
||||
acceptsArgs: true,
|
||||
args: [],
|
||||
},
|
||||
{
|
||||
name: "agentstatus",
|
||||
description: "Status",
|
||||
acceptsArgs: false,
|
||||
args: [],
|
||||
},
|
||||
],
|
||||
parseCommandArgs: () => ({ values: {} }),
|
||||
resolveCommandArgMenu: (params: {
|
||||
@@ -394,6 +404,7 @@ describe("Slack native command argument menus", () => {
|
||||
let reportExternalHandler: (args: unknown) => Promise<void>;
|
||||
let reportLongHandler: (args: unknown) => Promise<void>;
|
||||
let unsafeConfirmHandler: (args: unknown) => Promise<void>;
|
||||
let agentStatusHandler: (args: unknown) => Promise<void>;
|
||||
let argMenuHandler: (args: unknown) => Promise<void>;
|
||||
let argMenuOptionsHandler: (args: unknown) => Promise<void>;
|
||||
|
||||
@@ -406,6 +417,7 @@ describe("Slack native command argument menus", () => {
|
||||
reportExternalHandler = requireHandler(harness.commands, "/reportexternal", "/reportexternal");
|
||||
reportLongHandler = requireHandler(harness.commands, "/reportlong", "/reportlong");
|
||||
unsafeConfirmHandler = requireHandler(harness.commands, "/unsafeconfirm", "/unsafeconfirm");
|
||||
agentStatusHandler = requireHandler(harness.commands, "/agentstatus", "/agentstatus");
|
||||
argMenuHandler = requireHandler(harness.actions, "openclaw_cmdarg", "arg-menu action");
|
||||
argMenuOptionsHandler = requireHandler(harness.options, "openclaw_cmdarg", "arg-menu options");
|
||||
});
|
||||
@@ -474,6 +486,11 @@ describe("Slack native command argument menus", () => {
|
||||
expect(call.ctx?.Body).toBe("/usage tokens");
|
||||
});
|
||||
|
||||
it("maps /agentstatus to /status when dispatching", async () => {
|
||||
await runCommandHandler(agentStatusHandler);
|
||||
expectSingleDispatchedSlashBody("/status");
|
||||
});
|
||||
|
||||
it("dispatches the command when a static_select option is chosen", async () => {
|
||||
await runArgMenuAction(argMenuHandler, {
|
||||
action: {
|
||||
|
||||
Reference in New Issue
Block a user