fix: route native status to active agent

This commit is contained in:
Peter Steinberger
2026-01-20 19:04:25 +00:00
parent 5c4079f66c
commit 243a8b019e
4 changed files with 61 additions and 12 deletions

View File

@@ -25,6 +25,7 @@ Docs: https://docs.clawd.bot
- TUI: keep thinking blocks ordered before content during streaming and isolate per-run assembly. (#1202) — thanks @aaronveklabs. - TUI: keep thinking blocks ordered before content during streaming and isolate per-run assembly. (#1202) — thanks @aaronveklabs.
- TUI: align custom editor initialization with the latest pi-tui API. (#1298) — thanks @sibbl. - TUI: align custom editor initialization with the latest pi-tui API. (#1298) — thanks @sibbl.
- CLI: avoid duplicating --profile/--dev flags when formatting commands. - CLI: avoid duplicating --profile/--dev flags when formatting commands.
- Status: route native `/status` to the active agent so model selection reflects the correct profile. (#1301)
- Exec: prefer bash when fish is default shell, falling back to sh if bash is missing. (#1297) — thanks @ysqander. - Exec: prefer bash when fish is default shell, falling back to sh if bash is missing. (#1297) — thanks @ysqander.
- Exec: merge login-shell PATH for host=gateway exec while keeping daemon PATH minimal. (#1304) - Exec: merge login-shell PATH for host=gateway exec while keeping daemon PATH minimal. (#1304)
- Plugins: add Nextcloud Talk manifest for plugin config validation. (#1297) — thanks @ysqander. - Plugins: add Nextcloud Talk manifest for plugin config validation. (#1297) — thanks @ysqander.

View File

@@ -5,7 +5,6 @@ import {
resolveAuthProfileDisplayLabel, resolveAuthProfileDisplayLabel,
resolveAuthProfileOrder, resolveAuthProfileOrder,
} from "../../agents/auth-profiles.js"; } from "../../agents/auth-profiles.js";
import { DEFAULT_MODEL, DEFAULT_PROVIDER } from "../../agents/defaults.js";
import { getCustomProviderApiKey, resolveEnvApiKey } from "../../agents/model-auth.js"; import { getCustomProviderApiKey, resolveEnvApiKey } from "../../agents/model-auth.js";
import { loadModelCatalog } from "../../agents/model-catalog.js"; import { loadModelCatalog } from "../../agents/model-catalog.js";
import { import {
@@ -13,7 +12,7 @@ import {
buildModelAliasIndex, buildModelAliasIndex,
modelKey, modelKey,
normalizeProviderId, normalizeProviderId,
resolveConfiguredModelRef, resolveDefaultModelForAgent,
resolveModelRefFromString, resolveModelRefFromString,
} from "../../agents/model-selection.js"; } from "../../agents/model-selection.js";
import { normalizeGroupActivation } from "../../auto-reply/group-activation.js"; import { normalizeGroupActivation } from "../../auto-reply/group-activation.js";
@@ -152,6 +151,7 @@ async function resolveModelOverride(params: {
cfg: ClawdbotConfig; cfg: ClawdbotConfig;
raw: string; raw: string;
sessionEntry?: SessionEntry; sessionEntry?: SessionEntry;
agentId: string;
}): Promise< }): Promise<
| { kind: "reset" } | { kind: "reset" }
| { | {
@@ -165,10 +165,9 @@ async function resolveModelOverride(params: {
if (!raw) return { kind: "reset" }; if (!raw) return { kind: "reset" };
if (raw.toLowerCase() === "default") return { kind: "reset" }; if (raw.toLowerCase() === "default") return { kind: "reset" };
const configDefault = resolveConfiguredModelRef({ const configDefault = resolveDefaultModelForAgent({
cfg: params.cfg, cfg: params.cfg,
defaultProvider: DEFAULT_PROVIDER, agentId: params.agentId,
defaultModel: DEFAULT_MODEL,
}); });
const currentProvider = params.sessionEntry?.providerOverride?.trim() || configDefault.provider; const currentProvider = params.sessionEntry?.providerOverride?.trim() || configDefault.provider;
const currentModel = params.sessionEntry?.modelOverride?.trim() || configDefault.model; const currentModel = params.sessionEntry?.modelOverride?.trim() || configDefault.model;
@@ -248,6 +247,7 @@ export function createSessionStatusTool(opts?: {
cfg, cfg,
raw: modelRaw, raw: modelRaw,
sessionEntry: resolved.entry, sessionEntry: resolved.entry,
agentId,
}); });
const nextEntry: SessionEntry = { const nextEntry: SessionEntry = {
...resolved.entry, ...resolved.entry,
@@ -275,11 +275,7 @@ export function createSessionStatusTool(opts?: {
} }
const agentDir = resolveAgentDir(cfg, agentId); const agentDir = resolveAgentDir(cfg, agentId);
const configured = resolveConfiguredModelRef({ const configured = resolveDefaultModelForAgent({ cfg, agentId });
cfg,
defaultProvider: DEFAULT_PROVIDER,
defaultModel: DEFAULT_MODEL,
});
const providerForCard = resolved.entry.providerOverride?.trim() || configured.provider; const providerForCard = resolved.entry.providerOverride?.trim() || configured.provider;
const usageProvider = resolveUsageProviderId(providerForCard); const usageProvider = resolveUsageProviderId(providerForCard);
let usageLine: string | undefined; let usageLine: string | undefined;
@@ -326,9 +322,18 @@ export function createSessionStatusTool(opts?: {
resolved.entry.queueDebounceMs ?? resolved.entry.queueCap ?? resolved.entry.queueDrop, resolved.entry.queueDebounceMs ?? resolved.entry.queueCap ?? resolved.entry.queueDrop,
); );
const agentDefaults = cfg.agents?.defaults ?? {};
const defaultLabel = `${configured.provider}/${configured.model}`;
const agentModel =
typeof agentDefaults.model === "object" && agentDefaults.model
? { ...agentDefaults.model, primary: defaultLabel }
: { primary: defaultLabel };
const statusText = buildStatusMessage({ const statusText = buildStatusMessage({
config: cfg, config: cfg,
agent: cfg.agents?.defaults ?? {}, agent: {
...agentDefaults,
model: agentModel,
},
sessionEntry: resolved.entry, sessionEntry: resolved.entry,
sessionKey: resolved.key, sessionKey: resolved.key,
groupActivation, groupActivation,

View File

@@ -242,4 +242,44 @@ describe("trigger handling", () => {
); );
}); });
}); });
it("uses the target agent model for native /status", async () => {
await withTempHome(async (home) => {
const cfg = {
agents: {
defaults: {
model: "anthropic/claude-opus-4-5",
workspace: join(home, "clawd"),
},
list: [{ id: "coding", model: "minimax/MiniMax-M2.1" }],
},
channels: {
telegram: {
allowFrom: ["*"],
},
},
session: { store: join(home, "sessions.json") },
};
const res = await getReplyFromConfig(
{
Body: "/status",
From: "telegram:111",
To: "telegram:111",
ChatType: "group",
Provider: "telegram",
Surface: "telegram",
SessionKey: "telegram:slash:111",
CommandSource: "native",
CommandTargetSessionKey: "agent:coding:telegram:group:123",
CommandAuthorized: true,
},
{},
cfg,
);
const text = Array.isArray(res) ? res[0]?.text : res?.text;
expect(text).toContain("minimax/MiniMax-M2.1");
});
});
}); });

View File

@@ -29,8 +29,11 @@ export async function getReplyFromConfig(
configOverride?: ClawdbotConfig, configOverride?: ClawdbotConfig,
): Promise<ReplyPayload | ReplyPayload[] | undefined> { ): Promise<ReplyPayload | ReplyPayload[] | undefined> {
const cfg = configOverride ?? loadConfig(); const cfg = configOverride ?? loadConfig();
const targetSessionKey =
ctx.CommandSource === "native" ? ctx.CommandTargetSessionKey?.trim() : undefined;
const agentSessionKey = targetSessionKey || ctx.SessionKey;
const agentId = resolveSessionAgentId({ const agentId = resolveSessionAgentId({
sessionKey: ctx.SessionKey, sessionKey: agentSessionKey,
config: cfg, config: cfg,
}); });
const agentCfg = cfg.agents?.defaults; const agentCfg = cfg.agents?.defaults;