<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Notes on Krishnatejaswi S</title>
    <link>https://KTS-o7.github.io/bear/notes/</link>
    <description>Recent content in Notes on Krishnatejaswi S</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <managingEditor>shentharkrishnatejaswi@gmail.com (Krishnatejaswi S)</managingEditor>
    <webMaster>shentharkrishnatejaswi@gmail.com (Krishnatejaswi S)</webMaster>
    <copyright>Krishnatejaswi S</copyright>
    <lastBuildDate>Sat, 02 May 2026 00:00:00 +0530</lastBuildDate>
    <atom:link href="https://KTS-o7.github.io/bear/notes/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Teaching Myself CS: The Plan</title>
      <link>https://KTS-o7.github.io/bear/notes/teaching_myself_cs/</link>
      <pubDate>Sat, 02 May 2026 00:00:00 +0530</pubDate><author>shentharkrishnatejaswi@gmail.com (Krishnatejaswi S)</author>
      <guid>https://KTS-o7.github.io/bear/notes/teaching_myself_cs/</guid>
      <description>&lt;p&gt;I&amp;rsquo;ve been building things with code for a while now, but there are gaps. Not the kind that show up in day-to-day work &amp;ndash; the kind that show up when you&amp;rsquo;re reading a paper and hit a concept you sort of understand but can&amp;rsquo;t really explain, or when you&amp;rsquo;re debugging something deep in a system and realize you&amp;rsquo;re guessing at the underlying mechanics.&lt;/p&gt;&#xA;&lt;p&gt;The fix is obvious in theory: go back and learn the fundamentals properly. The hard part is doing it without spending two years on a degree or burning out on a curriculum that assumes you have nothing else going on.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>I&rsquo;ve been building things with code for a while now, but there are gaps. Not the kind that show up in day-to-day work &ndash; the kind that show up when you&rsquo;re reading a paper and hit a concept you sort of understand but can&rsquo;t really explain, or when you&rsquo;re debugging something deep in a system and realize you&rsquo;re guessing at the underlying mechanics.</p>
<p>The fix is obvious in theory: go back and learn the fundamentals properly. The hard part is doing it without spending two years on a degree or burning out on a curriculum that assumes you have nothing else going on.</p>
<p>I&rsquo;ve been working through <a href="https://teachyourselfcs.com/">teachyourselfcs.com</a> as my backbone. Here&rsquo;s the plan I&rsquo;ve laid out for myself and why I structured it this way.</p>
<h2 id="the-curriculum">The Curriculum</h2>
<p>TYCS breaks CS into 9 subjects and gives you a primary book and video course for each. The order is a suggestion, not a law:</p>
<table>
  <thead>
      <tr>
          <th>Subject</th>
          <th>Book</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Programming</td>
          <td>SICP</td>
      </tr>
      <tr>
          <td>Computer Architecture</td>
          <td>CS:APP / Nand2Tetris</td>
      </tr>
      <tr>
          <td>Algorithms &amp; Data Structures</td>
          <td>The Algorithm Design Manual (Skiena)</td>
      </tr>
      <tr>
          <td>Math for CS</td>
          <td>MIT 6.042J notes</td>
      </tr>
      <tr>
          <td>Operating Systems</td>
          <td>OSTEP</td>
      </tr>
      <tr>
          <td>Computer Networking</td>
          <td>Top-Down Approach</td>
      </tr>
      <tr>
          <td>Databases</td>
          <td>Readings in Database Systems</td>
      </tr>
      <tr>
          <td>Languages &amp; Compilers</td>
          <td>Crafting Interpreters</td>
      </tr>
      <tr>
          <td>Distributed Systems</td>
          <td>DDIA + MIT 6.824</td>
      </tr>
  </tbody>
</table>
<p>The book choices are deliberate. SICP isn&rsquo;t just a programming book &ndash; it&rsquo;s a book about how to think computationally. OSTEP is genuinely readable in a way most OS textbooks aren&rsquo;t. DDIA is probably the most practically useful book on the list if you&rsquo;re building anything that handles data at scale.</p>
<p>The target is 100-200 hours per subject. That&rsquo;s not a sprint, it&rsquo;s a multi-year project. The goal isn&rsquo;t to finish &ndash; it&rsquo;s to build genuine depth in each area, then keep revisiting.</p>
<h2 id="the-problem-i-had-to-solve-first">The Problem I Had to Solve First</h2>
<p>Standard study advice &ndash; &ldquo;30 minutes every day&rdquo; &ndash; doesn&rsquo;t work for me. I have high activation energy to start anything. Once I&rsquo;m in, momentum takes over and I&rsquo;ll go for hours. But that first 15 minutes of friction is real and it kills sessions before they begin.</p>
<p>So the plan is ignition-focused rather than sustainment-focused:</p>
<ul>
<li>Sessions start with a 15-minute minimum, not a 2-hour block. The bar to start is low. Once started, I usually continue past it.</li>
<li>Entry point is whatever subject feels most alive right now, not necessarily the next one in sequence. The order matters less than actually engaging.</li>
<li>Each subject has a concrete project attached &ndash; something you build, not just something you read. The project gives momentum a direction.</li>
</ul>
<p>The Newton iteration thing from the TYCS intro stuck with me: when you hit something you don&rsquo;t understand, go back to the start of the section and re-read. Each pass gets you further. Don&rsquo;t skip over confusion &ndash; re-enter it.</p>
<h2 id="how-im-ordering-it">How I&rsquo;m Ordering It</h2>
<p>I&rsquo;m starting with three subjects in parallel across the first phase rather than going strictly sequential:</p>
<p><strong>Programming (SICP)</strong> &ndash; Chapters 1-3, doing every exercise. The exercises are the learning. Reading without doing is just moving your eyes across text. I&rsquo;m supplementing with Exercism problems when I want something more applied.</p>
<p><strong>Computer Architecture (CS:APP / Nand2Tetris)</strong> &ndash; Starting with Nand2Tetris projects 1-5 because they&rsquo;re hands-on in a way that makes the abstractions stick. Build an ALU, then a CPU, then an assembler. By the time you reach CS:APP, you&rsquo;ve already built the thing the book describes.</p>
<p><strong>Distributed Systems (DDIA)</strong> &ndash; Running this in parallel because I&rsquo;m already working in this space and the reading compounds immediately with real work. DDIA cover-to-cover, then 2-3 papers per week from the MIT DSG reading list. The project target is implementing a Raft consensus module.</p>
<p>Algorithms and Math for CS come after the first wave. The ML path runs alongside: Andrew Ng&rsquo;s ML course after Algorithms, fast.ai after OS and Networking.</p>
<h2 id="what-im-not-doing">What I&rsquo;m Not Doing</h2>
<p>No video lectures unless I&rsquo;m stuck. The TYCS authors are explicit that books are the primary medium and videos are optional supplements. I&rsquo;ve defaulted to videos too many times in the past &ndash; they feel productive but the retention without active practice is low.</p>
<p>No skipping exercises to &ldquo;get through&rdquo; material faster. The only way through SICP is through the exercises. Same with Nand2Tetris. The projects aren&rsquo;t extra credit, they&rsquo;re the point.</p>
<p>No treating this as interview prep. The goal is actual understanding. Some of it will be useful in interviews, but that&rsquo;s a side effect, not the frame.</p>
<p>I&rsquo;ll track hours per subject and update this post as I go.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Building a Second Brain with Obsidian, Zettelkasten, and an AI Agent</title>
      <link>https://KTS-o7.github.io/bear/notes/obsidian_second_brain/</link>
      <pubDate>Tue, 21 Apr 2026 00:00:00 +0530</pubDate><author>shentharkrishnatejaswi@gmail.com (Krishnatejaswi S)</author>
      <guid>https://KTS-o7.github.io/bear/notes/obsidian_second_brain/</guid>
      <description>&lt;p&gt;I spend most of my time building things. CNCFlow, a side project blog, ML experiments, X threads. The problem is not a lack of output &amp;ndash; it is that none of it compounds. I finish a project, learn something real, and two months later I am re-deriving the same insight from scratch because it never got written down anywhere I would actually look again.&lt;/p&gt;&#xA;&lt;p&gt;I have tried Notion. Tried Apple Notes. Tried dumping things in a text file. All of them eventually become a graveyard of notes I never revisit.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>I spend most of my time building things. CNCFlow, a side project blog, ML experiments, X threads. The problem is not a lack of output &ndash; it is that none of it compounds. I finish a project, learn something real, and two months later I am re-deriving the same insight from scratch because it never got written down anywhere I would actually look again.</p>
<p>I have tried Notion. Tried Apple Notes. Tried dumping things in a text file. All of them eventually become a graveyard of notes I never revisit.</p>
<p>So I set up something different. This post is about the system &ndash; what it is, why it works, and the one thing that makes it actually stick.</p>
<h2 id="the-problem-with-most-note-taking">The problem with most note-taking</h2>
<p>Most people take notes the wrong way. They copy. They highlight. They summarize what they read. Then they file it somewhere and feel organized.</p>
<p>None of that is learning. None of it compounds.</p>
<p>When you copy a sentence from a textbook, you are transcribing, not thinking. The note exists but the understanding does not. Two weeks later the note is as foreign as the textbook was the first time.</p>
<p>The thing that actually builds knowledge is elaborative encoding &ndash; restating an idea in your own words, connecting it to something you already understand. This is not a productivity tip. It is how memory works. You encode new information by hooking it into existing mental models. No hooks, no retention.</p>
<p>A second brain should force you to do that. Most setups do not.</p>
<h2 id="two-systems-one-vault">Two systems, one vault</h2>
<p>The system I use is a hybrid of PARA and Zettelkasten. They solve different problems.</p>
<p>PARA (Projects, Areas, Resources, Archive) is for navigation. It answers &ldquo;where do I put this?&rdquo; and &ldquo;where do I find that?&rdquo; It is project-oriented, folder-based, practical. Good for builders.</p>
<p>Zettelkasten is for thinking. It answers &ldquo;what do I actually know?&rdquo; and &ldquo;how does this connect to that?&rdquo; It is idea-oriented, flat, link-based. Good for writers and researchers.</p>
<p>The mistake people make is picking one and ignoring the other. PARA without Zettelkasten gives you a well-organized filing cabinet you never think with. Zettelkasten without PARA gives you a beautiful graph of ideas with no place to track actual work.</p>
<p>The vault structure I landed on:</p>





<pre tabindex="0"><code>00-Inbox/          everything lands here first
Projects/          one subfolder per active project
Daily/             date-named daily notes
Notes/             Zettelkasten permanent notes (flat)
Learning/          STEM subjects, structured
Templates/         note templates
Archive/           completed projects, old notes</code></pre><p>Projects and Daily are pure PARA. Notes is pure Zettelkasten. Learning is the interesting hybrid.</p>
<h2 id="the-three-note-types-that-matter">The three note types that matter</h2>
<p>Zettelkasten has three kinds of notes, and most explanations of the system spend too much time on the taxonomy and not enough on why the types are different.</p>
<p><strong>Fleeting notes</strong> are raw captures. They live in 00-Inbox. They are temporary by design &ndash; process them within a week or delete them. Zero friction at capture time. Do not organize, do not format, just dump it.</p>
<p><strong>Concept notes</strong> live in Learning/. One concept per note, explained in your own words. Fixed structure: what it is in your words, the core intuition, a concrete example you can trace through, where you got confused, and how it connects to things you already know. That last field &ndash; where you got confused &ndash; is the most valuable part most people skip. Your confusions are where your understanding has gaps. Future you needs to know where those are.</p>
<p><strong>Permanent notes</strong> live in Notes/. These are the ones that compound. One fully-formed idea per note, stated as a claim. Not a topic &ndash; a claim.</p>
<p>BAD: <code>Eigenvalues</code>
GOOD: <code>Eigenvalues represent stretch magnitude along a transformation's invariant axes</code></p>
<p>BAD: <code>CNCFlow GTM</code>
GOOD: <code>CAD users switch tools only when workflow pain exceeds switching cost</code></p>
<p>The difference matters. A topic title is a filing label. A claim title is a thought. When you write it as a claim, you have to commit to believing something. That forces the thinking.</p>
<h2 id="the-rule-that-makes-everything-work">The rule that makes everything work</h2>
<p>Write in your own words only. No copy-pasting.</p>
<p>This sounds obvious. It is the hardest part. The temptation when reading a paper or watching a lecture is to quote the good parts, paste them into a note, and feel like you captured something. You did not. You moved text from one place to another.</p>
<p>A wrong note you wrote yourself is more valuable than a correct note you copied. When you write something wrong, you will notice the contradiction when you link it to something else. The note will tell you where your understanding broke. A copied note just sits there looking authoritative.</p>
<h2 id="learning-stem-in-the-vault">Learning STEM in the vault</h2>
<p>STEM is where this system earns its keep more than anywhere else.</p>
<p>The standard study loop &ndash; read, highlight, review &ndash; fails because it is passive. You are reading the author&rsquo;s thoughts, not building your own. By the third session you are highlighting things you highlighted before because nothing stuck.</p>
<p>The vault forces a different loop. After reading a section or watching a lecture, I write a Concept Note in Learning/{subject}/. Not a summary &ndash; my understanding. If I cannot explain it in my own words, I do not understand it yet, and that is useful to know.</p>
<p>Then I ask: does this connect to anything in Notes/? Can I extract a permanent note &ndash; a cross-domain insight?</p>
<p>Working through linear algebra:</p>
<ul>
<li>Concept Note in Learning/Math/Linear-Algebra/: eigenvalues</li>
<li>Then in Notes/: <code>Eigenvalues are to matrix transformations what CAD constraints are to parametric models -- they identify the invariant structure</code></li>
</ul>
<p>That second note is mine. Nobody wrote it in a textbook. It is hooked into my mental model of CAD, which I think about constantly. I will not forget it.</p>
<p>This is the compounding effect the system is supposed to produce. Your STEM learning starts talking to your project work. The graph of connected notes becomes a map of your actual understanding, not a collection of things you have read.</p>
<h2 id="wiring-an-ai-agent-into-the-vault">Wiring an AI agent into the vault</h2>
<p>The last piece is automation. I use Hermes (my local AI agent) to read and write to the vault directly.</p>
<p>Before any research task, Hermes searches Notes/ and Learning/ for what I already know. This prevents re-deriving things and surfaces relevant context automatically. If I ask it to explain something I have already written a concept note on, it reads the note first and builds on my existing understanding rather than explaining from scratch.</p>
<p>After a learning session, Hermes writes structured Concept Notes to the right Learning/ subfolder and extracts candidate permanent notes to Notes/. I review and edit them &ndash; the thinking is mine, but the structuring is automated.</p>
<p>For projects, Hermes appends decisions to the decisions log table in the relevant Project Note. Every non-obvious decision gets a row: what was decided, why. This sounds like overhead. It pays back immediately the first time you pick up a paused project and actually remember why you made the choices you did.</p>
<h2 id="what-i-skip">What I skip</h2>
<p>I do not write notes for things I can re-derive in five minutes. I do not write notes for things that are already in the code, the commit history, or the PR description. I do not write notes to feel productive.</p>
<p>The weekly review is Sunday, twenty minutes. Process Inbox, promote or delete every note, update status tags on Learning notes (seedling &ndash; just captured, growing &ndash; building understanding, evergreen &ndash; solid and stable), write or update one permanent note. If the review takes longer than twenty minutes, the system is too complicated.</p>
<p>Delete freely. A cluttered vault is a dead vault. If a note has not been touched in six months and is not evergreen, archive it or delete it.</p>
<h2 id="the-real-test">The real test</h2>
<p>The system works if, six months from now, I can open the vault and quickly surface what I actually think about a topic &ndash; not what I have read about it, but what I understand and how it connects to everything else I am working on.</p>
<p>The graph view in Obsidian will show clusters. Notes in the CS cluster linking to notes in the Projects cluster. An insight from linear algebra linking to a CNCFlow architecture decision. A note on organic growth on X linking to a note on network effects from graph theory.</p>
<p>Those links are the point. Not the notes themselves &ndash; the connections between them. That is the second brain: not a better filing cabinet, but a map of how your own thinking connects.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Fixing Silent $0 Streaming Costs in AgentBudget: An OSS Contribution</title>
      <link>https://KTS-o7.github.io/bear/notes/agentbudget_ulimit_for_ai_agents/</link>
      <pubDate>Thu, 16 Apr 2026 00:00:00 +0530</pubDate><author>shentharkrishnatejaswi@gmail.com (Krishnatejaswi S)</author>
      <guid>https://KTS-o7.github.io/bear/notes/agentbudget_ulimit_for_ai_agents/</guid>
      <description>&lt;p&gt;AgentBudget patches the OpenAI and Anthropic SDKs to track the cost of every LLM call. Set a budget, get a hard limit. Simple premise.&lt;/p&gt;&#xA;&lt;p&gt;Except there was a gap. Every streaming call cost $0.00 in the ledger. Silently. No error, no warning &amp;ndash; just wrong numbers.&lt;/p&gt;&#xA;&lt;p&gt;I found the gap, fixed it, and got the PR merged. This is the story of how streaming cost tracking actually works.&lt;/p&gt;&#xA;&lt;h2 id=&#34;what-agentbudget-does&#34;&gt;What AgentBudget does&lt;/h2&gt;&#xA;&lt;p&gt;AgentBudget is an open-source SDK that puts a hard dollar limit on AI agent sessions. Two lines, no infrastructure:&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>AgentBudget patches the OpenAI and Anthropic SDKs to track the cost of every LLM call. Set a budget, get a hard limit. Simple premise.</p>
<p>Except there was a gap. Every streaming call cost $0.00 in the ledger. Silently. No error, no warning &ndash; just wrong numbers.</p>
<p>I found the gap, fixed it, and got the PR merged. This is the story of how streaming cost tracking actually works.</p>
<h2 id="what-agentbudget-does">What AgentBudget does</h2>
<p>AgentBudget is an open-source SDK that puts a hard dollar limit on AI agent sessions. Two lines, no infrastructure:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln">1</span><span class="cl"><span class="kn">import</span> <span class="nn">agentbudget</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="n">agentbudget</span><span class="o">.</span><span class="n">init</span><span class="p">(</span><span class="s2">&#34;$5.00&#34;</span><span class="p">)</span></span></span></code></pre></div><p>It works by monkey-patching <code>Completions.create</code> (OpenAI) and <code>Messages.create</code> (Anthropic) at init time. Every call goes through a wrapper that looks up the model cost, accumulates spend, and raises <code>BudgetExhausted</code> when the limit is hit.</p>
<p>The non-streaming path worked fine. The streaming path did not.</p>
<h2 id="the-bug">The bug</h2>
<p>When <code>stream=True</code>, the patched method receives a <code>Stream</code> object back from the SDK &ndash; not a completed response with token counts. The original code had no handling for this case. It silently passed the stream through untracked.</p>
<p>Every streaming call registered as $0.00 in the ledger. Any agent using streaming could blow past its budget with zero resistance. The circuit breaker was blind to half its traffic.</p>
<h2 id="why-streaming-is-harder-to-cost">Why streaming is harder to cost</h2>
<p>Non-streaming is straightforward: the response comes back with a <code>usage</code> object containing <code>prompt_tokens</code> and <code>completion_tokens</code>. Multiply by the per-token rate, done.</p>
<p>Streaming returns a sequence of chunks. Token counts are not available upfront &ndash; they only appear after the stream is exhausted. For OpenAI specifically, usage data on the final chunk is opt-in: you need <code>stream_options={&quot;include_usage&quot;: True}</code> in the request, otherwise the final chunk carries no usage data and there is nothing to cost.</p>
<p>Anthropic handles it differently. Usage data is always present, split across two events: <code>message_start</code> carries input tokens, <code>message_delta</code> carries output tokens at the end.</p>
<h2 id="the-fix-transparent-wrapper-classes">The fix: transparent wrapper classes</h2>
<p>The solution is four wrapper classes that intercept the stream, yield every chunk unchanged, and record cost after the iterator is exhausted:</p>
<table>
  <thead>
      <tr>
          <th>Class</th>
          <th>Wraps</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>_OpenAIStreamWrapper</code></td>
          <td><code>openai.Stream[ChatCompletionChunk]</code></td>
      </tr>
      <tr>
          <td><code>_AsyncOpenAIStreamWrapper</code></td>
          <td><code>openai.AsyncStream[ChatCompletionChunk]</code></td>
      </tr>
      <tr>
          <td><code>_AnthropicStreamWrapper</code></td>
          <td><code>anthropic.Stream[RawMessageStreamEvent]</code></td>
      </tr>
      <tr>
          <td><code>_AsyncAnthropicStreamWrapper</code></td>
          <td><code>anthropic.AsyncStream[RawMessageStreamEvent]</code></td>
      </tr>
  </tbody>
