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}