fix: remove false-positive billing error rewrite on normal assistant text (openclaw#17834) thanks @niceysam
Verified: - pnpm install --frozen-lockfile - pnpm build - pnpm check - pnpm test:macmini Co-authored-by: niceysam <256747835+niceysam@users.noreply.github.com> Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
This commit is contained in:
@@ -34,6 +34,7 @@ Docs: https://docs.openclaw.ai
|
||||
|
||||
- Security/Exec: block `sort --compress-program` in `tools.exec.safeBins` policy so allowlist-mode safe-bin checks cannot be used to bypass approval and spawn external programs. Thanks @tdjackey for reporting.
|
||||
- Doctor/State integrity: only require/create the OAuth credentials directory when WhatsApp or pairing-backed channels are configured, and downgrade fresh-install missing-dir noise to an informational warning.
|
||||
- Agents/Sanitization: stop rewriting billing-shaped assistant text outside explicit error context so normal replies about billing/credits/payment are preserved across messaging channels. (#17834, fixes #11359)
|
||||
- Security/Agents: cap embedded Pi runner outer retry loop with a higher profile-aware dynamic limit (32-160 attempts) and return an explicit `retry_limit` error payload when retries never converge, preventing unbounded internal retry cycles (`GHSA-76m6-pj3w-v7mf`).
|
||||
- Telegram: detect duplicate bot-token ownership across Telegram accounts at startup/status time, mark secondary accounts as not configured with an explicit fix message, and block duplicate account startup before polling to avoid endless `getUpdates` conflict loops.
|
||||
- Agents/Tool images: include source filenames in `agents/tool-images` resize logs so compression events can be traced back to specific files.
|
||||
|
||||
@@ -72,9 +72,14 @@ describe("sanitizeUserFacingText", () => {
|
||||
expect(sanitizeUserFacingText(text)).toBe(text);
|
||||
});
|
||||
|
||||
it("rewrites billing error-shaped text", () => {
|
||||
it("does not rewrite billing error-shaped text without errorContext", () => {
|
||||
const text = "billing: please upgrade your plan";
|
||||
expect(sanitizeUserFacingText(text)).toContain("billing error");
|
||||
expect(sanitizeUserFacingText(text)).toBe(text);
|
||||
});
|
||||
|
||||
it("rewrites billing error-shaped text with errorContext", () => {
|
||||
const text = "billing: please upgrade your plan";
|
||||
expect(sanitizeUserFacingText(text, { errorContext: true })).toContain("billing error");
|
||||
});
|
||||
|
||||
it("sanitizes raw API error payloads", () => {
|
||||
|
||||
@@ -244,18 +244,6 @@ function shouldRewriteContextOverflowText(raw: string): boolean {
|
||||
);
|
||||
}
|
||||
|
||||
function shouldRewriteBillingText(raw: string): boolean {
|
||||
if (!isBillingErrorMessage(raw)) {
|
||||
return false;
|
||||
}
|
||||
return (
|
||||
isRawApiErrorPayload(raw) ||
|
||||
isLikelyHttpErrorText(raw) ||
|
||||
ERROR_PREFIX_RE.test(raw) ||
|
||||
BILLING_ERROR_HEAD_RE.test(raw)
|
||||
);
|
||||
}
|
||||
|
||||
type ErrorPayload = Record<string, unknown>;
|
||||
|
||||
function isErrorPayloadObject(payload: unknown): payload is ErrorPayload {
|
||||
@@ -552,13 +540,6 @@ export function sanitizeUserFacingText(text: string, opts?: { errorContext?: boo
|
||||
}
|
||||
}
|
||||
|
||||
// Preserve legacy behavior for explicit billing-head text outside known
|
||||
// error contexts (e.g., "billing: please upgrade your plan"), while
|
||||
// keeping conversational billing mentions untouched.
|
||||
if (shouldRewriteBillingText(trimmed)) {
|
||||
return BILLING_ERROR_USER_MESSAGE;
|
||||
}
|
||||
|
||||
// Strip leading blank lines (including whitespace-only lines) without clobbering indentation on
|
||||
// the first content line (e.g. markdown/code blocks).
|
||||
const withoutLeadingEmptyLines = stripped.replace(/^(?:[ \t]*\r?\n)+/, "");
|
||||
|
||||
Reference in New Issue
Block a user