</table>
<p>Each wrapper is fully transparent to the caller. The existing code pattern &ndash; <code>for chunk in stream:</code> or <code>async for chunk in stream:</code> or <code>with client.stream(...) as stream:</code> &ndash; continues to work without any changes.</p>
<p>The wrapper accumulates token counts as chunks arrive, then records the cost in the session ledger once the stream ends.</p>
<p>For OpenAI:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="k">class</span> <span class="nc">_OpenAIStreamWrapper</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">stream</span><span class="p">,</span> <span class="n">session</span><span class="p">,</span> <span class="n">model</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">_stream</span> <span class="o">=</span> <span class="n">stream</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">_session</span> <span class="o">=</span> <span class="n">session</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">_model</span> <span class="o">=</span> <span class="n">model</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">    <span class="k">def</span> <span class="fm">__iter__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">        <span class="k">for</span> <span class="n">chunk</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_stream</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">            <span class="c1"># Track usage from the final chunk</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">            <span class="k">if</span> <span class="n">chunk</span><span class="o">.</span><span class="n">usage</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">                <span class="n">cost</span> <span class="o">=</span> <span class="n">price</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_model</span><span class="p">,</span> <span class="n">chunk</span><span class="o">.</span><span class="n">usage</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">                <span class="bp">self</span><span class="o">.</span><span class="n">_session</span><span class="o">.</span><span class="n">record</span><span class="p">(</span><span class="n">cost</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">            <span class="k">yield</span> <span class="n">chunk</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">
</span></span><span class="line"><span class="ln">15</span><span class="cl">    <span class="c1"># Full protocol: __enter__, __exit__, close()</span></span></span></code></pre></div><p>For Anthropic, the accumulation spans two event types:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="k">class</span> <span class="nc">_AnthropicStreamWrapper</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">    <span class="k">def</span> <span class="fm">__iter__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">        <span class="n">input_tokens</span> <span class="o">=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">        <span class="n">output_tokens</span> <span class="o">=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">        <span class="k">for</span> <span class="n">event</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_stream</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">            <span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="n">type</span> <span class="o">==</span> <span class="s2">&#34;message_start&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">                <span class="n">input_tokens</span> <span class="o">=</span> <span class="n">event</span><span class="o">.</span><span class="n">message</span><span class="o">.</span><span class="n">usage</span><span class="o">.</span><span class="n">input_tokens</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">            <span class="k">elif</span> <span class="n">event</span><span class="o">.</span><span class="n">type</span> <span class="o">==</span> <span class="s2">&#34;message_delta&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">                <span class="n">output_tokens</span> <span class="o">=</span> <span class="n">event</span><span class="o">.</span><span class="n">usage</span><span class="o">.</span><span class="n">output_tokens</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">            <span class="k">yield</span> <span class="n">event</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">        <span class="n">cost</span> <span class="o">=</span> <span class="n">price</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_model</span><span class="p">,</span> <span class="n">input_tokens</span><span class="p">,</span> <span class="n">output_tokens</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">_session</span><span class="o">.</span><span class="n">record</span><span class="p">(</span><span class="n">cost</span><span class="p">)</span></span></span></code></pre></div><p>The detection of whether a response is a stream happens via <code>isinstance</code> checks guarded by <code>ImportError</code>, so the wrapper degrades gracefully if only one SDK is installed.</p>
<h2 id="implementing-the-full-protocol">Implementing the full protocol</h2>
<p>The tricky part is not the cost tracking logic &ndash; it is making the wrapper implement the full stream protocol correctly.</p>
<p>Python streams support multiple usage patterns: iterator (<code>for chunk in stream</code>), context manager (<code>with stream</code>), async iterator, async context manager, and explicit <code>close()</code>/<code>aclose()</code>. Missing any of these means certain callers will break with an <code>AttributeError</code> or a resource leak.</p>
<p>The wrapper needs to implement all of them:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># Sync: iterator + context manager + close</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="k">def</span> <span class="fm">__iter__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="o">...</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="k">def</span> <span class="fm">__enter__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">return</span> <span class="bp">self</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="k">def</span> <span class="fm">__exit__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="k">def</span> <span class="nf">close</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">_stream</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="c1"># Async: async iterator + async context manager + aclose</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="k">async</span> <span class="k">def</span> <span class="fm">__aiter__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="o">...</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="k">async</span> <span class="k">def</span> <span class="fm">__aenter__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">return</span> <span class="bp">self</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="k">async</span> <span class="k">def</span> <span class="fm">__aexit__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">):</span> <span class="k">await</span> <span class="bp">self</span><span class="o">.</span><span class="n">aclose</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="k">async</span> <span class="k">def</span> <span class="nf">aclose</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">await</span> <span class="bp">self</span><span class="o">.</span><span class="n">_stream</span><span class="o">.</span><span class="n">aclose</span><span class="p">()</span></span></span></code></pre></div><p>Getting this wrong is invisible in unit tests with mocks but breaks immediately against real SDK objects.</p>
<h2 id="tests">Tests</h2>
<p>The PR added 19 tests covering:</p>
<ul>
<li>Cost recorded correctly after stream exhaustion</li>
<li>Chunks with no usage data skipped without error</li>
<li>Passthrough identity &ndash; every chunk the caller sees is unchanged</li>
<li><code>BudgetExhausted</code> propagates correctly mid-stream</li>
<li>Both <code>for chunk in stream:</code> and <code>with client.stream() as stream:</code> patterns</li>
<li><code>close()</code> and <code>aclose()</code> delegation to the underlying stream</li>
<li>Drop-in mode (<code>agentbudget.init()</code>) wrapping end-to-end</li>
<li>No-session noop &ndash; if no budget session is active, streaming is fully transparent</li>
</ul>
<p>All 129 pre-existing tests continued to pass. 148 total passing at merge.</p>
<h2 id="the-known-limitation">The known limitation</h2>
<p>OpenAI streaming requires the caller to pass <code>stream_options={&quot;include_usage&quot;: True}</code>. Without it, the final chunk carries no usage data, and the cost is silently $0.</p>
<p>This is OpenAI&rsquo;s API behaviour &ndash; usage data on streams is opt-in. The limitation is documented in the module docstring. A future improvement could auto-inject the option at the patch layer, but that requires modifying the outbound request, which is a bigger change than this PR intended to be.</p>
<p>Anthropic has no equivalent limitation &ndash; usage is always present.</p>
<h2 id="what-i-learned">What I learned</h2>
<p><strong>Transparent wrappers need the full protocol.</strong> It is tempting to implement just <code>__iter__</code> and call it done. But real callers use context managers, explicit close, and async variants. Implementing the minimum breaks production code in ways that are hard to debug.</p>
<p><strong>Streaming costs are provider-specific.</strong> OpenAI and Anthropic have different conventions for where usage data appears in the stream. Any SDK that claims to support both needs to handle both separately.</p>
<p><strong>Test against real SDK objects, not just mocks.</strong> The <code>isinstance</code> detection and chunk structure only behave correctly against live SDK classes. Mock-based tests passed for the wrong reasons until I verified against an actual installed SDK.</p>
<h2 id="links">Links</h2>
<ul>
<li><a href="https://github.com/AgentBudget/agentbudget/pull/6">PR #6 &ndash; feat: track costs for streaming OpenAI and Anthropic responses</a></li>
<li><a href="https://github.com/AgentBudget/agentbudget">AgentBudget on GitHub</a></li>
<li><a href="https://pypi.org/project/agentbudget/">PyPI</a></li>
</ul>
]]></content:encoded>
    </item>
    <item>
      <title>Building a Local AI Stack: Hermes, Bifrost, Telegram, and Camoufox</title>
      <link>https://KTS-o7.github.io/bear/notes/hermes_local_ai_stack/</link>
      <pubDate>Wed, 15 Apr 2026 00:00:00 +0530</pubDate><author>shentharkrishnatejaswi@gmail.com (Krishnatejaswi S)</author>
      <guid>https://KTS-o7.github.io/bear/notes/hermes_local_ai_stack/</guid>
      <description>&lt;p&gt;I wanted a persistent AI agent that lives on my machine, reaches cloud models through a single gateway, and talks back to me on Telegram. Not a SaaS. Not a wrapper. Something I own end-to-end.&lt;/p&gt;&#xA;&lt;p&gt;This is the story of setting that up in one session, and the parts that went sideways.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-stack&#34;&gt;The Stack&lt;/h2&gt;&#xA;&lt;p&gt;Four moving parts:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Bifrost&lt;/strong&gt; &amp;ndash; LLM gateway already running on localhost:24242, routing to Ollama cloud models&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Hermes Agent&lt;/strong&gt; &amp;ndash; open-source AI agent framework by Nous Research, pointed at Bifrost&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Ollama&lt;/strong&gt; &amp;ndash; cloud relay for gemma4 and qwen3.5 cloud models via ollama.com&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Camoufox&lt;/strong&gt; &amp;ndash; Firefox fork with TLS fingerprint spoofing for scraping tasks&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;The goal was to have Hermes run as a Telegram bot so I could assign it tasks from my phone, with all model traffic flowing through Bifrost so routing stays centralized.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>I wanted a persistent AI agent that lives on my machine, reaches cloud models through a single gateway, and talks back to me on Telegram. Not a SaaS. Not a wrapper. Something I own end-to-end.</p>
<p>This is the story of setting that up in one session, and the parts that went sideways.</p>
<h2 id="the-stack">The Stack</h2>
<p>Four moving parts:</p>
<ul>
<li><strong>Bifrost</strong> &ndash; LLM gateway already running on localhost:24242, routing to Ollama cloud models</li>
<li><strong>Hermes Agent</strong> &ndash; open-source AI agent framework by Nous Research, pointed at Bifrost</li>
<li><strong>Ollama</strong> &ndash; cloud relay for gemma4 and qwen3.5 cloud models via ollama.com</li>
<li><strong>Camoufox</strong> &ndash; Firefox fork with TLS fingerprint spoofing for scraping tasks</li>
</ul>
<p>The goal was to have Hermes run as a Telegram bot so I could assign it tasks from my phone, with all model traffic flowing through Bifrost so routing stays centralized.</p>
<h2 id="bifrost-first">Bifrost First</h2>
<p>Bifrost was already up on port 24242 with Ollama configured. The only addition needed was an <code>ollama-cloud</code> provider pointing at <code>https://ollama.com</code> rather than localhost. This is a non-obvious distinction.</p>
<p>The trap: Ollama&rsquo;s OpenAI-compatible endpoint (<code>/v1/chat/completions</code>) does not work for cloud models. It hangs. Cloud models only work through Ollama&rsquo;s native <code>/api/chat</code> endpoint. Pointing Bifrost directly at <code>https://ollama.com</code> instead of <code>localhost:11434</code> bypasses the broken compat layer and hits the right path.</p>
<p>Once the provider was registered and <code>OLLAMA_API_KEY</code> was set in <code>.zshrc</code>, both cloud models confirmed working:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">ollama pull gemma4:31b-cloud
</span></span><span class="line"><span class="ln">2</span><span class="cl">ollama pull qwen3.5:cloud</span></span></code></pre></div><h2 id="installing-hermes">Installing Hermes</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh <span class="p">|</span> bash</span></span></code></pre></div><p>That puts everything under <code>~/.hermes/</code>. The setup wizard runs next:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">hermes setup</span></span></code></pre></div><p>It walks through provider selection interactively. I pointed it at the Bifrost custom endpoint (<code>http://localhost:24242/v1</code>) and picked <code>ollama-cloud/gemma4:31b-cloud</code> as the default model.</p>
<p>Key config paths:</p>





<pre tabindex="0"><code>~/.hermes/config.yaml    -- main settings
~/.hermes/.env           -- secrets and API keys
~/.hermes/skills/        -- reusable agent procedures
~/.hermes/sessions/      -- full conversation history (searchable)</code></pre><p>After setup, a quick smoke test confirmed the agent was up and routing through Bifrost correctly:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">hermes chat -q <span class="s2">&#34;what model are you using and where does traffic go&#34;</span></span></span></code></pre></div><h2 id="context-window">Context Window</h2>
<p>The default context length was under 20k tokens. Ollama cloud models support much larger windows. One config set:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">hermes config <span class="nb">set</span> model.context_length <span class="m">200000</span></span></span></code></pre></div><p>Takes effect on the next session restart.</p>
<h2 id="telegram-bot">Telegram Bot</h2>
<p>This is where Hermes gets genuinely useful. The gateway turns it into a bot that accepts tasks from any platform you connect.</p>
<p>Create a bot via BotFather, get the token, then add it to <code>~/.hermes/.env</code>:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="nv">TELEGRAM_BOT_TOKEN</span><span class="o">=</span>&lt;your-bot-token&gt;
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="nv">TELEGRAM_ALLOWED_USERS</span><span class="o">=</span>&lt;your-numeric-telegram-id&gt;</span></span></code></pre></div><p><code>TELEGRAM_ALLOWED_USERS</code> takes the numeric user ID, not the username. Lock it down. Anyone who finds the bot URL can send it commands if this is not set.</p>
<p>Start the gateway:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">hermes gateway run</span></span></code></pre></div><p>For persistent background operation, install it as a service:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">hermes gateway install
</span></span><span class="line"><span class="ln">2</span><span class="cl">hermes gateway start</span></span></code></pre></div><p>A set of aliases in <code>.zshrc</code> makes it easier to manage day to day:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="nb">alias</span> hermes-gateway-start<span class="o">=</span><span class="s2">&#34;hermes gateway start&#34;</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="nb">alias</span> hermes-gateway-stop<span class="o">=</span><span class="s2">&#34;hermes gateway stop&#34;</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="nb">alias</span> hermes-gateway-log<span class="o">=</span><span class="s2">&#34;tail -f ~/.hermes/logs/gateway.log&#34;</span></span></span></code></pre></div><p>First run hit a missing Python dependency and failed silently. The fix was running <code>hermes gateway run</code> in the foreground once to see the real error, installing the missing package, then moving back to the service.</p>
<h2 id="camoufox">Camoufox</h2>
<p>Camoufox is a Firefox fork built for scraping. It spoofs TLS fingerprints so sites see a legitimate browser rather than a Playwright or CDP signature. It exposes a CDP endpoint that Hermes&rsquo;s browser tool connects to.</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">git clone https://github.com/daijro/camoufox
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="nb">cd</span> camoufox <span class="o">&amp;&amp;</span> npm install
</span></span><span class="line"><span class="ln">3</span><span class="cl">python -m camoufox fetch   <span class="c1"># ~300MB download</span></span></span></code></pre></div><p>The <code>camoufox fetch</code> step downloads the actual browser binary and does not run automatically via postinstall. If you skip it, the first start fails silently. Run it manually and wait for the download to finish before starting the server.</p>
<p>Start it on port 9377:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">python -m camoufox server --port <span class="m">9377</span> <span class="p">&amp;</span></span></span></code></pre></div><p>Smoke test via Hermes:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">hermes chat -q <span class="s2">&#34;use the browser to fetch the title of example.com&#34;</span></span></span></code></pre></div><p>Aliases for day-to-day:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="nb">alias</span> camofox-start<span class="o">=</span><span class="s2">&#34;python -m camoufox server --port 9377 &amp;&#34;</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="nb">alias</span> camofox-stop<span class="o">=</span><span class="s2">&#34;pkill -f &#39;camoufox server&#39;&#34;</span></span></span></code></pre></div><h2 id="what-actually-went-wrong">What Actually Went Wrong</h2>
<p><strong>Ollama native vs compat endpoint.</strong> Already covered above, but it cost a couple of hours. If a cloud model hangs at the provider level, check whether your gateway is talking to the right API path.</p>
<p><strong>Camoufox silent failure.</strong> The binary fetch is not in postinstall. No error, just no browser. Always run <code>python -m camoufox fetch</code> explicitly before the first start.</p>
<p><strong>Hermes gateway dependency.</strong> First start printed nothing useful. Run in foreground before daemonizing so you can see the actual error.</p>
<p><strong>Bifrost and empty API keys.</strong> Ollama initially rejected non-empty dummy keys in the Authorization header. Setting the key to an empty string before switching to the real <code>OLLAMA_API_KEY</code> got things unstuck. The order mattered.</p>
<p><strong>Session corruption in OpenCode.</strong> An OpenCode session used to orchestrate this setup got a zombie assistant message from an interrupted stream. The message had an empty string for content. Bifrost converted that empty string to null before forwarding, and the upstream provider rejected the entire next request with <code>messages.315.member.content must not be null</code>. Every retry included the same zombie in history, so the error was permanent until manually fixed.</p>
<p>The fix is to delete the zombie row directly from the OpenCode SQLite database:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">sqlite3 ~/.local/share/opencode/opencode.db <span class="se">\
</span></span></span><span class="line"><span class="ln">2</span><span class="cl">  <span class="s2">&#34;DELETE FROM message WHERE id = &#39;&lt;zombie-message-id&gt;&#39; AND session_id = &#39;&lt;session-id&gt;&#39;;&#34;</span></span></span></code></pre></div><p>There is no built-in repair command. Back up the database before editing it.</p>
<h2 id="final-state">Final State</h2>
<p>Services running when done:</p>





<pre tabindex="0"><code>bifrost    :24242  -- Ollama cloud routes
ollama     :11434  -- cloud relay (gemma4, qwen3.5)
camoufox   :9377   -- CDP browser endpoint
hermes     gateway -- Telegram bot (restricted to single user)</code></pre><p>The agent receives messages on Telegram, runs tool calls locally (terminal, browser, file ops, web search), and routes all model traffic through Bifrost.</p>
<h2 id="whats-left">What&rsquo;s Left</h2>
<p>The original plan included running a local Qwen3.5-27B model via llama.cpp with Metal acceleration. That is a 13.5GB download and a build-from-source step, so it was deferred to the next session. The cloud routing setup works fine in the meantime.</p>
<h2 id="references">References</h2>
<ul>
<li>Hermes Agent: <a href="https://github.com/NousResearch/hermes-agent">https://github.com/NousResearch/hermes-agent</a></li>
<li>Hermes docs: <a href="https://hermes-agent.nousresearch.com/docs/">https://hermes-agent.nousresearch.com/docs/</a></li>
<li>Bifrost: <a href="https://github.com/maximhq/bifrost">https://github.com/maximhq/bifrost</a></li>
<li>Camoufox: <a href="https://github.com/daijro/camoufox">https://github.com/daijro/camoufox</a></li>
<li>OpenCode: <a href="https://opencode.ai">https://opencode.ai</a></li>
</ul>
]]></content:encoded>
    </item>
    <item>
      <title>Freeseek: Turning DeepSeek&#39;s Web Chat into an OpenAI-Compatible API</title>
      <link>https://KTS-o7.github.io/bear/notes/freeseek_proxy/</link>
      <pubDate>Sat, 14 Mar 2026 00:00:00 +0530</pubDate><author>shentharkrishnatejaswi@gmail.com (Krishnatejaswi S)</author>
      <guid>https://KTS-o7.github.io/bear/notes/freeseek_proxy/</guid>
      <description>&lt;p&gt;I wanted to use DeepSeek with tools that only speak OpenAI&amp;rsquo;s API. DeepSeek&amp;rsquo;s official API has rate limits and costs money. Their web chat is free and unrestricted but it isn&amp;rsquo;t an API — it&amp;rsquo;s a browser session with Cloudflare protection, Proof-of-Work challenges, and a proprietary SSE format.&lt;/p&gt;&#xA;&lt;p&gt;So I built &lt;a href=&#34;https://github.com/KTS-o7/freeseek-proxy&#34;&gt;freeseek-proxy&lt;/a&gt;: a local proxy that sits between OpenAI-compatible clients (opencode, Claude Code, any SDK) and DeepSeek&amp;rsquo;s web chat backend. You send standard &lt;code&gt;/v1/chat/completions&lt;/code&gt; requests; it handles sessions, PoW, TLS fingerprinting, and SSE translation behind the scenes.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>I wanted to use DeepSeek with tools that only speak OpenAI&rsquo;s API. DeepSeek&rsquo;s official API has rate limits and costs money. Their web chat is free and unrestricted but it isn&rsquo;t an API — it&rsquo;s a browser session with Cloudflare protection, Proof-of-Work challenges, and a proprietary SSE format.</p>
<p>So I built <a href="https://github.com/KTS-o7/freeseek-proxy">freeseek-proxy</a>: a local proxy that sits between OpenAI-compatible clients (opencode, Claude Code, any SDK) and DeepSeek&rsquo;s web chat backend. You send standard <code>/v1/chat/completions</code> requests; it handles sessions, PoW, TLS fingerprinting, and SSE translation behind the scenes.</p>
<p>This post covers the four hardest problems I had to solve.</p>
<h2 id="the-architecture-its-two-processes-not-one">The architecture (it&rsquo;s two processes, not one)</h2>
<p>The proxy is split into two halves that talk over localhost:</p>





<pre tabindex="0"><code>                  ┌──────────────────────────┐
                  │   Client                 │
                  │   (opencode / curl / SDK)│
                  └────────────┬─────────────┘
                               │
                  POST /v1/chat/completions
                       (OpenAI format)
                               │
                  ┌────────────▼─────────────┐
                  │   TypeScript Proxy       │
                  │   Hono on Bun :9123      │
                  │                          │
                  │   · Request normalization│
                  │   · Tool-call compat     │
                  │   · SSE reformatting     │
                  │   · Session management   │
                  └────────────┬─────────────┘
                               │
                    HTTP localhost:8081
                               │
                  ┌────────────▼─────────────┐
                  │   Python Backend         │
                  │   FastAPI + uvicorn      │
                  │                          │
                  │   · curl_cffi (TLS spoof)│
                  │   · WASM PoW solver      │
                  │   · Cookie management    │
                  │   · Auth (token / login) │
                  └────────────┬─────────────┘
                               │
                   HTTPS chat.deepseek.com
                               │
                  ┌────────────▼─────────────┐
                  │      DeepSeek API        │
                  └──────────────────────────┘</code></pre><p>Why two languages? DeepSeek does browser fingerprinting. Their servers check TLS fingerprints, and if yours looks like <code>python-requests</code> or <code>node-fetch</code>, you get blocked. The Python side uses <code>curl_cffi</code> with <code>impersonate=&quot;chrome120&quot;</code> to produce a TLS handshake indistinguishable from Chrome. The TypeScript side handles everything else — request translation, streaming, tool calls — where Bun&rsquo;s performance and type safety matter more.</p>
