@@ -6,6 +6,7 @@ import { SessionManager } from "@earendil-works/pi-coding-agent";
66import type { EmbeddedRunAttemptParams } from "openclaw/plugin-sdk/agent-harness" ;
77import {
88 embeddedAgentLog ,
9+ nativeHookRelayTesting ,
910 PREEMPTIVE_OVERFLOW_ERROR_TEXT ,
1011 queueAgentHarnessMessage ,
1112 type HarnessContextEngine as ContextEngine ,
@@ -311,6 +312,22 @@ function getRequestInputTextAt(
311312 . join ( "\n" ) ;
312313}
313314
315+ function extractRelayIdFromThreadRequest ( params : unknown ) : string {
316+ const config = ( params as { config ?: Record < string , unknown > } ) . config ;
317+ const entries = config ?. [ "hooks.PreToolUse" ] ;
318+ if ( ! Array . isArray ( entries ) ) {
319+ throw new Error ( "pre-tool hook config missing" ) ;
320+ }
321+ const command = ( entries as Array < { hooks ?: Array < { command ?: string } > } > )
322+ . flatMap ( ( entry ) => entry . hooks ?? [ ] )
323+ . find ( ( hook ) => typeof hook . command === "string" ) ?. command ;
324+ const match = command ?. match ( / - - r e l a y - i d ( [ ^ ] + ) / ) ;
325+ if ( ! match ?. [ 1 ] ) {
326+ throw new Error ( `relay id missing from command: ${ command } ` ) ;
327+ }
328+ return match [ 1 ] ;
329+ }
330+
314331type CodexNativeThreadLifecycleEvent = Extract <
315332 DiagnosticEventPayload ,
316333 { type : "codex.native_thread.lifecycle" }
@@ -337,6 +354,7 @@ describe("runCodexAppServerAttempt context-engine lifecycle", () => {
337354
338355 afterEach ( async ( ) => {
339356 resetCodexAppServerClientFactoryForTest ( ) ;
357+ nativeHookRelayTesting . clearNativeHookRelaysForTests ( ) ;
340358 resetDiagnosticEventsForTest ( ) ;
341359 vi . restoreAllMocks ( ) ;
342360 await fs . rm ( tempDir , { recursive : true , force : true } ) ;
@@ -1568,14 +1586,19 @@ describe("runCodexAppServerAttempt context-engine lifecycle", () => {
15681586 params . contextEngine = contextEngine ;
15691587 params . contextTokenBudget = 16_000 ;
15701588
1571- const result = await runCodexAppServerAttempt ( params ) ;
1589+ const result = await runCodexAppServerAttempt ( params , {
1590+ nativeHookRelay : { enabled : true , events : [ "pre_tool_use" ] } ,
1591+ } ) ;
15721592
15731593 expect ( result . promptError ) . toBe ( PREEMPTIVE_OVERFLOW_ERROR_TEXT ) ;
15741594 expect ( result . promptErrorSource ) . toBe ( "precheck" ) ;
15751595 expect ( result . preflightRecovery ?. route ) . not . toBe ( "fits" ) ;
15761596 expect ( compact ) . not . toHaveBeenCalled ( ) ;
15771597 expect ( assemble ) . toHaveBeenCalledTimes ( 2 ) ;
15781598 expect ( await readCodexAppServerBinding ( sessionFile ) ) . toBeUndefined ( ) ;
1599+ const startRequest = harness . requests . find ( ( request ) => request . method === "thread/start" ) ;
1600+ const relayId = extractRelayIdFromThreadRequest ( startRequest ?. params ) ;
1601+ expect ( nativeHookRelayTesting . getNativeHookRelayRegistrationForTests ( relayId ) ) . toBeUndefined ( ) ;
15791602 expect ( harness . requests . map ( ( request ) => request . method ) ) . toEqual ( [
15801603 "thread/resume" ,
15811604 "thread/start" ,
0 commit comments