diff --git a/build.zig b/build.zig index 08765bd1df..24a3a88f28 100644 --- a/build.zig +++ b/build.zig @@ -11,6 +11,7 @@ const grammar_build = @import("zig/build/grammar.zig"); const counters_build = @import("zig/build/metal_counters.zig"); const exl3_build = @import("zig/build/exl3.zig"); const exlr8_build = @import("zig/build/exlr8.zig"); +const server_build = @import("zig/build/server.zig"); const golden_build = @import("zig/build/golden.zig"); comptime { @@ -204,6 +205,7 @@ fn nativeServer(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.b .imports = &.{ .{ .name = "engine_api", .module = api }, .{ .name = "tokenizer", .module = tokenizer }, .{ .name = "template", .module = template }, .{ .name = "native_engines", .module = engines }, .{ .name = "checkpoint_cli", .module = b.createModule(.{ .root_source_file = b.path("zig/src/cli/cli.zig"), .target = target, .optimize = .ReleaseSafe, .link_libc = true, .imports = &.{ .{ .name = "native_engines", .module = engines }, exlr8_build.cliImport(b, target, .ReleaseSafe, engine) } }) } }, }) }); exe.root_module.addOptions("build_options", build_options); + _ = server_build.addTo(b, exe.root_module, target, .ReleaseSafe); if (test_step == null) { exe.root_module.strip = true; return exe; @@ -221,10 +223,13 @@ fn nativeServer(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.b .link_libc = true, .imports = &.{ .{ .name = "engine_api", .module = api }, .{ .name = "tokenizer", .module = tokenizer }, .{ .name = "template", .module = template } }, }); + const server_json = server_build.addTo(b, server_tests, target, .Debug); test_step.?.dependOn(&b.addRunArtifact(b.addTest(.{ .root_module = server_tests })).step); + test_step.?.dependOn(&b.addRunArtifact(b.addTest(.{ .root_module = server_json })).step); @import("zig/build/cortheon_fuzz.zig").add(b, target, api, tokenizer, template); // the parse half's tests, as their own test binary (zig/src/server/tool_parse_test.zig) const tool_parse_tests = b.addTest(.{ .root_module = b.createModule(.{ .root_source_file = b.path("zig/src/server/tool_parse_test.zig"), .target = target, .optimize = .Debug, .link_libc = true, .imports = &.{ .{ .name = "engine_api", .module = api }, .{ .name = "tokenizer", .module = tokenizer }, .{ .name = "template", .module = template } } }) }); + _ = server_build.addTo(b, tool_parse_tests.root_module, target, .Debug); test_step.?.dependOn(&b.addRunArtifact(tool_parse_tests).step); // the chat-template engine's tests (zig/src/core/template/tests.zig), which no other test binary reaches test_step.?.dependOn(&b.addRunArtifact(b.addTest(.{ .root_module = b.createModule(.{ .root_source_file = b.path("zig/src/core/template/tests.zig"), .target = target, .optimize = .Debug, .link_libc = true }) })).step); diff --git a/zig/build/cortheon_fuzz.zig b/zig/build/cortheon_fuzz.zig index b17d0e99d0..709bf01f37 100644 --- a/zig/build/cortheon_fuzz.zig +++ b/zig/build/cortheon_fuzz.zig @@ -20,6 +20,7 @@ pub fn add(b: *std.Build, target: std.Build.ResolvedTarget, api: *Module, tokeni }), .filters = &.{"cortheon.fuzz."}, }); + _ = @import("server.zig").addTo(b, harness.root_module, target, optimize); const step = b.step("fuzz-cortheon", "Cortheon's page, link, search and filter readers under the fuzz harness"); step.dependOn(&b.addRunArtifact(harness).step); } diff --git a/zig/build/cuda.zig b/zig/build/cuda.zig index eac681628c..a05e74ccd0 100644 --- a/zig/build/cuda.zig +++ b/zig/build/cuda.zig @@ -173,6 +173,7 @@ fn nativeServer(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.b .imports = &.{ .{ .name = "engine_api", .module = m.api }, .{ .name = "tokenizer", .module = tokenizer }, .{ .name = "template", .module = template }, .{ .name = "native_engines", .module = m.engines }, .{ .name = "checkpoint_cli", .module = checkpointCli(b, target, .ReleaseSafe, null, m.engines, core) } }, }) }); exe.root_module.addOptions("build_options", build_options); + _ = @import("server.zig").addTo(b, exe.root_module, target, .ReleaseSafe); if (!install_native) { exe.root_module.strip = true; return exe; @@ -201,9 +202,14 @@ pub fn hostTests(b: *std.Build, draft_ids: *std.Build.Module, build_options: *st .link_libc = true, .imports = &.{ .{ .name = "engine_api", .module = native_modules.api }, .{ .name = "tokenizer", .module = mods.tokenizer }, .{ .name = "template", .module = template } }, }); + const server_json = @import("server.zig").addTo(b, server_tests, host, .debug); const server_test = b.addRunArtifact(b.addTest(.{ .root_module = server_tests })); - step.dependOn(&server_test.step); - b.step("test-server-cpu", "The HTTP server's unit tests (routes, templates, tool parsing) without a GPU").dependOn(&server_test.step); + const json_test = b.addRunArtifact(b.addTest(.{ .root_module = server_json })); + const server_step = b.step("test-server-cpu", "The HTTP server's unit tests (routes, templates, tool parsing) without a GPU"); + for ([_]*std.Build.Step.Run{ server_test, json_test }) |run| { + step.dependOn(&run.step); + server_step.dependOn(&run.step); + } // the server goldens and Cortheon's fuzz step here when the target is not macOS, whose Metal build defines them if (server_steps) { golden_build.step(b, host, server_tests, native_modules.api, mods.tokenizer, template); diff --git a/zig/build/server.zig b/zig/build/server.zig new file mode 100644 index 0000000000..54b94bbe16 --- /dev/null +++ b/zig/build/server.zig @@ -0,0 +1,14 @@ +//! The server's shared JSON values, available to server and family modules. +const std = @import("std"); + +/// The server's JSON values as a module (zig/src/server/json.zig), so a family's serving code shares them. +pub fn json(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode) *std.Build.Module { + return b.createModule(.{ .root_source_file = b.path("zig/src/server/json.zig"), .target = target, .optimize = optimize }); +} + +/// Attach a server's shared JSON module; its tests run separately from the server's root. +pub fn addTo(b: *std.Build, m: *std.Build.Module, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode) *std.Build.Module { + const j = json(b, target, optimize); + m.addImport("json", j); + return j; +} diff --git a/zig/src/server/anthropic.zig b/zig/src/server/anthropic.zig index bf465e7ac2..c283689367 100644 --- a/zig/src/server/anthropic.zig +++ b/zig/src/server/anthropic.zig @@ -1,6 +1,6 @@ //! Anthropic's Messages routes over the chat handler: typed SSE events, tool_use blocks, count_tokens. const std = @import("std"); -const json = @import("json.zig"); +const json = @import("json"); const errors = @import("errors.zig"); const http_body = @import("http_body.zig"); const fields = @import("fields.zig"); diff --git a/zig/src/server/anthropic_translate.zig b/zig/src/server/anthropic_translate.zig index f70b6a112c..095ad66c0a 100644 --- a/zig/src/server/anthropic_translate.zig +++ b/zig/src/server/anthropic_translate.zig @@ -1,6 +1,6 @@ //! Anthropic Messages requests as the chat requests that run them (``anthropic_translate.translate``). const std = @import("std"); -const json = @import("json.zig"); +const json = @import("json"); const errors = @import("errors.zig"); const fields = @import("fields.zig"); const pyrepr = @import("pyrepr.zig"); diff --git a/zig/src/server/chat.zig b/zig/src/server/chat.zig index 7c702ef432..4921b742b0 100644 --- a/zig/src/server/chat.zig +++ b/zig/src/server/chat.zig @@ -1,7 +1,7 @@ //! One reply, as ``ChatApp.chat`` makes it: render, submit to the engine, stream text, reasoning and calls. const std = @import("std"); const api = @import("engine_api"); -const json = @import("json.zig"); +const json = @import("json"); const errors = @import("errors.zig"); const fields_mod = @import("fields.zig"); const reply_text = @import("reply_text.zig"); diff --git a/zig/src/server/chunk_plan.zig b/zig/src/server/chunk_plan.zig index 2a4505cdca..9c2ab0e3f3 100644 --- a/zig/src/server/chunk_plan.zig +++ b/zig/src/server/chunk_plan.zig @@ -1,6 +1,6 @@ //! Where a prompt's prefill chunks start (Python's PrefillPlan and message_markers): prompts that agree up to a start cut alike up to it. const std = @import("std"); -const json = @import("json.zig"); +const json = @import("json"); const errors = @import("errors.zig"); const prompt = @import("prompt.zig"); const Server = @import("server.zig").Server; diff --git a/zig/src/server/compact.zig b/zig/src/server/compact.zig index a295aba25b..fce4234e7b 100644 --- a/zig/src/server/compact.zig +++ b/zig/src/server/compact.zig @@ -1,6 +1,6 @@ //! Note and reply are ordinary greedy or keyed generations, so the same request compacts and answers the same way. const std = @import("std"); -const json = @import("json.zig"); +const json = @import("json"); const chat = @import("chat.zig"); const stored = @import("compact_mem.zig"); const server_mod = @import("server.zig"); diff --git a/zig/src/server/compact_mem.zig b/zig/src/server/compact_mem.zig index eca242ed0f..b45513bad6 100644 --- a/zig/src/server/compact_mem.zig +++ b/zig/src/server/compact_mem.zig @@ -1,6 +1,6 @@ //! The compaction note file and the hash of the messages a note already covers. const std = @import("std"); -const json = @import("json.zig"); +const json = @import("json"); const Server = @import("server.zig").Server; const Value = json.Value; const Allocator = std.mem.Allocator; diff --git a/zig/src/server/compact_test.zig b/zig/src/server/compact_test.zig index b78bf4eff2..986fd10922 100644 --- a/zig/src/server/compact_test.zig +++ b/zig/src/server/compact_test.zig @@ -1,7 +1,7 @@ //! Host checks for opt-in compaction. The fake engine records each prompt and answers OK. const std = @import("std"); const api = @import("engine_api"); -const json = @import("json.zig"); +const json = @import("json"); const errors = @import("errors.zig"); const model_text = @import("model_text.zig"); const chat = @import("chat.zig"); diff --git a/zig/src/server/completion_prompt_test.zig b/zig/src/server/completion_prompt_test.zig index ae32cef584..51fc932caf 100644 --- a/zig/src/server/completion_prompt_test.zig +++ b/zig/src/server/completion_prompt_test.zig @@ -1,7 +1,7 @@ //! Token ids in a completion prompt, top-level or nested: ids in the vocabulary are served, other values get a 400. const std = @import("std"); const api = @import("engine_api"); -const json = @import("json.zig"); +const json = @import("json"); const model_text = @import("model_text.zig"); const openai = @import("openai.zig"); const Server = @import("server.zig").Server; diff --git a/zig/src/server/cortheon/checks.zig b/zig/src/server/cortheon/checks.zig index 90a754c665..d6e7b53f76 100644 --- a/zig/src/server/cortheon/checks.zig +++ b/zig/src/server/cortheon/checks.zig @@ -1,6 +1,6 @@ //! Cortheon's checks before a reply ends: changed files tested before "done", researched answers naming sources. const std = @import("std"); -const json = @import("../json.zig"); +const json = @import("json"); const tools = @import("tools.zig"); const Value = json.Value; diff --git a/zig/src/server/cortheon/cortheon.zig b/zig/src/server/cortheon/cortheon.zig index fd51addf2d..665c4f5a68 100644 --- a/zig/src/server/cortheon/cortheon.zig +++ b/zig/src/server/cortheon/cortheon.zig @@ -1,6 +1,6 @@ //! Cortheon in the server (--cortheon): its reasoning program, web research before building, server-run web tools. const std = @import("std"); -const json = @import("../json.zig"); +const json = @import("json"); const chat = @import("../chat.zig"); const grammar = @import("../grammar.zig"); const prompt_mod = @import("../prompt.zig"); diff --git a/zig/src/server/cortheon/cortheon_test.zig b/zig/src/server/cortheon/cortheon_test.zig index 019fcf7f1d..2287eaac82 100644 --- a/zig/src/server/cortheon/cortheon_test.zig +++ b/zig/src/server/cortheon/cortheon_test.zig @@ -1,7 +1,7 @@ //! Cortheon end to end on a scripted engine and a stand-in web: rounds, research, streams, splices and checks. const std = @import("std"); const api = @import("engine_api"); -const json = @import("../json.zig"); +const json = @import("json"); const model_text = @import("../model_text.zig"); const openai = @import("../openai.zig"); const server_mod = @import("../server.zig"); diff --git a/zig/src/server/cortheon/loop.zig b/zig/src/server/cortheon/loop.zig index 6939e14580..52eb5db2cc 100644 --- a/zig/src/server/cortheon/loop.zig +++ b/zig/src/server/cortheon/loop.zig @@ -1,6 +1,6 @@ //! Cortheon's reply loop: rounds with the model's server tool calls run between them, checks at the end, one reply. const std = @import("std"); -const json = @import("../json.zig"); +const json = @import("json"); const errors = @import("../errors.zig"); const chat = @import("../chat.zig"); const tool_parse = @import("../tool_parse.zig"); diff --git a/zig/src/server/cortheon/memory.zig b/zig/src/server/cortheon/memory.zig index f90a11aa44..b067e8b255 100644 --- a/zig/src/server/cortheon/memory.zig +++ b/zig/src/server/cortheon/memory.zig @@ -1,6 +1,6 @@ //! What a reply's client never saw (server tool rounds, Cortheon notes), kept to splice back in front of it next turn. const std = @import("std"); -const json = @import("../json.zig"); +const json = @import("json"); const Value = json.Value; const Allocator = std.mem.Allocator; diff --git a/zig/src/server/cortheon/research.zig b/zig/src/server/cortheon/research.zig index ef07c1af5e..7483b53e32 100644 --- a/zig/src/server/cortheon/research.zig +++ b/zig/src/server/cortheon/research.zig @@ -1,6 +1,6 @@ //! Research before building: the model names searches, the server runs them and reads the best pages, as hidden rounds. const std = @import("std"); -const json = @import("../json.zig"); +const json = @import("json"); const errors = @import("../errors.zig"); const chat = @import("../chat.zig"); const ids = @import("../ids.zig"); diff --git a/zig/src/server/cortheon/search.zig b/zig/src/server/cortheon/search.zig index 36fadd40cf..590a216f30 100644 --- a/zig/src/server/cortheon/search.zig +++ b/zig/src/server/cortheon/search.zig @@ -1,6 +1,6 @@ //! Web search for Cortheon: DuckDuckGo's keyless HTML results, or Brave's search API when a key is set. const std = @import("std"); -const json = @import("../json.zig"); +const json = @import("json"); const html = @import("html.zig"); const Allocator = std.mem.Allocator; diff --git a/zig/src/server/cortheon/tools.zig b/zig/src/server/cortheon/tools.zig index 376706ee19..8901629781 100644 --- a/zig/src/server/cortheon/tools.zig +++ b/zig/src/server/cortheon/tools.zig @@ -1,6 +1,6 @@ //! Cortheon's server-run tools: their specs, which calls are theirs, and each call run into the text the model reads. const std = @import("std"); -const json = @import("../json.zig"); +const json = @import("json"); const search = @import("search.zig"); const Seen = @import("seen.zig").Seen; const Value = json.Value; diff --git a/zig/src/server/decisions.zig b/zig/src/server/decisions.zig index b3bd3b64fa..ad87626352 100644 --- a/zig/src/server/decisions.zig +++ b/zig/src/server/decisions.zig @@ -1,6 +1,6 @@ //! /v1/decisions checks a body the way 0.6.6 checks it, then scores through the engine hook when a family sets one. const std = @import("std"); -const json = @import("json.zig"); +const json = @import("json"); const errors = @import("errors.zig"); const fields = @import("fields.zig"); const pyrepr = @import("pyrepr.zig"); diff --git a/zig/src/server/decisions_test.zig b/zig/src/server/decisions_test.zig index 160622e9a9..ca3dc87acb 100644 --- a/zig/src/server/decisions_test.zig +++ b/zig/src/server/decisions_test.zig @@ -1,7 +1,7 @@ //! Request checks for /v1/decisions, and a fake engine hook that scores one choice. const std = @import("std"); const api = @import("engine_api"); -const json = @import("json.zig"); +const json = @import("json"); const errors = @import("errors.zig"); const openai = @import("openai.zig"); const model_text = @import("model_text.zig"); diff --git a/zig/src/server/fields.zig b/zig/src/server/fields.zig index cd2a9d7340..0ccdc64f18 100644 --- a/zig/src/server/fields.zig +++ b/zig/src/server/fields.zig @@ -1,6 +1,6 @@ //! Request field checks shared by every route: numbers, stops, thinking switches, efforts, probabilities. const std = @import("std"); -const json = @import("json.zig"); +const json = @import("json"); const errors = @import("errors.zig"); const Value = json.Value; const Cx = errors.Cx; diff --git a/zig/src/server/grammar.zig b/zig/src/server/grammar.zig index c8a68b5c97..543f08a265 100644 --- a/zig/src/server/grammar.zig +++ b/zig/src/server/grammar.zig @@ -1,7 +1,7 @@ //! Structured-output fields checked as ``engine.grammar.request_spec`` checks them; the engine enforces them. const std = @import("std"); const api = @import("engine_api"); -const json = @import("json.zig"); +const json = @import("json"); const errors = @import("errors.zig"); const pyrepr = @import("pyrepr.zig"); const tool_specs = @import("tool_specs.zig"); diff --git a/zig/src/server/hf_text.zig b/zig/src/server/hf_text.zig index 65c3a474d5..8a912a29e1 100644 --- a/zig/src/server/hf_text.zig +++ b/zig/src/server/hf_text.zig @@ -2,7 +2,7 @@ const std = @import("std"); const tokenizer = @import("tokenizer"); const template = @import("template"); -const json = @import("json.zig"); +const json = @import("json"); const model_text = @import("model_text.zig"); const Value = json.Value; const Allocator = std.mem.Allocator; diff --git a/zig/src/server/http_body.zig b/zig/src/server/http_body.zig index ad2951ebcc..257d11e1be 100644 --- a/zig/src/server/http_body.zig +++ b/zig/src/server/http_body.zig @@ -1,6 +1,6 @@ //! Bounded request bodies, fixed-length or chunked, refused as the Python server refuses them. const std = @import("std"); -const json = @import("json.zig"); +const json = @import("json"); const errors = @import("errors.zig"); const Conn = @import("http_conn.zig").Conn; const Allocator = std.mem.Allocator; diff --git a/zig/src/server/json.zig b/zig/src/server/json.zig index 2b69a19fc6..c0a035874f 100644 --- a/zig/src/server/json.zig +++ b/zig/src/server/json.zig @@ -5,6 +5,7 @@ const Allocator = std.mem.Allocator; pub const parse = @import("json_parse.zig").parse; pub const parseText = @import("json_parse.zig").parseText; pub const ParseResult = @import("json_parse.zig").Result; +pub const wtf8Encode = @import("json_parse.zig").wtf8Encode; pub const write = @import("json_write.zig").write; pub const writeString = @import("json_write.zig").writeString; pub const Options = @import("json_write.zig").Options; diff --git a/zig/src/server/live.zig b/zig/src/server/live.zig index cb0cbaf640..8a1f7df742 100644 --- a/zig/src/server/live.zig +++ b/zig/src/server/live.zig @@ -1,7 +1,7 @@ //! The live status line (connections, decode and prefill tok/s), redrawn in a terminal, and /health's copy of it. const std = @import("std"); const api = @import("engine_api"); -const json = @import("json.zig"); +const json = @import("json"); const log = @import("log.zig"); const Allocator = std.mem.Allocator; diff --git a/zig/src/server/logprobs.zig b/zig/src/server/logprobs.zig index 669c07f060..549ec9ea15 100644 --- a/zig/src/server/logprobs.zig +++ b/zig/src/server/logprobs.zig @@ -1,7 +1,7 @@ //! OpenAI ``logprobs`` (who may ask, ``choices[0].logprobs`` from the engine's rows) and vLLM's ``prompt_logprobs``. const std = @import("std"); const api = @import("engine_api"); -const json = @import("json.zig"); +const json = @import("json"); const errors = @import("errors.zig"); const reply_text = @import("reply_text.zig"); const Server = @import("server.zig").Server; diff --git a/zig/src/server/main.zig b/zig/src/server/main.zig index 4b85fca8cd..b2e0b971b5 100644 --- a/zig/src/server/main.zig +++ b/zig/src/server/main.zig @@ -1,6 +1,6 @@ //! ``tensorfold-native``: ``capabilities --json`` for the Python switch, and ``serve MODEL [flags]`` with no Python. const std = @import("std"); -const json = @import("json.zig"); +const json = @import("json"); const cli = @import("cli.zig"); const log = @import("log.zig"); const hub = @import("hub.zig"); diff --git a/zig/src/server/memory_routes.zig b/zig/src/server/memory_routes.zig index 5a168451b5..a8fa319137 100644 --- a/zig/src/server/memory_routes.zig +++ b/zig/src/server/memory_routes.zig @@ -1,7 +1,7 @@ //! Authenticated, read-only sizing diagnostics; unknown counters and plans are omitted rather than guessed. const std = @import("std"); const api = @import("engine_api"); -const json = @import("json.zig"); +const json = @import("json"); const process = @import("process_memory.zig"); const routes = @import("routes.zig"); const Server = @import("server.zig").Server; diff --git a/zig/src/server/messages.zig b/zig/src/server/messages.zig index 9559ed784b..978eb98aa3 100644 --- a/zig/src/server/messages.zig +++ b/zig/src/server/messages.zig @@ -1,6 +1,6 @@ //! Chat messages as the template sees them: leading instructions merged, text parts joined, call arguments as objects. const std = @import("std"); -const json = @import("json.zig"); +const json = @import("json"); const errors = @import("errors.zig"); const fields = @import("fields.zig"); const Value = json.Value; diff --git a/zig/src/server/model_text.zig b/zig/src/server/model_text.zig index 0b36055a7f..d7b56167ca 100644 --- a/zig/src/server/model_text.zig +++ b/zig/src/server/model_text.zig @@ -1,6 +1,6 @@ //! The tokenizer and chat template a server renders prompts and replies with (the tok and jinja branches plug in here). const std = @import("std"); -const json = @import("json.zig"); +const json = @import("json"); const Allocator = std.mem.Allocator; pub const RenderOptions = struct { diff --git a/zig/src/server/openai.zig b/zig/src/server/openai.zig index b8782aaf96..157ade230b 100644 --- a/zig/src/server/openai.zig +++ b/zig/src/server/openai.zig @@ -1,6 +1,6 @@ //! POST /v1/chat/completions and /v1/completions, JSON or SSE, as ``server.http`` answers them. const std = @import("std"); -const json = @import("json.zig"); +const json = @import("json"); const errors = @import("errors.zig"); const fields = @import("fields.zig"); const chat = @import("chat.zig"); diff --git a/zig/src/server/prompt.zig b/zig/src/server/prompt.zig index e68363bfe7..f02c112a39 100644 --- a/zig/src/server/prompt.zig +++ b/zig/src/server/prompt.zig @@ -1,6 +1,6 @@ //! Prompt ids from a request, as ``prepare_prompt`` and ``render_prompt_ids`` make them. const std = @import("std"); -const json = @import("json.zig"); +const json = @import("json"); const errors = @import("errors.zig"); const messages_mod = @import("messages.zig"); const model_text = @import("model_text.zig"); diff --git a/zig/src/server/pyrepr.zig b/zig/src/server/pyrepr.zig index d560773580..255232af62 100644 --- a/zig/src/server/pyrepr.zig +++ b/zig/src/server/pyrepr.zig @@ -1,6 +1,6 @@ //! Python's ``repr`` of decoded JSON, for refusal messages that quote a request's value. const std = @import("std"); -const json = @import("json.zig"); +const json = @import("json"); const Value = json.Value; const Allocator = std.mem.Allocator; diff --git a/zig/src/server/request_log.zig b/zig/src/server/request_log.zig index ea4c8b7997..7abf7e022e 100644 --- a/zig/src/server/request_log.zig +++ b/zig/src/server/request_log.zig @@ -1,6 +1,6 @@ //! TENSORFOLD_REQUEST_LOG: each chat and completion body appended as one JSON line, images redacted, for replays. const std = @import("std"); -const json = @import("json.zig"); +const json = @import("json"); const Value = json.Value; const Allocator = std.mem.Allocator; diff --git a/zig/src/server/responses.zig b/zig/src/server/responses.zig index 2e096025b5..e84a74d0a9 100644 --- a/zig/src/server/responses.zig +++ b/zig/src/server/responses.zig @@ -1,6 +1,6 @@ //! OpenAI's Responses API: each request runs as its chat completion, translated item by item and event by event. const std = @import("std"); -const json = @import("json.zig"); +const json = @import("json"); const errors = @import("errors.zig"); const http_body = @import("http_body.zig"); const openai = @import("openai.zig"); diff --git a/zig/src/server/responses_include_test.zig b/zig/src/server/responses_include_test.zig index e117f116b5..3039b8907b 100644 --- a/zig/src/server/responses_include_test.zig +++ b/zig/src/server/responses_include_test.zig @@ -1,6 +1,6 @@ //! Responses' include: OpenAI's values accepted and ignored, anything else refused by name. const std = @import("std"); -const json = @import("json.zig"); +const json = @import("json"); const errors = @import("errors.zig"); const responses_translate = @import("responses_translate.zig"); diff --git a/zig/src/server/responses_translate.zig b/zig/src/server/responses_translate.zig index 8b1b2b17f3..6a5f4c8282 100644 --- a/zig/src/server/responses_translate.zig +++ b/zig/src/server/responses_translate.zig @@ -1,6 +1,6 @@ //! A Responses request as the chat completion that runs it (``responses_translate.translate``). const std = @import("std"); -const json = @import("json.zig"); +const json = @import("json"); const errors = @import("errors.zig"); const fields = @import("fields.zig"); const pyrepr = @import("pyrepr.zig"); diff --git a/zig/src/server/root.zig b/zig/src/server/root.zig index 7630f5217a..29e2fecdde 100644 --- a/zig/src/server/root.zig +++ b/zig/src/server/root.zig @@ -1,5 +1,5 @@ //! The native HTTP server's surface: what main and the test servers build a server from. -pub const json = @import("json.zig"); +pub const json = @import("json"); pub const errors = @import("errors.zig"); pub const auth = @import("auth.zig"); pub const cli = @import("cli.zig"); @@ -17,7 +17,7 @@ pub const Config = server.Config; test { @import("std").testing.refAllDecls(@This()); - _ = @import("json.zig"); + _ = @import("json"); _ = @import("std_options.zig"); _ = @import("fields.zig"); _ = @import("reply_text.zig"); diff --git a/zig/src/server/routes.zig b/zig/src/server/routes.zig index 44981cdda9..35186a5eca 100644 --- a/zig/src/server/routes.zig +++ b/zig/src/server/routes.zig @@ -1,6 +1,6 @@ //! Method and path dispatch, as ``do_GET``, ``do_POST`` and ``do_DELETE`` route them. const std = @import("std"); -const json = @import("json.zig"); +const json = @import("json"); const http_conn = @import("http_conn.zig"); const http_body = @import("http_body.zig"); const auth = @import("auth.zig"); diff --git a/zig/src/server/serve.zig b/zig/src/server/serve.zig index da27cb6b0e..b5e73ed53b 100644 --- a/zig/src/server/serve.zig +++ b/zig/src/server/serve.zig @@ -1,7 +1,7 @@ //! A server's life: keys, the listening socket, the startup lines, the live line, and a clean stop on SIGTERM or SIGINT. const std = @import("std"); const api = @import("engine_api"); -const json = @import("json.zig"); +const json = @import("json"); const auth = @import("auth.zig"); const cli = @import("cli.zig"); const log = @import("log.zig"); diff --git a/zig/src/server/server.zig b/zig/src/server/server.zig index 011734ee9a..97ab3e9c0c 100644 --- a/zig/src/server/server.zig +++ b/zig/src/server/server.zig @@ -1,7 +1,7 @@ //! The server: one engine and tokenizer behind the HTTP routes, one thread a connection. const std = @import("std"); const api = @import("engine_api"); -const json = @import("json.zig"); +const json = @import("json"); const errors = @import("errors.zig"); const fields = @import("fields.zig"); const auth = @import("auth.zig"); diff --git a/zig/src/server/server_init_test.zig b/zig/src/server/server_init_test.zig index 627d8a7691..0a4872b177 100644 --- a/zig/src/server/server_init_test.zig +++ b/zig/src/server/server_init_test.zig @@ -1,7 +1,7 @@ //! A server init that fails after its idle keepalive started stops that ticker and frees all it took. const std = @import("std"); const api = @import("engine_api"); -const json = @import("json.zig"); +const json = @import("json"); const model_text = @import("model_text.zig"); const server = @import("server.zig"); const Allocator = std.mem.Allocator; diff --git a/zig/src/server/slide.zig b/zig/src/server/slide.zig index 0312840011..c57ddf819f 100644 --- a/zig/src/server/slide.zig +++ b/zig/src/server/slide.zig @@ -1,7 +1,7 @@ //! Sliding Weights over HTTP: /v1/slide/learn streams learning, /v1/slide/graph lists or clears facts, /slide draws. const std = @import("std"); const api = @import("engine_api"); -const json = @import("json.zig"); +const json = @import("json"); const sse = @import("sse.zig"); const http_body = @import("http_body.zig"); const routes = @import("routes.zig"); diff --git a/zig/src/server/slide_ask.zig b/zig/src/server/slide_ask.zig index fca6c989ef..57e3c8aa16 100644 --- a/zig/src/server/slide_ask.zig +++ b/zig/src/server/slide_ask.zig @@ -1,7 +1,7 @@ //! What a lesson asks the model and how replies become examples: chat replies, continuations, token ids. const std = @import("std"); const api = @import("engine_api"); -const json = @import("json.zig"); +const json = @import("json"); const chat = @import("chat.zig"); const prompt = @import("prompt.zig"); const errors = @import("errors.zig"); diff --git a/zig/src/server/slide_graph.zig b/zig/src/server/slide_graph.zig index 596da2b110..e975f5b081 100644 --- a/zig/src/server/slide_graph.zig +++ b/zig/src/server/slide_graph.zig @@ -1,7 +1,7 @@ //! The Sliding Weights fact graph: what was taught, how far each lesson is, where its neurons went; never the weights. const std = @import("std"); const api = @import("engine_api"); -const json = @import("json.zig"); +const json = @import("json"); const slide_model = @import("slide_model.zig"); const Allocator = std.mem.Allocator; const Io = std.Io; diff --git a/zig/src/server/slide_lesson.zig b/zig/src/server/slide_lesson.zig index fbcb5eb609..cb0784abca 100644 --- a/zig/src/server/slide_lesson.zig +++ b/zig/src/server/slide_lesson.zig @@ -1,7 +1,7 @@ //! A fact's lesson written by the model itself: the teller's questions, short answers, near misses, keep prompts. const std = @import("std"); const api = @import("engine_api"); -const json = @import("json.zig"); +const json = @import("json"); const chat = @import("chat.zig"); const prompt = @import("prompt.zig"); const errors = @import("errors.zig"); diff --git a/zig/src/server/slide_model.zig b/zig/src/server/slide_model.zig index 274f9bb59b..014fcca7c1 100644 --- a/zig/src/server/slide_model.zig +++ b/zig/src/server/slide_model.zig @@ -1,6 +1,6 @@ //! The served model as the Sliding Weights view draws it: its layers, its pockets, and the shards that hold them. const std = @import("std"); -const json = @import("json.zig"); +const json = @import("json"); const Allocator = std.mem.Allocator; const Io = std.Io; diff --git a/zig/src/server/slide_teacher.zig b/zig/src/server/slide_teacher.zig index a6743a0ce2..7d1534e111 100644 --- a/zig/src/server/slide_teacher.zig +++ b/zig/src/server/slide_teacher.zig @@ -1,7 +1,7 @@ //! What every lesson shares, written once: keep prompts with the model's answers, the personal bank, the turn's end. const std = @import("std"); const api = @import("engine_api"); -const json = @import("json.zig"); +const json = @import("json"); const log = @import("log.zig"); const prompts = @import("slide_prompts.zig"); const slide_ask = @import("slide_ask.zig"); diff --git a/zig/src/server/slide_think.zig b/zig/src/server/slide_think.zig index dce2cb1ba6..26f361597b 100644 --- a/zig/src/server/slide_think.zig +++ b/zig/src/server/slide_think.zig @@ -1,7 +1,7 @@ //! A lesson with thinking on: the model's reasoning to where it restates the question, then a learned recall line. const std = @import("std"); const api = @import("engine_api"); -const json = @import("json.zig"); +const json = @import("json"); const chat = @import("chat.zig"); const prompt = @import("prompt.zig"); const errors = @import("errors.zig"); diff --git a/zig/src/server/sse.zig b/zig/src/server/sse.zig index de30ac1212..0942a7e145 100644 --- a/zig/src/server/sse.zig +++ b/zig/src/server/sse.zig @@ -1,6 +1,6 @@ //! Server-sent events as the Python server frames them: the head, ``data:`` frames, typed ``event:`` frames, ``[DONE]``. const std = @import("std"); -const json = @import("json.zig"); +const json = @import("json"); const Conn = @import("http_conn.zig").Conn; const Allocator = std.mem.Allocator; diff --git a/zig/src/server/status_routes.zig b/zig/src/server/status_routes.zig index 89ee5c8488..9c220f4445 100644 --- a/zig/src/server/status_routes.zig +++ b/zig/src/server/status_routes.zig @@ -1,7 +1,7 @@ //! GET /health, /v1/models, /metrics, and the opt-in dashboard. const std = @import("std"); const api = @import("engine_api"); -const json = @import("json.zig"); +const json = @import("json"); const live = @import("live.zig"); const routes = @import("routes.zig"); const Server = @import("server.zig").Server; diff --git a/zig/src/server/tokens.zig b/zig/src/server/tokens.zig index 3a2e351921..81a3deed62 100644 --- a/zig/src/server/tokens.zig +++ b/zig/src/server/tokens.zig @@ -1,6 +1,6 @@ //! vLLM's /tokenize and /detokenize (the ids the chat and completion routes would run), and a reply's token SHA. const std = @import("std"); -const json = @import("json.zig"); +const json = @import("json"); const errors = @import("errors.zig"); const fields = @import("fields.zig"); const messages = @import("messages.zig"); diff --git a/zig/src/server/tool_grammar.zig b/zig/src/server/tool_grammar.zig index 27b76df1c9..f087833d5e 100644 --- a/zig/src/server/tool_grammar.zig +++ b/zig/src/server/tool_grammar.zig @@ -1,7 +1,7 @@ //! tool_choice "required" or a named function as a grammar: calls in the template's markup, arguments in their schema. const std = @import("std"); const api = @import("engine_api"); -const json = @import("json.zig"); +const json = @import("json"); const errors = @import("errors.zig"); const prompt = @import("prompt.zig"); const tool_specs = @import("tool_specs.zig"); diff --git a/zig/src/server/tool_params.zig b/zig/src/server/tool_params.zig index c59d11cfbe..51352dc5ec 100644 --- a/zig/src/server/tool_params.zig +++ b/zig/src/server/tool_params.zig @@ -1,6 +1,6 @@ //! Typed tool parameters: XML parameter text decoded by the offered schema (``tool_parameters.py``). const std = @import("std"); -const json = @import("json.zig"); +const json = @import("json"); const reply_text = @import("reply_text.zig"); const tool_specs = @import("tool_specs.zig"); const Value = json.Value; @@ -324,7 +324,7 @@ const Literal = struct { fn appendCode(a: Allocator, out: *std.ArrayList(u8), v: u21) Error!void { if (v > 0x10ffff) return error.Invalid; var buf: [4]u8 = undefined; - const n = @import("json_parse.zig").wtf8Encode(v, &buf); + const n = @import("json").wtf8Encode(v, &buf); try out.appendSlice(a, buf[0..n]); } diff --git a/zig/src/server/tool_parse.zig b/zig/src/server/tool_parse.zig index b660b3b73d..b496d0851a 100644 --- a/zig/src/server/tool_parse.zig +++ b/zig/src/server/tool_parse.zig @@ -1,6 +1,6 @@ //! Tool calls in a finished reply, every family's markup, as OpenAI tool_calls (``tools.parse_tool_calls_from_content``). const std = @import("std"); -const json = @import("json.zig"); +const json = @import("json"); const ids = @import("ids.zig"); const reply_text = @import("reply_text.zig"); const tool_params = @import("tool_params.zig"); diff --git a/zig/src/server/tool_parse_test.zig b/zig/src/server/tool_parse_test.zig index 7481f1e311..f503f88006 100644 --- a/zig/src/server/tool_parse_test.zig +++ b/zig/src/server/tool_parse_test.zig @@ -1,6 +1,6 @@ //! The tool_parse tests, as their own test binary: whole-reply parses and the close-call helpers. const std = @import("std"); -const json = @import("json.zig"); +const json = @import("json"); const tool_parse = @import("tool_parse.zig"); const parse = tool_parse.parse; const closeCall = tool_parse.closeCall; diff --git a/zig/src/server/tool_specs.zig b/zig/src/server/tool_specs.zig index 1a20f48025..cca2610dd8 100644 --- a/zig/src/server/tool_specs.zig +++ b/zig/src/server/tool_specs.zig @@ -1,6 +1,6 @@ //! Offered tools and tool_choice as the template should see them (``tools.active_tool_specs``). const std = @import("std"); -const json = @import("json.zig"); +const json = @import("json"); const errors = @import("errors.zig"); const Value = json.Value; const Cx = errors.Cx; diff --git a/zig/src/server/tool_stream.zig b/zig/src/server/tool_stream.zig index 74b8610e7b..b55659c239 100644 --- a/zig/src/server/tool_stream.zig +++ b/zig/src/server/tool_stream.zig @@ -1,6 +1,6 @@ //! Tool calls while they are written: XML calls as argument deltas, and the one-call policy's text filter. const std = @import("std"); -const json = @import("json.zig"); +const json = @import("json"); const ids = @import("ids.zig"); const reply_text = @import("reply_text.zig"); const tool_params = @import("tool_params.zig"); diff --git a/zig/src/server/tool_stream_test.zig b/zig/src/server/tool_stream_test.zig index e1ed215f02..d33ef34813 100644 --- a/zig/src/server/tool_stream_test.zig +++ b/zig/src/server/tool_stream_test.zig @@ -1,5 +1,5 @@ const std = @import("std"); -const json = @import("json.zig"); +const json = @import("json"); const tool_params = @import("tool_params.zig"); const stream = @import("tool_stream.zig"); const Streamer = stream.Streamer; diff --git a/zig/src/server/tool_streaming.zig b/zig/src/server/tool_streaming.zig index 700caedd7c..48fe167eea 100644 --- a/zig/src/server/tool_streaming.zig +++ b/zig/src/server/tool_streaming.zig @@ -1,6 +1,6 @@ //! The streaming half of tool calls: each finished call's opening delta, then its arguments (``stream_tool_call_deltas``). const std = @import("std"); -const json = @import("json.zig"); +const json = @import("json"); const tool_specs = @import("tool_specs.zig"); const Value = json.Value; const Allocator = std.mem.Allocator; diff --git a/zig/src/server/warm.zig b/zig/src/server/warm.zig index f02f8a0c7d..1bf80ce4b2 100644 --- a/zig/src/server/warm.zig +++ b/zig/src/server/warm.zig @@ -1,7 +1,7 @@ //! After a chat reply, the next turn's shared prompt prefilled in the background, so that turn resumes past the reply. const std = @import("std"); const api = @import("engine_api"); -const json = @import("json.zig"); +const json = @import("json"); const errors = @import("errors.zig"); const prompt_mod = @import("prompt.zig"); const chat = @import("chat.zig"); diff --git a/zig/tests/server/build.sh b/zig/tests/server/build.sh index 63dfaa28c2..b3587d521c 100755 --- a/zig/tests/server/build.sh +++ b/zig/tests/server/build.sh @@ -11,10 +11,10 @@ version="$(sed -n 's/^[[:space:]]*\.version = "\([0-9]*\.[0-9]*\.[0-9]*\)",$/\1/ options="$out/build_options.zig" printf 'pub const version = "%s";\n' "$version" > "$options" core=(--dep lanes "-Mengine_api=$root/zig/src/core/engine_api.zig" "-Mlanes=$root/zig/src/core/lanes/lanes.zig" - "-Mtokenizer=$root/zig/src/core/tokenizer/tokenizer.zig" "-Mtemplate=$root/zig/src/core/template/template.zig") + "-Mtokenizer=$root/zig/src/core/tokenizer/tokenizer.zig" "-Mtemplate=$root/zig/src/core/template/template.zig" "-Mjson=$root/zig/src/server/json.zig") "$zig" build-exe -lc -O "${OPT:-ReleaseSafe}" --dep server --dep engine_api "-Mroot=$root/zig/tests/server/fake_serve.zig" \ - --dep engine_api --dep tokenizer --dep template "-Mserver=$root/zig/src/server/root.zig" "${core[@]}" \ + --dep engine_api --dep tokenizer --dep template --dep json "-Mserver=$root/zig/src/server/root.zig" "${core[@]}" \ --name fake_serve -femit-bin="$out/fake_serve" -"$zig" build-exe -lc -O "${OPT:-ReleaseSafe}" --dep engine_api --dep tokenizer --dep template --dep native_engines --dep build_options \ +"$zig" build-exe -lc -O "${OPT:-ReleaseSafe}" --dep engine_api --dep tokenizer --dep template --dep json --dep native_engines --dep build_options \ "-Mroot=$root/zig/src/server/main.zig" --dep engine_api "-Mnative_engines=$root/zig/src/native/none.zig" "${core[@]}" \ "-Mbuild_options=$options" --name tensorfold-native -femit-bin="$out/tensorfold-native" diff --git a/zig/tests/server/zig_test.sh b/zig/tests/server/zig_test.sh index 4f583f439c..687071980d 100755 --- a/zig/tests/server/zig_test.sh +++ b/zig/tests/server/zig_test.sh @@ -3,10 +3,12 @@ set -euo pipefail zig="${ZIG:-zig}" root="$(cd "$(dirname "$0")/../../.." && pwd)" -"$zig" test -lc --dep engine_api --dep tokenizer --dep template \ +"$zig" test -lc --dep engine_api --dep tokenizer --dep template --dep json \ "-Mroot=$root/zig/src/server/root.zig" \ + "-Mjson=$root/zig/src/server/json.zig" \ --dep lanes "-Mengine_api=$root/zig/src/core/engine_api.zig" \ "-Mlanes=$root/zig/src/core/lanes/lanes.zig" \ "-Mtokenizer=$root/zig/src/core/tokenizer/tokenizer.zig" \ "-Mtemplate=$root/zig/src/core/template/template.zig" "$@" +"$zig" test "$root/zig/src/server/json.zig" "$zig" test -lc --dep lanes "-Mroot=$root/zig/src/core/engine_api.zig" "-Mlanes=$root/zig/src/core/lanes/lanes.zig"