<h2 id="problem-1-proof-of-work-with-a-wasm-sha3-solver">Problem 1: Proof-of-Work with a WASM SHA3 solver</h2>
<p>DeepSeek doesn&rsquo;t just check your auth token. Before every chat completion, you must solve a Proof-of-Work challenge. The flow is:</p>
<ol>
<li>Request a challenge from <code>/api/v0/chat/create_pow_challenge</code></li>
<li>The server returns a challenge string, salt, difficulty, and expiry</li>
<li>You run a SHA3-based hash computation until you find a valid answer</li>
<li>Encode the answer as base64 JSON and send it as <code>x-ds-pow-response</code> header</li>
</ol>
<p>The catch: DeepSeek&rsquo;s PoW algorithm is implemented in a WebAssembly module. In the browser, this runs natively. Outside the browser, you need a WASM runtime.</p>
<p>The solver uses <code>wasmtime</code> (a standalone WASM runtime for Python) to load DeepSeek&rsquo;s own <code>sha3_wasm_bg.wasm</code> binary and call its exported <code>wasm_solve</code> function:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="k">class</span> <span class="nc">DeepSeekHash</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">    <span class="k">def</span> <span class="nf">init</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">wasm_path</span><span class="p">:</span> <span class="nb">str</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">        <span class="n">engine</span> <span class="o">=</span> <span class="n">wasmtime</span><span class="o">.</span><span class="n">Engine</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">        <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">wasm_path</span><span class="p">,</span> <span class="s2">&#34;rb&#34;</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">            <span class="n">wasm_bytes</span> <span class="o">=</span> <span class="n">f</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">        <span class="n">module</span> <span class="o">=</span> <span class="n">wasmtime</span><span class="o">.</span><span class="n">Module</span><span class="p">(</span><span class="n">engine</span><span class="p">,</span> <span class="n">wasm_bytes</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">store</span> <span class="o">=</span> <span class="n">wasmtime</span><span class="o">.</span><span class="n">Store</span><span class="p">(</span><span class="n">engine</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">        <span class="n">linker</span> <span class="o">=</span> <span class="n">wasmtime</span><span class="o">.</span><span class="n">Linker</span><span class="p">(</span><span class="n">engine</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">        <span class="n">linker</span><span class="o">.</span><span class="n">define_wasi</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">instance</span> <span class="o">=</span> <span class="n">linker</span><span class="o">.</span><span class="n">instantiate</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">store</span><span class="p">,</span> <span class="n">module</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">memory</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">instance</span><span class="o">.</span><span class="n">exports</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">store</span><span class="p">)[</span><span class="s2">&#34;memory&#34;</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">        <span class="k">return</span> <span class="bp">self</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">
</span></span><span class="line"><span class="ln">14</span><span class="cl">    <span class="k">def</span> <span class="nf">calculate_hash</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">algorithm</span><span class="p">,</span> <span class="n">challenge</span><span class="p">,</span> <span class="n">salt</span><span class="p">,</span> <span class="n">difficulty</span><span class="p">,</span> <span class="n">expire_at</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">        <span class="n">prefix</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">&#34;</span><span class="si">{</span><span class="n">salt</span><span class="si">}</span><span class="s2">_</span><span class="si">{</span><span class="n">expire_at</span><span class="si">}</span><span class="s2">_&#34;</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">        <span class="c1"># Allocate WASM memory, write challenge + prefix</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">        <span class="n">challenge_ptr</span><span class="p">,</span> <span class="n">challenge_len</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_write_to_memory</span><span class="p">(</span><span class="n">challenge</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">        <span class="n">prefix_ptr</span><span class="p">,</span> <span class="n">prefix_len</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_write_to_memory</span><span class="p">(</span><span class="n">prefix</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">        <span class="c1"># Call the exported solver</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">instance</span><span class="o">.</span><span class="n">exports</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">store</span><span class="p">)[</span><span class="s2">&#34;wasm_solve&#34;</span><span class="p">](</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">            <span class="bp">self</span><span class="o">.</span><span class="n">store</span><span class="p">,</span> <span class="n">retptr</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">            <span class="n">challenge_ptr</span><span class="p">,</span> <span class="n">challenge_len</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">            <span class="n">prefix_ptr</span><span class="p">,</span> <span class="n">prefix_len</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl">            <span class="nb">float</span><span class="p">(</span><span class="n">difficulty</span><span class="p">),</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl">        <span class="p">)</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl">        <span class="c1"># Read the answer from WASM memory</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">        <span class="n">value_bytes</span> <span class="o">=</span> <span class="nb">bytes</span><span class="p">(</span><span class="n">memory_view</span><span class="p">[</span><span class="n">retptr</span> <span class="o">+</span> <span class="mi">8</span> <span class="p">:</span> <span class="n">retptr</span> <span class="o">+</span> <span class="mi">16</span><span class="p">])</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl">        <span class="n">value</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">frombuffer</span><span class="p">(</span><span class="n">value_bytes</span><span class="p">,</span> <span class="n">dtype</span><span class="o">=</span><span class="n">np</span><span class="o">.</span><span class="n">float64</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">29</span><span class="cl">        <span class="k">return</span> <span class="nb">int</span><span class="p">(</span><span class="n">value</span><span class="p">)</span></span></span></code></pre></div><p>The memory management is manual — you allocate via <code>__wbindgen_export_0</code>, write UTF-8 bytes one at a time, call the solver, then read the result from a return pointer. Stack pointer cleanup happens in a <code>finally</code> block. It&rsquo;s the kind of code where one off-by-one error means silent corruption.</p>
<p><strong>Why Python 3.11 specifically?</strong> The <code>wasmtime</code> + <code>numpy</code> + <code>curl_cffi</code> stack was verified working on 3.11. Python 3.14 caused silent failures in the WASM path during testing — the process would get <code>killed</code> mid-computation with no error message. This isn&rsquo;t a &ldquo;should work&rdquo; situation; it&rsquo;s a &ldquo;was tested and doesn&rsquo;t&rdquo; situation.</p>
<h2 id="problem-2-tls-fingerprinting-and-cloudflare">Problem 2: TLS fingerprinting and Cloudflare</h2>
<p>DeepSeek sits behind Cloudflare. Standard HTTP clients get 403s or &ldquo;Just a moment&hellip;&rdquo; challenge pages because their TLS Client Hello doesn&rsquo;t match what a real browser sends.</p>
<p>The fix is <code>curl_cffi</code> with browser impersonation:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln">1</span><span class="cl"><span class="n">response</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">post</span><span class="p">(</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">    <span class="sa">f</span><span class="s2">&#34;</span><span class="si">{</span><span class="n">BASE_URL</span><span class="si">}{</span><span class="n">path</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">    <span class="n">headers</span><span class="o">=</span><span class="n">headers</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl">    <span class="n">json</span><span class="o">=</span><span class="n">body</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">    <span class="n">cookies</span><span class="o">=</span><span class="n">cookies</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl">    <span class="n">impersonate</span><span class="o">=</span><span class="s2">&#34;chrome120&#34;</span><span class="p">,</span>  <span class="c1"># TLS fingerprint matches Chrome 120</span>
</span></span><span class="line"><span class="ln">7</span><span class="cl">    <span class="n">stream</span><span class="o">=</span><span class="n">stream</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">8</span><span class="cl"><span class="p">)</span></span></span></code></pre></div><p><code>impersonate=&quot;chrome120&quot;</code> makes the TLS handshake (cipher suites, extensions, ALPN) identical to Chrome 120. This is why the backend is Python, not Node — there&rsquo;s no equivalent library in the JS ecosystem that matches real browser TLS fingerprints this precisely.</p>
<p>The cookie management layer adds another defense: if a request hits Cloudflare anyway, the proxy can automatically refresh cookies via a configurable shell command:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln">1</span><span class="cl"><span class="k">def</span> <span class="nf">refresh_cookies</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">dict</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="nb">str</span><span class="p">]:</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">    <span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">refresh_command</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">load_cookies</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl">    <span class="n">subprocess</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">refresh_command</span><span class="p">,</span> <span class="n">shell</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">check</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">    <span class="n">cookies</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">load_cookies</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl">    <span class="bp">self</span><span class="o">.</span><span class="n">save_cookies</span><span class="p">(</span><span class="n">cookies</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">7</span><span class="cl">    <span class="k">return</span> <span class="n">cookies</span></span></span></code></pre></div><p>This lets you plug in whatever cookie extraction tool you prefer — a headless browser script, a browser extension export, etc.</p>
<h2 id="problem-3-translating-sse-formats">Problem 3: Translating SSE formats</h2>
<p>DeepSeek&rsquo;s streaming format is not OpenAI&rsquo;s streaming format. Both use Server-Sent Events, but the payload structure is completely different.</p>
<p><strong>OpenAI format</strong> (what clients expect):</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="ln">1</span><span class="cl"><span class="err">data:</span> <span class="p">{</span><span class="nt">&#34;choices&#34;</span><span class="p">:[{</span><span class="nt">&#34;delta&#34;</span><span class="p">:{</span><span class="nt">&#34;content&#34;</span><span class="p">:</span><span class="s2">&#34;Hello&#34;</span><span class="p">},</span><span class="nt">&#34;index&#34;</span><span class="p">:</span><span class="mi">0</span><span class="p">}],</span><span class="nt">&#34;model&#34;</span><span class="p">:</span><span class="s2">&#34;gpt-4&#34;</span><span class="p">}</span></span></span></code></pre></div><p><strong>DeepSeek format</strong> (what the server sends):</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="ln">1</span><span class="cl"><span class="err">data:</span> <span class="p">{</span><span class="nt">&#34;v&#34;</span><span class="p">:{</span><span class="nt">&#34;response&#34;</span><span class="p">:{</span><span class="nt">&#34;fragments&#34;</span><span class="p">:[{</span><span class="nt">&#34;type&#34;</span><span class="p">:</span><span class="s2">&#34;text&#34;</span><span class="p">,</span><span class="nt">&#34;content&#34;</span><span class="p">:</span><span class="s2">&#34;Hello&#34;</span><span class="p">}]}},</span><span class="nt">&#34;o&#34;</span><span class="p">:</span><span class="s2">&#34;APPEND&#34;</span><span class="p">}</span></span></span></code></pre></div><p>DeepSeek uses a nested structure where content lives inside <code>response.fragments</code>, operations can be <code>APPEND</code>, <code>SET</code>, or <code>BATCH</code>, and thinking content is separated from regular content by fragment type. There&rsquo;s also metadata like <code>response/status</code> and <code>response/accumulated_token_usage</code> mixed into the stream that clients don&rsquo;t want.</p>
<p>The proxy handles this translation in <code>parseSSELine</code> and <code>extractDeepSeekContent</code>:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-typescript" data-lang="typescript"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kd">function</span> <span class="nx">extractDeepSeekContent</span><span class="p">(</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">  <span class="nx">data</span>: <span class="kt">DeepSeekSSEData</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">  <span class="nx">includeThinking</span>: <span class="kt">boolean</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="p">)</span><span class="o">:</span> <span class="kt">string</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">  <span class="c1">// DeepSeek nests content in multiple possible locations
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl">  <span class="kr">const</span> <span class="nx">target</span> <span class="o">=</span> <span class="nx">data</span><span class="p">.</span><span class="nx">v</span><span class="o">?</span><span class="p">.</span><span class="nx">response</span> <span class="o">??</span> <span class="nx">data</span><span class="p">.</span><span class="nx">response</span> <span class="o">??</span> <span class="nx">data</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">  <span class="kr">const</span> <span class="nx">fragments</span> <span class="o">=</span> <span class="nx">target</span><span class="o">?</span><span class="p">.</span><span class="nx">fragments</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">  <span class="k">if</span> <span class="p">(</span><span class="nb">Array</span><span class="p">.</span><span class="nx">isArray</span><span class="p">(</span><span class="nx">fragments</span><span class="p">))</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">    <span class="k">return</span> <span class="nx">fragments</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">      <span class="p">.</span><span class="nx">filter</span><span class="p">(</span><span class="nx">f</span> <span class="o">=&gt;</span> <span class="nx">includeThinking</span> <span class="o">||</span> <span class="nx">f</span><span class="p">.</span><span class="kr">type</span> <span class="o">!==</span> <span class="s2">&#34;thinking&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">      <span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="nx">f</span> <span class="o">=&gt;</span> <span class="nx">f</span><span class="p">.</span><span class="nx">content</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">      <span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="s2">&#34;&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">
</span></span><span class="line"><span class="ln">16</span><span class="cl">  <span class="c1">// Fallback: direct content field
</span></span></span><span class="line"><span class="ln">17</span><span class="cl">  <span class="k">if</span> <span class="p">(</span><span class="k">typeof</span> <span class="nx">data</span><span class="p">.</span><span class="nx">v</span> <span class="o">===</span> <span class="s2">&#34;string&#34;</span><span class="p">)</span> <span class="k">return</span> <span class="nx">data</span><span class="p">.</span><span class="nx">v</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">  <span class="k">if</span> <span class="p">(</span><span class="k">typeof</span> <span class="nx">data</span><span class="p">.</span><span class="nx">content</span> <span class="o">===</span> <span class="s2">&#34;string&#34;</span><span class="p">)</span> <span class="k">return</span> <span class="nx">data</span><span class="p">.</span><span class="nx">content</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">  <span class="k">return</span> <span class="s2">&#34;&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><p>For streaming responses, each DeepSeek SSE chunk gets translated into an OpenAI <code>chat.completion.chunk</code> on the fly. For non-streaming, the proxy accumulates all chunks, then builds a single <code>chat.completion</code> response.</p>
<h2 id="problem-4-tool-calls-on-a-model-that-doesnt-support-them">Problem 4: Tool calls on a model that doesn&rsquo;t support them</h2>
<p>This is the most interesting problem. DeepSeek&rsquo;s web chat API doesn&rsquo;t support OpenAI-style tool calls. There&rsquo;s no <code>tools</code> parameter, no <code>tool_choice</code>, no <code>tool_calls</code> in the response. But clients like opencode and Claude Code rely heavily on tool use — without it, the agent can&rsquo;t read files, run commands, or interact with your codebase.</p>
<p>The solution is a prompt-engineering compatibility layer. When the proxy detects tool-related fields in the request, it:</p>
<ol>
<li><strong>Injects a system prompt</strong> describing available tools and the expected JSON format</li>
<li><strong>Flattens the conversation</strong> into a single prompt (including tool results from previous turns)</li>
<li><strong>Parses the model&rsquo;s response</strong> for JSON tool call envelopes</li>
<li><strong>Translates back</strong> into OpenAI&rsquo;s <code>tool_calls</code> format</li>
</ol>
<p>The injected system prompt instructs the model to output tool calls as JSON:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-typescript" data-lang="typescript"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kd">function</span> <span class="nx">buildToolSystemPrompt</span><span class="p">(</span><span class="nx">tools</span><span class="p">,</span> <span class="nx">toolChoice</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">  <span class="k">return</span> <span class="p">[</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">    <span class="s2">&#34;You are replying through an OpenAI-compatible proxy that supports tool use.&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">    <span class="nx">toolChoiceRule</span><span class="p">,</span> <span class="c1">// varies by mode: auto/required/none/function
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl">    <span class="sb">`If you decide to call a tool, output only valid JSON with this exact shape:`</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">    <span class="sb">`{&#34;opencode_tool_call&#34;: {&#34;name&#34;: &#34;tool_name&#34;, &#34;arguments&#34;: { ... }}}.`</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">    <span class="sb">`For multiple calls: {&#34;opencode_tool_calls&#34;: [...]}.`</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">    <span class="s2">&#34;Do not wrap the JSON in markdown.&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    <span class="s2">&#34;Available tools:&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">    <span class="nx">availableTools</span><span class="p">,</span> <span class="c1">// name, description, JSON schema for each
</span></span></span><span class="line"><span class="ln">11</span><span class="cl">  <span class="p">].</span><span class="nx">join</span><span class="p">(</span><span class="s2">&#34;\n\n&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><p>The conversation history gets flattened because DeepSeek&rsquo;s chat API takes a single prompt string, not an array of messages:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-typescript" data-lang="typescript"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kd">function</span> <span class="nx">formatConversationForDeepSeek</span><span class="p">(</span><span class="nx">messages</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">  <span class="k">return</span> <span class="nx">messages</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="nx">message</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="nx">message</span><span class="p">.</span><span class="nx">role</span> <span class="o">===</span> <span class="s2">&#34;system&#34;</span><span class="p">)</span> <span class="k">return</span> <span class="sb">`System: </span><span class="si">${</span><span class="nx">content</span><span class="si">}</span><span class="sb">`</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="nx">message</span><span class="p">.</span><span class="nx">role</span> <span class="o">===</span> <span class="s2">&#34;user&#34;</span><span class="p">)</span> <span class="k">return</span> <span class="sb">`User: </span><span class="si">${</span><span class="nx">content</span><span class="si">}</span><span class="sb">`</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="nx">message</span><span class="p">.</span><span class="nx">role</span> <span class="o">===</span> <span class="s2">&#34;assistant&#34;</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">      <span class="k">if</span> <span class="p">(</span><span class="nx">message</span><span class="p">.</span><span class="nx">tool_calls</span><span class="o">?</span><span class="p">.</span><span class="nx">length</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">        <span class="k">return</span> <span class="sb">`Assistant tool request: </span><span class="si">${</span><span class="nx">formatted</span> <span class="nx">calls</span><span class="si">}</span><span class="sb">`</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">      <span class="k">return</span> <span class="sb">`Assistant: </span><span class="si">${</span><span class="nx">content</span><span class="si">}</span><span class="sb">`</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="nx">message</span><span class="p">.</span><span class="nx">role</span> <span class="o">===</span> <span class="s2">&#34;tool&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">      <span class="k">return</span> <span class="sb">`Tool (</span><span class="si">${</span><span class="nx">message</span><span class="p">.</span><span class="nx">tool_call_id</span><span class="si">}</span><span class="sb">) result: </span><span class="si">${</span><span class="nx">content</span><span class="si">}</span><span class="sb">`</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">  <span class="p">}).</span><span class="nx">join</span><span class="p">(</span><span class="s2">&#34;\n\n&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><p>On the response side, <code>parseToolEnvelope</code> scans the model output for JSON objects containing <code>opencode_tool_call</code> or <code>opencode_tool_calls</code> keys, validates that the function names match known tools, and converts them into proper OpenAI <code>tool_calls</code> with generated IDs:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-typescript" data-lang="typescript"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kd">function</span> <span class="nx">parseToolEnvelope</span><span class="p">(</span><span class="nx">text</span><span class="p">,</span> <span class="nx">tools</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">  <span class="k">for</span> <span class="p">(</span><span class="kr">const</span> <span class="nx">candidate</span> <span class="k">of</span> <span class="nx">extractJsonObjectCandidates</span><span class="p">(</span><span class="nx">text</span><span class="p">.</span><span class="nx">trim</span><span class="p">()))</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">    <span class="kr">const</span> <span class="nx">payload</span> <span class="o">=</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">candidate</span><span class="p">);</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">    <span class="kr">const</span> <span class="nx">rawCalls</span> <span class="o">=</span> <span class="nx">payload</span><span class="p">.</span><span class="nx">opencode_tool_calls</span> <span class="o">??</span> <span class="p">[</span><span class="nx">payload</span><span class="p">.</span><span class="nx">opencode_tool_call</span><span class="p">];</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    <span class="kr">const</span> <span class="nx">toolCalls</span> <span class="o">=</span> <span class="nx">rawCalls</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">      <span class="p">.</span><span class="nx">filter</span><span class="p">(</span><span class="nx">call</span> <span class="o">=&gt;</span> <span class="nx">tools</span><span class="p">.</span><span class="nx">some</span><span class="p">(</span><span class="nx">t</span> <span class="o">=&gt;</span> <span class="nx">t</span><span class="p">.</span><span class="kd">function</span><span class="p">.</span><span class="nx">name</span> <span class="o">===</span> <span class="nx">call</span><span class="p">.</span><span class="nx">name</span><span class="p">))</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">      <span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="nx">call</span> <span class="o">=&gt;</span> <span class="p">({</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">        <span class="nx">id</span><span class="o">:</span> <span class="sb">`call_</span><span class="si">${</span><span class="nx">uuidv4</span><span class="p">()</span><span class="si">}</span><span class="sb">`</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">        <span class="kr">type</span><span class="o">:</span> <span class="s2">&#34;function&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">        <span class="kd">function</span><span class="o">:</span> <span class="p">{</span> <span class="nx">name</span>: <span class="kt">call.name</span><span class="p">,</span> <span class="nx">arguments</span>: <span class="kt">JSON.stringify</span><span class="p">(</span><span class="nx">call</span><span class="p">.</span><span class="nx">arguments</span><span class="p">)</span> <span class="p">},</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">      <span class="p">}));</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="nx">toolCalls</span><span class="p">.</span><span class="nx">length</span><span class="p">)</span> <span class="k">return</span> <span class="p">{</span> <span class="nx">toolCalls</span> <span class="p">};</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">  <span class="k">return</span> <span class="kc">null</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><p>The JSON extraction is deliberately robust — it uses a bracket-depth parser to find JSON objects embedded in natural language, handles escaped strings, and tries multiple candidates. This matters because the model sometimes wraps tool calls in explanatory text despite being told not to.</p>
<p>For streaming with tools, there&rsquo;s an extra step. The proxy can&rsquo;t stream tool calls token-by-token (the client needs the complete tool call object). So when tools are present, the proxy collects the full response first, parses tool calls, then re-streams the result as a synthetic SSE sequence. This adds ~latency but is the only correct approach.</p>
<h2 id="what-the-client-sees">What the client sees</h2>
<p>After all this translation, what comes out the other end is a standard OpenAI response:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">curl http://localhost:9123/v1/chat/completions <span class="se">\
</span></span></span><span class="line"><span class="ln">2</span><span class="cl">  -H <span class="s2">&#34;Content-Type: application/json&#34;</span> <span class="se">\
</span></span></span><span class="line"><span class="ln">3</span><span class="cl">  -d <span class="s1">&#39;{
</span></span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="s1">    &#34;model&#34;: &#34;deepseek-chat&#34;,
</span></span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="s1">    &#34;messages&#34;: [{&#34;role&#34;: &#34;user&#34;, &#34;content&#34;: &#34;Hello&#34;}],
</span></span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="s1">    &#34;stream&#34;: true
</span></span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="s1">  }&#39;</span></span></span></code></pre></div>




<pre tabindex="0"><code>data: {&#34;id&#34;:&#34;chatcmpl-abc&#34;,&#34;object&#34;:&#34;chat.completion.chunk&#34;,&#34;choices&#34;:[{&#34;delta&#34;:{&#34;role&#34;:&#34;assistant&#34;},&#34;index&#34;:0}]}
data: {&#34;id&#34;:&#34;chatcmpl-abc&#34;,&#34;object&#34;:&#34;chat.completion.chunk&#34;,&#34;choices&#34;:[{&#34;delta&#34;:{&#34;content&#34;:&#34;Hello&#34;},&#34;index&#34;:0}]}
data: {&#34;id&#34;:&#34;chatcmpl-abc&#34;,&#34;object&#34;:&#34;chat.completion.chunk&#34;,&#34;choices&#34;:[{&#34;delta&#34;:{&#34;content&#34;:&#34;!&#34;},&#34;index&#34;:0}]}
data: [DONE]</code></pre><p>Indistinguishable from OpenAI. Any client that speaks the OpenAI protocol works without modification.</p>
<h2 id="what-i-learned">What I learned</h2>
<h3 id="wasm-outside-the-browser-is-viable-but-fragile">WASM outside the browser is viable but fragile</h3>
<p>The <code>wasmtime</code> runtime works, but debugging WASM memory issues from Python is miserable. There&rsquo;s no stack trace when you read the wrong offset — you just get garbage bytes. The debug flags in <code>pow.py</code> exist because I needed them.</p>
<h3 id="tls-fingerprinting-is-the-real-gate-not-auth-tokens">TLS fingerprinting is the real gate, not auth tokens</h3>
<p>I initially thought the hard part would be authentication. It wasn&rsquo;t. The hard part was making HTTP requests that don&rsquo;t get blocked. <code>curl_cffi</code> with browser impersonation is the only reliable solution I found for Python. If you&rsquo;re building any kind of web scraper or API proxy in 2026, TLS fingerprinting is the first problem you&rsquo;ll hit.</p>
<h3 id="tool-call-compatibility-via-prompting-is-surprisingly-reliable">Tool call compatibility via prompting is surprisingly reliable</h3>
<p>I expected the prompt-engineering approach to tool calls to be flaky. It&rsquo;s not. DeepSeek&rsquo;s models are good at following structured output instructions, and the JSON extraction parser handles edge cases well. The key is being very explicit about the expected format and validating against the known tool list.</p>
<h3 id="two-process-architecture-was-the-right-call">Two-process architecture was the right call</h3>
<p>Splitting into TypeScript + Python felt like overengineering at first. It wasn&rsquo;t. Each language does what it&rsquo;s best at: Python for the &ldquo;pretend to be a browser&rdquo; parts (TLS, WASM), TypeScript for the &ldquo;translate between API formats&rdquo; parts (streaming, types, request handling). Trying to do both in one language would have meant worse tooling for at least half the problem.</p>
<h2 id="links">Links</h2>
<ul>
<li><strong>Repo</strong>: <a href="https://github.com/KTS-o7/freeseek-proxy">freeseek-proxy</a></li>
<li><strong>curl_cffi</strong>: <a href="https://curl-cffi.readthedocs.io/">docs</a> — Python HTTP client with browser TLS impersonation</li>
<li><strong>wasmtime-py</strong>: <a href="https://github.com/bytecodealliance/wasmtime-py">GitHub</a> — Python bindings for the Wasmtime WASM runtime</li>
<li><strong>Hono</strong>: <a href="https://hono.dev/">hono.dev</a> — Lightweight web framework for Bun/Node/Deno</li>
</ul>
]]></content:encoded>
    </item>
    <item>
      <title>Fixing Parallel Tool Call Streaming in Bifrost: An OSS Bug Hunt</title>
      <link>https://KTS-o7.github.io/bear/notes/bifrost_parallel_tool_call_fix/</link>
      <pubDate>Mon, 02 Mar 2026 00:00:00 +0000</pubDate><author>shentharkrishnatejaswi@gmail.com (Krishnatejaswi S)</author>
      <guid>https://KTS-o7.github.io/bear/notes/bifrost_parallel_tool_call_fix/</guid>
      <description>&lt;p&gt;An AI agent calls three tools in parallel. The LLM streams back interleaved deltas — a few bytes of &lt;code&gt;search_documents&lt;/code&gt; arguments, then a few bytes of &lt;code&gt;get_user&lt;/code&gt;, then more &lt;code&gt;search_documents&lt;/code&gt;. On the other end, the gateway reassembles these fragments into complete tool calls.&lt;/p&gt;&#xA;&lt;p&gt;Except it doesn&amp;rsquo;t. It concatenates them all into one call: &lt;code&gt;search_documentsget_usersearch_documents&lt;/code&gt;. The agent hallucinates, retries, and loops. I stared at the telemetry for twenty minutes before I realized the bug wasn&amp;rsquo;t in the agent — it was in the gateway&amp;rsquo;s streaming accumulator.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>An AI agent calls three tools in parallel. The LLM streams back interleaved deltas — a few bytes of <code>search_documents</code> arguments, then a few bytes of <code>get_user</code>, then more <code>search_documents</code>. On the other end, the gateway reassembles these fragments into complete tool calls.</p>
<p>Except it doesn&rsquo;t. It concatenates them all into one call: <code>search_documentsget_usersearch_documents</code>. The agent hallucinates, retries, and loops. I stared at the telemetry for twenty minutes before I realized the bug wasn&rsquo;t in the agent — it was in the gateway&rsquo;s streaming accumulator.</p>
<p>This is the story of how I found and fixed a parallel tool call merging bug in <a href="https://github.com/maximhq/bifrost">Bifrost</a>, a 2.6k-star open-source AI gateway.</p>
<h2 id="what-is-bifrost">What is Bifrost?</h2>
<p>Bifrost is a high-performance AI gateway written in Go. It sits between your application and LLM providers (OpenAI, Anthropic, Bedrock, Vertex, etc.), providing a unified OpenAI-compatible API with automatic failover, load balancing, semantic caching, and streaming support. Think of it as an intelligent reverse proxy for AI — one API, fifteen providers, ~11µs overhead at 5k RPS.</p>
<p>The relevant piece here is the <strong>streaming accumulator</strong>. When you make a streaming chat completion request, the LLM sends back a sequence of Server-Sent Events (SSE), each containing a small delta — a few tokens of text, or a fragment of a tool call&rsquo;s arguments. The accumulator&rsquo;s job is to reassemble these deltas into complete messages.</p>
<h2 id="the-bug-recency-based-routing">The bug: recency-based routing</h2>
<p>Here&rsquo;s the scenario. You ask Claude or GPT to call two tools in parallel:</p>





<pre tabindex="0"><code>User: &#34;Search for compliance circulars about RBI and also get the user&#39;s profile&#34;</code></pre><p>The model decides to call both <code>search_circulars</code> and <code>get_user_profile</code> simultaneously. During streaming, the provider sends interleaved deltas:</p>





<pre tabindex="0"><code>Delta 1: tool_call[0] name=&#34;search&#34; (index=0, id=call_abc)
Delta 2: tool_call[1] name=&#34;get_us&#34; (index=1, id=call_xyz)
Delta 3: tool_call[0] args=&#39;{&#34;query&#34;: &#34;RBI&#39;   (index=0)
Delta 4: tool_call[1] args=&#39;{&#34;user_id&#34;: &#34;u&#39;   (index=1)
Delta 5: tool_call[0] args=&#39; circulars&#34;}&#39;      (index=0)
Delta 6: tool_call[1] args=&#39;123&#34;}&#39;             (index=1)</code></pre><p>Each delta carries an <code>index</code> (and optionally an <code>id</code>) that identifies which tool call it belongs to. The expected behavior: two distinct tool calls with their own names and arguments.</p>
<p>The actual behavior in Bifrost&rsquo;s accumulator before the fix:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1">// Old logic (simplified)</span><span class="w">
</span></span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="k">if</span><span class="w"> </span><span class="nx">deltaToolCall</span><span class="p">.</span><span class="nx">Function</span><span class="p">.</span><span class="nx">Name</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">nil</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="w">    </span><span class="c1">// New tool call — create it</span><span class="w">
</span></span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="w">    </span><span class="nx">existingToolCalls</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nb">append</span><span class="p">(</span><span class="nx">existingToolCalls</span><span class="p">,</span><span class="w"> </span><span class="nx">newToolCall</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="w">    </span><span class="c1">// Argument delta — append to the LAST tool call</span><span class="w">
</span></span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="w">    </span><span class="nx">toolCallToModify</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="o">&amp;</span><span class="nx">existingToolCalls</span><span class="p">[</span><span class="nb">len</span><span class="p">(</span><span class="nx">existingToolCalls</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span><span class="w">
</span></span></span><span class="line"><span class="ln">8</span><span class="cl"><span class="w">    </span><span class="nx">toolCallToModify</span><span class="p">.</span><span class="nx">Function</span><span class="p">.</span><span class="nx">Arguments</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="nx">deltaToolCall</span><span class="p">.</span><span class="nx">Function</span><span class="p">.</span><span class="nx">Arguments</span><span class="w">
</span></span></span><span class="line"><span class="ln">9</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><p>The routing logic was based on <strong>recency</strong>: if a delta has a <code>Name</code>, it&rsquo;s a new tool call; otherwise, append arguments to the most recent one. This works perfectly when tool calls arrive sequentially. It breaks completely when they&rsquo;re interleaved.</p>
<p>With the deltas above:</p>
<ul>
<li>Delta 3 (index=0 args) arrives → appended to the <strong>last</strong> tool call, which is <code>get_user_profile</code> (index=1). Wrong target.</li>
<li>Delta 5 (index=0 args) arrives → again appended to <code>get_user_profile</code>. Now <code>get_user_profile</code> has arguments from two different calls mashed together.</li>
</ul>
<p>The result: concatenated tool names, merged arguments, and an agent stuck in a retry loop trying to invoke <code>search_circularsget_user_profile</code> — a tool that doesn&rsquo;t exist.</p>
<h2 id="finding-the-bug">Finding the bug</h2>
<p>I hit this in production. Our compliance platform uses an AI agent that calls multiple tools in parallel — searching circulars, fetching regulatory data, looking up user context. The agent kept failing with tool resolution errors, and the telemetry showed impossible tool names:</p>





<pre tabindex="0"><code>search_circularsearch_circularsearch_circular</code></pre><p>At first I suspected the agent&rsquo;s tool-calling logic. Then I looked at the raw SSE stream from the provider — the deltas were correct. Each one had the right <code>index</code> and <code>id</code>. The corruption was happening between the provider response and the final accumulated message.</p>
<p>I traced it to <code>accumulateToolCallsInMessage</code> in <code>framework/streaming/accumulator.go</code>. The function had no concept of tool call identity. It used the presence of a <code>Name</code> field as a heuristic for &ldquo;new vs. continuation,&rdquo; which is fragile and incorrect when deltas arrive out of order.</p>
<h2 id="the-fix">The fix</h2>
<p>The fix is conceptually simple: <strong>route deltas by identity, not by recency.</strong></p>
<p>Each tool call delta carries two potential identifiers:</p>
<ol>
<li><code>tool_call.id</code> — a string like <code>call_abc123</code> (set by OpenAI/Anthropic)</li>
<li><code>tool_call.index</code> — an integer position (0, 1, 2, &hellip;)</li>
</ol>
<p>The new logic builds lookup maps on existing tool calls and uses them to route each incoming delta to the correct target:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1">// Build lookup maps for identity-based routing</span><span class="w">
</span></span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="nx">idToIndex</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nb">make</span><span class="p">(</span><span class="kd">map</span><span class="p">[</span><span class="kt">string</span><span class="p">]</span><span class="kt">int</span><span class="p">,</span><span class="w"> </span><span class="nb">len</span><span class="p">(</span><span class="nx">existingToolCalls</span><span class="p">))</span><span class="w">
</span></span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="nx">indexToIndex</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nb">make</span><span class="p">(</span><span class="kd">map</span><span class="p">[</span><span class="kt">uint16</span><span class="p">]</span><span class="kt">int</span><span class="p">,</span><span class="w"> </span><span class="nb">len</span><span class="p">(</span><span class="nx">existingToolCalls</span><span class="p">))</span><span class="w">
</span></span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="k">for</span><span class="w"> </span><span class="nx">i</span><span class="p">,</span><span class="w"> </span><span class="nx">toolCall</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="k">range</span><span class="w"> </span><span class="nx">existingToolCalls</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="nx">toolCall</span><span class="p">.</span><span class="nx">ID</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">nil</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="o">*</span><span class="nx">toolCall</span><span class="p">.</span><span class="nx">ID</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="s">&#34;&#34;</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="w">        </span><span class="nx">idToIndex</span><span class="p">[</span><span class="o">*</span><span class="nx">toolCall</span><span class="p">.</span><span class="nx">ID</span><span class="p">]</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">i</span><span class="w">
</span></span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="ln">8</span><span class="cl"><span class="w">    </span><span class="nx">indexToIndex</span><span class="p">[</span><span class="nx">toolCall</span><span class="p">.</span><span class="nx">Index</span><span class="p">]</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">i</span><span class="w">
</span></span></span><span class="line"><span class="ln">9</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><p>For each incoming delta, routing follows a priority chain:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="k">for</span><span class="w"> </span><span class="nx">_</span><span class="p">,</span><span class="w"> </span><span class="nx">deltaToolCall</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="k">range</span><span class="w"> </span><span class="nx">deltaToolCalls</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="w">    </span><span class="nx">index</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="o">-</span><span class="mi">1</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="w">    </span><span class="c1">// Priority 1: match by tool_call.id</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="nx">deltaToolCall</span><span class="p">.</span><span class="nx">ID</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">nil</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="o">*</span><span class="nx">deltaToolCall</span><span class="p">.</span><span class="nx">ID</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="s">&#34;&#34;</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="nx">existingIndex</span><span class="p">,</span><span class="w"> </span><span class="nx">ok</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">idToIndex</span><span class="p">[</span><span class="o">*</span><span class="nx">deltaToolCall</span><span class="p">.</span><span class="nx">ID</span><span class="p">];</span><span class="w"> </span><span class="nx">ok</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="w">            </span><span class="nx">index</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">existingIndex</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="w">        </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="w">    </span><span class="c1">// Priority 2: match by tool_call.index</span><span class="w">
</span></span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="nx">index</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="o">-</span><span class="mi">1</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="nx">existingIndex</span><span class="p">,</span><span class="w"> </span><span class="nx">ok</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">indexToIndex</span><span class="p">[</span><span class="nx">deltaToolCall</span><span class="p">.</span><span class="nx">Index</span><span class="p">];</span><span class="w"> </span><span class="nx">ok</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="w">            </span><span class="nx">index</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">existingIndex</span><span class="w">
</span></span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="w">        </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="w">    </span><span class="c1">// Priority 3: no match → create new tool call (if name present)</span><span class="w">
</span></span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="nx">index</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="o">-</span><span class="mi">1</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="nx">deltaToolCall</span><span class="p">.</span><span class="nx">Function</span><span class="p">.</span><span class="nx">Name</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="kc">nil</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="ln">21</span><span class="cl"><span class="w">            </span><span class="c1">// Can&#39;t create a tool call without a name</span><span class="w">
</span></span></span><span class="line"><span class="ln">22</span><span class="cl"><span class="w">            </span><span class="k">continue</span><span class="w">
</span></span></span><span class="line"><span class="ln">23</span><span class="cl"><span class="w">        </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="ln">24</span><span class="cl"><span class="w">        </span><span class="nx">newToolCall</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">schemas</span><span class="p">.</span><span class="nx">ChatAssistantMessageToolCall</span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="ln">25</span><span class="cl"><span class="w">            </span><span class="nx">Index</span><span class="p">:</span><span class="w">    </span><span class="nx">deltaToolCall</span><span class="p">.</span><span class="nx">Index</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="ln">26</span><span class="cl"><span class="w">            </span><span class="nx">ID</span><span class="p">:</span><span class="w">       </span><span class="nx">deltaToolCall</span><span class="p">.</span><span class="nx">ID</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="ln">27</span><span class="cl"><span class="w">            </span><span class="nx">Function</span><span class="p">:</span><span class="w"> </span><span class="cm">/* ... */</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="ln">28</span><span class="cl"><span class="w">        </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="ln">29</span><span class="cl"><span class="w">        </span><span class="nx">existingToolCalls</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nb">append</span><span class="p">(</span><span class="nx">existingToolCalls</span><span class="p">,</span><span class="w"> </span><span class="nx">newToolCall</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="ln">30</span><span class="cl"><span class="w">        </span><span class="c1">// Update maps for future deltas</span><span class="w">
</span></span></span><span class="line"><span class="ln">31</span><span class="cl"><span class="w">        </span><span class="nx">indexToIndex</span><span class="p">[</span><span class="nx">newToolCall</span><span class="p">.</span><span class="nx">Index</span><span class="p">]</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nb">len</span><span class="p">(</span><span class="nx">existingToolCalls</span><span class="p">)</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="w">
</span></span></span><span class="line"><span class="ln">32</span><span class="cl"><span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="nx">newToolCall</span><span class="p">.</span><span class="nx">ID</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">nil</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="ln">33</span><span class="cl"><span class="w">            </span><span class="nx">idToIndex</span><span class="p">[</span><span class="o">*</span><span class="nx">newToolCall</span><span class="p">.</span><span class="nx">ID</span><span class="p">]</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nb">len</span><span class="p">(</span><span class="nx">existingToolCalls</span><span class="p">)</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="w">
</span></span></span><span class="line"><span class="ln">34</span><span class="cl"><span class="w">        </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="ln">35</span><span class="cl"><span class="w">        </span><span class="k">continue</span><span class="w">
</span></span></span><span class="line"><span class="ln">36</span><span class="cl"><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="ln">37</span><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="ln">38</span><span class="cl"><span class="w">    </span><span class="c1">// Append arguments to the correct tool call</span><span class="w">
</span></span></span><span class="line"><span class="ln">39</span><span class="cl"><span class="w">    </span><span class="nx">existingToolCalls</span><span class="p">[</span><span class="nx">index</span><span class="p">].</span><span class="nx">Function</span><span class="p">.</span><span class="nx">Arguments</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="nx">deltaToolCall</span><span class="p">.</span><span class="nx">Function</span><span class="p">.</span><span class="nx">Arguments</span><span class="w">
</span></span></span><span class="line"><span class="ln">40</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><p>The key insight is that the maps are updated as new tool calls are created, so subsequent deltas for the same call always find their target — even if they arrive many chunks later.</p>
<h2 id="the-same-bug-twice">The same bug, twice</h2>
<p>During code review, a reviewer (<a href="https://github.com/Pratham-Mishra04">Pratham-Mishra04</a>) pointed out that the same recency-based routing existed in a second code path: the <strong>Responses API streaming</strong> handler in <code>responses.go</code>.</p>
<p>The Responses API is OpenAI&rsquo;s newer streaming format (the <code>/v1/responses</code> endpoint). It uses <code>ItemID</code> instead of <code>tool_call.index</code>, but the accumulation logic had the same flaw — <code>FunctionCallArgumentsDelta</code> events were always appended to the last message:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1">// Old responses.go logic</span><span class="w">
</span></span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="k">if</span><span class="w"> </span><span class="nx">resp</span><span class="p">.</span><span class="nx">Delta</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">nil</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="nb">len</span><span class="p">(</span><span class="nx">messages</span><span class="p">)</span><span class="w"> </span><span class="p">&gt;</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="w">    </span><span class="c1">// Always targets the last message — wrong for parallel calls</span><span class="w">
</span></span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="w">    </span><span class="nx">a</span><span class="p">.</span><span class="nf">appendFunctionArgumentsDeltaToResponsesMessage</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="w">        </span><span class="o">&amp;</span><span class="nx">messages</span><span class="p">[</span><span class="nb">len</span><span class="p">(</span><span class="nx">messages</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span><span class="p">],</span><span class="w"> </span><span class="o">*</span><span class="nx">resp</span><span class="p">.</span><span class="nx">Delta</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><p>The fix follows the same pattern: search for a message matching <code>resp.ItemID</code>, and only fall back to the last message when no <code>ItemID</code> is present. If an <code>ItemID</code> exists but no message matches, create a stub message to hold the delta rather than merging it into the wrong call:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="k">if</span><span class="w"> </span><span class="nx">resp</span><span class="p">.</span><span class="nx">Delta</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">nil</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="nb">len</span><span class="p">(</span><span class="nx">messages</span><span class="p">)</span><span class="w"> </span><span class="p">&gt;</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="w">    </span><span class="nx">targetIdx</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nb">len</span><span class="p">(</span><span class="nx">messages</span><span class="p">)</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="nx">resp</span><span class="p">.</span><span class="nx">ItemID</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">nil</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="w">        </span><span class="nx">targetIdx</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="o">-</span><span class="mi">1</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="w">        </span><span class="k">for</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nb">len</span><span class="p">(</span><span class="nx">messages</span><span class="p">)</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">&gt;=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="o">--</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="nx">messages</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">ID</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">nil</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="o">*</span><span class="nx">messages</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">ID</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="o">*</span><span class="nx">resp</span><span class="p">.</span><span class="nx">ItemID</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="w">                </span><span class="nx">targetIdx</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">i</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="w">                </span><span class="k">break</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="w">            </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="w">        </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="nx">targetIdx</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="o">-</span><span class="mi">1</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="w">            </span><span class="c1">// Create stub to avoid merging into wrong message</span><span class="w">
</span></span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="w">            </span><span class="nx">id</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="o">*</span><span class="nx">resp</span><span class="p">.</span><span class="nx">ItemID</span><span class="w">
</span></span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="w">            </span><span class="nx">messages</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nb">append</span><span class="p">(</span><span class="nx">messages</span><span class="p">,</span><span class="w"> </span><span class="nx">schemas</span><span class="p">.</span><span class="nx">ResponsesMessage</span><span class="p">{</span><span class="nx">ID</span><span class="p">:</span><span class="w"> </span><span class="o">&amp;</span><span class="nx">id</span><span class="p">})</span><span class="w">
</span></span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="w">            </span><span class="nx">targetIdx</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nb">len</span><span class="p">(</span><span class="nx">messages</span><span class="p">)</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="w">
</span></span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="w">        </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="w">    </span><span class="nx">a</span><span class="p">.</span><span class="nf">appendFunctionArgumentsDeltaToResponsesMessage</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="w">        </span><span class="o">&amp;</span><span class="nx">messages</span><span class="p">[</span><span class="nx">targetIdx</span><span class="p">],</span><span class="w"> </span><span class="o">*</span><span class="nx">resp</span><span class="p">.</span><span class="nx">Delta</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><h2 id="testing-parallel-accumulation">Testing parallel accumulation</h2>
<p>The regression test simulates the exact interleaving pattern that triggers the bug:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">TestAccumulateToolCallsInterleavedParallel</span><span class="p">(</span><span class="nx">t</span><span class="w"> </span><span class="o">*</span><span class="nx">testing</span><span class="p">.</span><span class="nx">T</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="w">    </span><span class="c1">// ...</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="w">    </span><span class="nx">toolCallID0</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="s">&#34;call_0&#34;</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="w">    </span><span class="nx">toolCallID1</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="s">&#34;call_1&#34;</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="w">    </span><span class="nx">toolNameAdd</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="s">&#34;add&#34;</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="w">    </span><span class="nx">toolNameMultiply</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="s">&#34;multiply&#34;</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="w">    </span><span class="c1">// Simulate interleaved deltas</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="w">    </span><span class="nf">accumulate</span><span class="p">(</span><span class="nf">makeDelta</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="nx">toolCallID0</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="nx">toolNameAdd</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;&#34;</span><span class="p">))</span><span class="w">       </span><span class="c1">// create call 0</span><span class="w">
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="w">    </span><span class="nf">accumulate</span><span class="p">(</span><span class="nf">makeDelta</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="nx">toolCallID1</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="nx">toolNameMultiply</span><span class="p">,</span><span class="w"> </span><span class="s">&#34;&#34;</span><span class="p">))</span><span class="w">  </span><span class="c1">// create call 1</span><span class="w">
</span></span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="w">    </span><span class="nf">accumulate</span><span class="p">(</span><span class="nf">makeDelta</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="kc">nil</span><span class="p">,</span><span class="w"> </span><span class="kc">nil</span><span class="p">,</span><span class="w"> </span><span class="s">`{&#34;a&#34;: 1`</span><span class="p">))</span><span class="w">                  </span><span class="c1">// args for call 0</span><span class="w">
</span></span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="w">    </span><span class="nf">accumulate</span><span class="p">(</span><span class="nf">makeDelta</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="kc">nil</span><span class="p">,</span><span class="w"> </span><span class="kc">nil</span><span class="p">,</span><span class="w"> </span><span class="s">`{&#34;a&#34;: 2`</span><span class="p">))</span><span class="w">                  </span><span class="c1">// args for call 1</span><span class="w">
</span></span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="w">    </span><span class="nf">accumulate</span><span class="p">(</span><span class="nf">makeDelta</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="kc">nil</span><span class="p">,</span><span class="w"> </span><span class="kc">nil</span><span class="p">,</span><span class="w"> </span><span class="s">`, &#34;b&#34;: 3}`</span><span class="p">))</span><span class="w">                </span><span class="c1">// more args for call 0</span><span class="w">
</span></span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="w">    </span><span class="nf">accumulate</span><span class="p">(</span><span class="nf">makeDelta</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="kc">nil</span><span class="p">,</span><span class="w"> </span><span class="kc">nil</span><span class="p">,</span><span class="w"> </span><span class="s">`, &#34;b&#34;: 4}`</span><span class="p">))</span><span class="w">                </span><span class="c1">// more args for call 1</span><span class="w">
</span></span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="w">    </span><span class="c1">// Assert: two distinct tool calls with correct arguments</span><span class="w">
</span></span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="w">    </span><span class="nf">assert</span><span class="p">(</span><span class="nx">addCall</span><span class="p">.</span><span class="nx">Arguments</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="s">`{&#34;a&#34;: 1, &#34;b&#34;: 3}`</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="w">    </span><span class="nf">assert</span><span class="p">(</span><span class="nx">multiplyCall</span><span class="p">.</span><span class="nx">Arguments</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="s">`{&#34;a&#34;: 2, &#34;b&#34;: 4}`</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><p>Without the fix, <code>add</code> would end up with <code>multiply</code>&rsquo;s arguments concatenated in. With the fix, each call accumulates only its own deltas.</p>
<p>A second test covers the Responses API path with <code>ItemID</code>-based routing, using the same interleaving pattern but with <code>OutputItemAdded</code> + <code>FunctionCallArgumentsDelta</code> events.</p>
<h2 id="the-pr-lifecycle">The PR lifecycle</h2>
<p>I filed <a href="https://github.com/maximhq/bifrost/issues/1829">Issue #1829</a> with reproduction details from production telemetry, then opened <a href="https://github.com/maximhq/bifrost/pull/1830">PR #1830</a> with the fix and tests.</p>
<p>The review process was smooth:</p>
<ol>
<li>First commit: fix the Chat Completions accumulator + regression test</li>
<li>Reviewer feedback: same bug exists in Responses API — please fix there too + add changelog entries</li>
<li>Second commit: fix Responses API routing + regression test + changelogs</li>
<li>Merged by <a href="https://github.com/akshaydeo">akshaydeo</a> (Bifrost maintainer)</li>
</ol>
<p>Total: 3 commits, ~280 lines of Go across 5 files. Same-day turnaround from issue to merge.</p>
<h2 id="what-i-learned">What I learned</h2>
<h3 id="1-recency-is-not-identity">1. Recency is not identity</h3>
<p>The original code used position (last element) as a proxy for identity. This is a common pattern in sequential streaming — and it works, until the stream isn&rsquo;t sequential. The fix is to use the actual identity field that the protocol already provides.</p>
<p>This is a general principle: <strong>if the protocol gives you an ID field, use it.</strong> Don&rsquo;t rely on ordering assumptions that hold today but break when concurrency enters.</p>
<h3 id="2-the-same-bug-pattern-repeats-across-api-surfaces">2. The same bug pattern repeats across API surfaces</h3>
<p>Bifrost supports two streaming formats: Chat Completions (the classic <code>tool_calls</code> array) and Responses API (the newer <code>ItemID</code>-based format). Both had the same routing flaw because the accumulation logic was duplicated rather than shared. The reviewer catching this in a different file was the most valuable part of the review.</p>
<h3 id="3-oss-contributions-are-about-context-not-complexity">3. OSS contributions are about context, not complexity</h3>
<p>The fix itself is straightforward — build a map, use it for lookup. The hard part was:</p>
<ul>
<li><strong>Finding</strong> the bug in a codebase I&rsquo;d never seen before</li>
<li><strong>Understanding</strong> why the existing approach was wrong</li>
<li><strong>Testing</strong> with realistic interleaved deltas</li>
<li><strong>Responding</strong> to review feedback about a parallel code path I hadn&rsquo;t initially noticed</li>
</ul>
<p>The code change was ~100 lines. The context-building was hours.</p>
<h3 id="4-production-telemetry-is-the-best-bug-report">4. Production telemetry is the best bug report</h3>
<p>The issue report included the exact malformed tool name from production: <code>search_circularsearch_circularsearch_circular</code>. That single string made the bug immediately reproducible and the fix trivially verifiable. If you&rsquo;re filing a bug, include the malformed output — it&rsquo;s worth more than a paragraph of description.</p>
<h2 id="links">Links</h2>
<ul>
<li><strong>PR</strong>: <a href="https://github.com/maximhq/bifrost/pull/1830">fix: preserve parallel tool call deltas — #1830</a></li>
<li><strong>Issue</strong>: <a href="https://github.com/maximhq/bifrost/issues/1829">Streaming tool call deltas merge in parallel tool calling — #1829</a></li>
<li><strong>Project</strong>: <a href="https://github.com/maximhq/bifrost">Bifrost AI Gateway</a> — 2.6k ⭐, fastest enterprise AI gateway</li>
</ul>
]]></content:encoded>
    </item>
    <item>
      <title>Many Small Tasks, One Deadline: Running Parallel AI Agents with Git Worktrees</title>
      <link>https://KTS-o7.github.io/bear/notes/codex_worktrees_adventure/</link>
      <pubDate>Thu, 19 Feb 2026 00:00:00 +0530</pubDate><author>shentharkrishnatejaswi@gmail.com (Krishnatejaswi S)</author>
      <guid>https://KTS-o7.github.io/bear/notes/codex_worktrees_adventure/</guid>
      <description>&lt;p&gt;I thought this would be an easy day.&lt;/p&gt;&#xA;&lt;p&gt;The tasks were small. The backlog was not. This is the worst possible combo for a normal workflow because the fixed overhead dominates: branch setup, dependency sync, commits, reviewable diffs, and PR management. Doing it serially feels safe, but it is slow in a way that doesn&amp;rsquo;t show up in estimates.&lt;/p&gt;&#xA;&lt;p&gt;So I tried the obvious cheat: run multiple AI agents in parallel.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>I thought this would be an easy day.</p>
<p>The tasks were small. The backlog was not. This is the worst possible combo for a normal workflow because the fixed overhead dominates: branch setup, dependency sync, commits, reviewable diffs, and PR management. Doing it serially feels safe, but it is slow in a way that doesn&rsquo;t show up in estimates.</p>
<p>So I tried the obvious cheat: run multiple AI agents in parallel.</p>
<p>It worked, but only after I tripped over three problems that are easy to reproduce if you try this without thinking through git state, shells, and sandbox boundaries.</p>
<h2 id="what-the-system-looked-like-so-you-dont-think-this-is-a-demo-problem">What the system looked like (so you don&rsquo;t think this is a demo problem)</h2>
<p>I ended up writing a small orchestration script with three phases:</p>
<ol>
<li>Create (or reuse) one worktree per task.</li>
<li>Install dependencies in parallel.</li>
<li>Run <code>codex exec</code> in batched parallel, then push branches and open draft PRs.</li>
</ol>
<p>The key detail is that batching wasn&rsquo;t “run everything at once”. It was “parallel within a batch, sequential across batches”, grouped by expected file overlap.</p>
<p>Here is the redacted shape of the script (this is not pseudocode; it&rsquo;s a sanitized skeleton of what I ran):</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-zsh" data-lang="zsh"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="cp">#!/usr/bin/env zsh
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="nb">set</span> -euo pipefail
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="nv">WORKTREE_DIR</span><span class="o">=</span><span class="s2">&#34;.worktrees&#34;</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="nv">BASE_BRANCH</span><span class="o">=</span><span class="s2">&#34;&lt;base-branch&gt;&#34;</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="nv">LOG_DIR</span><span class="o">=</span><span class="s2">&#34;</span><span class="si">${</span><span class="nv">WORKTREE_DIR</span><span class="si">}</span><span class="s2">/_logs&#34;</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">mkdir -p <span class="s2">&#34;</span><span class="si">${</span><span class="nv">WORKTREE_DIR</span><span class="si">}</span><span class="s2">&#34;</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">LOG_DIR</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="c1"># Phase 1: worktrees + deps (parallel installs)</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">hdr <span class="s2">&#34;Phase 1: Setting up worktrees&#34;</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">git worktree add -b <span class="s2">&#34;&lt;feature-branch&gt;&#34;</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">WORKTREE_DIR</span><span class="si">}</span><span class="s2">/&lt;lane&gt;&#34;</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">BASE_BRANCH</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="o">(</span><span class="nb">cd</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">WORKTREE_DIR</span><span class="si">}</span><span class="s2">/&lt;lane&gt;/frontend&#34;</span> <span class="o">&amp;&amp;</span> bun install --frozen-lockfile<span class="o">)</span> <span class="p">&amp;</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="o">(</span><span class="nb">cd</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">WORKTREE_DIR</span><span class="si">}</span><span class="s2">/&lt;lane&gt;/backend&#34;</span>  <span class="o">&amp;&amp;</span> uv sync<span class="o">)</span> <span class="p">&amp;</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="nb">wait</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">
</span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="c1"># Phase 2: batched parallel codex exec (one log per lane)</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">hdr <span class="s2">&#34;Phase 2: Running Codex&#34;</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">codex <span class="nb">exec</span> --dangerously-bypass-approvals-and-sandbox -C <span class="s2">&#34;</span><span class="si">${</span><span class="nv">WORKTREE_DIR</span><span class="si">}</span><span class="s2">/&lt;lane&gt;&#34;</span> -m <span class="s2">&#34;</span><span class="si">${</span><span class="nv">CODEX_MODEL</span><span class="si">}</span><span class="s2">&#34;</span> <span class="s2">&#34;&lt;prompt&gt;&#34;</span> &gt; <span class="s2">&#34;</span><span class="si">${</span><span class="nv">LOG_DIR</span><span class="si">}</span><span class="s2">/&lt;lane&gt;.log&#34;</span> 2&gt;<span class="p">&amp;</span><span class="m">1</span> <span class="p">&amp;</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="nb">wait</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">
</span></span><span class="line"><span class="ln">22</span><span class="cl"><span class="c1"># Phase 3: push + PRs</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">hdr <span class="s2">&#34;Phase 3: PRs to </span><span class="si">${</span><span class="nv">BASE_BRANCH</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl">git -C <span class="s2">&#34;</span><span class="si">${</span><span class="nv">WORKTREE_DIR</span><span class="si">}</span><span class="s2">/&lt;lane&gt;&#34;</span> push -u origin <span class="s2">&#34;&lt;feature-branch&gt;&#34;</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl">gh pr create --base <span class="s2">&#34;</span><span class="si">${</span><span class="nv">BASE_BRANCH</span><span class="si">}</span><span class="s2">&#34;</span> --head <span class="s2">&#34;&lt;feature-branch&gt;&#34;</span> --draft --body <span class="s2">&#34;&lt;templated body&gt;&#34;</span></span></span></code></pre></div><p>Notice what this gives you immediately: one directory per lane, one log file per lane, and a clean boundary between “make changes” and “publish changes”.</p>
<p>Now for the parts that went wrong.</p>
<h2 id="failure-1-the-shell-lied-about-what-bash-means">Failure #1: The shell lied about what “Bash” means</h2>
<p>The first failure happened before any parallelism even started. The orchestration was written with associative arrays, and the system shell rejected it with:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">declare: -A: invalid option</span></span></code></pre></div><p>This is the kind of bug that looks embarrassing until you realize it is inevitable. macOS ships an older Bash; other environments may default to <code>sh</code>; CI runners may use different interpreters. If your control-plane script can&rsquo;t build the lane-to-branch mapping reliably, your entire run becomes a dice roll.</p>
<p>The fix was not “make it work on my machine”. The fix was pinning the interpreter and failing fast (<code>set -euo pipefail</code>). Once the script ran under the interpreter it was written for, this class of failure disappeared.</p>
<h2 id="failure-2-the-sandbox-was-fine-until-it-touched-git">Failure #2: The sandbox was fine until it touched <code>.git</code></h2>
<p>The second failure was more instructive: everything looked successful until commit/push time, and then git failed when trying to write worktree metadata:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">fatal: Unable to create &#39;.git/worktrees/&lt;lane&gt;/index.lock&#39;: Operation not permitted</span></span></code></pre></div><p>The important mental model is: “can edit files” is not equivalent to “can finish delivery”. Git history mutation needs to create locks and update metadata under <code>.git/</code>. Sandboxed agents often allow workspace file edits while denying <code>.git</code> writes by design.</p>
<p>The fix is to treat permissions as architecture. In my runbook now, implementation and version-control mutation are distinct phases. I keep guardrails on while generating and editing code, and only elevate privileges for <code>commit</code>, <code>rebase</code>, <code>push</code>, and PR creation. That sounds procedural, but it is the difference between parallelism and chaos.</p>
<h2 id="failure-3-the-pr-diff-was-computed-against-the-wrong-reality">Failure #3: The PR diff was computed against the wrong reality</h2>
<p>The third failure was the “ghost diff” class: the PR contained changes that “weren&rsquo;t part of the task” even though the worktree looked clean locally. This is not a GitHub bug. It is a merge-base bug.</p>
<p>PR diff is computed from:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">merge_base(feature, base) .. feature</span></span></code></pre></div><p>If your base ref is stale when the feature branch is compared, <code>merge_base</code> resolves behind your intended base, and commits that should be “already in base” appear as if they were introduced by the feature.</p>
<p>The only reliable approach is to verify ancestry before review and rebase if needed:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">git merge-base --is-ancestor origin/&lt;base-branch&gt; HEAD <span class="o">||</span> <span class="nb">echo</span> REBASE_REQUIRED
</span></span><span class="line"><span class="ln">2</span><span class="cl">git diff --name-only origin/&lt;base-branch&gt;...HEAD</span></span></code></pre></div><p>This takes seconds and saves you from burning reviewer attention on diff noise.</p>
<h2 id="what-changed-once-i-actually-read-the-codex-cli-docs">What changed once I actually read the Codex CLI docs</h2>
<p>My first attempt treated Codex like a generic shell command that prints code. The docs made the control surface explicit, and that changed how I designed the run.</p>
<p>Approval and sandbox mode became part of the plan instead of an afterthought. Configuration precedence became something I could reason about when a lane behaved differently. Non-interactive <code>codex exec</code> became the default because it is scriptable and produces logs you can archive. And built-in review flows (like <code>/review</code>) became a lane-local quality gate before humans ever see the PR.</p>
<p>I also stopped mixing two different kinds of parallelism. Worktrees are for isolating tasks across lanes. Multi-agent mode is for decomposing one task inside a lane. When you treat them as separate tools, your system stays debuggable.</p>
<h2 id="the-boring-checklist">The boring checklist</h2>
<p>At this point the process is intentionally boring, which is exactly what you want near a deadline. My checklist is short:</p>
<ul>
<li>If the lane can&rsquo;t commit/push, it doesn&rsquo;t “count” as done. Fix the permission boundary first.</li>
<li>If the PR diff scope isn&rsquo;t what you expect, stop and fix ancestry before asking for review.</li>
<li>If a lane doesn&rsquo;t have a log file, assume it didn&rsquo;t run deterministically.</li>
</ul>
<h2 id="appendix-redacted-script-skeleton">Appendix: Redacted Script Skeleton</h2>
<p>Below is a condensed, anonymized skeleton of the script I used. It preserves the mechanics (worktrees, batching, logs, PR creation) but removes identity details.</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-zsh" data-lang="zsh"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="cp">#!/usr/bin/env zsh
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="nb">set</span> -euo pipefail
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="nv">BASE_BRANCH</span><span class="o">=</span><span class="s2">&#34;&lt;base-branch&gt;&#34;</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="nv">WORKTREE_DIR</span><span class="o">=</span><span class="s2">&#34;.worktrees&#34;</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="nv">LOG_DIR</span><span class="o">=</span><span class="s2">&#34;</span><span class="si">${</span><span class="nv">WORKTREE_DIR</span><span class="si">}</span><span class="s2">/_logs&#34;</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">mkdir -p <span class="s2">&#34;</span><span class="si">${</span><span class="nv">WORKTREE_DIR</span><span class="si">}</span><span class="s2">&#34;</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">LOG_DIR</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="nb">typeset</span> -A TASK_BRANCH TASK_TITLE TASK_PLAN TASK_LABEL
</span></span><span class="line"><span class="ln">11</span><span class="cl">TASK_BRANCH<span class="o">[</span>001<span class="o">]=</span><span class="s2">&#34;feature/lane-001&#34;</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">TASK_TITLE<span class="o">[</span>001<span class="o">]=</span><span class="s2">&#34;Lane 001: &lt;title&gt;&#34;</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">TASK_PLAN<span class="o">[</span>001<span class="o">]=</span><span class="s2">&#34;docs/plans/&lt;plan&gt;.md&#34;</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">TASK_LABEL<span class="o">[</span>001<span class="o">]=</span><span class="s2">&#34;&lt;label&gt;&#34;</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">
</span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="nv">BATCH_1</span><span class="o">=(</span><span class="m">001</span> 002<span class="o">)</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="nv">BATCH_2</span><span class="o">=(</span>003<span class="o">)</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">
</span></span><span class="line"><span class="ln">19</span><span class="cl">setup_lane<span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">  <span class="nb">local</span> <span class="nv">id</span><span class="o">=</span><span class="s2">&#34;</span><span class="nv">$1</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">  <span class="nb">local</span> <span class="nv">branch</span><span class="o">=</span><span class="s2">&#34;</span><span class="si">${</span><span class="nv">TASK_BRANCH</span><span class="p">[</span><span class="nv">$id</span><span class="p">]</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">  <span class="nb">local</span> <span class="nv">worktree</span><span class="o">=</span><span class="s2">&#34;</span><span class="si">${</span><span class="nv">WORKTREE_DIR</span><span class="si">}</span><span class="s2">/lane-</span><span class="si">${</span><span class="nv">id</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">
</span></span><span class="line"><span class="ln">24</span><span class="cl">  <span class="k">if</span> <span class="o">[[</span> -d <span class="s2">&#34;</span><span class="si">${</span><span class="nv">worktree</span><span class="si">}</span><span class="s2">&#34;</span> <span class="o">]]</span><span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl">    <span class="nb">echo</span> <span class="s2">&#34;Reusing </span><span class="si">${</span><span class="nv">worktree</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl">  <span class="k">else</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">    git worktree add -b <span class="s2">&#34;</span><span class="si">${</span><span class="nv">branch</span><span class="si">}</span><span class="s2">&#34;</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">worktree</span><span class="si">}</span><span class="s2">&#34;</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">BASE_BRANCH</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl">  <span class="k">fi</span>
</span></span><span class="line"><span class="ln">29</span><span class="cl">
</span></span><span class="line"><span class="ln">30</span><span class="cl">  <span class="o">(</span><span class="nb">cd</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">worktree</span><span class="si">}</span><span class="s2">/frontend&#34;</span> <span class="o">&amp;&amp;</span> bun install --frozen-lockfile<span class="o">)</span> <span class="p">&amp;</span>
</span></span><span class="line"><span class="ln">31</span><span class="cl">  <span class="o">(</span><span class="nb">cd</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">worktree</span><span class="si">}</span><span class="s2">/backend&#34;</span>  <span class="o">&amp;&amp;</span> uv sync<span class="o">)</span> <span class="p">&amp;</span>
</span></span><span class="line"><span class="ln">32</span><span class="cl">  <span class="nb">wait</span>
</span></span><span class="line"><span class="ln">33</span><span class="cl"><span class="o">}</span>
</span></span><span class="line"><span class="ln">34</span><span class="cl">
</span></span><span class="line"><span class="ln">35</span><span class="cl">run_lane<span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="ln">36</span><span class="cl">  <span class="nb">local</span> <span class="nv">id</span><span class="o">=</span><span class="s2">&#34;</span><span class="nv">$1</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="ln">37</span><span class="cl">  <span class="nb">local</span> <span class="nv">worktree</span><span class="o">=</span><span class="s2">&#34;</span><span class="si">${</span><span class="nv">WORKTREE_DIR</span><span class="si">}</span><span class="s2">/lane-</span><span class="si">${</span><span class="nv">id</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="ln">38</span><span class="cl">  <span class="nb">local</span> <span class="nv">log</span><span class="o">=</span><span class="s2">&#34;</span><span class="si">${</span><span class="nv">LOG_DIR</span><span class="si">}</span><span class="s2">/lane-</span><span class="si">${</span><span class="nv">id</span><span class="si">}</span><span class="s2">.log&#34;</span>
</span></span><span class="line"><span class="ln">39</span><span class="cl">  <span class="nb">local</span> <span class="nv">prompt</span><span class="o">=</span><span class="s2">&#34;&lt;redacted prompt built from plan + conventions&gt;&#34;</span>
</span></span><span class="line"><span class="ln">40</span><span class="cl">
</span></span><span class="line"><span class="ln">41</span><span class="cl">  codex <span class="nb">exec</span> --dangerously-bypass-approvals-and-sandbox -C <span class="s2">&#34;</span><span class="si">${</span><span class="nv">worktree</span><span class="si">}</span><span class="s2">&#34;</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">prompt</span><span class="si">}</span><span class="s2">&#34;</span> &gt; <span class="s2">&#34;</span><span class="si">${</span><span class="nv">log</span><span class="si">}</span><span class="s2">&#34;</span> 2&gt;<span class="p">&amp;</span><span class="m">1</span>
</span></span><span class="line"><span class="ln">42</span><span class="cl"><span class="o">}</span>
</span></span><span class="line"><span class="ln">43</span><span class="cl">
</span></span><span class="line"><span class="ln">44</span><span class="cl">create_pr<span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="ln">45</span><span class="cl">  <span class="nb">local</span> <span class="nv">id</span><span class="o">=</span><span class="s2">&#34;</span><span class="nv">$1</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="ln">46</span><span class="cl">  <span class="nb">local</span> <span class="nv">branch</span><span class="o">=</span><span class="s2">&#34;</span><span class="si">${</span><span class="nv">TASK_BRANCH</span><span class="p">[</span><span class="nv">$id</span><span class="p">]</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="ln">47</span><span class="cl">  <span class="nb">local</span> <span class="nv">title</span><span class="o">=</span><span class="s2">&#34;</span><span class="si">${</span><span class="nv">TASK_TITLE</span><span class="p">[</span><span class="nv">$id</span><span class="p">]</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="ln">48</span><span class="cl">  <span class="nb">local</span> <span class="nv">worktree</span><span class="o">=</span><span class="s2">&#34;</span><span class="si">${</span><span class="nv">WORKTREE_DIR</span><span class="si">}</span><span class="s2">/lane-</span><span class="si">${</span><span class="nv">id</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="ln">49</span><span class="cl">
</span></span><span class="line"><span class="ln">50</span><span class="cl">  git -C <span class="s2">&#34;</span><span class="si">${</span><span class="nv">worktree</span><span class="si">}</span><span class="s2">&#34;</span> push -u origin <span class="s2">&#34;</span><span class="si">${</span><span class="nv">branch</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="ln">51</span><span class="cl">  gh pr create --base <span class="s2">&#34;</span><span class="si">${</span><span class="nv">BASE_BRANCH</span><span class="si">}</span><span class="s2">&#34;</span> --head <span class="s2">&#34;</span><span class="si">${</span><span class="nv">branch</span><span class="si">}</span><span class="s2">&#34;</span> --draft --title <span class="s2">&#34;</span><span class="si">${</span><span class="nv">title</span><span class="si">}</span><span class="s2">&#34;</span> --body <span class="s2">&#34;&lt;templated body&gt;&#34;</span>
</span></span><span class="line"><span class="ln">52</span><span class="cl"><span class="o">}</span></span></span></code></pre></div><h2 id="references">References</h2>
<ul>
<li>Codex docs hub: <a href="https://developers.openai.com/codex">https://developers.openai.com/codex</a></li>
<li>Codex CLI overview: <a href="https://developers.openai.com/codex/cli">https://developers.openai.com/codex/cli</a></li>
<li>Codex CLI features: <a href="https://developers.openai.com/codex/cli/features">https://developers.openai.com/codex/cli/features</a></li>
<li>Codex multi-agent docs: <a href="https://developers.openai.com/codex/multi-agent">https://developers.openai.com/codex/multi-agent</a></li>
<li>Codex security/sandbox docs: <a href="https://developers.openai.com/codex/security">https://developers.openai.com/codex/security</a></li>
<li>Codex config basics: <a href="https://developers.openai.com/codex/config-basic">https://developers.openai.com/codex/config-basic</a></li>
<li>Codex config reference: <a href="https://developers.openai.com/codex/config-reference">https://developers.openai.com/codex/config-reference</a></li>
<li>Codex CLI GitHub README: <a href="https://github.com/openai/codex/blob/main/README.md">https://github.com/openai/codex/blob/main/README.md</a></li>
<li>Ralph loop agent (Vercel Labs): <a href="https://github.com/vercel-labs/ralph-loop-agent">https://github.com/vercel-labs/ralph-loop-agent</a></li>
<li>Ralph from first principles (Geoffrey Huntley): <a href="https://www.youtube.com/watch?v=4Nna09dG_c0">https://www.youtube.com/watch?v=4Nna09dG_c0</a></li>
<li>Git worktree docs: <a href="https://git-scm.com/docs/git-worktree">https://git-scm.com/docs/git-worktree</a></li>
</ul>
]]></content:encoded>
    </item>
    <item>
      <title>Git</title>
      <link>https://KTS-o7.github.io/bear/notes/git/</link>
      <pubDate>Thu, 04 Dec 2025 00:00:00 +0530</pubDate><author>shentharkrishnatejaswi@gmail.com (Krishnatejaswi S)</author>
      <guid>https://KTS-o7.github.io/bear/notes/git/</guid>
      <description>&lt;h2 id=&#34;git&#34;&gt;Git&lt;/h2&gt;&#xA;&lt;p&gt;Before we start, here&amp;rsquo;s a link to one of the best free books on Git: &lt;a href=&#34;https://git-scm.com/book/en/v2&#34;&gt;Pro Git Book&lt;/a&gt;&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;h3 id=&#34;what-is-version-control&#34;&gt;What is Version Control?&lt;/h3&gt;&#xA;&lt;p&gt;When working on a project, we often need to keep track of changes made to the code. Version control systems help us track and reconcile changes across different versions of our codebase.&lt;/p&gt;&#xA;&lt;p&gt;Think of your codebase as a tree. Each change you make can create a new branch in the tree. It&amp;rsquo;s up to you to decide if your changes are good enough to become part of the main branch. But why a tree? Because we have a single source of truth (the &lt;code&gt;main&lt;/code&gt; branch) based on which we can reconcile all changes.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h2 id="git">Git</h2>
<p>Before we start, here&rsquo;s a link to one of the best free books on Git: <a href="https://git-scm.com/book/en/v2">Pro Git Book</a></p>
<hr>
<h3 id="what-is-version-control">What is Version Control?</h3>
<p>When working on a project, we often need to keep track of changes made to the code. Version control systems help us track and reconcile changes across different versions of our codebase.</p>
<p>Think of your codebase as a tree. Each change you make can create a new branch in the tree. It&rsquo;s up to you to decide if your changes are good enough to become part of the main branch. But why a tree? Because we have a single source of truth (the <code>main</code> branch) based on which we can reconcile all changes.</p>
<p>Imagine the source of truth is a single branch called <code>main</code>. When you want to work on a new feature, you create a branch from <code>main</code>, make your changes in that branch, and once you&rsquo;re done, you can merge the branch back into <code>main</code>.</p>
<p>This approach allows us to:</p>
<ol>
<li>Work on multiple features in parallel</li>
<li>Enable multiple people to work on the same codebase simultaneously</li>
<li>Revert to previous stable states if something goes wrong</li>
</ol>
<p><a href="https://mermaid.live/edit#pako:eNp1klFvgjAQx78Kub2ia7GINovJBH3zbU8TH6pchQQoqWWZE7_7KjAjyexT737__92lvQscVILA4ahFlTofUVw69rxvNyIrd85otGj2WpSHtHGW2zUKU2uku140wOEf9nq8bHGCX5irqnGiu_1tr18XB1UUmTn12nCoXd1r_aONWm2B-oiNs-4G7chqQLrcyZxztKPKLM_5C1LpS_lI1k_JsidSSob0kYRPSfSUrAYEXPvgWQLc6BpdsCMX4hbC5eaJwaRYYAzcXhOUos5NDHF5tbZKlJ9KFX9OrepjClyK_GSjukqEwSgT9jeLe1ZjmaAOVV0a4JSwtgjwC3wD9xgbU0KCKQ1oQGaUBC6cgU-mbEymJGABmwXEY97VhZ-2LRmziT-n1GfE8zx_TnwXMMmM0ptukdp9uv4C9ee5ZA"><img src="https://mermaid.ink/img/pako:eNp1klFvgjAQx78Kub2ia7GINovJBH3zbU8TH6pchQQoqWWZE7_7KjAjyexT737__92lvQscVILA4ahFlTofUVw69rxvNyIrd85otGj2WpSHtHGW2zUKU2uku140wOEf9nq8bHGCX5irqnGiu_1tr18XB1UUmTn12nCoXd1r_aONWm2B-oiNs-4G7chqQLrcyZxztKPKLM_5C1LpS_lI1k_JsidSSob0kYRPSfSUrAYEXPvgWQLc6BpdsCMX4hbC5eaJwaRYYAzcXhOUos5NDHF5tbZKlJ9KFX9OrepjClyK_GSjukqEwSgT9jeLe1ZjmaAOVV0a4JSwtgjwC3wD9xgbU0KCKQ1oQGaUBC6cgU-mbEymJGABmwXEY97VhZ-2LRmziT-n1GfE8zx_TnwXMMmM0ptukdp9uv4C9ee5ZA?type=png" alt=""></a></p>
<h3 id="getting-started">Getting Started</h3>
<p>First, download Git from <a href="https://git-scm.com/downloads">here</a> and install it.</p>
<p>In this guide, we&rsquo;ll cover:</p>
<ol>
<li>Setting up Git credentials</li>
<li>Creating a new repository</li>
<li>Understanding the staging area and making commits</li>
<li>Working with branches</li>
<li>Merging branches</li>
<li>Working with remote repositories</li>
<li>Common Git commands and workflows</li>
</ol>
<h4 id="1-setting-up-git-credentials">1. Setting Up Git Credentials</h4>
<p>Before you start using Git, configure your name and email. These will be associated with all your commits.</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">git config --global user.name <span class="s2">&#34;Your Name&#34;</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">git config --global user.email <span class="s2">&#34;your.email@example.com&#34;</span></span></span></code></pre></div><p>You can verify your configuration with:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">git config --list</span></span></code></pre></div><h4 id="2-creating-a-new-repository">2. Creating a New Repository</h4>
<p>Navigate to the directory where you want to create the repository. You can either:</p>
<ul>
<li>Initialize an existing directory as a Git repository</li>
<li>Create a new directory and then initialize it</li>
</ul>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># Option 1: Initialize current directory</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">git init
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># Option 2: Create new directory and initialize</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">mkdir my-project
</span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="nb">cd</span> my-project
</span></span><span class="line"><span class="ln">7</span><span class="cl">git init</span></span></code></pre></div><h4 id="3-understanding-the-staging-area-and-making-commits">3. Understanding the Staging Area and Making Commits</h4>
<p>Git uses a three-stage workflow:</p>
<ol>
<li><strong>Working Directory</strong>: Your files as they exist on disk</li>
<li><strong>Staging Area</strong>: Files you&rsquo;ve marked to be included in the next commit</li>
<li><strong>Repository</strong>: Committed snapshots of your project</li>
</ol>
<p>Let&rsquo;s create a file and commit it:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># Create a new file</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;Hello, World!&#34;</span> &gt; hello.txt
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># Stage the file (add it to the staging area)</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">git add hello.txt
</span></span><span class="line"><span class="ln">6</span><span class="cl">
</span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="c1"># Commit the changes with a descriptive message</span>
</span></span><span class="line"><span class="ln">8</span><span class="cl">git commit -m <span class="s2">&#34;Add hello.txt file&#34;</span></span></span></code></pre></div><p><strong>Key Commands:</strong></p>
<ul>
<li><code>git status</code> - See which files are modified, staged, or untracked</li>
<li><code>git add &lt;file&gt;</code> - Stage a specific file</li>
<li><code>git add .</code> - Stage all changes in the current directory</li>
<li><code>git commit -m &quot;message&quot;</code> - Commit staged changes with a message</li>
</ul>
<h4 id="4-working-with-branches">4. Working with Branches</h4>
<p>Branches allow you to work on features, experiments, or fixes without affecting the main codebase.</p>
<p><strong>Create and switch to a new branch:</strong></p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">git checkout -b feature1</span></span></code></pre></div><p>This is equivalent to:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">git branch feature1      <span class="c1"># Create the branch</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">git checkout feature1    <span class="c1"># Switch to the branch</span></span></span></code></pre></div><p><strong>Modern alternative (Git 2.23+):</strong></p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">git switch -c feature1   <span class="c1"># Create and switch</span></span></span></code></pre></div><p><strong>Make changes in the new branch:</strong></p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;Hello, World! in feature1&#34;</span> &gt; hello.txt</span></span></code></pre></div><p><strong>View all branches:</strong></p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">git branch                <span class="c1"># List local branches</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">git branch -a            <span class="c1"># List all branches (local and remote)</span></span></span></code></pre></div><h4 id="5-committing-changes-to-a-branch">5. Committing Changes to a Branch</h4>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">git add hello.txt
</span></span><span class="line"><span class="ln">2</span><span class="cl">git commit -m <span class="s2">&#34;Update hello.txt in feature1 branch&#34;</span></span></span></code></pre></div><h4 id="6-merging-branches">6. Merging Branches</h4>
<p>Once your feature is complete, merge it back into <code>main</code>:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># Switch back to main branch</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">git checkout main
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># Merge feature1 into main</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">git merge feature1</span></span></code></pre></div><p><strong>Note:</strong> If there are no conflicts, Git will automatically create a merge commit. If conflicts occur, you&rsquo;ll need to resolve them manually.</p>
<h4 id="7-working-with-remote-repositories">7. Working with Remote Repositories</h4>
<p>Remote repositories allow you to collaborate with others and back up your code.</p>
<p><strong>Add a remote repository:</strong></p>
<p>First, create a new repository on a platform like GitHub, GitLab, or Bitbucket. Then copy the repository URL and add it as a remote:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">git remote add origin &lt;remote-repository-URL&gt;</span></span></code></pre></div><p><strong>View remote repositories:</strong></p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">git remote -v              <span class="c1"># List all remotes with URLs</span></span></span></code></pre></div><p><strong>Update remote URL (if needed):</strong></p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">git remote set-url origin &lt;new-URL&gt;</span></span></code></pre></div><h4 id="8-pushing-changes-to-remote">8. Pushing Changes to Remote</h4>
<p>Push your local commits to the remote repository:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">git push -u origin main</span></span></code></pre></div><p>The <code>-u</code> flag sets up tracking, so future pushes can be done with just <code>git push</code>.</p>
<p><strong>Push to a specific branch:</strong></p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">git push origin feature1</span></span></code></pre></div><h4 id="9-pulling-changes-from-remote">9. Pulling Changes from Remote</h4>
<p><code>git pull</code> fetches changes from the remote and merges them into your current branch:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">git pull origin main</span></span></code></pre></div><p><strong>Note:</strong> <code>git pull</code> is equivalent to <code>git fetch</code> followed by <code>git merge</code>.</p>
<h4 id="10-fetching-changes-from-remote">10. Fetching Changes from Remote</h4>
<p><code>git fetch</code> downloads changes from the remote without merging them:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">git fetch origin</span></span></code></pre></div><p>This is useful when you want to see what changes exist on the remote before merging them. After fetching, you can review changes with:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">git log origin/main..main    <span class="c1"># See commits on remote</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">git diff origin/main          <span class="c1"># See differences</span></span></span></code></pre></div><hr>
<h3 id="additional-useful-commands">Additional Useful Commands</h3>
<h4 id="viewing-history-and-changes">Viewing History and Changes</h4>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">git log                      <span class="c1"># View commit history</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">git log --oneline            <span class="c1"># Compact one-line view</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">git log --graph --oneline    <span class="c1"># Visual branch history</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl">git diff                     <span class="c1"># See unstaged changes</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">git diff --staged            <span class="c1"># See staged changes</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl">git show &lt;commit-hash&gt;       <span class="c1"># Show details of a specific commit</span></span></span></code></pre></div><h4 id="undoing-changes">Undoing Changes</h4>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">git restore &lt;file&gt;           <span class="c1"># Discard changes in working directory</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">git restore --staged &lt;file&gt;  <span class="c1"># Unstage a file</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">git reset HEAD~1             <span class="c1"># Undo last commit (keeps changes)</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl">git reset --hard HEAD~1      <span class="c1"># Undo last commit (discards changes) - use with caution!</span></span></span></code></pre></div><h4 id="working-with-gitignore">Working with .gitignore</h4>
<p>Create a <code>.gitignore</code> file to exclude files from version control:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># Example .gitignore</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">node_modules/
</span></span><span class="line"><span class="ln">3</span><span class="cl">*.log
</span></span><span class="line"><span class="ln">4</span><span class="cl">.env
</span></span><span class="line"><span class="ln">5</span><span class="cl">.DS_Store</span></span></code></pre></div><h4 id="cloning-a-repository">Cloning a Repository</h4>
<p>To get a copy of an existing repository:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">git clone &lt;repository-URL&gt;</span></span></code></pre></div><p>This creates a new directory with the repository name and downloads all files and history.</p>
<hr>
<h3 id="common-workflows">Common Workflows</h3>
<p><strong>Typical workflow:</strong></p>
<ol>
<li><code>git pull</code> - Get latest changes</li>
<li><code>git checkout -b feature-name</code> - Create feature branch</li>
<li>Make changes and <code>git add</code> files</li>
<li><code>git commit -m &quot;message&quot;</code> - Commit changes</li>
<li><code>git push origin feature-name</code> - Push to remote</li>
<li>Create pull/merge request on platform</li>
<li>After review, merge to main</li>
<li><code>git checkout main &amp;&amp; git pull</code> - Update local main</li>
</ol>
<hr>
<h3 id="tips-and-best-practices">Tips and Best Practices</h3>
<ol>
<li><strong>Write clear commit messages</strong>: Describe what and why, not how</li>
<li><strong>Commit often</strong>: Small, logical commits are easier to review and revert</li>
<li><strong>Pull before push</strong>: Always pull latest changes before pushing</li>
<li><strong>Use branches</strong>: Keep main stable, work on features in branches</li>
<li><strong>Review before merging</strong>: Check your changes with <code>git diff</code> and <code>git status</code></li>
</ol>
]]></content:encoded>
    </item>
    <item>
      <title>Gray Code</title>
      <link>https://KTS-o7.github.io/bear/notes/gray_code/</link>
      <pubDate>Fri, 19 Sep 2025 23:03:51 +0530</pubDate><author>shentharkrishnatejaswi@gmail.com (Krishnatejaswi S)</author>
      <guid>https://KTS-o7.github.io/bear/notes/gray_code/</guid>
      <description>&lt;p&gt;Link to the problem : &lt;a href=&#34;https://cses.fi/problemset/task/2205&#34;&gt;Gray Code&lt;/a&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;intuition&#34;&gt;Intuition&lt;/h2&gt;&#xA;&lt;p&gt;The problem is asking us to generate the gray code for a given number n.&lt;/p&gt;&#xA;&lt;p&gt;Gray code is a binary numeral system where two successive values differ in only one bit.&#xA;This is similar to bit strings problem. But instead of printing the binary representation of the number, we need to print the gray code.&lt;/p&gt;&#xA;&lt;p&gt;The formula to generate the gray code for a given number n is:&#xA;&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Link to the problem : <a href="https://cses.fi/problemset/task/2205">Gray Code</a></p>
<h2 id="intuition">Intuition</h2>
<p>The problem is asking us to generate the gray code for a given number n.</p>
<p>Gray code is a binary numeral system where two successive values differ in only one bit.
This is similar to bit strings problem. But instead of printing the binary representation of the number, we need to print the gray code.</p>
<p>The formula to generate the gray code for a given number n is:
</p>
$$G(n) = n \oplus (n >> 1)$$<h2 id="solution">Solution</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln">1</span><span class="cl"><span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">    <span class="n">n</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="nb">input</span><span class="p">())</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">    <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">2</span><span class="o">**</span><span class="n">n</span><span class="p">):</span>   
</span></span><span class="line"><span class="ln">4</span><span class="cl">        <span class="n">num</span> <span class="o">=</span> <span class="n">i</span><span class="o">^</span><span class="p">(</span><span class="n">i</span><span class="o">&gt;&gt;</span><span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">        <span class="n">num_str</span> <span class="o">=</span> <span class="nb">bin</span><span class="p">(</span><span class="n">num</span><span class="p">)[</span><span class="mi">2</span><span class="p">:]</span><span class="o">.</span><span class="n">zfill</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="n">num_str</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s2">&#34;</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">7</span><span class="cl">
</span></span><span class="line"><span class="ln">8</span><span class="cl"><span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&#34;__main__&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">9</span><span class="cl">    <span class="n">main</span><span class="p">()</span></span></span></code></pre></div><h2 id="other-possible-solutions">Other possible solutions</h2>
<h3 id="bit-by-bit-approach">Bit-by-Bit Approach</h3>
<p>This approach constructs the Gray code by calculating each bit position individually using the property that the i-th bit of the Gray code is the XOR of the i-th and (i+1)-th bits of the binary representation.</p>
<h4 id="dry-run-for-n--2">Dry Run for n = 2</h4>
<p>For n = 2, we need to generate 4 Gray codes (2² = 4). Let&rsquo;s walk through each iteration:</p>
<p><strong>Iteration 1: i = 0</strong></p>
<ul>
<li>Binary representation: 00</li>
<li><strong>Bit position 0 (rightmost):</strong>
<ul>
<li>Current bit: (0 &raquo; 0) &amp; 1 = 0 &amp; 1 = 0</li>
<li>Next bit: (0 &raquo; 1) &amp; 1 = 0 &amp; 1 = 0 (since bit position 1 &lt; n=2)</li>
<li>Gray bit: 0 ⊕ 0 = 0</li>
<li>Set bit: gray = 0 | (0 &laquo; 0) = 0</li>
</ul>
</li>
<li><strong>Bit position 1:</strong>
<ul>
<li>Current bit: (0 &raquo; 1) &amp; 1 = 0 &amp; 1 = 0</li>
<li>Next bit: 0 (since bit position 2 &gt;= n=2)</li>
<li>Gray bit: 0 ⊕ 0 = 0</li>
<li>Set bit: gray = 0 | (0 &laquo; 1) = 0</li>
</ul>
</li>
<li>Result: 00</li>
</ul>
<p><strong>Iteration 2: i = 1</strong></p>
<ul>
<li>Binary representation: 01</li>
<li><strong>Bit position 0:</strong>
<ul>
<li>Current bit: (1 &raquo; 0) &amp; 1 = 1 &amp; 1 = 1</li>
<li>Next bit: (1 &raquo; 1) &amp; 1 = 0 &amp; 1 = 0</li>
<li>Gray bit: 1 ⊕ 0 = 1</li>
<li>Set bit: gray = 0 | (1 &laquo; 0) = 1</li>
</ul>
</li>
<li><strong>Bit position 1:</strong>
<ul>
<li>Current bit: (1 &raquo; 1) &amp; 1 = 0 &amp; 1 = 0</li>
<li>Next bit: 0 (since bit position 2 &gt;= n=2)</li>
<li>Gray bit: 0 ⊕ 0 = 0</li>
<li>Set bit: gray = 1 | (0 &laquo; 1) = 1</li>
</ul>
</li>
<li>Result: 01</li>
</ul>
<p><strong>Iteration 3: i = 2</strong></p>
<ul>
<li>Binary representation: 10</li>
<li><strong>Bit position 0:</strong>
<ul>
<li>Current bit: (2 &raquo; 0) &amp; 1 = 2 &amp; 1 = 0 (2 in binary is 10, rightmost bit is 0)</li>
<li>Next bit: (2 &raquo; 1) &amp; 1 = 1 &amp; 1 = 1</li>
<li>Gray bit: 0 ⊕ 1 = 1</li>
<li>Set bit: gray = 0 | (1 &laquo; 0) = 1</li>
</ul>
</li>
<li><strong>Bit position 1:</strong>
<ul>
<li>Current bit: (2 &raquo; 1) &amp; 1 = 1 &amp; 1 = 1</li>
<li>Next bit: 0 (since bit position 2 &gt;= n=2)</li>
<li>Gray bit: 1 ⊕ 0 = 1</li>
<li>Set bit: gray = 1 | (1 &laquo; 1) = 1 | 2 = 3</li>
</ul>
</li>
<li>Result: 11</li>
</ul>
<p><strong>Iteration 4: i = 3</strong></p>
<ul>
<li>Binary representation: 11</li>
<li><strong>Bit position 0:</strong>
<ul>
<li>Current bit: (3 &raquo; 0) &amp; 1 = 3 &amp; 1 = 1 (3 in binary is 11, rightmost bit is 1)</li>
<li>Next bit: (3 &raquo; 1) &amp; 1 = 1 &amp; 1 = 1</li>
<li>Gray bit: 1 ⊕ 1 = 0</li>
<li>Set bit: gray = 0 | (0 &laquo; 0) = 0</li>
</ul>
</li>
<li><strong>Bit position 1:</strong>
<ul>
<li>Current bit: (3 &raquo; 1) &amp; 1 = 1 &amp; 1 = 1</li>
<li>Next bit: 0 (since bit position 2 &gt;= n=2)</li>
<li>Gray bit: 1 ⊕ 0 = 1</li>
<li>Set bit: gray = 0 | (1 &laquo; 1) = 2</li>
</ul>
</li>
<li>Result: 10</li>
</ul>
<p><strong>Final Gray Code Sequence:</strong> 00, 01, 11, 10</p>
<p>Notice how each consecutive Gray code differs by only one bit:</p>
<ul>
<li>00 → 01 (bit 0 changes: 0→1)</li>
<li>01 → 11 (bit 1 changes: 0→1)</li>
<li>11 → 10 (bit 0 changes: 1→0)</li>
</ul>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="k">def</span> <span class="nf">generate_gray_code_bitwise</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">    <span class="n">result</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">    <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">2</span><span class="o">**</span><span class="n">n</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">        <span class="n">gray</span> <span class="o">=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">        <span class="k">for</span> <span class="n">bit</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">            <span class="c1"># Gray bit is XOR of current bit and next bit</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">            <span class="n">current_bit</span> <span class="o">=</span> <span class="p">(</span><span class="n">i</span> <span class="o">&gt;&gt;</span> <span class="n">bit</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mi">1</span> <span class="c1"># this step get the current bit using bitwise shift and bitwise and</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">            <span class="n">next_bit</span> <span class="o">=</span> <span class="p">(</span><span class="n">i</span> <span class="o">&gt;&gt;</span> <span class="p">(</span><span class="n">bit</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span> <span class="o">&amp;</span> <span class="mi">1</span> <span class="k">if</span> <span class="n">bit</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">&lt;</span> <span class="n">n</span> <span class="k">else</span> <span class="mi">0</span> <span class="c1"># this step get the next bit using bitwise shift and bitwise and</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">            <span class="n">gray_bit</span> <span class="o">=</span> <span class="n">current_bit</span> <span class="o">^</span> <span class="n">next_bit</span> <span class="c1"># this step get the gray bit using bitwise xor</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">            <span class="n">gray</span> <span class="o">|=</span> <span class="p">(</span><span class="n">gray_bit</span> <span class="o">&lt;&lt;</span> <span class="n">bit</span><span class="p">)</span> <span class="c1"># this step set the gray bit using bitwise or</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">        <span class="n">result</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="nb">bin</span><span class="p">(</span><span class="n">gray</span><span class="p">)[</span><span class="mi">2</span><span class="p">:]</span><span class="o">.</span><span class="n">zfill</span><span class="p">(</span><span class="n">n</span><span class="p">))</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">    <span class="k">return</span> <span class="n">result</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">
</span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">    <span class="n">n</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="nb">input</span><span class="p">())</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">    <span class="n">gray_codes</span> <span class="o">=</span> <span class="n">generate_gray_code_bitwise</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">    <span class="k">for</span> <span class="n">code</span> <span class="ow">in</span> <span class="n">gray_codes</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="n">code</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">
</span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&#34;__main__&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">    <span class="n">main</span><span class="p">()</span></span></span></code></pre></div>]]></content:encoded>
    </item>
    <item>
      <title>Bit Strings</title>
      <link>https://KTS-o7.github.io/bear/notes/bit_strings/</link>
      <pubDate>Fri, 19 Sep 2025 22:53:15 +0530</pubDate><author>shentharkrishnatejaswi@gmail.com (Krishnatejaswi S)</author>
      <guid>https://KTS-o7.github.io/bear/notes/bit_strings/</guid>
      <description>&lt;p&gt;Link to the problem : &lt;a href=&#34;https://cses.fi/problemset/task/1617&#34;&gt;Bit Strings&lt;/a&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;intuition&#34;&gt;Intuition&lt;/h2&gt;&#xA;&lt;p&gt;Problem is asking us to find the number of combinations of 0s and 1s of length n.&#xA;Basically its 2^n combinations.&lt;/p&gt;&#xA;&lt;h2 id=&#34;solution&#34;&gt;Solution&lt;/h2&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;ln&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;ln&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;n&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;input&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;ln&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;**&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;n&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1000000007&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;ln&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;ln&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;vm&#34;&gt;__name__&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;__main__&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;ln&#34;&gt;6&lt;/span&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In python it feels cheating to use the power operator **, but it is a valid way to solve the problem.&lt;/p&gt;&#xA;&lt;p&gt;In lower level languages like C, C++, Java, we need to use a loop to calculate the power of 2 and each time we take modulo 1e9+7.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Link to the problem : <a href="https://cses.fi/problemset/task/1617">Bit Strings</a></p>
<h2 id="intuition">Intuition</h2>
<p>Problem is asking us to find the number of combinations of 0s and 1s of length n.
Basically its 2^n combinations.</p>
<h2 id="solution">Solution</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln">1</span><span class="cl"><span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">    <span class="n">n</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="nb">input</span><span class="p">())</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="mi">2</span><span class="o">**</span><span class="n">n</span> <span class="o">%</span> <span class="mi">1000000007</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl">
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&#34;__main__&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl">    <span class="n">main</span><span class="p">()</span></span></span></code></pre></div><p>In python it feels cheating to use the power operator **, but it is a valid way to solve the problem.</p>
<p>In lower level languages like C, C++, Java, we need to use a loop to calculate the power of 2 and each time we take modulo 1e9+7.</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdlib.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    <span class="kt">int</span> <span class="n">n</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">    <span class="nf">scanf</span><span class="p">(</span><span class="s">&#34;%d&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">n</span><span class="p">);</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">    <span class="kt">long</span> <span class="kt">long</span> <span class="n">result</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">    <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">        <span class="n">result</span> <span class="o">=</span> <span class="p">(</span><span class="n">result</span> <span class="o">*</span> <span class="mi">2</span><span class="p">)</span> <span class="o">%</span> <span class="mi">1000000007</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">    <span class="nf">printf</span><span class="p">(</span><span class="s">&#34;%lld</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">result</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="p">}</span></span></span></code></pre></div>]]></content:encoded>
    </item>
    <item>
      <title>Two Sets</title>
      <link>https://KTS-o7.github.io/bear/notes/two_sets/</link>
      <pubDate>Fri, 19 Sep 2025 15:41:11 +0530</pubDate><author>shentharkrishnatejaswi@gmail.com (Krishnatejaswi S)</author>
      <guid>https://KTS-o7.github.io/bear/notes/two_sets/</guid>
      <description>&lt;p&gt;Link to the problem : &lt;a href=&#34;https://cses.fi/problemset/task/1092&#34;&gt;Two Sets&lt;/a&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;intuition&#34;&gt;Intuition&lt;/h2&gt;&#xA;&lt;p&gt;The problem asking us to partition the given set of numbers into two sets such that the sum of the numbers in the two sets are equal.&lt;/p&gt;&#xA;&lt;p&gt;For the sum of two sets to be equal the total sum of the numbers must be even.&#xA;That means sum(numbers) % 2 == 0.&#xA;by the forumla for the sum of the first n natural numbers, sum(numbers) = n * (n + 1) / 2.&#xA;So that means sum of each set must be n * (n + 1) / 4.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Link to the problem : <a href="https://cses.fi/problemset/task/1092">Two Sets</a></p>
<h2 id="intuition">Intuition</h2>
<p>The problem asking us to partition the given set of numbers into two sets such that the sum of the numbers in the two sets are equal.</p>
<p>For the sum of two sets to be equal the total sum of the numbers must be even.
That means sum(numbers) % 2 == 0.
by the forumla for the sum of the first n natural numbers, sum(numbers) = n * (n + 1) / 2.
So that means sum of each set must be n * (n + 1) / 4.</p>
<p>Hence we got that n mod 4 is 0  or (n+1) mod 4 is 0, combining both we get n mod 4 must be 0 or 3 to be able to partition the numbers into two sets.
So this becomes a necessary condition for the problem to be solvable.</p>
<p>but this is not a sufficient condition.</p>
<p>When
n mod 4 = 0:
Total sum is even, partition is possible.
The set can be split so both subsets have the same number of elements (equal size).</p>
<p>Example:
n=8</p>
<p>Pairs: (8,1), (7,2), (6,3), (5,4)</p>
<p>Assign two pairs to one set, the other two pairs to the other set—both sum to 18.</p>
<p>When n mod 4 = 3:
Total sum is even, partition is possible.</p>
<p>The sets will have different sizes (one will have one more element).
Example:
n=7</p>
<p>Pairs: (7,1,6) sums to 14, rest (2,3,4,5) sum to 14.</p>
<p>The sum of each smallest–largest pair is always n+1.</p>
<p>For  n mod 4 = 0: you can split pairs alternately between the two sets.</p>
<p>For n mod 4 = 3:  this is a tricky case
Consider some integer k such that we have n = 4k+3. that means n mod 4 = 3.
Now sum of n numbers is n * (n + 1) / 2 = (4k+3) * (4k+4) / 2 = (4k+3) * (2k+2)</p>
<hr>
<h3 id="mathematical-derivation">Mathematical Derivation</h3>
<p>For n = 4k + 3, we assign:</p>
<ul>
<li><strong>Set 1</strong>: numbers where i ≡ 1 or 2 (mod 4)</li>
<li><strong>Set 2</strong>: numbers where i ≡ 0 or 3 (mod 4)</li>
</ul>
<h4 id="count-of-numbers-in-each-residue-class">Count of numbers in each residue class:</h4>
<ul>
<li><strong>≡ 0 mod 4</strong>: k numbers (4, 8, &hellip;, 4k)</li>
<li><strong>≡ 1 mod 4</strong>: k+1 numbers (1, 5, &hellip;, 4k+1)</li>
<li><strong>≡ 2 mod 4</strong>: k+1 numbers (2, 6, &hellip;, 4k+2)</li>
<li><strong>≡ 3 mod 4</strong>: k+1 numbers (3, 7, &hellip;, 4k+3)</li>
</ul>
<h4 id="sum-of-each-residue-class">Sum of each residue class:</h4>
<p><strong>≡ 0 mod 4</strong>:</p>





<pre tabindex="0"><code>4 + 8 + ... + 4k = 4(1 + 2 + ... + k) = 4 × k(k+1)/2 = 2k(k+1)</code></pre><p><strong>≡ 1 mod 4</strong>:</p>





<pre tabindex="0"><code>1 + 5 + 9 + ... + (4k+1)</code></pre><p>Arithmetic series: first term = 1, last term = 4k+1, common difference = 4, terms = k+1</p>





<pre tabindex="0"><code>Sum = (k+1) × (1 + 4k+1)/2 = (k+1) × (4k+2)/2 = (k+1) × 2(k+1) = 2(k+1)²</code></pre><p><strong>≡ 2 mod 4</strong>:</p>





<pre tabindex="0"><code>2 + 6 + 10 + ... + (4k+2)</code></pre><p>Arithmetic series: first term = 2, last term = 4k+2, common difference = 4, terms = k+1</p>





<pre tabindex="0"><code>Sum = (k+1) × (2 + 4k+2)/2 = (k+1) × (4k+4)/2 = (k+1) × 2(k+2) = 2(k+1)(k+2)</code></pre><p><strong>≡ 3 mod 4</strong>:</p>





<pre tabindex="0"><code>3 + 7 + 11 + ... + (4k+3)</code></pre><p>Arithmetic series: first term = 3, last term = 4k+3, common difference = 4, terms = k+1</p>





<pre tabindex="0"><code>Sum = (k+1) × (3 + 4k+3)/2 = (k+1) × (4k+6)/2 = (k+1) × 2(k+3) = 2(k+1)(k+3)</code></pre><h4 id="total-sum-verification">Total sum verification:</h4>





<pre tabindex="0"><code>Total sum = 2k(k+1) + 2(k+1)² + 2(k+1)(k+2) + 2(k+1)(k+3)
         = 2(k+1) × [k + (k+1) + (k+2) + (k+3)]
         = 2(k+1) × (4k + 6)
         = 2(k+1) × 2(2k + 3)
         = 4(k+1)(2k + 3)</code></pre><p>Each set should sum to: <strong>2(k+1)(2k + 3)</strong></p>
<h4 id="sum-of-each-set">Sum of each set:</h4>
<p><strong>Set 1 (≡1 or ≡2 mod 4)</strong>:</p>





<pre tabindex="0"><code>Sum = 2(k+1)² + 2(k+1)(k+2) = 2(k+1) × [(k+1) + (k+2)] = 2(k+1) × (2k + 3)</code></pre><p><strong>Set 2 (≡0 or ≡3 mod 4)</strong>:</p>





<pre tabindex="0"><code>Sum = 2k(k+1) + 2(k+1)(k+3) = 2(k+1) × [k + (k+3)] = 2(k+1) × (2k + 3)</code></pre><p>Both sets sum to <strong>2(k+1)(2k + 3)</strong>, which is exactly half the total sum.</p>
<hr>
<h2 id="solution">Solution</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">    <span class="n">n</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="nb">input</span><span class="p">())</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">    <span class="k">if</span> <span class="n">n</span> <span class="o">%</span> <span class="mi">4</span> <span class="ow">not</span> <span class="ow">in</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">3</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;NO&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">        <span class="k">return</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">    
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">    <span class="n">set1</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">    <span class="n">set2</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    <span class="n">toggle</span> <span class="o">=</span> <span class="kc">True</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">    
</span></span><span class="line"><span class="ln">11</span><span class="cl">    <span class="k">if</span> <span class="n">n</span> <span class="o">%</span> <span class="mi">4</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">        <span class="n">low</span> <span class="o">=</span> <span class="mi">1</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">        <span class="n">high</span> <span class="o">=</span> <span class="n">n</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">        <span class="k">while</span> <span class="n">low</span> <span class="o">&lt;=</span> <span class="n">high</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">            <span class="k">if</span> <span class="n">toggle</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">                <span class="n">set1</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">low</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">                <span class="n">set1</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">high</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">            <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">                <span class="n">set2</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">low</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">                <span class="n">set2</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">high</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">            <span class="n">low</span> <span class="o">+=</span> <span class="mi">1</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">            <span class="n">high</span> <span class="o">-=</span> <span class="mi">1</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">            <span class="n">toggle</span> <span class="o">=</span> <span class="ow">not</span> <span class="n">toggle</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl">    <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl">        <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">n</span><span class="o">+</span><span class="mi">1</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl">            <span class="k">if</span> <span class="n">i</span> <span class="o">%</span> <span class="mi">4</span> <span class="o">==</span> <span class="mi">1</span> <span class="ow">or</span> <span class="n">i</span> <span class="o">%</span> <span class="mi">4</span> <span class="o">==</span> <span class="mi">2</span><span class="p">:</span> <span class="c1"># </span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">                <span class="n">set1</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl">            <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">29</span><span class="cl">                <span class="n">set2</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">30</span><span class="cl">    
</span></span><span class="line"><span class="ln">31</span><span class="cl">    <span class="c1"># Output the result</span>
</span></span><span class="line"><span class="ln">32</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;YES&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">33</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">set1</span><span class="p">))</span>
</span></span><span class="line"><span class="ln">34</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34; &#34;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="nb">map</span><span class="p">(</span><span class="nb">str</span><span class="p">,</span> <span class="n">set1</span><span class="p">)))</span>
</span></span><span class="line"><span class="ln">35</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">set2</span><span class="p">))</span>
</span></span><span class="line"><span class="ln">36</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34; &#34;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="nb">map</span><span class="p">(</span><span class="nb">str</span><span class="p">,</span> <span class="n">set2</span><span class="p">)))</span>
</span></span><span class="line"><span class="ln">37</span><span class="cl">
</span></span><span class="line"><span class="ln">38</span><span class="cl"><span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&#34;__main__&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">39</span><span class="cl">    <span class="n">main</span><span class="p">()</span></span></span></code></pre></div>]]></content:encoded>
    </item>
    <item>
      <title>Permutations</title>
      <link>https://KTS-o7.github.io/bear/notes/permutations/</link>
      <pubDate>Thu, 18 Sep 2025 22:49:10 +0530</pubDate><author>shentharkrishnatejaswi@gmail.com (Krishnatejaswi S)</author>
      <guid>https://KTS-o7.github.io/bear/notes/permutations/</guid>
      <description>&lt;p&gt;Link to the problem : &lt;a href=&#34;https://cses.fi/problemset/task/1070&#34;&gt;Permutations&lt;/a&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;intuition&#34;&gt;Intuition&lt;/h2&gt;&#xA;&lt;p&gt;The idea is to generate a permutation of the numbers from 1 to n such that the difference between any two consecutive elements is at least greater than 1.&lt;/p&gt;&#xA;&lt;p&gt;One way to do this is to first write all the even numbers between 1 and n in increasing order and then write all the odd numbers between 1 and n in increasing order.&lt;/p&gt;&#xA;&lt;p&gt;This is only one such solution. There are other solutions as well.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Link to the problem : <a href="https://cses.fi/problemset/task/1070">Permutations</a></p>
