2025-12-09 16:36:13
In Part 1, we covered how we trained our NES model, including topics such as the special tokens we use, the LoRA-based fine-tuning on Gemini Flash Lite, and how we utilized a judge LLM to evaluate the model.
However, the end experience is far more than just building a good model. To make NES feel “intent-aware” inside your editor, we needed to give the model the right context at the right moment.
In part 2, we’ll talk about that runtime system, or to be precise, how Pochi manages, ranks, and streams real-time edit context. This is the core that helps NES to understand your intent and predict the next meaningful change.
To start, let’s understand what context management is. In our case, it’s the layer between when a user starts typing and when the model is called with a well-formed prompt. During that in-between phase, the system gathers and prepares all the relevant context the LLM needs before we make a model request.
As to why it matters, imagine simply sending the entire file to the model on every keystroke. Not only will the model become slower and noisier, but you’d get unstable predictions and over 20 model calls per second, rendering the whole experience unusable.
Instead, as previewed in the first article, we provide NES with three kinds of context:
Each of these depends on clever filtering, segmentation, and timing - all of which happen in milliseconds during normal typing, as we’ll learn below.
The first question to solve: “Where is the user editing right now?”. This is the foundation of every NES prompt. We answer this by gathering three quick pieces of information from the VS Code API:
Using this information, we compute what is called “the editable region”. This region is generally a small code window around the user’s cursor of ~10 lines.
Why ~10 lines?
Because realistically, the next edit will almost always happen very close to where the user is already editing. This small window keeps the latency extremely low and is large enough to capture the structure around the edit.
And while we observe many models are over-eager and hallucinate changes elsewhere, our model is prevented from rewriting parts of the file the user wasn’t touching.
An example of the editable region would be:
So far, we have learnt where the user is currently editing, but we also need to understand how the code is changing over time. This is the part where edit history becomes important for the edit model to predict the user’s intent.
Now, while we could use the VS Code API to register a listener for text change events, this ends up triggering an event for almost every keystroke. For example, if a user updates a type from string to email, it ends up producing ~6 events.
These are not your meaningful edit steps. If we send this to the model, it will think each keystroke is a new “user intent” and will fire too many requests with wildly different predictions. Instead, we reconstruct real edit steps using an internal change segmentation grouping.
How we group events into meaningful steps
Since we cannot directly use the listener events, we decided to reduce them to events that represent edit steps. To achieve this, we group raw text-change events into undo-redo scale units.
Most editors record undo-redo steps on a word scale - for example, when a user inputs a sentence, an undo action will revert the last input word. In our case, for building edit prediction prompts, we do this on a larger scale.
Once we receive information on a user’s cursor position and tracking gets initiated, we create an edit steps list, where each step is an accumulation of several text change events. We found that 5 steps is the sweet spot to build a prompt. Anything more than that adds noise, and if less, loses the intent.
For each received text change event, we check if it is adjacent to the previous one. If yes, it belongs to the same edit step; otherwise, if it happens in a different part of the file, we consider it as a new edit step.
So continuing our example from earlier, if the user happens to add a validateEmail function next, we now have two edit steps in tracking.
The first edit step:
The second edit step:
NES receives these steps wrapped inside <|edit_history|> token to learn how the code is evolving.
Special Case: Git Checkout Noise
One edge case we uncovered is when users run git checkout to switch branches. This triggers massive file changes, none of which represent real user intent. If we were to treat these as edit steps, the model would end up thinking the user rewrote half the codebase. In order to avoid polluting the model direction, we:
Code rarely exists in isolation. If you’re editing a function call, the model may need the definition. Likewise, if you’re modifying a type, the model may need the type declaration.
To give NES this kind of project-aware understanding, we pull additional snippets using the user’s installed language server. For this, we have two VS Code / LSP APIs:
We use vscode.provideDocumentRangeSemanticTokens to scan the editable region for each token type. Then we can find the tokens of interest, like a function, interface, or type defined in another file.
Next, we use the VS Code commandvscode.executeDefinitionProvider to get the target location for the definition code snippets. This is like Ctrl / Cmd + clicking on a function to see the definition in another file.
These two commands are provided by the language server (LSP), which should be available when the language plugin is installed in VS Code. We then extract the definition snippet and include it in <|additional_context|> token as shown below:NES Cover Image
This gives the model the same context a developer would mentally reference before typing the next edit.
Note: We do realise that some of the functions could be huge or a type might be hundreds of lines, with LSP sometimes returning entire class bodies. Therefore, to throttle/limit semantic snippet extraction, we’ve currently hard-coded a maximum of 2000 characters per snippet for now.
Meanwhile, in cases where good LSP support is lacking, like plain text, we don’t add any related snippets context to the prompt. Instead, the prompt will still contain the prefix, suffix, and edit records.
As learned above, every NES request contains the <|editable_region|>, <|edit_history|> and <|additional_context|>tokens.
At the end, each piece is carefully constructed into the model exactly the way it was trained. This symmetry between training and runtime makes NES far more reliable than native autocomplete-style approaches.
In our next post, we’ll talk about Request Management, the system that ensures the model never gets a chance to be wrong about the user’s current context.
We all understand real coding experience involves a lot of short, focused typing, moving the cursor to different places, and continuing to edit while a request is still in flight. This means the model requests can become outdated before their response arrives, or worse, it might produce suggestions for code that no longer exists.
One of the reasons NES feels fast is because everything that isn’t the latest user intent is thrown away immediately. This cancellation of stale predictions is one of the biggest reasons Pochi’s NES feels so smooth and accurate.
More on this in our upcoming Part 3 post. Stay tuned!
2025-12-09 16:35:19
Or: How I Learned to Stop Worrying and Love the Model Context Protocol
Remember the days when your AI assistant was like that friend who's really smart but has absolutely no idea what's happening in your actual life? They could write you a sonnet about quantum physics but couldn't tell you where you saved last quarter's sales report. Well, those days are officially over, thanks to the Model Context Protocol (MCP).
Think of MCP as a universal translator for AI assistants. It's like giving your AI a backstage pass to all your internal tools, databases, and systems. Instead of copy-pasting data back and forth like some kind of digital stenographer, your AI can now directly tap into your company's knowledge treasure trove.
The Model Context Protocol is an open standard developed by Anthropic that lets AI models securely connect to your data sources and tools. It's basically the difference between telling someone about your vacation and showing them the photos way more context, way less "wait, which beach was that again?"
The Setup: Connect MCP to your Google Drive, Dropbox, or internal file system.
The Magic: Instead of spending 20 minutes hunting through folders with names like "Final_FINAL_v3_actually_final," you just ask: "Find our Q3 sales presentation." Your AI assistant instantly locates it, can summarize the key points, and even help you update it with current data.
Real Impact: One startup reported saving their sales team an average of 3 hours per week on document hunting. That's 156 hours a year. Basically a whole month of productive work that was previously spent playing hide-and-seek with PowerPoint files.
The Setup: Connect MCP to your PostgreSQL, MySQL, or MongoDB databases.
The Magic: Your AI becomes a data analyst on steroids. Ask questions in plain English like "Show me our top 10 customers by revenue this quarter" or "Which products have the highest return rate?" and get instant, accurate answers. No SQL knowledge required (though your database admins will still feel important, don't worry).
Real Impact: A mid-sized e-commerce company reduced their reporting time from 2 days to 2 minutes. Their analysts went from being report generators to actual strategic thinkers. Revolutionary? Maybe. But definitely evolutionary.
The Setup: Integrate MCP with Slack or Microsoft Teams.
The Magic: Ever joined a project mid-stream and felt completely lost? Now your AI can read through months of chat history and give you a TL;DR that doesn't make you want to cry. "Summarize what the design team decided about the new logo" gets you caught up faster than five cups of coffee and three confused stand-up meetings.
Real Impact: New employees report 40% faster onboarding when they can ask an AI to summarize team discussions instead of reading through 10,000 messages of GIFs and "this" reactions.
The Setup: Connect MCP to your CRM (Salesforce, HubSpot, etc.), support ticket system, and knowledge base.
The Magic: Support agents can ask, "Show me this customer's full history and suggest solutions to their current issue." The AI pulls from past tickets, purchase history, product documentation, and known issues to provide comprehensive, personalized responses.
Real Impact: A SaaS company reduced average ticket resolution time from 4 hours to 45 minutes. Their customer satisfaction scores jumped from "meh" to "wow, you actually know who I am!"
The Setup: Link MCP to GitHub, GitLab, or your version control system.
The Magic: "Review this pull request and check if it follows our coding standards" becomes a reality. The AI can reference your style guides, past code reviews, and architectural decisions to give contextual feedback that doesn't sound like it came from a textbook.
Real Impact: Development teams report 30% fewer bugs making it to production and junior developers learning best practices 2x faster because the feedback is instant and specific to their actual codebase.
The Setup: Connect MCP to Jira, Asana, Linear, or your project management tool.
The Magic: Ask "What are our current blockers?" or "Which team member is overloaded?" and get real-time answers based on actual data, not gut feelings from the last stand-up meeting. You can even have the AI create tasks, update statuses, or reassign work based on current workloads.
Real Impact: Project managers save an average of 10 hours per week on status updates and administrative overhead. That's 10 more hours for actually, you know, managing projects.
The Setup: Integrate MCP with Gmail or Outlook.
The Magic: "Find all emails from clients mentioning the Phoenix project in the last 6 months" or "What did the legal team say about that contract?" No more drowning in search results that include every email where someone mentioned Phoenix, Arizona in their vacation plans.
Real Impact: Sales teams close deals 25% faster because they can instantly recall every conversation detail without manually scrolling through email chains that look like Russian novels.
The Setup: Connect MCP to your internal API documentation and testing environments.
The Magic: Developers can ask, "How do I authenticate with our payment API?" or "Show me examples of using the user management endpoint" and get accurate, up-to-date answers pulled directly from your living documentation.
Real Impact: Developer onboarding time cut in half, and those "it worked on my machine" moments become much rarer because everyone's working from the same source of truth.
Setting up MCP typically involves:
Most MCP servers are surprisingly easy to set up. We're talking minutes, not weeks. And if you can set up a webhook, you can probably set up an MCP server.
Valid question! Here's the deal:
It's actually more secure than that intern who keeps emailing sensitive docs to their personal Gmail "for convenience."
Don't try to connect everything at once. That's like trying to eat an entire pizza in one bite theoretically possible but inadvisable.
Week 1: Start with one tool that causes the most pain. For most teams, that's document search.
Week 2: Add your most-used database or CRM.
Week 3: Connect your communication tools.
Week 4: Evaluate, iterate, and expand to other systems.
By month two, you'll wonder how you ever lived without it, like smartphones or coffee delivery apps.
Let's do some napkin math:
Your CFO just perked up, didn't they?
We're moving from AI assistants that are generally smart to AI assistants that are specifically smart about your business. That's the difference between a consultant who read the industry report and one who's been embedded in your company for years.
MCP isn't just a technical protocol. It's a fundamental shift in how we work with AI. Instead of treating AI as an external oracle, we're making it an integrated team member that actually knows what's going on.
The Model Context Protocol is turning AI from a party trick into a productivity powerhouse. By connecting your internal tools and databases, you're not just saving time. You're fundamentally changing how your team accesses and uses information.
So stop copy-pasting. Stop context switching between a dozen tools. Stop explaining the same background information to your AI for the tenth time this week.
Connect your tools, empower your AI, and get back to doing the work that actually matters.
Your future self (and your keyboard, which is tired of all that Ctrl+C, Ctrl+V action) will thank you.
Ready to implement MCP in your organization? Start with one tool, prove the value, and scale from there. And remember: the best time to start was yesterday. The second-best time is right now.
Have questions or want to share your MCP success story? Drop a comment below! And if you found this helpful, give it a ❤️ so others can find it too.
2025-12-09 16:31:01
For a long time, I kept hearing terms like Single Thread and Event-Driven whenever someone mentioned Node.js.
They sounded like buzzwords people casually throw around in technical discussions, but I never fully understood why they mattered.
So I went back to the basics:
What is a “thread” in the first place?
Imagine an office with a single employee.
This employee:
This is the essence of a thread — the execution path your program follows step by step.
Traditional languages like Java, C#, and Python handle heavy load in a straightforward way:
“More requests? Create more threads.”
If you’re dealing with 500 requests, you might end up spawning dozens or even hundreds of threads.
Each thread has its own memory, context, and overhead.
The result?
Node.js decided to challenge this traditional model.
A single thread… but a smart one.
A system designed so one worker can efficiently distribute tasks without getting stuck.
The idea is simple: wait for an event, then react.
Inside Node.js, everything is driven by events:
The main thread doesn’t execute every task itself.
It briefly takes control, delegates work, then returns to an idle state.
Meanwhile, the Event Loop processes each event, triggers its handler, and keeps moving.
This allows Node.js to handle thousands of concurrent requests
— without thousands of threads and without unnecessary complexity.
Once you understand the Event Loop, you realize Node.js isn’t just a runtime —
it’s a complete event-driven architecture.
Nothing happens unless an event occurs.
And every event has a clear, direct response.
The result?
Node.js creates a system that flows smoothly, handles massive loads, and delivers performance that’s genuinely hard to compete with.
2025-12-09 16:29:53
Alright, let's get one thing straight right off the bat—if you're Googling "Java string sin() method," I feel you, but we need to clear something up. Java Strings don't have a sin() method. Like, at all. That's a math thing (Math.sin()) for trigonometry, totally different universe. But you searching for that probably means you're trying to do something with strings that feels mathematical or transformative, and guess what? Java's String class is packed with methods that are arguably cooler than any sine function. Let's dive into the real magic.
Wait, What Even is a String in Java?
Think of a String as that text message you're typing, the username you're logging in with, or that massive JSON response from an API—it's basically a sequence of characters. In Java, String isn't a primitive data type (like int or char); it's a full-blown class. And because it's used everywhere, Java treats it with some special privileges (like String immutability, but we'll get to that).
When you write:
java
String vibe = "Hello World";
You're not just storing text. You're creating an object that comes with a whole toolkit of methods ready to transform, inspect, and manipulate that text.
The Real Rockstars: String Methods You'll Actually Use
Since sin() was a no-go, let me hit you with the methods that actually earn their keep in your code. These aren't just academic exercises—they're your daily drivers.
length() - The Basic But Essential
java
String tweet = "Just deployed my app! #Winning";
int tweetLength = tweet.length(); // Returns 30
Real-world use: Validating input fields (like Twitter's character limit), processing text files line by line.
charAt() - The Precision Extractor
java
String password = "P@ssw0rd!";
char firstChar = password.charAt(0); // 'P'
char lastChar = password.charAt(password.length() - 1); // '!'
Pro tip: Always check length() first to avoid StringIndexOutOfBoundsException. Been there, got the error message.
java
String quote = "Code is poetry";
String part1 = quote.substring(5); // "is poetry" (starts at index 5)
String part2 = quote.substring(0, 4); // "Code" (index 0 to 3)
Heads up: The second parameter is exclusive. substring(0, 4) gives you characters at indices 0, 1, 2, and 3. This trips up everyone at first.
java
String s1 = new String("Hello");
String s2 = new String("Hello");
String s3 = "Hello";
String s4 = "Hello";
System.out.println(s1 == s2); // false (different objects in memory)
System.out.println(s1.equals(s2)); // true (same content)
System.out.println(s3 == s4); // true (string pool magic!)
Golden rule: Always use .equals() for comparing string content. == checks if they're the same object in memory, which leads to bugs that'll have you debugging at 2 AM.
java
String userInput = "YeS";
if(userInput.equalsIgnoreCase("yes")) {
// This works for "YES", "yes", "Yes", "yEs"...
System.out.println("Proceeding...");
}
Real-world use: Processing user commands, normalizing data for comparison, preparing case-insensitive searches.
java
String userEmail = " [email protected] ";
String cleanEmail = userEmail.trim(); // "[email protected]"
Life-saving moment: When users inevitably add spaces before/after their email in login forms.
java
String csvData = "Java,Python,JavaScript,C++";
String[] languages = csvData.split(",");
// Result: ["Java", "Python", "JavaScript", "C++"]
// Pro level: regex splitting
String sentence = "Hello world from Java";
String[] words = sentence.split("\\s+"); // Splits on one or more spaces
Use case: Parsing CSV files, processing log files, breaking down URLs or file paths.
Immutability: The String's Superpower (and Sometimes Headache)
Here's the thing that changes how you think about Strings: they're immutable. Once created, a String object cannot be changed. At all.
java
String original = "Hello";
original.concat(" World"); // Does nothing to 'original'
System.out.println(original); // Still "Hello"
String modified = original.concat(" World"); // Creates NEW string
System.out.println(modified); // "Hello World"
Why this matters:
Thread-safe: Multiple threads can read strings without synchronization issues
Security: Critical for passwords, database URLs, etc.
Hash caching: Strings cache their hash code, making HashMap operations blazing fast
The performance catch: When you're doing heavy string manipulation (like in a loop), each operation creates a new object. That's where StringBuilder and StringBuffer come to the rescue.
StringBuilder: When You Need to Build Strings Like a Pro
java
// Don't do this in loops:
String result = "";
for(int i = 0; i < 1000; i++) {
result += i; // Creates 1000+ string objects!
}
// Do this instead:
StringBuilder sb = new StringBuilder();
for(int i = 0; i < 1000; i++) {
sb.append(i); // Much more efficient
}
String finalResult = sb.toString();
Rule of thumb: Use String for fixed text, StringBuilder for building strings dynamically (single-threaded), and StringBuffer for thread-safe scenarios.
Real-World Applications You'll Actually Build
java
public boolean isValidEmail(String email) {
if(email == null || email.trim().isEmpty()) return false;
return email.contains("@") &&
email.indexOf("@") < email.lastIndexOf(".") &&
email.length() - email.lastIndexOf(".") >= 3;
}
java
String logEntry = "2024-01-15 14:30:22 [ERROR] Database connection failed";
String[] parts = logEntry.split(" ");
String date = parts[0];
String time = parts[1];
String logLevel = parts[2].replace("[", "").replace("]", "");
String message = logEntry.substring(logEntry.indexOf("]") +
2);
java
String url = "https://codercrafter.in/courses/java-bootcamp";
String domain = url.substring(url.indexOf("://") + 3, url.indexOf("/", 8));
String path = url.substring(url.indexOf("/", 8));
// Or better yet, use Java's built-in URI class for serious work
Best Practices That'll Save Your Sanity
Always check for null first: if(str == null || str.isEmpty())
Use StringBuilder for concatenation in loops
Favor equalsIgnoreCase() for user-facing comparisons
Remember that strings are case-sensitive in most operations
Use String.format() for complex string building:
java
String message = String.format("User %s logged in at %s", username, timestamp);
FAQ: What You're Probably Wondering
Q: Why is there no sin() method in String class?
A: Because sin() is a mathematical function that operates on numbers, not text. You want Math.sin() for that. Strings are for text manipulation.
Q: What's the string pool I keep hearing about?
A: It's a special memory area where Java stores string literals to save memory. When you write String s = "hello", Java checks if "hello" exists in the pool first. If it does, s points to that existing object. That's why "hello" == "hello" can return true.
Q: When should I use String vs StringBuilder?
A: Use String for fixed text or simple concatenation (outside loops). Use StringBuilder when you're building strings dynamically, especially in loops or complex logic.
Q: How do I reverse a string?
A: new StringBuilder(originalString).reverse().toString() is your friend. No built-in reverse() method in String class itself.
Q: What's the deal with intern() method?
A: It puts the string in the string pool (or returns existing one). Useful when you have many duplicate strings and want to save memory, but use cautiously as it can cause issues if overused.
Wrapping Up: Strings Are Your Foundation
Mastering Java Strings isn't about memorizing every method—it's about understanding the core concepts (immutability, pool, comparison) and knowing which tool to reach for when. Whether you're validating user input, parsing data, or generating dynamic content, strings are where the rubber meets the road in most applications.
The journey from "Hello World" to building complex, efficient string manipulation logic is what separates beginners from professionals. And speaking of professional journeys...
Want to level up from string basics to building full applications? To learn professional software development courses such as Python Programming, Full Stack Development, and MERN Stack, visit and enroll today at codercrafter.in. We turn curious coders into job-ready developers with hands-on projects and industry-relevant curriculum. Check out our development tools to see the kind of practical applications you'll be building.
Remember, every expert was once a beginner who kept coding. Your next breakthrough is just one method call away. Keep experimenting, keep building, and may your strings always be properly formatted!
2025-12-09 16:26:14
Managing images, PDFs, JSON files, or QR codes usually requires switching between multiple websites. StackConvert solves this by offering a complete set of free online tools in one place — fast, secure and without requiring any registration.
Here’s a quick breakdown of what it provides.
🔹 Image Conversion Tools
Convert and optimize images across popular formats:
JPG, PNG, WebP, AVIF, HEIC, SVG, GIF, TIFF, BMP and more
Compress, resize, batch convert
Strip metadata for privacy
Convert image → Base64 or JSON
Convert images → PDF
Try it: https://stackconvert.com/image-converter
🔹 PDF Tools
Everything you need for PDF files:
Merge PDFs
Split by pages or ranges
Reorder or rotate pages
Convert images to PDF
Real-time preview before processing
Explore: https://stackconvert.com/pdf-tools
🔹 JSON Utilities
Perfect for developers:
JSON viewer + tree view
Formatter and minifier
JSON diff comparison
Schema validation
Import/export JSON
Tools: https://stackconvert.com/json-tools
🔹 QR Code Generator
Create professional, high-resolution QR codes:
URLs, WiFi, email, SMS, vCard, text
Custom colors, gradients, frames
Add your logo
Adjustable sizes and error correction
Generate QR: https://stackconvert.com/qr-code-generator
🔹 Extra Utilities
A few more helpful tools:
Base64 encoder/decoder
Hash generator (MD5, SHA1, SHA256, SHA512)
ZIP file creator
Time converter
Browse all tools: https://stackconvert.com
🔒 Privacy Focused
StackConvert securely processes your files and does not store them. No signup, no tracking, fully browser-based. Safe for personal and professional use.
📘 Full Blog Guide
Read the complete, in-depth feature breakdown here:
👉 https://stackconvert.com/blogs/what-is-stackconvert
🚀 Try StackConvert
Whether you're a developer, creator, or everyday user, StackConvert makes file processing simple, fast and accessible.
Start here: https://stackconvert.com
2025-12-09 16:17:27
Making the switch from a cloud-based WAF like Cloudflare to a self-hosted WAF solution such as SafeLine might sound like a big leap, but for many developers and teams, it’s a no-brainer when it comes to control, privacy, and customization. If you’ve been feeling limited by Cloudflare’s templates or concerned about where your data resides, self-hosting could be the perfect solution.
This guide will walk you through the process of migrating from a cloud WAF to SafeLine, help you avoid common pitfalls, and share useful tips to make the transition as smooth as possible.
While cloud WAFs like Cloudflare are convenient, they come with a set of limitations:
With SafeLine WAF, you run it entirely on your own infrastructure, which means:
Before jumping into the migration, it’s important to take inventory of your current Cloudflare setup to avoid missing anything important. Make sure to:
This gives you a solid starting point before diving into the setup process.
Since SafeLine is a self-hosted solution, you’ll need a Linux server to get started. Here are the recommended specs:
# Pull SafeLine Docker image
docker pull safeline/waf:latest
# Start SafeLine container
docker-compose up -d
Cloudflare usually handles SSL termination at the edge. With SafeLine, you’ll have full control over SSL. SafeLine supports both Let’s Encrypt and custom certificates.
Once configured, SafeLine will serve traffic securely, without relying on Cloudflare’s proxy.
Now it’s time to bring over your existing Cloudflare settings. You’ll want to:
Example:
# Limit /api/login to 5 req/sec per IP
docker exec -it safeline-cli set-rule /api/login rate-limit 5
Tip: Start with a staging subdomain to test the rules before fully cutting over your production traffic.
After going live, it’s time to fine-tune your setup:
tail -f /data/safeline/logs/nginx/safeline/access.log | grep "bot"
Monitor CPU and memory usage.
Adjust custom rules based on real traffic patterns to optimize bot protection and rate-limiting.
Migrating from a cloud WAF to a self-hosted solution like SafeLine may seem complex at first, but the benefits—complete ownership, improved privacy, and more customization—make it worthwhile. By following the steps above, you can smoothly transition and ensure your application is fully protected while maintaining control over your security policies.