fix(microsoft-foundry): keep connection test error truncation UTF-16 safe (#102605)

* fix(microsoft-foundry): keep connection test error truncation UTF-16 safe

Replace `.slice(0, 200)` with `truncateUtf16Safe(body, 200)` in
testFoundryConnection error messages to prevent surrogate pair corruption.

Ref. lsr911 pattern — mechanical substitution, no behavior change.

* test(microsoft-foundry): cover UTF-16-safe connection errors

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
This commit is contained in:
huangjianxiong 2026-07-09 18:51:38 +08:00 committed by GitHub
parent bebf0b98c1
commit c067802cda
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 39 additions and 2 deletions

View file

@ -70,4 +70,40 @@ describe("testFoundryConnection", () => {
"Connection Test",
);
});
it.each([
{
status: 400,
expectedPrefix:
"Endpoint is reachable but returned 400 Bad Request - check your deployment name and API version.\n",
expectedSuffix: "",
},
{
status: 503,
expectedPrefix: "Warning: test request returned 503. ",
expectedSuffix: "\nProceeding anyway - you can fix the endpoint later.",
},
])(
"keeps $status error-body previews UTF-16 safe",
async ({ status, expectedPrefix, expectedSuffix }) => {
const note = vi.fn();
const prefix = "x".repeat(199);
hoisted.fetchWithSsrFGuard.mockResolvedValue({
response: new Response(`${prefix}😀tail`, { status }),
release: async () => {},
});
await testFoundryConnection({
ctx: { prompter: { note } } as never,
endpoint: "https://example.openai.azure.com",
modelId: "gpt-4o",
api: DEFAULT_API,
});
expect(note).toHaveBeenCalledExactlyOnceWith(
`${expectedPrefix}${prefix}${expectedSuffix}`,
"Connection Test",
);
},
);
});

View file

@ -7,6 +7,7 @@ import {
normalizeOptionalString,
normalizeStringifiedOptionalString,
} from "openclaw/plugin-sdk/string-coerce-runtime";
import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
import {
azLoginDeviceCode,
azLoginDeviceCodeWithOptions,
@ -613,7 +614,7 @@ export async function testFoundryConnection(params: {
FOUNDRY_CONNECTION_TEST_ERROR_BODY_LIMIT_BYTES,
).catch(() => "");
await params.ctx.prompter.note(
`Endpoint is reachable but returned 400 Bad Request - check your deployment name and API version.\n${body.slice(0, 200)}`,
`Endpoint is reachable but returned 400 Bad Request - check your deployment name and API version.\n${truncateUtf16Safe(body, 200)}`,
"Connection Test",
);
} else if (!res.ok) {
@ -622,7 +623,7 @@ export async function testFoundryConnection(params: {
FOUNDRY_CONNECTION_TEST_ERROR_BODY_LIMIT_BYTES,
).catch(() => "");
await params.ctx.prompter.note(
`Warning: test request returned ${res.status}. ${body.slice(0, 200)}\nProceeding anyway - you can fix the endpoint later.`,
`Warning: test request returned ${res.status}. ${truncateUtf16Safe(body, 200)}\nProceeding anyway - you can fix the endpoint later.`,
"Connection Test",
);
} else {