<h2 id="intuition">Intuition</h2>
<p>The idea is to generate a permutation of the numbers from 1 to n such that the difference between any two consecutive elements is at least greater than 1.</p>
<p>One way to do this is to first write all the even numbers between 1 and n in increasing order and then write all the odd numbers between 1 and n in increasing order.</p>
<p>This is only one such solution. There are other solutions as well.</p>
<p>Edge case:</p>
<ul>
<li>If n is 1, print 1. this is  because there are no consecutive elements in the permutation, hence is a valid permutation.</li>
<li>If n is less than 4, print &ldquo;NO SOLUTION&rdquo;.
because for n &lt; 4, any permutation will have a difference between any two consecutive elements less than 1.
example
1 2 3 4, 1 3 2 4, 1 3 4 2, etc are not valid permutations.</li>
</ul>
<h2 id="solution">Solution</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">    <span class="n">n</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="nb">input</span><span class="p">())</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">    <span class="k">if</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">        <span class="k">return</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">    <span class="k">if</span> <span class="n">n</span> <span class="o">&lt;</span> <span class="mi">4</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;NO SOLUTION&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">        <span class="k">return</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span><span class="n">n</span><span class="o">+</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s2">&#34; &#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">    <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="n">n</span><span class="o">+</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s2">&#34; &#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">
</span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&#34;__main__&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">    <span class="n">main</span><span class="p">()</span></span></span></code></pre></div><h3 id="other-possible-solutions">Other possible solutions</h3>
<ul>
<li>Write all the odd numbers between 1 and n in increasing order and then write all the even numbers between 1 and n in increasing order.</li>
<li>Write all the odd numbers between 1 and n in decreasing order and then write all the even numbers between 1 and n in decreasing order.</li>
<li>Write all the even numbers between 1 and n in increasing order and then write all the odd numbers between 1 and n in decreasing order.</li>
</ul>
]]></content:encoded>
    </item>
    <item>
      <title>Increasing Array</title>
      <link>https://KTS-o7.github.io/bear/notes/increasing_array/</link>
      <pubDate>Thu, 18 Sep 2025 22:37:39 +0530</pubDate><author>shentharkrishnatejaswi@gmail.com (Krishnatejaswi S)</author>
      <guid>https://KTS-o7.github.io/bear/notes/increasing_array/</guid>
      <description>&lt;p&gt;Link to the problem : &lt;a href=&#34;https://cses.fi/problemset/task/1094&#34;&gt;Increasing Array&lt;/a&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;intuition&#34;&gt;Intuition&lt;/h2&gt;&#xA;&lt;p&gt;The idea is to make an array increasing by making the current element equal to or greater than the previous element.&#xA;and in each step we can increase the value of a single element by 1.&lt;/p&gt;&#xA;&lt;p&gt;That means for &lt;code&gt;i&lt;/code&gt;th element which is less than the &lt;code&gt;i-1&lt;/code&gt;th element, we need &lt;code&gt;elem[i-1] - elem[i]&lt;/code&gt; steps to make it equal to or greater than the &lt;code&gt;i-1&lt;/code&gt;th element.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Link to the problem : <a href="https://cses.fi/problemset/task/1094">Increasing Array</a></p>
