fix(regression): honor internal provider auth for directives

This commit is contained in:
Tak Hoffman
2026-03-27 16:15:09 -05:00
parent f41cd12b54
commit c125c33724
6 changed files with 48 additions and 1 deletions

View File

@@ -99,10 +99,12 @@ export async function handleDirectiveOnly(
}).sandboxed;
const shouldHintDirectRuntime = directives.hasElevatedDirective && !runtimeIsSandboxed;
const allowInternalExecPersistence = canPersistInternalExecDirective({
messageProvider: params.messageProvider,
surface: params.surface,
gatewayClientScopes: params.gatewayClientScopes,
});
const allowInternalVerbosePersistence = canPersistInternalVerboseDirective({
messageProvider: params.messageProvider,
surface: params.surface,
gatewayClientScopes: params.gatewayClientScopes,
});

View File

@@ -717,4 +717,39 @@ describe("persistInlineDirectives internal exec scope gate", () => {
expect(sessionEntry.verboseLevel).toBeUndefined();
});
it("treats internal provider context as authoritative over external surface metadata", async () => {
const allowedModelKeys = new Set(["anthropic/claude-opus-4-5", "openai/gpt-4o"]);
const directives = parseInlineDirectives("/verbose full");
const sessionEntry = {
sessionId: "s1",
updatedAt: Date.now(),
} as SessionEntry;
const sessionStore = { "agent:main:main": sessionEntry };
await persistInlineDirectives({
directives,
cfg: baseConfig(),
sessionEntry,
sessionStore,
sessionKey: "agent:main:main",
storePath: "/tmp/sessions.json",
elevatedEnabled: true,
elevatedAllowed: true,
defaultProvider: "anthropic",
defaultModel: "claude-opus-4-5",
aliasIndex: baseAliasIndex(),
allowedModelKeys,
provider: "anthropic",
model: "claude-opus-4-5",
initialModelLabel: "anthropic/claude-opus-4-5",
formatModelSwitchEvent: (label) => `Switched to ${label}`,
agentCfg: undefined,
messageProvider: "webchat",
surface: "telegram",
gatewayClientScopes: ["operator.write"],
});
expect(sessionEntry.verboseLevel).toBeUndefined();
});
});

View File

@@ -31,6 +31,7 @@ export type HandleDirectiveOnlyCoreParams = {
};
export type HandleDirectiveOnlyParams = HandleDirectiveOnlyCoreParams & {
messageProvider?: string;
currentThinkLevel?: ThinkLevel;
currentFastMode?: boolean;
currentVerboseLevel?: VerboseLevel;

View File

@@ -41,6 +41,7 @@ export async function persistInlineDirectives(params: {
initialModelLabel: string;
formatModelSwitchEvent: (label: string, alias?: string) => string;
agentCfg: NonNullable<OpenClawConfig["agents"]>["defaults"] | undefined;
messageProvider?: string;
surface?: string;
gatewayClientScopes?: string[];
}): Promise<{ provider: string; model: string; contextTokens: number }> {
@@ -63,10 +64,12 @@ export async function persistInlineDirectives(params: {
} = params;
let { provider, model } = params;
const allowInternalExecPersistence = canPersistInternalExecDirective({
messageProvider: params.messageProvider,
surface: params.surface,
gatewayClientScopes: params.gatewayClientScopes,
});
const allowInternalVerbosePersistence = canPersistInternalVerboseDirective({
messageProvider: params.messageProvider,
surface: params.surface,
gatewayClientScopes: params.gatewayClientScopes,
});

View File

@@ -24,10 +24,14 @@ export const formatInternalVerboseCurrentReplyOnlyText = () =>
"Verbose logging set for the current reply only.";
function canPersistInternalDirective(params: {
messageProvider?: string;
surface?: string;
gatewayClientScopes?: string[];
}): boolean {
if (!isInternalMessageChannel(params.surface)) {
const authoritativeChannel = isInternalMessageChannel(params.messageProvider)
? params.messageProvider
: params.surface;
if (!isInternalMessageChannel(authoritativeChannel)) {
return true;
}
const scopes = params.gatewayClientScopes ?? [];

View File

@@ -233,6 +233,7 @@ export async function applyInlineDirectiveOverrides(params: {
currentVerboseLevel,
currentReasoningLevel,
currentElevatedLevel,
messageProvider: ctx.Provider,
surface: ctx.Surface,
gatewayClientScopes: ctx.GatewayClientScopes,
});
@@ -328,6 +329,7 @@ export async function applyInlineDirectiveOverrides(params: {
initialModelLabel,
formatModelSwitchEvent,
agentCfg,
messageProvider: ctx.Provider,
surface: ctx.Surface,
gatewayClientScopes: ctx.GatewayClientScopes,
});