Skip to content

Commit 2070911

Browse files
committed
fix(channels/telegram): return 'off' on unresolved SecretRef instead of default scope
Codex follow-up on PR #75445 noted: returning DEFAULT_INLINE_BUTTONS_SCOPE ('allowlist') when resolveTelegramAccount throws on an unresolved SecretRef silently advertises inline-button capability even when the account is configured with capabilities.inlineButtons: 'off'. Prompt-prep paths like agentPrompt.messageToolCapabilities then prompt the model to generate inline-button payloads the runtime cannot honor. Return 'off' instead — strictly conservative for the prompt-discovery use case. The runtime send path still uses the resolved snapshot, so a real configured account gets the right capability there. Update the regression tests to assert the exact value rather than just non-throwing.
1 parent 66ef7be commit 2070911

2 files changed

Lines changed: 20 additions & 13 deletions

File tree

extensions/telegram/src/inline-buttons.test.ts

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ describe("resolveTelegramInlineButtonsScope (#75433 SecretRef tolerance)", () =>
9696
// snapshot has resolved channel credentials. Returning a benign default
9797
// instead of throwing keeps the embedded reply run alive.
9898

99-
it("returns the safe default scope when botToken is an unresolved SecretRef", () => {
99+
it('returns "off" when botToken is an unresolved SecretRef so prompt prep does not advertise an unverified inline-buttons capability', () => {
100100
const cfg = {
101101
channels: {
102102
telegram: {
@@ -105,14 +105,17 @@ describe("resolveTelegramInlineButtonsScope (#75433 SecretRef tolerance)", () =>
105105
},
106106
} as unknown as OpenClawConfig;
107107

108-
expect(() => resolveTelegramInlineButtonsScope({ cfg })).not.toThrow();
109-
// The DEFAULT_INLINE_BUTTONS_SCOPE is "all" — the contract is just that
110-
// we do not crash. Verify isTelegramInlineButtonsEnabled also tolerates
111-
// the same condition (used by describeMessageTool's buttonsEnabled flag).
112-
expect(() => isTelegramInlineButtonsEnabled({ cfg })).not.toThrow();
108+
// Codex follow-up on PR #75445: the previous fallback returned the
109+
// default scope ("allowlist") which prompted the model to generate inline
110+
// button payloads even when the account had `capabilities.inlineButtons:
111+
// "off"`. The conservative fallback returns "off" so prompt-prep paths
112+
// (e.g. agentPrompt.messageToolCapabilities) cannot misreport capability;
113+
// the runtime send path uses the resolved snapshot and re-asks.
114+
expect(resolveTelegramInlineButtonsScope({ cfg })).toBe("off");
115+
expect(isTelegramInlineButtonsEnabled({ cfg })).toBe(false);
113116
});
114117

115-
it("returns the safe default scope when scoped account token is an unresolved SecretRef", () => {
118+
it('returns "off" when scoped account token is an unresolved SecretRef', () => {
116119
const cfg = {
117120
channels: {
118121
telegram: {
@@ -125,7 +128,7 @@ describe("resolveTelegramInlineButtonsScope (#75433 SecretRef tolerance)", () =>
125128
},
126129
} as unknown as OpenClawConfig;
127130

128-
expect(() => resolveTelegramInlineButtonsScope({ cfg, accountId: "ops" })).not.toThrow();
129-
expect(() => isTelegramInlineButtonsEnabled({ cfg, accountId: "ops" })).not.toThrow();
131+
expect(resolveTelegramInlineButtonsScope({ cfg, accountId: "ops" })).toBe("off");
132+
expect(isTelegramInlineButtonsEnabled({ cfg, accountId: "ops" })).toBe(false);
130133
});
131134
});

extensions/telegram/src/inline-buttons.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,15 +63,19 @@ export function resolveTelegramInlineButtonsScope(params: {
6363
// Embedded prompt prep calls this from raw config before the active runtime
6464
// snapshot has resolved channel credentials. If channels.telegram.botToken is
6565
// a non-env SecretRef, `resolveTelegramAccount` throws an unresolved-SecretRef
66-
// error (#75433). Treat that as "no inline-button capability for prompt
67-
// discovery" instead of crashing the embedded reply run; the runtime send
68-
// path uses the resolved snapshot.
66+
// error (#75433). Treat that as "inline buttons disabled for prompt
67+
// discovery" — return "off" rather than the default "allowlist" so the
68+
// model never advertises inline-button support when the account hasn't been
69+
// resolved yet (the runtime send path uses the resolved snapshot, so a real
70+
// configured account still gets the right capability there). Returning
71+
// "allowlist" here would prompt the model to generate inline-button payloads
72+
// even when capabilities.inlineButtons is configured "off".
6973
let account: ReturnType<typeof resolveTelegramAccount>;
7074
try {
7175
account = resolveTelegramAccount({ cfg: params.cfg, accountId: params.accountId });
7276
} catch (err) {
7377
if (err instanceof Error && /unresolved SecretRef/i.test(err.message)) {
74-
return DEFAULT_INLINE_BUTTONS_SCOPE;
78+
return "off";
7579
}
7680
throw err;
7781
}

0 commit comments

Comments
 (0)