<h2 id="intuition">Intuition</h2>
<p>The idea is to make an array increasing by making the current element equal to or greater than the previous element.
and in each step we can increase the value of a single element by 1.</p>
<p>That means for <code>i</code>th element which is less than the <code>i-1</code>th element, we need <code>elem[i-1] - elem[i]</code> steps to make it equal to or greater than the <code>i-1</code>th element.</p>
<p>So we can come up with the following algorithm:</p>
<ul>
<li>Loop through the array</li>
<li>If the current element is less than the previous element, we need to increase the current element to the previous element.</li>
<li>Increment the count by the difference between the previous element and the current element.</li>
<li>Update the current element to the previous element.</li>
</ul>
<p>At the end of the loop, we will have the minimum number of steps to make the array increasing.</p>
<h2 id="solution">Solution</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">    <span class="n">n</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="nb">input</span><span class="p">())</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">    <span class="n">nums</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="nb">map</span><span class="p">(</span><span class="nb">int</span><span class="p">,</span> <span class="nb">input</span><span class="p">()</span><span class="o">.</span><span class="n">split</span><span class="p">()))</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">    <span class="n">count</span> <span class="o">=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">        <span class="k">if</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">]:</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">            <span class="n">count</span> <span class="o">+=</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">-</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">]</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">            <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="n">count</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&#34;__main__&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">    <span class="n">main</span><span class="p">()</span></span></span></code></pre></div><h3 id="mathematical-proof">Mathematical Proof</h3>
<p><strong>Theorem:</strong> The greedy algorithm that ensures each element is at least as large as its predecessor gives the minimum total cost to make the array non-decreasing.</p>
<p><strong>Proof by Induction:</strong></p>
<p><strong>Base Cases:</strong></p>
<ul>
<li>For an array of size 1: The cost is 0, which is trivially optimal.</li>
<li>For an array of size 2: If <code>nums[0] ≤ nums[1]</code>, cost is 0. If <code>nums[0] &gt; nums[1]</code>, we must increment <code>nums[1]</code> by <code>nums[0] - nums[1]</code> to make it ≥ <code>nums[0]</code>. This is optimal since we must satisfy <code>nums[1] ≥ nums[0]</code>.</li>
</ul>
<p><strong>Inductive Hypothesis:</strong> Assume the greedy algorithm is optimal for arrays of size ≤ k.</p>
<p><strong>Inductive Step:</strong> Consider an array of size k+1. Let the array be <code>a[0], a[1], ..., a[k]</code>.</p>
<p>Apply the greedy algorithm:</p>
<ol>
<li>Process the first k elements optimally (by inductive hypothesis)</li>
<li>For the last element <code>a[k]</code>, if <code>a[k-1] ≤ a[k]</code>, no change needed (cost 0)</li>
<li>If <code>a[k-1] &gt; a[k]</code>, increment <code>a[k]</code> to <code>a[k-1]</code>, costing <code>a[k-1] - a[k]</code></li>
</ol>
<p><strong>Why this is optimal:</strong> Any optimal solution must satisfy <code>a'[i] ≥ a'[i-1]</code> for all i, where <code>a'</code> is the final array.</p>
<p>For the prefix <code>a'[0] ... a'[k-1]</code>, the inductive hypothesis says our greedy choices give the minimum cost.</p>
<p>For the last pair <code>a'[k-1]</code> and <code>a'[k]</code>:</p>
<ul>
<li>We must have <code>a'[k] ≥ a'[k-1]</code></li>
<li>The minimum cost to achieve this is exactly <code>max(0, a'[k-1] - a'[k])</code></li>
<li>Our greedy algorithm achieves exactly this minimum cost</li>
</ul>
<p><strong>Key insight:</strong> The greedy choice doesn&rsquo;t affect the optimality of the prefix because:</p>
<ol>
<li>The prefix constraints are already satisfied optimally</li>
<li>Setting <code>a[k] = max(a[k], a[k-1])</code> only affects the relationship between a[k-1] and a[k]</li>
<li>This choice is independent of future elements since there are none</li>
</ol>
<p><strong>Proof by Contradiction :</strong>
Suppose there exists an optimal solution with lower total cost than the greedy algorithm.
Let the greedy algorithm produce array <code>g</code> with cost <code>C_g</code>.
Let the optimal solution produce array <code>o</code> with cost <code>C_o &lt; C_g</code>.</p>
<p>Since both <code>g</code> and <code>o</code> must satisfy <code>g[i] ≥ g[i-1]</code> and <code>o[i] ≥ o[i-1]</code> for all i:</p>
<ul>
<li>At the first position where <code>g</code> and <code>o</code> differ, the optimal solution must have made a different choice</li>
<li>But making a different choice would either violate the non-decreasing constraint or require more operations later, contradicting optimality</li>
</ul>
<p>Therefore, the greedy algorithm is optimal.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Repeatations</title>
      <link>https://KTS-o7.github.io/bear/notes/repeatations/</link>
      <pubDate>Thu, 18 Sep 2025 17:23:25 +0530</pubDate><author>shentharkrishnatejaswi@gmail.com (Krishnatejaswi S)</author>
      <guid>https://KTS-o7.github.io/bear/notes/repeatations/</guid>
      <description>&lt;p&gt;Link to the problem : &lt;a href=&#34;https://cses.fi/problemset/task/1069&#34;&gt;Repeatations&lt;/a&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;intuition&#34;&gt;Intuition&lt;/h2&gt;&#xA;&lt;p&gt;This problem wants us to find the longest substring of a string that has only 1 type of character.&#xA;input has A,G,C and T only.&lt;/p&gt;&#xA;&lt;p&gt;Edge case: if the string is empty, return 0.&lt;/p&gt;&#xA;&lt;p&gt;We need to keep track of the current length of the substring and the maximum length of the substring seen so far which satisfies the condition.&lt;/p&gt;&#xA;&lt;p&gt;Loop through the string and check if the current character is the same as the previous character.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Link to the problem : <a href="https://cses.fi/problemset/task/1069">Repeatations</a></p>
