Telegram: fix /think command to show current level when no arg
This commit is contained in:
@@ -124,6 +124,25 @@ describe("directive parsing", () => {
|
|||||||
expect(res.thinkLevel).toBe("high");
|
expect(res.thinkLevel).toBe("high");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("does not match /think followed by extra letters", () => {
|
||||||
|
// e.g. someone typing "/think" + extra letter "hink"
|
||||||
|
const res = extractThinkDirective("/thinkstuff");
|
||||||
|
expect(res.hasDirective).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("matches /think with no argument", () => {
|
||||||
|
const res = extractThinkDirective("/think");
|
||||||
|
expect(res.hasDirective).toBe(true);
|
||||||
|
expect(res.thinkLevel).toBeUndefined();
|
||||||
|
expect(res.rawLevel).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("matches /t with no argument", () => {
|
||||||
|
const res = extractThinkDirective("/t");
|
||||||
|
expect(res.hasDirective).toBe(true);
|
||||||
|
expect(res.thinkLevel).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
it("matches queue directive", () => {
|
it("matches queue directive", () => {
|
||||||
const res = extractQueueDirective("please /queue interrupt now");
|
const res = extractQueueDirective("please /queue interrupt now");
|
||||||
expect(res.hasDirective).toBe(true);
|
expect(res.hasDirective).toBe(true);
|
||||||
@@ -355,6 +374,51 @@ describe("directive parsing", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("shows current think level when /think has no argument", async () => {
|
||||||
|
await withTempHome(async (home) => {
|
||||||
|
vi.mocked(runEmbeddedPiAgent).mockReset();
|
||||||
|
|
||||||
|
const res = await getReplyFromConfig(
|
||||||
|
{ Body: "/think", From: "+1222", To: "+1222" },
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
agent: {
|
||||||
|
model: "anthropic/claude-opus-4-5",
|
||||||
|
workspace: path.join(home, "clawd"),
|
||||||
|
thinkingDefault: "high",
|
||||||
|
},
|
||||||
|
session: { store: path.join(home, "sessions.json") },
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const text = Array.isArray(res) ? res[0]?.text : res?.text;
|
||||||
|
expect(text).toContain("Current thinking level: high");
|
||||||
|
expect(runEmbeddedPiAgent).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("shows off when /think has no argument and no default set", async () => {
|
||||||
|
await withTempHome(async (home) => {
|
||||||
|
vi.mocked(runEmbeddedPiAgent).mockReset();
|
||||||
|
|
||||||
|
const res = await getReplyFromConfig(
|
||||||
|
{ Body: "/think", From: "+1222", To: "+1222" },
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
agent: {
|
||||||
|
model: "anthropic/claude-opus-4-5",
|
||||||
|
workspace: path.join(home, "clawd"),
|
||||||
|
},
|
||||||
|
session: { store: path.join(home, "sessions.json") },
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const text = Array.isArray(res) ? res[0]?.text : res?.text;
|
||||||
|
expect(text).toContain("Current thinking level: off");
|
||||||
|
expect(runEmbeddedPiAgent).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it("rejects invalid elevated level", async () => {
|
it("rejects invalid elevated level", async () => {
|
||||||
await withTempHome(async (home) => {
|
await withTempHome(async (home) => {
|
||||||
vi.mocked(runEmbeddedPiAgent).mockReset();
|
vi.mocked(runEmbeddedPiAgent).mockReset();
|
||||||
|
|||||||
@@ -469,6 +469,9 @@ export async function getReplyFromConfig(
|
|||||||
isGroup,
|
isGroup,
|
||||||
})
|
})
|
||||||
) {
|
) {
|
||||||
|
const currentThinkLevel =
|
||||||
|
(sessionEntry?.thinkingLevel as ThinkLevel | undefined) ??
|
||||||
|
(agentCfg?.thinkingDefault as ThinkLevel | undefined);
|
||||||
const directiveReply = await handleDirectiveOnly({
|
const directiveReply = await handleDirectiveOnly({
|
||||||
cfg,
|
cfg,
|
||||||
directives,
|
directives,
|
||||||
@@ -488,6 +491,7 @@ export async function getReplyFromConfig(
|
|||||||
model,
|
model,
|
||||||
initialModelLabel,
|
initialModelLabel,
|
||||||
formatModelSwitchEvent,
|
formatModelSwitchEvent,
|
||||||
|
currentThinkLevel,
|
||||||
});
|
});
|
||||||
typing.cleanup();
|
typing.cleanup();
|
||||||
return directiveReply;
|
return directiveReply;
|
||||||
|
|||||||
@@ -309,6 +309,7 @@ export async function handleDirectiveOnly(params: {
|
|||||||
model: string;
|
model: string;
|
||||||
initialModelLabel: string;
|
initialModelLabel: string;
|
||||||
formatModelSwitchEvent: (label: string, alias?: string) => string;
|
formatModelSwitchEvent: (label: string, alias?: string) => string;
|
||||||
|
currentThinkLevel?: ThinkLevel;
|
||||||
}): Promise<ReplyPayload | undefined> {
|
}): Promise<ReplyPayload | undefined> {
|
||||||
const {
|
const {
|
||||||
directives,
|
directives,
|
||||||
@@ -326,6 +327,7 @@ export async function handleDirectiveOnly(params: {
|
|||||||
resetModelOverride,
|
resetModelOverride,
|
||||||
initialModelLabel,
|
initialModelLabel,
|
||||||
formatModelSwitchEvent,
|
formatModelSwitchEvent,
|
||||||
|
currentThinkLevel,
|
||||||
} = params;
|
} = params;
|
||||||
|
|
||||||
if (directives.hasModelDirective) {
|
if (directives.hasModelDirective) {
|
||||||
@@ -379,8 +381,13 @@ export async function handleDirectiveOnly(params: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (directives.hasThinkDirective && !directives.thinkLevel) {
|
if (directives.hasThinkDirective && !directives.thinkLevel) {
|
||||||
|
// If no argument was provided, show the current level
|
||||||
|
if (!directives.rawThinkLevel) {
|
||||||
|
const level = currentThinkLevel ?? "off";
|
||||||
|
return { text: `Current thinking level: ${level}.` };
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
text: `Unrecognized thinking level "${directives.rawThinkLevel ?? ""}". Valid levels: off, minimal, low, medium, high.`,
|
text: `Unrecognized thinking level "${directives.rawThinkLevel}". Valid levels: off, minimal, low, medium, high.`,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (directives.hasVerboseDirective && !directives.verboseLevel) {
|
if (directives.hasVerboseDirective && !directives.verboseLevel) {
|
||||||
|
|||||||
@@ -16,9 +16,9 @@ export function extractThinkDirective(body?: string): {
|
|||||||
hasDirective: boolean;
|
hasDirective: boolean;
|
||||||
} {
|
} {
|
||||||
if (!body) return { cleaned: "", hasDirective: false };
|
if (!body) return { cleaned: "", hasDirective: false };
|
||||||
// Match the longest keyword first to avoid partial captures (e.g. "/think:high")
|
// Match with optional argument - require word boundary via lookahead after keyword
|
||||||
const match = body.match(
|
const match = body.match(
|
||||||
/(?:^|\s)\/(?:thinking|think|t)\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 thinkLevel = normalizeThinkLevel(match?.[1]);
|
||||||
const cleaned = match
|
const cleaned = match
|
||||||
|
|||||||
Reference in New Issue
Block a user