@@ -110,6 +110,7 @@ const MAX_TOOL_OUTPUT_DELTA_MESSAGES_PER_ITEM = 20;
110110const TOOL_TRANSCRIPT_OUTPUT_MAX_CHARS = 12_000 ;
111111const GENERATED_IMAGE_MEDIA_SUBDIR = "tool-image-generation" ;
112112const BYTES_PER_MB = 1024 * 1024 ;
113+ const SHELL_INVOCATION_FAILURE_EXIT_CODES = new Set ( [ 126 , 127 ] ) ;
113114// Match OpenClaw's default image media cap for generated image tool outputs.
114115const DEFAULT_GENERATED_IMAGE_MAX_BYTES = 6 * BYTES_PER_MB ;
115116const TRANSCRIPT_PROGRESS_SUPPRESSED_TOOL_NAMES = new Set ( [
@@ -1924,6 +1925,9 @@ function itemTitle(item: CodexThreadItem): string {
19241925function itemStatus ( item : CodexThreadItem ) : "completed" | "failed" | "running" | "blocked" {
19251926 const status = readItemString ( item , "status" ) ;
19261927 if ( status === "failed" ) {
1928+ if ( isCompletedCommandExit ( item ) ) {
1929+ return "completed" ;
1930+ }
19271931 return "failed" ;
19281932 }
19291933 if ( status === "declined" ) {
@@ -1939,6 +1943,17 @@ function isNonSuccessItemStatus(status: ReturnType<typeof itemStatus>): boolean
19391943 return status === "failed" || status === "blocked" ;
19401944}
19411945
1946+ function isCompletedCommandExit ( item : CodexThreadItem ) : boolean {
1947+ // Codex marks nonzero native shell exits as failed. OpenClaw's exec contract
1948+ // treats process exits as completed tool runs; callers read exitCode/output
1949+ // for command semantics, while 126/127 still mean the shell could not run it.
1950+ return (
1951+ item . type === "commandExecution" &&
1952+ typeof item . exitCode === "number" &&
1953+ ! SHELL_INVOCATION_FAILURE_EXIT_CODES . has ( item . exitCode )
1954+ ) ;
1955+ }
1956+
19421957function itemName ( item : CodexThreadItem ) : string | undefined {
19431958 if ( item . type === "dynamicToolCall" && typeof item . tool === "string" ) {
19441959 return item . tool ;
@@ -2082,7 +2097,7 @@ function itemToolResult(item: CodexThreadItem): { result?: Record<string, unknow
20822097 if ( item . type === "commandExecution" ) {
20832098 return {
20842099 result : sanitizeCodexAgentEventRecord ( {
2085- status : item . status ,
2100+ status : itemStatus ( item ) ,
20862101 exitCode : item . exitCode ,
20872102 durationMs : item . durationMs ,
20882103 } ) ,
@@ -2091,15 +2106,15 @@ function itemToolResult(item: CodexThreadItem): { result?: Record<string, unknow
20912106 if ( item . type === "fileChange" ) {
20922107 return {
20932108 result : sanitizeCodexAgentEventRecord ( {
2094- status : item . status ,
2109+ status : itemStatus ( item ) ,
20952110 changes : itemFileChanges ( item ) ,
20962111 } ) ,
20972112 } ;
20982113 }
20992114 if ( item . type === "mcpToolCall" ) {
21002115 return {
21012116 result : sanitizeCodexAgentEventRecord ( {
2102- status : item . status ,
2117+ status : itemStatus ( item ) ,
21032118 durationMs : item . durationMs ,
21042119 ...( item . error ? { error : item . error } : { } ) ,
21052120 ...( item . result ? { result : item . result } : { } ) ,
0 commit comments