<h2 id="intuition">Intuition</h2>
<p>This problem wants us to find the longest substring of a string that has only 1 type of character.
input has A,G,C and T only.</p>
<p>Edge case: if the string is empty, return 0.</p>
<p>We need to keep track of the current length of the substring and the maximum length of the substring seen so far which satisfies the condition.</p>
<p>Loop through the string and check if the current character is the same as the previous character.</p>
<ul>
<li>If it is, increment the current length.
Update the maximum length if the current length is greater than the maximum length.</li>
<li>If it is not, reset the current length to 1.</li>
</ul>
<h2 id="solution">Solution</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">    <span class="n">string</span> <span class="o">=</span> <span class="nb">input</span><span class="p">()</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">    <span class="k">if</span> <span class="ow">not</span> <span class="n">string</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">        <span class="k">return</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">    
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">    <span class="n">max_len</span> <span class="o">=</span> <span class="mi">1</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">    <span class="n">current_len</span> <span class="o">=</span> <span class="mi">1</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    
</span></span><span class="line"><span class="ln">10</span><span class="cl">    <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">string</span><span class="p">)):</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">        <span class="k">if</span> <span class="n">string</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">string</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">]:</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">            <span class="n">current_len</span> <span class="o">+=</span> <span class="mi">1</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">            <span class="n">max_len</span> <span class="o">=</span> <span class="nb">max</span><span class="p">(</span><span class="n">max_len</span><span class="p">,</span> <span class="n">current_len</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">        <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">            <span class="n">current_len</span> <span class="o">=</span> <span class="mi">1</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">    
</span></span><span class="line"><span class="ln">17</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="n">max_len</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">
</span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&#34;__main__&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">    <span class="n">main</span><span class="p">()</span></span></span></code></pre></div><h3 id="time-complexity">Time complexity</h3>
<p>O(n)</p>
<h3 id="space-complexity">Space complexity</h3>
<p>O(1)</p>
<p>This is a greedy problem.
A greedy approach is something that makes the best local choice at each step in the hope that this choice will lead to the global optimal solution.</p>
<p>here the best local choice is to increment the current length if the current character is the same as the previous character.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Missing Number</title>
      <link>https://KTS-o7.github.io/bear/notes/missing_number/</link>
      <pubDate>Thu, 18 Sep 2025 17:17:22 +0530</pubDate><author>shentharkrishnatejaswi@gmail.com (Krishnatejaswi S)</author>
      <guid>https://KTS-o7.github.io/bear/notes/missing_number/</guid>
      <description>&lt;p&gt;Link to the problem : &lt;a href=&#34;https://cses.fi/problemset/task/1083&#34;&gt;Missing Number&lt;/a&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;intuition&#34;&gt;Intuition&lt;/h2&gt;&#xA;&lt;p&gt;This problem wants us to find the missing number in a sequence of numbers from 1 to n.&#xA;The naive approach is to use a hash map to store the numbers and then find the missing number.&#xA;But this is not efficient.&lt;/p&gt;&#xA;&lt;p&gt;The idea is to use the formula for the sum of an arithmetic series.&#xA;The sum of an arithmetic series is given by the formula:&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Link to the problem : <a href="https://cses.fi/problemset/task/1083">Missing Number</a></p>
<h2 id="intuition">Intuition</h2>
<p>This problem wants us to find the missing number in a sequence of numbers from 1 to n.
The naive approach is to use a hash map to store the numbers and then find the missing number.
But this is not efficient.</p>
<p>The idea is to use the formula for the sum of an arithmetic series.
The sum of an arithmetic series is given by the formula:</p>
$$S = \frac{n}{2} (a + l)$$<p>
where <code>n</code> is the number of terms, <code>a</code> is the first term, and <code>l</code> is the last term.
In this problem, the first term is 1 and the last term is <code>n</code>.
So the sum of the series is given by the formula:
</p>
$$S = \frac{n}{2} (1 + n)$$<p>now if we accumulate the sum of the numbers in the list, we can find the missing number by subtracting the sum of the numbers in the list from the sum of the series.
Since only one number is missing, the sum of the numbers in the list will be less than the sum of the series and the difference will be the missing number.</p>
<h2 id="solution">Solution</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">    <span class="n">n</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="nb">input</span><span class="p">())</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">    <span class="n">nums_list</span> <span class="o">=</span> <span class="nb">input</span><span class="p">()</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">    <span class="n">nums</span> <span class="o">=</span> <span class="n">nums_list</span><span class="o">.</span><span class="n">split</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    <span class="n">total</span> <span class="o">=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">    <span class="k">for</span> <span class="n">num</span> <span class="ow">in</span> <span class="n">nums</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">        <span class="n">total</span> <span class="o">+=</span> <span class="nb">int</span><span class="p">(</span><span class="n">num</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">    <span class="n">tot</span> <span class="o">=</span> <span class="n">n</span> <span class="o">*</span> <span class="p">(</span><span class="n">n</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">//</span> <span class="mi">2</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="n">tot</span> <span class="o">-</span> <span class="n">total</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">
</span></span><span class="line"><span class="ln">11</span><span class="cl">
</span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&#34;__main__&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">    <span class="n">main</span><span class="p">()</span></span></span></code></pre></div><h2 id="some-formulae-for-arithmetic-series">Some formulae for arithmetic series</h2>
<h3 id="nth-term">nth term</h3>
$$a_n = a + (n-1)d$$<p>
where <code>a</code> is the first term, <code>d</code> is the common difference, and <code>n</code> is the number of terms.</p>
<h3 id="sum-of-the-first-n-terms">sum of the first n terms</h3>
$$S = \frac{n}{2} (a + l)$$<p>
where <code>n</code> is the number of terms, <code>a</code> is the first term, and <code>l</code> is the last term.</p>
<h3 id="sum-of-the-first-n-terms-1">sum of the first n terms</h3>
$$S = \frac{n}{2} (2a + (n-1)d)$$<p>
where <code>n</code> is the number of terms, <code>a</code> is the first term, and <code>d</code> is the common difference.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Weird Algorithm</title>
      <link>https://KTS-o7.github.io/bear/notes/weird_algorithm/</link>
      <pubDate>Thu, 18 Sep 2025 17:05:38 +0530</pubDate><author>shentharkrishnatejaswi@gmail.com (Krishnatejaswi S)</author>
      <guid>https://KTS-o7.github.io/bear/notes/weird_algorithm/</guid>
      <description>&lt;p&gt;Link to the problem: &lt;a href=&#34;https://cses.fi/problemset/task/1068&#34;&gt;Weird Algorithm&lt;/a&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;intuition&#34;&gt;Intuition&lt;/h2&gt;&#xA;&lt;p&gt;This problem is a direct implementation of the algorithm described in the problem statement.&lt;/p&gt;&#xA;&lt;p&gt;Given a number &lt;code&gt;n&lt;/code&gt;, we need to apply the following algorithm:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;If &lt;code&gt;n&lt;/code&gt; is even, divide it by 2.&lt;/li&gt;&#xA;&lt;li&gt;If &lt;code&gt;n&lt;/code&gt; is odd, multiply it by 3 and add 1.&lt;/li&gt;&#xA;&lt;li&gt;Repeat the process until &lt;code&gt;n&lt;/code&gt; becomes 1.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;solution&#34;&gt;Solution&lt;/h2&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;ln&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;weird_algorithm&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;n&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;ln&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;while&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;n&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;ln&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;n&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;end&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;ln&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;n&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;ln&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;n&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;n&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;//&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;ln&#34;&gt;6&lt;/span&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;ln&#34;&gt;7&lt;/span&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;n&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;n&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;ln&#34;&gt;8&lt;/span&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;n&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;geek-fact&#34;&gt;Geek fact&lt;/h2&gt;&#xA;&lt;p&gt;This is a famous problem in the field math called the Collatz conjecture.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Link to the problem: <a href="https://cses.fi/problemset/task/1068">Weird Algorithm</a></p>
<h2 id="intuition">Intuition</h2>
<p>This problem is a direct implementation of the algorithm described in the problem statement.</p>
<p>Given a number <code>n</code>, we need to apply the following algorithm:</p>
<ol>
<li>If <code>n</code> is even, divide it by 2.</li>
<li>If <code>n</code> is odd, multiply it by 3 and add 1.</li>
<li>Repeat the process until <code>n</code> becomes 1.</li>
</ol>
<h2 id="solution">Solution</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln">1</span><span class="cl"><span class="k">def</span> <span class="nf">weird_algorithm</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">    <span class="k">while</span> <span class="n">n</span> <span class="o">!=</span> <span class="mi">1</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s2">&#34; &#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl">        <span class="k">if</span> <span class="n">n</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">            <span class="n">n</span> <span class="o">=</span> <span class="n">n</span> <span class="o">//</span> <span class="mi">2</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl">        <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">7</span><span class="cl">            <span class="n">n</span> <span class="o">=</span> <span class="mi">3</span> <span class="o">*</span> <span class="n">n</span> <span class="o">+</span> <span class="mi">1</span>
</span></span><span class="line"><span class="ln">8</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="n">n</span><span class="p">)</span></span></span></code></pre></div><h2 id="geek-fact">Geek fact</h2>
<p>This is a famous problem in the field math called the Collatz conjecture.</p>
<p>Collatz conjecture is a conjecture in mathematics that states that for any positive integer <code>n</code>, the sequence of numbers generated by the following algorithm will eventually reach 1.</p>
<p>So far, the conjecture has been verified for all positive integers up to 2^68.</p>
<blockquote>
<p>Wikipedia link: <a href="https://en.wikipedia.org/wiki/Collatz_conjecture">Collatz conjecture</a></p>
</blockquote>
]]></content:encoded>
    </item>
    <item>
      <title>markdown stuff</title>
      <link>https://KTS-o7.github.io/bear/notes/markdown_stuff/</link>
      <pubDate>Sun, 14 Jan 2024 07:07:07 +0100</pubDate><author>shentharkrishnatejaswi@gmail.com (Krishnatejaswi S)</author>
      <guid>https://KTS-o7.github.io/bear/notes/markdown_stuff/</guid>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&lt;p&gt;This is &lt;strong&gt;bold&lt;/strong&gt; text, and this is &lt;em&gt;emphasized&lt;/em&gt; text.&lt;/p&gt;&#xA;&lt;p&gt;Visit the &lt;a href=&#34;https://gohugo.io&#34;&gt;Hugo&lt;/a&gt; website!&lt;/p&gt;&#xA;&lt;h2 id=&#34;mathematical-examples&#34;&gt;Mathematical Examples&lt;/h2&gt;&#xA;&lt;p&gt;Here are some mathematical expressions rendered using LaTeX:&lt;/p&gt;&#xA;&lt;h3 id=&#34;inline-math&#34;&gt;Inline Math&lt;/h3&gt;&#xA;&lt;p&gt;The quadratic formula is $x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}$.&lt;/p&gt;&#xA;&lt;h3 id=&#34;display-math&#34;&gt;Display Math&lt;/h3&gt;&#xA;&lt;p&gt;The Pythagorean theorem:&#xA;&lt;/p&gt;&#xA;$$&#xA;a^2 + b^2 = c^2&#xA;$$&lt;h3 id=&#34;more-complex-equations&#34;&gt;More Complex Equations&lt;/h3&gt;&#xA;&lt;p&gt;The area of a circle:&#xA;&lt;/p&gt;&#xA;$$&#xA;A = \pi r^2&#xA;$$&lt;p&gt;Integration by parts:&#xA;&lt;/p&gt;&#xA;$$&#xA;\int u \, dv = uv - \int v \, du&#xA;$$&lt;h3 id=&#34;matrices&#34;&gt;Matrices&lt;/h3&gt;&#xA;&lt;p&gt;A simple 2x2 matrix:&#xA;&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h2 id="introduction">Introduction</h2>
