fix: relax slash command parsing

This commit is contained in:
Peter Steinberger
2026-01-08 03:22:14 +01:00
parent 36b443f4f3
commit ad5c87c193
18 changed files with 226 additions and 31 deletions

View File

@@ -30,7 +30,10 @@ import { parseAgentSessionKey } from "../../routing/session-key.js";
import { resolveSendPolicy } from "../../sessions/send-policy.js";
import { normalizeE164 } from "../../utils.js";
import { resolveCommandAuthorization } from "../command-auth.js";
import { shouldHandleTextCommands } from "../commands-registry.js";
import {
normalizeCommandBody,
shouldHandleTextCommands,
} from "../commands-registry.js";
import {
normalizeGroupActivation,
parseActivationCommand,
@@ -154,9 +157,9 @@ export function buildCommandContext(params: {
const abortKey =
sessionKey ?? (auth.from || undefined) ?? (auth.to || undefined);
const rawBodyNormalized = triggerBodyNormalized;
const commandBodyNormalized = isGroup
? stripMentions(rawBodyNormalized, ctx, cfg)
: rawBodyNormalized;
const commandBodyNormalized = normalizeCommandBody(
isGroup ? stripMentions(rawBodyNormalized, ctx, cfg) : rawBodyNormalized,
);
return {
surface,

View File

@@ -310,6 +310,9 @@ export async function handleDirectiveOnly(params: {
initialModelLabel: string;
formatModelSwitchEvent: (label: string, alias?: string) => string;
currentThinkLevel?: ThinkLevel;
currentVerboseLevel?: VerboseLevel;
currentReasoningLevel?: ReasoningLevel;
currentElevatedLevel?: ElevatedLevel;
}): Promise<ReplyPayload | undefined> {
const {
directives,
@@ -328,6 +331,9 @@ export async function handleDirectiveOnly(params: {
initialModelLabel,
formatModelSwitchEvent,
currentThinkLevel,
currentVerboseLevel,
currentReasoningLevel,
currentElevatedLevel,
} = params;
if (directives.hasModelDirective) {
@@ -391,18 +397,33 @@ export async function handleDirectiveOnly(params: {
};
}
if (directives.hasVerboseDirective && !directives.verboseLevel) {
if (!directives.rawVerboseLevel) {
const level = currentVerboseLevel ?? "off";
return { text: `Current verbose level: ${level}.` };
}
return {
text: `Unrecognized verbose level "${directives.rawVerboseLevel ?? ""}". Valid levels: off, on.`,
text: `Unrecognized verbose level "${directives.rawVerboseLevel}". Valid levels: off, on.`,
};
}
if (directives.hasReasoningDirective && !directives.reasoningLevel) {
if (!directives.rawReasoningLevel) {
const level = currentReasoningLevel ?? "off";
return { text: `Current reasoning level: ${level}.` };
}
return {
text: `Unrecognized reasoning level "${directives.rawReasoningLevel ?? ""}". Valid levels: on, off, stream.`,
text: `Unrecognized reasoning level "${directives.rawReasoningLevel}". Valid levels: on, off, stream.`,
};
}
if (directives.hasElevatedDirective && !directives.elevatedLevel) {
if (!directives.rawElevatedLevel) {
if (!elevatedEnabled || !elevatedAllowed) {
return { text: "elevated is not available right now." };
}
const level = currentElevatedLevel ?? "off";
return { text: `Current elevated level: ${level}.` };
}
return {
text: `Unrecognized elevated level "${directives.rawElevatedLevel ?? ""}". Valid levels: off, on.`,
text: `Unrecognized elevated level "${directives.rawElevatedLevel}". Valid levels: off, on.`,
};
}
if (

View File

@@ -18,7 +18,7 @@ export function extractThinkDirective(body?: string): {
if (!body) return { cleaned: "", hasDirective: false };
// Match with optional argument - require word boundary via lookahead after keyword
const match = body.match(
/(?:^|\s)\/(?:thinking|think|t)(?=$|\s|:)(?:\s*:?\s*([a-zA-Z-]+)\b)?/i,
/(?:^|\s)\/(?:thinking|think|t)(?=$|\s|:)(?:\s*:?\s*(?:([a-zA-Z-]+)\b)?)?/i,
);
const thinkLevel = normalizeThinkLevel(match?.[1]);
const cleaned = match
@@ -40,7 +40,7 @@ export function extractVerboseDirective(body?: string): {
} {
if (!body) return { cleaned: "", hasDirective: false };
const match = body.match(
/(?:^|\s)\/(?:verbose|v)(?=$|\s|:)\s*:?\s*([a-zA-Z-]+)\b/i,
/(?:^|\s)\/(?:verbose|v)(?=$|\s|:)(?:\s*:?\s*(?:([a-zA-Z-]+)\b)?)?/i,
);
const verboseLevel = normalizeVerboseLevel(match?.[1]);
const cleaned = match
@@ -62,7 +62,7 @@ export function extractElevatedDirective(body?: string): {
} {
if (!body) return { cleaned: "", hasDirective: false };
const match = body.match(
/(?:^|\s)\/(?:elevated|elev)(?=$|\s|:)\s*:?\s*([a-zA-Z-]+)\b/i,
/(?:^|\s)\/(?:elevated|elev)(?=$|\s|:)(?:\s*:?\s*(?:([a-zA-Z-]+)\b)?)?/i,
);
const elevatedLevel = normalizeElevatedLevel(match?.[1]);
const cleaned = match
@@ -84,7 +84,7 @@ export function extractReasoningDirective(body?: string): {
} {
if (!body) return { cleaned: "", hasDirective: false };
const match = body.match(
/(?:^|\s)\/(?:reasoning|reason)(?=$|\s|:)\s*:?\s*([a-zA-Z-]+)\b/i,
/(?:^|\s)\/(?:reasoning|reason)(?=$|\s|:)(?:\s*:?\s*(?:([a-zA-Z-]+)\b)?)?/i,
);
const reasoningLevel = normalizeReasoningLevel(match?.[1]);
const cleaned = match
@@ -103,7 +103,7 @@ export function extractStatusDirective(body?: string): {
hasDirective: boolean;
} {
if (!body) return { cleaned: "", hasDirective: false };
const match = body.match(/(?:^|\s)\/status(?=$|\s|:)\b/i);
const match = body.match(/(?:^|\s)\/status(?=$|\s|:)(?:\s*:\s*)?/i);
const cleaned = match
? body.replace(match[0], "").replace(/\s+/g, " ").trim()
: body.trim();