fix(web): show API errors when agent publishing fails (#39756)

This commit is contained in:
Joel 2026-07-29 17:37:18 +08:00 committed by GitHub
parent 155e4fbdc5
commit fd804dfcc0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 54 additions and 5 deletions

View File

@ -975,11 +975,45 @@ describe('useAgentConfigureSync', () => {
})
})
await expect(result.current.publishDraft()).rejects.toThrow(
'Failed to save agent composer draft.',
)
await expect(result.current.publishDraft()).rejects.toThrow('save failed')
expect(publishAgentMutationFn).not.toHaveBeenCalled()
expect(toastMock.error).toHaveBeenCalledWith('save failed')
})
it('should show the API error message when publishing fails', async () => {
const responseError = new Response(
JSON.stringify({
code: 'invalid_model_credentials',
message: 'Model credential validation failed',
status: 400,
}),
{
headers: {
'Content-Type': 'application/json',
},
status: 400,
statusText: 'Bad Request',
},
)
publishAgentMutationFn.mockRejectedValueOnce(responseError)
const { result } = renderUseAgentConfigureSync({
currentModel: configuredModel,
})
await expect(result.current.publishDraft()).rejects.toBe(responseError)
expect(toastMock.error).toHaveBeenCalledWith('Model credential validation failed')
})
it('should show the default error when publish rejection has no message', async () => {
publishAgentMutationFn.mockRejectedValueOnce({ code: 'publish_failed' })
const { result } = renderUseAgentConfigureSync({
currentModel: configuredModel,
})
await expect(result.current.publishDraft()).rejects.toEqual({ code: 'publish_failed' })
expect(toastMock.error).toHaveBeenCalledWith('common.api.actionFailed')
})
@ -1249,6 +1283,7 @@ describe('useAgentConfigureSync', () => {
expect(result.current.isPublishing).toBe(false)
expect(toastMock.error).toHaveBeenCalledTimes(1)
expect(toastMock.error).toHaveBeenCalledWith('publish failed')
expect(composerPutMutationFn).toHaveBeenCalledTimes(2)
expect(composerPutMutationFn).toHaveBeenLastCalledWith(
expect.objectContaining({

View File

@ -135,9 +135,10 @@ export function useAgentConfigureSync({
agent_soul: configSnapshot,
},
})
} catch {
} catch (error) {
// Autosave is silent and keeps the local draft intact; explicit commands must stop at this boundary.
if (!silent) {
if (publish) throw error
throw new Error('Failed to save agent composer draft.')
}
@ -378,7 +379,20 @@ export function useAgentConfigureSync({
})
toast.success(tCommon(($) => $['api.actionSuccess']))
} catch (error) {
toast.error(tCommon(($) => $['api.actionFailed']))
let errorData: unknown = error
if (error instanceof Response) {
try {
errorData = await error.clone().json()
} catch {}
}
toast.error(
errorData &&
typeof errorData === 'object' &&
'message' in errorData &&
typeof errorData.message === 'string'
? errorData.message
: tCommon(($) => $['api.actionFailed']),
)
throw error
} finally {
publishInFlightRef.current = false