<p>This is <strong>bold</strong> text, and this is <em>emphasized</em> text.</p>
<p>Visit the <a href="https://gohugo.io">Hugo</a> website!</p>
<h2 id="mathematical-examples">Mathematical Examples</h2>
<p>Here are some mathematical expressions rendered using LaTeX:</p>
<h3 id="inline-math">Inline Math</h3>
<p>The quadratic formula is $x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}$.</p>
<h3 id="display-math">Display Math</h3>
<p>The Pythagorean theorem:
</p>
$$
a^2 + b^2 = c^2
$$<h3 id="more-complex-equations">More Complex Equations</h3>
<p>The area of a circle:
</p>
$$
A = \pi r^2
$$<p>Integration by parts:
</p>
$$
\int u \, dv = uv - \int v \, du
$$<h3 id="matrices">Matrices</h3>
<p>A simple 2x2 matrix:
</p>
$$
\begin{pmatrix}
a & b \\
c & d
\end{pmatrix}
$$<h3 id="limits-and-derivatives">Limits and Derivatives</h3>
$$
\text{If } f(x) = x^{2}, \text{ then } \frac{d}{dx} (x^{2}) = 2x.
$$<p>Limit as x approaches infinity:
</p>
$$
\lim_{x \to \infty} \frac{1}{x} = 0
$$<h3 id="this-is-how-code-looks-like">This is how code looks like</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln">1</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">&#34;Hello, World!&#34;</span><span class="p">)</span></span></span></code></pre></div><blockquote>
<p>This is a blockquote</p>
<blockquote>
<p>This is a nested blockquote</p>
<blockquote>
<p>This is a nested nested blockquote</p>
</blockquote>
</blockquote>
</blockquote>
<h3 id="this-is-how-a-table-looks-like">This is how a table looks like</h3>
<table>
  <thead>
      <tr>
          <th>Name</th>
          <th>Age</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>John</td>
          <td>25</td>
      </tr>
  </tbody>
