<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: DocWire</title>
    <description>The latest articles on DEV Community by DocWire (docwire).</description>
    <link>https://dev.to/docwire</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F13957%2Fc5404c98-16a1-47b8-b045-73e50c892321.png</url>
      <title>DEV Community: DocWire</title>
      <link>https://dev.to/docwire</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/docwire"/>
    <language>en</language>
    <item>
      <title>DocWire SDK 2026.07.07 — llama.cpp backend, IBM Granite by default, and a codebase-wide rename</title>
      <dc:creator>Krzysztof Nowicki</dc:creator>
      <pubDate>Thu, 09 Jul 2026 18:28:20 +0000</pubDate>
      <link>https://dev.to/docwire/docwire-sdk-20260707-llamacpp-backend-ibm-granite-by-default-and-a-codebase-wide-rename-p27</link>
      <guid>https://dev.to/docwire/docwire-sdk-20260707-llamacpp-backend-ibm-granite-by-default-and-a-codebase-wide-rename-p27</guid>
      <description>&lt;p&gt;Latest release 2026.07.07 restructures the local AI subsystem from the ground up and ships one change every existing user needs to know about before upgrading. The &lt;a href="https://docwire.io/blog/2026/07/08/docwire-release-2026.07.07" rel="noopener noreferrer"&gt;full release write-up is on docwire.io&lt;/a&gt;; this post focuses on what changes in your code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Breaking change first: everything is snake_case now
&lt;/h2&gt;

&lt;p&gt;We converted all public type names to &lt;code&gt;snake_case&lt;/code&gt; per our newly published &lt;a href="https://github.com/docwire/docwire/blob/master/doc/coding_guidelines.md" rel="noopener noreferrer"&gt;coding guidelines&lt;/a&gt;. If you're upgrading from an earlier version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gd"&gt;- ChainElement
&lt;/span&gt;&lt;span class="gi"&gt;+ chain_element
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="gd"&gt;- ParsingChain
&lt;/span&gt;&lt;span class="gi"&gt;+ parsing_chain
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="gd"&gt;- PlainTextExporter
&lt;/span&gt;&lt;span class="gi"&gt;+ plain_text_exporter
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="gd"&gt;- HtmlWriter
&lt;/span&gt;&lt;span class="gi"&gt;+ html_writer
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="gd"&gt;- TransformerFunc
&lt;/span&gt;&lt;span class="gi"&gt;+ transformer_func
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="gd"&gt;- FileStream
&lt;/span&gt;&lt;span class="gi"&gt;+ file_stream
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="gd"&gt;- ZipReader
&lt;/span&gt;&lt;span class="gi"&gt;+ zip_reader
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Document element tags and enums follow the same rule:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gd"&gt;- document::Text
&lt;/span&gt;&lt;span class="gi"&gt;+ document::text
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="gd"&gt;- mail::Mail
&lt;/span&gt;&lt;span class="gi"&gt;+ mail::mail
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="gd"&gt;- openai::Model
&lt;/span&gt;&lt;span class="gi"&gt;+ openai::model
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The migration is mechanical for the most part — nothing here compiles silently, so the compiler walks you through it. We chose one big cut over years of deprecation aliases: the codebase now matches the written standard it claims to follow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Abstract AI runner interface
&lt;/h2&gt;

&lt;p&gt;New pure virtual base class &lt;code&gt;docwire::ai::ai_runner&lt;/code&gt; defines the contract for every local inference backend: &lt;code&gt;process()&lt;/code&gt; for text generation tasks, &lt;code&gt;embed()&lt;/code&gt; for embeddings, and &lt;code&gt;unload()&lt;/code&gt; for deterministic teardown. Backends guarantee thread safety.&lt;/p&gt;

&lt;p&gt;If you want to plug your own inference engine into a DocWire pipeline, this is the seam.&lt;/p&gt;

&lt;h2&gt;
  
  
  llama.cpp backend + IBM Granite
&lt;/h2&gt;

&lt;p&gt;The new optional &lt;code&gt;docwire_ai_llama&lt;/code&gt; library wraps llama.cpp behind the runner interface, so any GGUF model can drive summarization, translation, or embedding steps inside a pipeline — no network calls, no external services.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;local-ai-model-granite&lt;/code&gt; vcpkg feature installs &lt;strong&gt;IBM Granite 4.0 1B Q8_0&lt;/strong&gt; as the default model, so a working offline LLM pipeline is available out of the box.&lt;/p&gt;

