mirror of
https://github.com/wu736139669/hapi.git
synced 2026-10-15 20:29:55 +00:00
fix(codex): preserve native safety behavior (#1024)
* test: reproduce issue #1020 * fix: preserve Codex safety behavior (closes #1020) * test: cover Codex safety buffering dismissal * test: cover Codex safety retry edge cases * fix: keep dismissed safety buffering prompts hidden
This commit is contained in:
@@ -72,7 +72,12 @@ describe('AppServerEventConverter', () => {
|
||||
expect(interrupted).toEqual([{ type: 'turn_aborted', turn_id: 'turn-1' }]);
|
||||
|
||||
const failed = converter.handleNotification('turn/completed', { turn: { id: 'turn-1' }, status: 'Failed', message: 'boom' });
|
||||
expect(failed).toEqual([{ type: 'task_failed', turn_id: 'turn-1', error: 'boom' }]);
|
||||
expect(failed).toEqual([{
|
||||
type: 'task_failed',
|
||||
turn_id: 'turn-1',
|
||||
terminal_source: 'turn_completed',
|
||||
error: 'boom'
|
||||
}]);
|
||||
});
|
||||
|
||||
it('accumulates agent message deltas', () => {
|
||||
@@ -693,6 +698,120 @@ describe('AppServerEventConverter', () => {
|
||||
expect(events).toEqual([{ type: 'task_failed', error: 'fatal' }]);
|
||||
});
|
||||
|
||||
it('preserves typed non-retryable cyber-policy errors', () => {
|
||||
const converter = new AppServerEventConverter();
|
||||
|
||||
const events = converter.handleNotification('error', {
|
||||
threadId: 'thread-1',
|
||||
turnId: 'turn-1',
|
||||
error: {
|
||||
message: 'This content was flagged for possible cybersecurity risk.',
|
||||
codexErrorInfo: 'cyberPolicy'
|
||||
},
|
||||
willRetry: false
|
||||
});
|
||||
|
||||
expect(events).toEqual([{
|
||||
type: 'task_failed',
|
||||
thread_id: 'thread-1',
|
||||
turn_id: 'turn-1',
|
||||
terminal_source: 'error',
|
||||
retryable: false,
|
||||
codex_error_info: 'cyberPolicy',
|
||||
error: 'This content was flagged for possible cybersecurity risk.'
|
||||
}]);
|
||||
});
|
||||
|
||||
it('preserves cyber-policy metadata from wrapped and completed-turn errors', () => {
|
||||
const converter = new AppServerEventConverter();
|
||||
|
||||
expect(converter.handleNotification('codex/event/error', {
|
||||
msg: {
|
||||
type: 'error',
|
||||
thread_id: 'thread-1',
|
||||
turn_id: 'turn-1',
|
||||
message: 'wrapped policy failure',
|
||||
codex_error_info: 'cyber_policy',
|
||||
will_retry: false
|
||||
}
|
||||
})).toEqual([{
|
||||
type: 'task_failed',
|
||||
thread_id: 'thread-1',
|
||||
turn_id: 'turn-1',
|
||||
retryable: false,
|
||||
codex_error_info: 'cyber_policy',
|
||||
error: 'wrapped policy failure'
|
||||
}]);
|
||||
|
||||
expect(converter.handleNotification('turn/completed', {
|
||||
threadId: 'thread-1',
|
||||
turn: {
|
||||
id: 'turn-1',
|
||||
status: 'failed',
|
||||
error: {
|
||||
message: 'completed policy failure',
|
||||
codexErrorInfo: 'CyberPolicy'
|
||||
}
|
||||
}
|
||||
})).toEqual([{
|
||||
type: 'task_failed',
|
||||
thread_id: 'thread-1',
|
||||
turn_id: 'turn-1',
|
||||
terminal_source: 'turn_completed',
|
||||
codex_error_info: 'CyberPolicy',
|
||||
error: 'completed policy failure'
|
||||
}]);
|
||||
});
|
||||
|
||||
it('maps Codex model safety notifications', () => {
|
||||
const converter = new AppServerEventConverter();
|
||||
|
||||
expect(converter.handleNotification('model/safetyBuffering/updated', {
|
||||
threadId: 'thread-1',
|
||||
turnId: 'turn-1',
|
||||
model: 'gpt-5.4',
|
||||
useCases: ['cyber'],
|
||||
reasons: ['review'],
|
||||
showBufferingUi: true,
|
||||
fasterModel: 'gpt-5.4-mini'
|
||||
})).toEqual([{
|
||||
type: 'model_safety_buffering',
|
||||
thread_id: 'thread-1',
|
||||
turn_id: 'turn-1',
|
||||
model: 'gpt-5.4',
|
||||
use_cases: ['cyber'],
|
||||
reasons: ['review'],
|
||||
show_buffering_ui: true,
|
||||
faster_model: 'gpt-5.4-mini'
|
||||
}]);
|
||||
|
||||
expect(converter.handleNotification('model/rerouted', {
|
||||
threadId: 'thread-1',
|
||||
turnId: 'turn-1',
|
||||
fromModel: 'gpt-5.4',
|
||||
toModel: 'gpt-5.4-codex',
|
||||
reason: 'highRiskCyberActivity'
|
||||
})).toEqual([{
|
||||
type: 'model_rerouted',
|
||||
thread_id: 'thread-1',
|
||||
turn_id: 'turn-1',
|
||||
from_model: 'gpt-5.4',
|
||||
to_model: 'gpt-5.4-codex',
|
||||
reason: 'highRiskCyberActivity'
|
||||
}]);
|
||||
|
||||
expect(converter.handleNotification('model/verification', {
|
||||
threadId: 'thread-1',
|
||||
turnId: 'turn-1',
|
||||
verifications: ['trustedAccessForCyber']
|
||||
})).toEqual([{
|
||||
type: 'model_verification',
|
||||
thread_id: 'thread-1',
|
||||
turn_id: 'turn-1',
|
||||
verifications: ['trustedAccessForCyber']
|
||||
}]);
|
||||
});
|
||||
|
||||
it('maps thread/compacted notifications', () => {
|
||||
const converter = new AppServerEventConverter();
|
||||
const events = converter.handleNotification('thread/compacted', {
|
||||
|
||||
Reference in New Issue
Block a user