From 2c530f43e7e0ef581ccdfe01b70b27aef777b5d2 Mon Sep 17 00:00:00 2001 From: renaissance04 <3103792194@qq.com> Date: Sun, 6 Sep 2026 02:25:16 +0800 Subject: [PATCH 1/3] fix(search): map output sensitivity to content filter exit code --- ERRORS.md | 1 + src/errors/api.ts | 9 +++++++++ test/errors/api.test.ts | 10 ++++++++++ 3 files changed, 20 insertions(+) diff --git a/ERRORS.md b/ERRORS.md index 8eae7d82..9ea439a3 100644 --- a/ERRORS.md +++ b/ERRORS.md @@ -226,6 +226,7 @@ No error scenarios — prints a message directing users to run `npm update -g mm | HTTP 401 / 403 | `API key rejected (HTTP ${status}).` | | HTTP 429 | `Rate limit or quota exceeded. ${apiMsg}` | | `status_code` 1002 / 1039 (content filter) | `Input content flagged by sensitivity filter (${filterType}).` | +| `status_msg` contains "new_sensitive" / output sensitivity (HTTP 200) | `Output withheld by content moderation (${apiMsg}).` | | `status_code` 1028 / 1030 (quota exhausted) | `Quota exhausted. ${apiMsg}` | | `status_code` 2061 (model not on plan) | `This model is not available on your current Token Plan. ${apiMsg}` | | Other API errors | `API error: ${apiMsg} (HTTP ${status})` | diff --git a/src/errors/api.ts b/src/errors/api.ts index ecdd5433..cb178314 100644 --- a/src/errors/api.ts +++ b/src/errors/api.ts @@ -106,6 +106,15 @@ export function mapApiError(status: number, body: ApiErrorBody, url?: string): C ); } + // output sensitivity (HTTP 200, e.g. "output new_sensitive") + if (/new_sensitive/i.test(apiMsg) || /output.*sensitive/i.test(apiMsg)) { + return new CLIError( + `Output withheld by content moderation (${apiMsg}).`, + ExitCode.CONTENT_FILTER, + 'Refine your query and try again.', + ); + } + return new CLIError( `API error: ${apiMsg} (HTTP ${status})`, ExitCode.GENERAL, diff --git a/test/errors/api.test.ts b/test/errors/api.test.ts index 29a0c80a..9e2ad914 100644 --- a/test/errors/api.test.ts +++ b/test/errors/api.test.ts @@ -73,6 +73,16 @@ describe('mapApiError', () => { expect(err.exitCode).toBe(ExitCode.QUOTA); }); + it('maps output sensitivity (HTTP 200) to CONTENT_FILTER', () => { + const err = mapApiError(200, { + base_resp: { status_code: 2001, status_msg: 'output new_sensitive' }, + }); + expect(err.exitCode).toBe(ExitCode.CONTENT_FILTER); + expect(err.message).toContain('content moderation'); + expect(err.message).toContain('output new_sensitive'); + expect(err.hint).toBeDefined(); + }); + it('maps unknown errors to GENERAL', () => { const err = mapApiError(500, { base_resp: { status_code: 0, status_msg: 'internal error' } }); expect(err.exitCode).toBe(ExitCode.GENERAL); From 024fc041a2934bda85d2019d91adf6400e386089 Mon Sep 17 00:00:00 2001 From: renaissance04 <3103792194@qq.com> Date: Sun, 6 Sep 2026 04:12:03 +0800 Subject: [PATCH 2/3] also match status_code 1027 for output sensitivity --- src/errors/api.ts | 4 ++-- test/errors/api.test.ts | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/errors/api.ts b/src/errors/api.ts index cb178314..6982d691 100644 --- a/src/errors/api.ts +++ b/src/errors/api.ts @@ -106,8 +106,8 @@ export function mapApiError(status: number, body: ApiErrorBody, url?: string): C ); } - // output sensitivity (HTTP 200, e.g. "output new_sensitive") - if (/new_sensitive/i.test(apiMsg) || /output.*sensitive/i.test(apiMsg)) { + // output sensitivity (status_code 1027, e.g. "output new_sensitive") + if (apiCode === 1027 || /new_sensitive/i.test(apiMsg) || /output.*sensitive/i.test(apiMsg)) { return new CLIError( `Output withheld by content moderation (${apiMsg}).`, ExitCode.CONTENT_FILTER, diff --git a/test/errors/api.test.ts b/test/errors/api.test.ts index 9e2ad914..83e01d3c 100644 --- a/test/errors/api.test.ts +++ b/test/errors/api.test.ts @@ -83,6 +83,13 @@ describe('mapApiError', () => { expect(err.hint).toBeDefined(); }); + it('maps output sensitivity code 1027 to CONTENT_FILTER', () => { + const err = mapApiError(200, { + base_resp: { status_code: 1027, status_msg: '输出内容涉敏' }, + }); + expect(err.exitCode).toBe(ExitCode.CONTENT_FILTER); + }); + it('maps unknown errors to GENERAL', () => { const err = mapApiError(500, { base_resp: { status_code: 0, status_msg: 'internal error' } }); expect(err.exitCode).toBe(ExitCode.GENERAL); From 8feefbc488a62ffb93e426cbb7520015112ed62c Mon Sep 17 00:00:00 2001 From: renaissance04 <3103792194@qq.com> Date: Sun, 6 Sep 2026 21:55:59 +0800 Subject: [PATCH 3/3] handle input sensitivity (1026) separately; narrow output match --- src/errors/api.ts | 4 ++-- test/errors/api.test.ts | 9 +++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/errors/api.ts b/src/errors/api.ts index 6982d691..48fb3013 100644 --- a/src/errors/api.ts +++ b/src/errors/api.ts @@ -75,7 +75,7 @@ export function mapApiError(status: number, body: ApiErrorBody, url?: string): C (/sensitive content/i.test(apiMsg) || /(?:^|\D)1026(?:\D|$)/.test(apiMsg)); // MiniMax content sensitivity filter - if (apiCode === 1002 || apiCode === 1039 || isV2ContentFilter) { + if (apiCode === 1002 || apiCode === 1039 || apiCode === 1026 || isV2ContentFilter) { const filterType = body.base_resp?.status_msg || body.error?.message || @@ -107,7 +107,7 @@ export function mapApiError(status: number, body: ApiErrorBody, url?: string): C } // output sensitivity (status_code 1027, e.g. "output new_sensitive") - if (apiCode === 1027 || /new_sensitive/i.test(apiMsg) || /output.*sensitive/i.test(apiMsg)) { + if (apiCode === 1027 || /output.*sensitive/i.test(apiMsg)) { return new CLIError( `Output withheld by content moderation (${apiMsg}).`, ExitCode.CONTENT_FILTER, diff --git a/test/errors/api.test.ts b/test/errors/api.test.ts index 83e01d3c..6a56f329 100644 --- a/test/errors/api.test.ts +++ b/test/errors/api.test.ts @@ -90,6 +90,15 @@ describe('mapApiError', () => { expect(err.exitCode).toBe(ExitCode.CONTENT_FILTER); }); + it('maps input sensitivity code 1026 to CONTENT_FILTER (not output)', () => { + const err = mapApiError(200, { + base_resp: { status_code: 1026, status_msg: 'input new_sensitive' }, + }); + expect(err.exitCode).toBe(ExitCode.CONTENT_FILTER); + expect(err.message).toContain('Input'); + expect(err.message).not.toContain('Output withheld'); + }); + it('maps unknown errors to GENERAL', () => { const err = mapApiError(500, { base_resp: { status_code: 0, status_msg: 'internal error' } }); expect(err.exitCode).toBe(ExitCode.GENERAL);