Welcome back! In Chapter 1: Command Registration Interface, we created the "Menu" for our restaurant. We told the system that a files command exists.
Now, we need to send the cook into the kitchen to actually make the dish. But waitβdoes the cook know which ingredients are available right now?
Imagine you hire a contractor to fix a window.
In our system, we don't let commands search globally for data. Instead, when we run a command, we hand it a specific object called ToolUseContext.
Think of ToolUseContext as a Briefcase. It contains a snapshot of everything the command needs to know about the current moment, specifically:
The context is a "snapshot" in time. It represents the state of the world at the exact moment the user pressed Enter.
readFileState
Inside our briefcase, there is a specific folder called readFileState. This acts like a cache. It remembers every file the AI has looked at recently. Our files command needs this to know what to list.
Let's look at the files.ts implementation. We need to accept this briefcase as an argument.
In Chapter 4, we will write the full logic, but for now, look at the function signature (the input).
import type { ToolUseContext } from '../../Tool.js'
// The 'call' function is the entry point
export async function call(
_args: string, // User input (not used here)
context: ToolUseContext, // <--- THE BRIEFCASE
) {
// Logic goes here...
}
Explanation:
context: This is automatically injected by the system. You don't create it; you just receive it.Now that we have the briefcase, let's look inside to find the list of files.
import { cacheKeys } from '../../utils/fileStateCache.js'
export async function call(_args: string, context: ToolUseContext) {
// Check if the specific "folder" exists in the briefcase
if (!context.readFileState) {
return { type: 'text', value: 'No files found.' }
}
// Extract the list of filenames
const files = cacheKeys(context.readFileState)
// ... continue logic
}
Explanation:
context.readFileState: We access the property directly.cacheKeys(...): This helper turns the raw state data into a simple list of file paths.You might be wondering: Who packs the briefcase?
The system has a central "Brain" that tracks everything. When a user runs a command, the Brain pauses, gathers all current data, packs it into the ToolUseContext, and hands it to the command.
While you don't need to write this part (the system handles it), it helps to understand what is happening behind the scenes.
Imagine a simplified System Runner:
// This is pseudo-code of what the System does
const currentSessionState = {
openFiles: { 'index.ts': '...', 'style.css': '...' },
currentUser: 'ant'
};
async function executeCommand(commandName) {
// 1. Pack the briefcase (Context)
const context = {
readFileState: currentSessionState.openFiles,
// ... other tools
};
// 2. Load the command (Lazy Loading - see Chapter 5)
const command = await import(`./commands/${commandName}.js`);
// 3. Hand over the briefcase
return command.call(null, context);
}
Explanation:
currentSessionState).context object specifically for this one command execution.In this chapter, we learned:
ToolUseContext.readFileState) necessary for the job.Now that we have the context and have processed the data, we need to return an answer to the user. We can't just return a raw string; we need a structured format.
Next Chapter: Standardized Result Objects
Generated by Code IQ