&lt;p&gt;Llama parameters are passed through dedicated strong types defined in &lt;code&gt;model_inference_config.h&lt;/code&gt; — &lt;code&gt;context_size&lt;/code&gt;, &lt;code&gt;thread_count&lt;/code&gt;, &lt;code&gt;token_limit&lt;/code&gt;, &lt;code&gt;temperature&lt;/code&gt;, &lt;code&gt;min_p&lt;/code&gt;, &lt;code&gt;batch_size&lt;/code&gt; — instead of a bag of ints, so misordered arguments become compile errors.&lt;/p&gt;

&lt;h2&gt;
  
  
  Modular backends
&lt;/h2&gt;

&lt;p&gt;The former monolithic local AI library is split:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Library&lt;/th&gt;
&lt;th&gt;Contents&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;docwire_ai&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;shared chain elements: &lt;code&gt;ai::task&lt;/code&gt;, &lt;code&gt;ai::summarize&lt;/code&gt;, &lt;code&gt;ai::translate&lt;/code&gt;, &lt;code&gt;ai::embed&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;docwire_ai_ct2&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;CTranslate2 runner and tokenizer (&lt;code&gt;docwire::ai::ct2&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;docwire_ai_llama&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;llama.cpp runner (&lt;code&gt;docwire::ai::llama&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Build only the backend you deploy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# CMake options&lt;/span&gt;
&lt;span class="nt"&gt;-DDOCWIRE_CT2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ON
&lt;span class="nt"&gt;-DDOCWIRE_LLAMA&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ON

&lt;span class="c"&gt;# vcpkg features&lt;/span&gt;
local-ai-ct2
local-ai-llama
local-ai-model-granite
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the common path, the &lt;code&gt;ai::local&lt;/code&gt; namespace adds convenience classes (&lt;code&gt;summarize&lt;/code&gt;, &lt;code&gt;translate&lt;/code&gt;, &lt;code&gt;task&lt;/code&gt;, &lt;code&gt;passage::embedder&lt;/code&gt;, &lt;code&gt;query::embedder&lt;/code&gt;) that pick a sensible default backend and model, so a pipeline like &lt;em&gt;parse → extract text → summarize locally&lt;/em&gt; stays a few lines.&lt;/p&gt;

&lt;h2&gt;
  
  
  EML parser: crash fixed, corner cases covered
&lt;/h2&gt;

&lt;p&gt;Malformed MIME boundaries — prematurely closed multipart sections — could crash the underlying &lt;code&gt;mailio&lt;/code&gt; library. The EML parser's &lt;code&gt;BoundaryTracker&lt;/code&gt; now detects these and injects empty parts where needed. Four new test fixtures lock the behavior in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;endboundary_first.eml
missing_inner_closing_boundary.eml
nested_multiparts_missing.eml
valid_format.eml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Real mailbox data is dirty; parsers that fall over on it are not infrastructure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing changes worth noting
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;New end-to-end integration tests for both backends: full pipeline from document parsing through text extraction to a local AI task&lt;/li&gt;
&lt;li&gt;Local AI summarization tests moved to fuzzy matching — exact-string assertions against LLM output were a flakiness generator&lt;/li&gt;
&lt;li&gt;Example tests requiring local AI libraries compile conditionally on target availability&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/docwire/docwire/releases/tag/2026.07.07" rel="noopener noreferrer"&gt;Full release notes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docwire.io/blog/2026/07/08/docwire-release-2026.07.07" rel="noopener noreferrer"&gt;Release blog post&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/docwire/docwire/blob/master/doc/manifesto.md" rel="noopener noreferrer"&gt;DocWire Manifesto&lt;/a&gt; and &lt;a href="https://github.com/docwire/docwire/blob/master/doc/coding_guidelines.md" rel="noopener noreferrer"&gt;Coding Guidelines&lt;/a&gt; — new in this release&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;*Yes - we drafted it with AI assistance (the most stubborn one), then reviewed and edited ourselves — every technical claim above maps to the actual release. If we got something wrong anyway, tell us in the comments or in dm's *&lt;/p&gt;

</description>
      <category>cpp</category>
      <category>ai</category>
      <category>opensource</category>
      <category>llm</category>
    </item>
  </channel>
</rss>
