mirror of
https://github.com/wu736139669/hapi.git
synced 2026-11-08 01:43:07 +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:
@@ -306,6 +306,18 @@ function extractStringArray(value: unknown): string[] {
|
||||
: [];
|
||||
}
|
||||
|
||||
function extractCodexErrorInfo(
|
||||
record: Record<string, unknown>,
|
||||
errorRecord: Record<string, unknown> | null
|
||||
): string | null {
|
||||
return asString(
|
||||
record.codexErrorInfo
|
||||
?? record.codex_error_info
|
||||
?? errorRecord?.codexErrorInfo
|
||||
?? errorRecord?.codex_error_info
|
||||
);
|
||||
}
|
||||
|
||||
function buildCollabAgentInput(item: Record<string, unknown>, toolName: string): Record<string, unknown> {
|
||||
const targets = extractStringArray(item.receiverThreadIds ?? item.receiver_thread_ids ?? item.targets);
|
||||
const input: Record<string, unknown> = {};
|
||||
@@ -526,12 +538,19 @@ export class AppServerEventConverter {
|
||||
|
||||
if (msgType === 'error') {
|
||||
const errorRecord = asRecord(msg.error);
|
||||
const willRetry = asBoolean(msg.will_retry ?? msg.willRetry ?? errorRecord?.will_retry ?? errorRecord?.willRetry) ?? false;
|
||||
const retryable = asBoolean(msg.will_retry ?? msg.willRetry ?? errorRecord?.will_retry ?? errorRecord?.willRetry);
|
||||
const willRetry = retryable ?? false;
|
||||
if (willRetry) {
|
||||
return [];
|
||||
}
|
||||
const error = asString(msg.message ?? msg.reason ?? errorRecord?.message);
|
||||
return error ? addEventScope([{ type: 'task_failed', error }], msgScope) : [];
|
||||
const codexErrorInfo = extractCodexErrorInfo(msg, errorRecord);
|
||||
return error ? addEventScope([{
|
||||
type: 'task_failed',
|
||||
...(retryable !== null ? { retryable } : {}),
|
||||
...(codexErrorInfo ? { codex_error_info: codexErrorInfo } : {}),
|
||||
error
|
||||
}], msgScope) : [];
|
||||
}
|
||||
|
||||
if (msgType === 'plan_update') {
|
||||
@@ -672,7 +691,9 @@ export class AppServerEventConverter {
|
||||
const statusRaw = asString(paramsRecord.status ?? turn.status);
|
||||
const status = statusRaw?.toLowerCase();
|
||||
const turnId = asString(turn.turnId ?? turn.turn_id ?? turn.id);
|
||||
const errorMessage = asString(paramsRecord.error ?? paramsRecord.message ?? paramsRecord.reason);
|
||||
const turnError = asRecord(paramsRecord.error ?? turn.error);
|
||||
const errorMessage = asString(paramsRecord.error ?? paramsRecord.message ?? paramsRecord.reason)
|
||||
?? asString(turnError?.message);
|
||||
|
||||
if (status === 'interrupted' || status === 'cancelled' || status === 'canceled') {
|
||||
events.push(scoped({ type: 'turn_aborted', ...(turnId ? { turn_id: turnId } : {}) }));
|
||||
@@ -680,7 +701,14 @@ export class AppServerEventConverter {
|
||||
}
|
||||
|
||||
if (status === 'failed' || status === 'error') {
|
||||
events.push(scoped({ type: 'task_failed', ...(turnId ? { turn_id: turnId } : {}), ...(errorMessage ? { error: errorMessage } : {}) }));
|
||||
const codexErrorInfo = extractCodexErrorInfo(paramsRecord, turnError);
|
||||
events.push(scoped({
|
||||
type: 'task_failed',
|
||||
...(turnId ? { turn_id: turnId } : {}),
|
||||
terminal_source: 'turn_completed',
|
||||
...(codexErrorInfo ? { codex_error_info: codexErrorInfo } : {}),
|
||||
...(errorMessage ? { error: errorMessage } : {})
|
||||
}));
|
||||
return events;
|
||||
}
|
||||
|
||||
@@ -702,12 +730,66 @@ export class AppServerEventConverter {
|
||||
return events;
|
||||
}
|
||||
|
||||
if (method === 'model/safetyBuffering/updated') {
|
||||
const model = asString(paramsRecord.model);
|
||||
const showBufferingUi = asBoolean(paramsRecord.showBufferingUi ?? paramsRecord.show_buffering_ui);
|
||||
if (!model || showBufferingUi === null) {
|
||||
return events;
|
||||
}
|
||||
events.push(scoped({
|
||||
type: 'model_safety_buffering',
|
||||
model,
|
||||
use_cases: extractStringArray(paramsRecord.useCases ?? paramsRecord.use_cases),
|
||||
reasons: extractStringArray(paramsRecord.reasons),
|
||||
show_buffering_ui: showBufferingUi,
|
||||
faster_model: asString(paramsRecord.fasterModel ?? paramsRecord.faster_model)
|
||||
}));
|
||||
return events;
|
||||
}
|
||||
|
||||
if (method === 'model/rerouted') {
|
||||
const fromModel = asString(paramsRecord.fromModel ?? paramsRecord.from_model);
|
||||
const toModel = asString(paramsRecord.toModel ?? paramsRecord.to_model);
|
||||
const reason = asString(paramsRecord.reason);
|
||||
if (fromModel && toModel && reason) {
|
||||
events.push(scoped({
|
||||
type: 'model_rerouted',
|
||||
from_model: fromModel,
|
||||
to_model: toModel,
|
||||
reason
|
||||
}));
|
||||
}
|
||||
return events;
|
||||
}
|
||||
|
||||
if (method === 'model/verification') {
|
||||
events.push(scoped({
|
||||
type: 'model_verification',
|
||||
verifications: extractStringArray(paramsRecord.verifications)
|
||||
}));
|
||||
return events;
|
||||
}
|
||||
|
||||
if (method === 'error') {
|
||||
const willRetry = asBoolean(paramsRecord.will_retry ?? paramsRecord.willRetry) ?? false;
|
||||
const errorRecord = asRecord(paramsRecord.error);
|
||||
const retryable = asBoolean(
|
||||
paramsRecord.will_retry
|
||||
?? paramsRecord.willRetry
|
||||
?? errorRecord?.will_retry
|
||||
?? errorRecord?.willRetry
|
||||
);
|
||||
const willRetry = retryable ?? false;
|
||||
if (willRetry) return events;
|
||||
const message = asString(paramsRecord.message) ?? asString(asRecord(paramsRecord.error)?.message);
|
||||
const message = asString(paramsRecord.message) ?? asString(errorRecord?.message);
|
||||
if (message) {
|
||||
events.push(scoped({ type: 'task_failed', error: message }));
|
||||
const codexErrorInfo = extractCodexErrorInfo(paramsRecord, errorRecord);
|
||||
events.push(scoped({
|
||||
type: 'task_failed',
|
||||
terminal_source: 'error',
|
||||
...(retryable !== null ? { retryable } : {}),
|
||||
...(codexErrorInfo ? { codex_error_info: codexErrorInfo } : {}),
|
||||
error: message
|
||||
}));
|
||||
}
|
||||
return events;
|
||||
}
|
||||
@@ -723,6 +805,7 @@ export class AppServerEventConverter {
|
||||
this.lastAgentMessageDeltaByItemId.set(itemId, delta);
|
||||
const prev = this.agentMessageBuffers.get(itemId) ?? '';
|
||||
this.agentMessageBuffers.set(itemId, prev + delta);
|
||||
events.push(scoped({ type: 'agent_message_delta' }));
|
||||
}
|
||||
return events;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user