diff --git a/CHANGELOG.md b/CHANGELOG.md index 783575b69..3318ae020 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ - Providers: add Microsoft Teams provider with polling, attachments, and CLI send support. (#404) — thanks @onutc - Slack: honor reply tags + replyToMode while keeping threaded replies in-thread. (#574) — thanks @bolismauro - Commands: accept /models as an alias for /model. +- Commands: add `/usage` as an alias for `/status`. (#492) — thanks @lc0rp - Models/Auth: show per-agent auth candidates in `/model status`, and add `clawdbot models auth order {get,set,clear}` (per-agent auth rotation overrides). — thanks @steipete - Debugging: add raw model stream logging flags and document gateway watch mode. - Gateway: decode dns-sd escaped UTF-8 in discovery output and show scan progress immediately. — thanks @steipete diff --git a/docs/tools/slash-commands.md b/docs/tools/slash-commands.md index d8e29444f..33e3fff6b 100644 --- a/docs/tools/slash-commands.md +++ b/docs/tools/slash-commands.md @@ -36,6 +36,7 @@ Directives (`/think`, `/verbose`, `/reasoning`, `/elevated`) are parsed even whe Text + native (when enabled): - `/help` - `/status` (alias: `/usage`) +- `/debug show|set|unset|reset` (runtime overrides, owner-only) - `/cost on|off` (toggle per-response usage line) - `/stop` - `/restart` @@ -46,7 +47,7 @@ Text + native (when enabled): - `/verbose on|off` (alias: `/v`) - `/reasoning on|off|stream` (alias: `/reason`; `stream` = Telegram draft only) - `/elevated on|off` (alias: `/elev`) -- `/model ` (or `/` from `agent.models.*.alias`) +- `/model ` (or `/` from `agents.defaults.models.*.alias`) - `/queue ` (plus options like `debounce:2s cap:25 drop:summarize`; send `/queue` to see current settings) Text-only: @@ -59,6 +60,24 @@ Notes: - `/verbose` is meant for debugging and extra visibility; keep it **off** in normal use. - `/reasoning` (and `/verbose`) are risky in group settings: they may reveal internal reasoning or tool output you did not intend to expose. Prefer leaving them off, especially in group chats. +## Debug overrides + +`/debug` lets you set **runtime-only** config overrides (memory, not disk). Owner-only. + +Examples: + +``` +/debug show +/debug set messages.responsePrefix="[clawdbot]" +/debug set whatsapp.allowFrom=["+1555","+4477"] +/debug unset messages.responsePrefix +/debug reset +``` + +Notes: +- Overrides apply immediately to new config reads, but do **not** write to `clawdbot.json`. +- Use `/debug reset` to clear all overrides and return to the on-disk config. + ## Surface notes - **Text commands** run in the normal chat session (DMs share `main`, groups have their own session). diff --git a/src/auto-reply/reply.directive.parse.test.ts b/src/auto-reply/reply.directive.parse.test.ts index e3a2fecfb..09785796e 100644 --- a/src/auto-reply/reply.directive.parse.test.ts +++ b/src/auto-reply/reply.directive.parse.test.ts @@ -144,6 +144,12 @@ describe("directive parsing", () => { expect(res.cleaned).toBe("thats not /tmp/hello"); }); + it("preserves spacing when stripping usage directives before paths", () => { + const res = extractStatusDirective("thats not /usage:/tmp/hello"); + expect(res.hasDirective).toBe(true); + expect(res.cleaned).toBe("thats not /tmp/hello"); + }); + it("parses queue options and modes", () => { const res = extractQueueDirective( "please /queue steer+backlog debounce:2s cap:5 drop:summarize now", diff --git a/src/auto-reply/reply.triggers.test.ts b/src/auto-reply/reply.triggers.test.ts index 38f60125d..ae8154278 100644 --- a/src/auto-reply/reply.triggers.test.ts +++ b/src/auto-reply/reply.triggers.test.ts @@ -242,6 +242,23 @@ describe("trigger handling", () => { }); }); + it("reports status via /usage without invoking the agent", async () => { + await withTempHome(async (home) => { + const res = await getReplyFromConfig( + { + Body: "/usage", + From: "+1002", + To: "+2000", + }, + {}, + makeCfg(home), + ); + const text = Array.isArray(res) ? res[0]?.text : res?.text; + expect(text).toContain("ClawdBot"); + expect(runEmbeddedPiAgent).not.toHaveBeenCalled(); + }); + }); + it("reports active auth profile and key snippet in status", async () => { await withTempHome(async (home) => { const cfg = makeCfg(home); diff --git a/src/auto-reply/reply/commands.ts b/src/auto-reply/reply/commands.ts index 7299a846d..1d2ba748b 100644 --- a/src/auto-reply/reply/commands.ts +++ b/src/auto-reply/reply/commands.ts @@ -594,7 +594,8 @@ export async function handleCommands(params: { const statusRequested = directives.hasStatusDirective || - command.commandBodyNormalized === "/status"; + command.commandBodyNormalized === "/status" || + command.commandBodyNormalized === "/usage"; if (allowTextCommands && statusRequested) { const reply = await buildStatusReply({ cfg, diff --git a/src/auto-reply/reply/directives.ts b/src/auto-reply/reply/directives.ts index d04180411..c6f431b30 100644 --- a/src/auto-reply/reply/directives.ts +++ b/src/auto-reply/reply/directives.ts @@ -170,7 +170,7 @@ export function extractStatusDirective(body?: string): { hasDirective: boolean; } { if (!body) return { cleaned: "", hasDirective: false }; - return extractSimpleDirective(body, ["status"]); + return extractSimpleDirective(body, ["status", "usage"]); } export type { ElevatedLevel, ReasoningLevel, ThinkLevel, VerboseLevel };