code wiki / (root) / nx_actor_role_image_grader.nx

nx_actor_role_image_grader.nx source

↩ module page · 155 lines · 5484 B

1// nx_actor_role_image_grader.nx -- image-grading actor role. 2// 3// Wraps [[nx_image_grade_v2]] (other-agent primitive) as a cooperative 4// actor. Composes with the rest of the parallel-companion substrate so 5// the multiplexer interleaves image-grading output alongside LLM tokens 6// + audio scores + game actions. 7// 8// Phases: 9// Phase 0 (INIT): reserved 10// Phase 1 (GRADE): calls nx_image_grade_v2 on caller-provided buffer 11// Phase 2 (EMIT): pushes IMAGE_TILE message with payload = 12// report.error_code (0 = OK, else NX_IGV2_ERR_*) 13// Phase 3 (DONE): terminal 14 15import "nx_syscalls.nx" 16import "nx_tier.nx" 17import "nx_image_grade_v2.nx" 18import "nx_actor.nx" 19import "nx_message.nx" 20 21// ===== Sealed enum: NxImageGraderPhase ============================ 22 23const NX_IM_PHASE_INIT: nx_int = 0 24const NX_IM_PHASE_GRADE: nx_int = 1 25const NX_IM_PHASE_EMIT: nx_int = 2 26const NX_IM_PHASE_DONE: nx_int = 3 27const NX_IM_PHASE_N: nx_int = 4 28 29// ===== Sealed enum: NxImageGraderVerdict ========================== 30 31const NX_IM_V_STEPPED: nx_int = 0 32const NX_IM_V_COMPLETED: nx_int = 1 33const NX_IM_V_FAILED_GRADE: nx_int = 2 34const NX_IM_V_INVALID: nx_int = 3 35const NX_IM_V_NULL: nx_int = 4 36const NX_IM_V_N: nx_int = 5 37 38// ===== Struct: NxImageGraderCtx =================================== 39 40struct NxImageGraderCtx { 41 input_buf: *u8, 42 input_size: nx_int, 43 report: *NxIgv2Report, 44 last_error_code: nx_int, 45 detected_format: nx_int, 46 skin_pixel_count: nx_int, 47 current_phase: nx_int, 48 last_step_verdict: nx_int, 49} 50 51const NX_IM_CTX_BYTES: nx_int = 64 // 8 fields * 8 52 53// ===== Validators ================================================= 54 55func nx_im_phase_is_valid(p: nx_int) -> nx_int { 56 if p < 0 { return 0 } 57 if p >= NX_IM_PHASE_N { return 0 } 58 return 1 59} 60 61func nx_im_v_is_valid(v: nx_int) -> nx_int { 62 if v < 0 { return 0 } 63 if v >= NX_IM_V_N { return 0 } 64 return 1 65} 66 67// ===== Constructor ================================================ 68 69func nx_im_actor_new(input_buf: *u8, input_size: nx_int) -> *NxImageGraderCtx { 70 if (input_buf as i64) == 0 { return 0 as *NxImageGraderCtx } 71 if input_size <= 0 { return 0 as *NxImageGraderCtx } 72 let raw: *u8 = sys_mmap(NX_IM_CTX_BYTES) 73 let ctx: *NxImageGraderCtx = raw as *NxImageGraderCtx 74 ctx.input_buf = input_buf 75 ctx.input_size = input_size 76 ctx.report = 0 as *NxIgv2Report 77 ctx.last_error_code = -1 78 ctx.detected_format = NX_IGV2_FORMAT_UNKNOWN 79 ctx.skin_pixel_count = 0 80 ctx.current_phase = NX_IM_PHASE_INIT 81 ctx.last_step_verdict = NX_IM_V_STEPPED 82 return ctx 83} 84 85// ===== Phase helpers ============================================== 86 87func _im_step_grade(ctx: *NxImageGraderCtx) -> nx_int { 88 let r: *NxIgv2Report = nx_image_grade_v2(ctx.input_buf, ctx.input_size) 89 if (r as i64) == 0 { return NX_IM_V_FAILED_GRADE } 90 ctx.report = r 91 ctx.last_error_code = r.error_code 92 ctx.detected_format = r.source_format 93 ctx.skin_pixel_count = r.skin_pixel_count 94 return NX_IM_V_STEPPED 95} 96 97func _im_step_emit(ctx: *NxImageGraderCtx, 98 bus: *NxMessageBus, 99 sender_actor_id: nx_int, 100 now_us: nx_size) -> nx_int { 101 if (bus as i64) == 0 { return NX_IM_V_STEPPED } 102 nx_ms_send_fanout(bus, sender_actor_id, NX_MS_KIND_IMAGE_TILE, 103 ctx.last_error_code as nx_size, 8, now_us) 104 return NX_IM_V_STEPPED 105} 106 107// ===== Public step ================================================ 108 109func nx_im_actor_step(ctx: *NxImageGraderCtx, 110 sched: *NxActorScheduler, 111 bus: *NxMessageBus, 112 actor_id: nx_int, 113 now_us: nx_size) -> nx_int { 114 if (ctx as i64) == 0 { return NX_IM_V_NULL } 115 if ctx.current_phase >= NX_IM_PHASE_DONE { return NX_IM_V_COMPLETED } 116 var v: nx_int = NX_IM_V_STEPPED 117 if ctx.current_phase == NX_IM_PHASE_INIT { v = NX_IM_V_STEPPED } 118 if ctx.current_phase == NX_IM_PHASE_GRADE { v = _im_step_grade(ctx) } 119 if ctx.current_phase == NX_IM_PHASE_EMIT { v = _im_step_emit(ctx, bus, actor_id, now_us) } 120 ctx.last_step_verdict = v 121 ctx.current_phase = ctx.current_phase + 1 122 if (sched as i64) != 0 { nx_ac_step(sched, actor_id, 1000, now_us) } 123 if ctx.current_phase >= NX_IM_PHASE_DONE { 124 if (sched as i64) != 0 { nx_ac_complete(sched, actor_id) } 125 return NX_IM_V_COMPLETED 126 } 127 if v != NX_IM_V_STEPPED { 128 if (sched as i64) != 0 { nx_ac_fail(sched, actor_id) } 129 return v 130 } 131 return NX_IM_V_STEPPED 132} 133 134// ===== Accessors ================================================== 135 136func nx_im_actor_phase(ctx: *NxImageGraderCtx) -> nx_int { 137 if (ctx as i64) == 0 { return NX_IM_PHASE_DONE } 138 return ctx.current_phase 139} 140 141func nx_im_actor_error_code(ctx: *NxImageGraderCtx) -> nx_int { 142 if (ctx as i64) == 0 { return -1 } 143 return ctx.last_error_code 144} 145 146func nx_im_actor_format(ctx: *NxImageGraderCtx) -> nx_int { 147 if (ctx as i64) == 0 { return NX_IGV2_FORMAT_UNKNOWN } 148 return ctx.detected_format 149} 150 151func nx_im_actor_is_done(ctx: *NxImageGraderCtx) -> nx_int { 152 if (ctx as i64) == 0 { return 0 } 153 if ctx.current_phase >= NX_IM_PHASE_DONE { return 1 } 154 return 0 155}