code wiki / _hdl_build / nx_nofloat_serve.nx
nx_nofloat_serve.nx source
↩ module page · 215 lines · 10818 B
1// nx_nofloat_serve.nx -- the DEPLOYABLE no-float LLM daemon (ops shell around the gated pure core
2// nx_nofloat_serve_core). Binds 127.0.0.1:8032 and serves the interactive app + JSON API for the sovereign
3// 100pct-integer Qwen2.5-0.5B: POST /gen {prompt,max_new,mode} -> readable text (byte-level-BPE decoded),
4// GET / app page, GET /health, GET /api. FAIL-FAST startup (Rule 20): the model is loaded and BOTH
5// dequant-once caches are built BEFORE bind/listen -- a daemon that accepts is a daemon that can serve.
6// Single accept loop = requests naturally serialize (one 16-core box, one pool). WSL2 forwards localhost
7// to Windows, so the app is browsable at http://localhost:8032/ on the host. Runs forever; build with
8// --build-only, run deliberately (same pattern as nx_relate_daemon :8027). license_tier: ORIGINAL
9import "nx_nofloat_serve_core.nx"
10const NSD_MAGIC_131072: i64 = 131072
11const NSD_MAGIC_262144: i64 = 262144
12
13const NSD_PORT: i64 = 0x1f60 // 8032
14const NSD_MODEL: *u8 = "/home/elderwesto/nx_stage/nx_real_model.gguf"
15
16func nsd_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
17func nsd_pn(v: i64) -> i64 { let b: *u8=sys_mmap(28); var m: i64=v; if m<0{sys_write(1,"-" as *u8,1);m=0-m} let t: *u8=sys_mmap(28); var k: i64=0; if m==0{t[0]=48 as u8;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} var i: i64=0; while i<k{b[i]=t[k-1-i];i=i+1} sys_write(1,b,k); return 0 }
18
19// bind address as DATA (2026-09-16): argv[3] names the interface this seat listens on. The default stays the
20// loopback contract every existing caller has; "0.0.0.0" (or a LAN address) is the estate's swarm-node door, so a
21// NAS plan row may drive this engine over the LAN (nx_bright_rewrite_run engine=a.b.c.d:port). A LAN bind is an
22// announced decision, never a silent default: the ready line prints the address that actually accepted.
23func nsd_addr(out: *u8, port: i64, a: i64, b: i64, c: i64, d: i64) -> i64 {
24 out[0] = 2 as u8
25 out[1] = 0 as u8
26 out[2] = ((port >> 8) & 0xff) as u8
27 out[3] = (port & 0xff) as u8
28 out[4] = a as u8
29 out[5] = b as u8
30 out[6] = c as u8
31 out[7] = d as u8
32 var i: i64 = 8
33 while i < 16 { out[i] = 0 as u8; i = i + 1 }
34 return 0
35}
36// "a.b.c.d" -> q[0..3]; 1 ok / 0 malformed (any other text keeps the loopback default and is announced as such)
37func nsd_parse_ipv4(s: *u8, q: *i64) -> i64 {
38 var i: i64 = 0
39 var part: i64 = 0
40 var v: i64 = 0
41 var digits: i64 = 0
42 var go: i64 = 1
43 while go == 1 {
44 let c: i64 = s[i] & 0xff
45 if c == 0 { go = 0 } else {
46 if c == 46 {
47 if part > 2 { return 0 }
48 if digits == 0 { return 0 }
49 if v > 255 { return 0 }
50 q[part] = v; part = part + 1; v = 0; digits = 0
51 } else {
52 if c < 48 { return 0 }
53 if c > 57 { return 0 }
54 v = v * 10 + (c - 48); digits = digits + 1
55 }
56 i = i + 1
57 }
58 }
59 if part != 3 { return 0 }
60 if digits == 0 { return 0 }
61 if v > 255 { return 0 }
62 q[3] = v
63 return 1
64}
65func nsd_write_all(fd: i64, buf: *u8, n: i64) -> i64 {
66 var w: i64 = 0
67 while w < n { let k: i64 = sys_write(fd, (buf as i64 + w) as *u8, n - w); if k <= 0 { return 0 - 1 } w = w + k }
68 return 0
69}
70// read ONE full HTTP request: until CRLFCRLF, plus Content-Length body bytes if present. returns total.
71func nsd_read_req(fd: i64, buf: *u8, cap: i64) -> i64 {
72 var n: i64 = 0
73 var hdr_end: i64 = 0 - 1
74 var want: i64 = 0 - 1
75 var go: i64 = 1
76 while go == 1 {
77 if n >= cap - 1 { go = 0 } else {
78 let r: i64 = sys_read(fd, (buf as i64 + n) as *u8, cap - 1 - n)
79 if r <= 0 { go = 0 } else {
80 n = n + r
81 if hdr_end < 0 {
82 var i: i64 = 0
83 while i + 3 < n {
84 if buf[i] == (13 as u8) { if buf[i+1] == (10 as u8) { if buf[i+2] == (13 as u8) { if buf[i+3] == (10 as u8) { hdr_end = i + 4; i = n } } } }
85 i = i + 1
86 }
87 if hdr_end >= 0 {
88 var cl: i64 = 0 - 1
89 let key: *u8 = "Content-Length:" as *u8
90 let kl: i64 = 15
91 var j: i64 = 0
92 while j + kl < hdr_end {
93 var k2: i64 = 0
94 var ok: i64 = 1
95 while k2 < kl { if buf[j+k2] != key[k2] { ok = 0; k2 = kl } else { k2 = k2 + 1 } }
96 if ok == 1 {
97 var p2: i64 = j + kl
98 cl = 0
99 var num: i64 = 1
100 while num == 1 {
101 if p2 >= hdr_end { num = 0 } else {
102 let c: i64 = buf[p2] & 0xff
103 if c == 32 { p2 = p2 + 1 } else {
104 if c >= 48 { if c <= 57 { cl = cl * 10 + (c - 48); p2 = p2 + 1 } else { num = 0 } } else { num = 0 }
105 }
106 }
107 }
108 j = hdr_end
109 }
110 j = j + 1
111 }
112 if cl >= 0 { want = hdr_end + cl } else { want = hdr_end }
113 }
114 }
115 if want >= 0 { if n >= want { go = 0 } }
116 }
117 }
118 }
119 return n
120}
121
122// argv (both optional, defaults = the original :8032 instruct contract -- no hardcode, one binary
123// serves any model/port pair): argv[1]=model gguf path, argv[2]=port. The CODER serve for the forge
124// runs the SAME elf as `nx_nofloat_serve.sov.elf <nx_coder_model.gguf> 8033` (port registry:
125// 8031 survey, 8032 instruct app, 11434/11438 f32 seats -> 8033 = coder no-float serve).
126func main(argc: i64, argv: *i64) -> i64 {
127 var model: *u8 = NSD_MODEL
128 var port: i64 = NSD_PORT
129 if argc >= 2 { model = argv[1] as *u8 }
130 if argc >= 3 {
131 let ps: *u8 = argv[2] as *u8
132 var pv: i64 = 0
133 var pi: i64 = 0
134 while ps[pi] != (0 as u8) {
135 let c: i64 = ps[pi] & 0xff
136 if c >= 48 { if c <= 57 { pv = pv * 10 + (c - 48) } }
137 pi = pi + 1
138 }
139 if pv > 0 { port = pv }
140 }
141 nsd_puts("NX-NOFLOAT-SERVE loading model + building dequant-once caches (fail-fast before bind)...\n" as *u8)
142 nsd_puts(" model=" as *u8)
143 nsd_puts(model)
144 nsd_puts(" port=" as *u8)
145 nsd_pn(port)
146 // argv[4] = weight route: "q4k" = LM4 resident-Q4_K (file-mapped weights dotted in place, no layer caches --
147 // the only route that fits a 7B in a 16 GB VM); anything else = the incumbent dequant-once i32+i8 caches.
148 // argv[4] = "i8": the memory-proportionate i8-only route (nsv_init_i8, no i32 cache: ~6 GB less at 1.5B), the
149 // route a LAN rewrite engine runs beside other jobs; /gen then defaults to i8 and refuses an explicit i32.
150 var q4k: i64 = 0
151 var i8only: i64 = 0
152 if argc >= 5 {
153 let ms: *u8 = argv[4] as *u8
154 if ms[0] == (113 as u8) { if ms[1] == (52 as u8) { if ms[2] == (107 as u8) { if ms[3] == (0 as u8) { q4k = 1 } } } }
155 if ms[0] == (105 as u8) { if ms[1] == (56 as u8) { if ms[2] == (0 as u8) { i8only = 1 } } }
156 if ms[0] == (113 as u8) { if ms[1] == (56 as u8) { if ms[2] == (0 as u8) { q4k = 1 } } } // "q8": the same resident lane over a Q8_0 gguf (search R0s block-native slots)
157 }
158 if q4k == 1 { nsd_puts(" route=q4k-resident" as *u8) } else { if i8only == 1 { nsd_puts(" route=i8-only" as *u8) } else { nsd_puts(" route=dequant-once-i32+i8" as *u8) } }
159 nsd_puts("\n" as *u8)
160 var rc: i64 = 0
161 if q4k == 1 { rc = nsv_init_q4k(model) } else { if i8only == 1 { rc = nsv_init_i8(model) } else { rc = nsv_init(model) } }
162 if rc != 0 {
163 nsd_puts("NX-NOFLOAT-SERVE init FAILED rc=" as *u8)
164 nsd_pn(rc)
165 nsd_puts(" (model missing/unparseable or cache OOM) -- fail closed, fail loud\n" as *u8)
166 return 1
167 }
168 // argv[3] = bind address (default loopback). A dotted quad binds that interface; anything else keeps the
169 // default and says so, so a typo can never silently expose or silently hide the seat.
170 let q: *i64 = sys_mmap(32) as *i64
171 q[0] = 127; q[1] = 0; q[2] = 0; q[3] = 1
172 var bind_note: *u8 = "loopback (default)" as *u8
173 if argc >= 4 {
174 let bs: *u8 = argv[3] as *u8
175 if nsd_parse_ipv4(bs, q) == 1 { bind_note = "argv[3]" as *u8 } else { q[0] = 127; q[1] = 0; q[2] = 0; q[3] = 1; bind_note = "argv[3] not a dotted quad -- loopback kept" as *u8 }
176 }
177 let addr: *u8 = sys_mmap(16)
178 nsd_addr(addr, port, q[0], q[1], q[2], q[3])
179 let lfd: i64 = sys_socket(AF_INET, SOCK_STREAM, 0)
180 if lfd < 0 { nsd_puts("NX-NOFLOAT-SERVE socket FAILED\n" as *u8); return 1 }
181 if sys_bind(lfd, addr, 16) < 0 {
182 nsd_puts("NX-NOFLOAT-SERVE bind " as *u8)
183 nsd_pn(q[0]); nsd_puts("." as *u8); nsd_pn(q[1]); nsd_puts("." as *u8); nsd_pn(q[2]); nsd_puts("." as *u8); nsd_pn(q[3]); nsd_puts(":" as *u8)
184 nsd_pn(port)
185 nsd_puts(" FAILED (port busy?)\n" as *u8)
186 return 1
187 }
188 if sys_listen(lfd, 16) < 0 { nsd_puts("NX-NOFLOAT-SERVE listen FAILED\n" as *u8); return 1 }
189 nsd_puts("NX-NOFLOAT-SERVE ready http://" as *u8)
190 nsd_pn(q[0]); nsd_puts("." as *u8); nsd_pn(q[1]); nsd_puts("." as *u8); nsd_pn(q[2]); nsd_puts("." as *u8); nsd_pn(q[3]); nsd_puts(":" as *u8)
191 nsd_pn(port)
192 nsd_puts(" bind=" as *u8); nsd_puts(bind_note)
193 nsd_puts("/ (modes i32 lossless / i8 fast; /gen /embed /health /api; accept loop)\n" as *u8)
194 let reqb: *u8 = sys_mmap(NSD_MAGIC_131072)
195 let resb: *u8 = sys_mmap(NSD_MAGIC_262144)
196 var go: i64 = 1
197 while go == 1 {
198 let cfd: i64 = sys_accept(lfd)
199 // DoS-starvation bound (nx_dos_timeout_scan seq321): one peer declaring a body it never finishes
200 // sending would otherwise starve this accept loop forever. ACCEPT_TMO_S is the shared named bound.
201 if cfd >= 0 { sys_set_socket_timeout(cfd, ACCEPT_TMO_S) }
202 if cfd >= 0 {
203 let rn: i64 = nsd_read_req(cfd, reqb, NSD_MAGIC_131072)
204 if rn > 0 {
205 // streaming route first (SSE writes straight to the socket); 0 = not-a-stream -> buffered path
206 if nsv_handle_stream(cfd, reqb, rn) == 0 {
207 let on: i64 = nsv_handle(reqb, rn, resb, NSD_MAGIC_262144)
208 nsd_write_all(cfd, resb, on)
209 }
210 }
211 sys_close(cfd)
212 }
213 }
214 return 0
215}