</table>
<p><code>inline code</code></p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="cp">&lt;!DOCTYPE html&gt;</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="p">&lt;</span><span class="nt">html</span> <span class="na">lang</span><span class="o">=</span><span class="s">&#34;en&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="p">&lt;</span><span class="nt">head</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">  <span class="p">&lt;</span><span class="nt">meta</span> <span class="na">charset</span><span class="o">=</span><span class="s">&#34;UTF-8&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">  <span class="p">&lt;</span><span class="nt">meta</span> <span class="na">name</span><span class="o">=</span><span class="s">&#34;viewport&#34;</span> <span class="na">content</span><span class="o">=</span><span class="s">&#34;width=device-width, initial-scale=1.0&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">  <span class="p">&lt;</span><span class="nt">title</span><span class="p">&gt;</span>Document<span class="p">&lt;/</span><span class="nt">title</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="p">&lt;/</span><span class="nt">head</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="p">&lt;</span><span class="nt">body</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">  <span class="p">&lt;</span><span class="nt">h1</span><span class="p">&gt;</span>Hello, World!<span class="p">&lt;/</span><span class="nt">h1</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="p">&lt;/</span><span class="nt">body</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="p">&lt;/</span><span class="nt">html</span><span class="p">&gt;</span></span></span></code></pre></div>]]></content:encoded>
    </item>
  </channel>
</rss>
