Repository navigation
Split modules into model (core), codec, contract (client) and implementations (client-*); byte[] SPIs - #35
Merged
Merged
Conversation
…ign names core keeps the TypeSafeClient interface, its decorators, TypeSafeException, the model and the JsonCodec SPI. DefaultTypeSafeClient, ApiKey and the HttpTransport SPI move to the new client-http module, so the compiler now enforces that core never sees the HTTP client; TypeSafeClient.builder() becomes DefaultTypeSafeClient.builder(). Every module's directory, artifact and package share one name: client-http-jdk, client-http-okhttp, codec-jackson2, codec-jackson3, client-local, client-mapping, client-testkit (io.github.dfa1.typesafe.<module>, dashes as dots). No client-* module depends on another in production. ADR 0003 records the layout (closes #12). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ckage The core artifact held two packages (core, codec); every other module holds exactly the package its name gives. JsonCodec now sits in core directly, as HttpTransport sits in client.http. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
core is now the model and JsonCodec only; the client contract (TypeSafeClient, TypeSafeException, Retrying/DeadlineTypeSafeClient, TokenCounter) is the new client module, which every client-* module builds on. Serializing the model (core + a codec) no longer pulls in any client code, and a module named X-Y now always builds on module X. ADR 0003 rewritten to match. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
JSON goes to and from the wire as UTF-8 bytes: writeValueAsBytes / writeValueAsPrettyBytes / readValue(byte[], ...), and a byte[] body on HttpTransport.post and HttpTransportResponse. No String copy on the success path; bodies become text only for error messages. Jackson2Codec enables COMBINE_UNICODE_SURROGATES_IN_UTF8: its UTF-8 writer otherwise escapes emoji as surrogate pairs, which changed what a local model tokenizes (caught by ClefEngineTest; now pinned by a codec test in both codecs). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The SPI is byte[] in and out, so it isn't JSON-specific: a binary codec (#37) can implement it. Builder.jsonCodec(...) becomes codec(...); client-http still needs a JSON codec, since the API speaks JSON. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Its one caller was the CLI's --verbose, and indentation is a JSON notion that doesn't belong on a format-neutral Codec. --verbose now prints compact JSON; pipe it into jq to read it. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
core held one piece of behaviour, the Codec SPI, and the codec-* modules broke the X-Y rule (no codec module to build on). Codec now lives in typesafe-java-codec (package io.github.dfa1.typesafe.codec), with no dependencies; codec-*, client-http and client-local depend on it. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements the layout agreed on #12, refined in review; recorded in ADR 0003.
Layout
Rule: a module's directory, artifact (
typesafe-java-<module>) and single package (io.github.dfa1.typesafe.<module>, dashes as dots) share one name; no package spans two modules; a module namedX-Ybuilds on moduleX.typesafe-java-*)io.github.dfa1.typesafe.*)corecorecodec(new)codecCodecSPI (wasjson.JsonCodec)codec-jackson2/codec-jackson3(werejackson2/jackson3)codec.jackson2/codec.jackson3client(new)clientTypeSafeClient,TypeSafeException,Retrying/DeadlineTypeSafeClient,TokenCounter(fromcore)client-http(new)client.httpDefaultTypeSafeClient,ApiKey,HttpTransportSPI (fromcore)client-http-jdk/client-http-okhttp(wereclient-jdk/client-okhttp)client.http.jdk/client.http.okhttpclient-local/client-mapping/client-testkit(werelocal/mapping/testkit)client.local/client.mapping/client.testkitclient-local)Breaking
TypeSafeClient.builder()is gone (clientcan't seeclient-http): useDefaultTypeSafeClient.builder().JsonCodecis nowCodec, and it andHttpTransportspeakbyte[](UTF-8 JSON for the shipped codecs), with noStringcopy on the success path;Builder.jsonCodec(...)is nowcodec(...):writeValueAsBytes/readValue(byte[], ...)(no pretty-printing variant; the CLI's--verboseprints compact JSON), and abyte[]body onpostandHttpTransportResponse.core/cli/bomis renamed, and every package exceptcore/climoves. There are no users yet, so no shims.Found along the way
Jackson 2's UTF-8 writer escapes emoji as surrogate pairs by default, unlike its
Stringwriter and Jackson 3. That changed what Clef tokenizes (ClefEngineTestcaught it).Jackson2Codecnow enablesCOMBINE_UNICODE_SURROGATES_IN_UTF8, and both codec tests pin it.Verified
./mvnw clean verify: all modules, checkstyle and the javadoc check.client-localmodel tests on real model files: 43/43, including Clef's token-for-token check against Python.Closes #12.
🤖 Generated with Claude Code