Welcome back! In Chapter 1: Input Orchestration, we acted as the "Switchboard Operator," deciding where user input should go.
If the user didn't type a special command (like /help) or run a terminal script, the switchboard routes the call to the Standard Prompt Processor. This is the default path for normal conversations, like asking the AI to write code or explain a concept.
Why can't we just send the user's text straight to the AI?
Imagine dropping a loose piece of paper into a mailbox. It might get lost, crumpled, or mixed up. You wouldn't have a tracking number, and the post office wouldn't know if it's urgent.
Standard Prompt Processing is like a Formal Processing Center. It takes your casual note and:
UserMessage object that the AI understands.Goal: The user types "Why is the sky blue?" We need to convert this simple text into a tracked, structured message object ready for the AI.
Before looking at the code, let's understand the three main jobs this processor does:
Here is the lifecycle of a standard text prompt:
The logic resides in processTextPrompt.ts. Let's walk through it piece by piece.
First, we generate a unique ID for this specific interaction. This effectively "stamps" the letter.
// processTextPrompt.ts
import { randomUUID } from 'crypto'
import { setPromptId } from 'src/bootstrap/state.js'
export function processTextPrompt(input, /*...args*/) {
// 1. Create a unique ID for this specific message
const promptId = randomUUID()
// 2. Save it to the global state so other parts of the app know it
setPromptId(promptId)
// ... continued below
Explanation: We use randomUUID() to create a string like 123e4567-e89b.... This ensures that even if two users type "Hello" at the exact same time, the system treats them as distinct events.
Next, we log the event. This is crucial for understanding how the application is being used. We handle both simple text strings (CLI) and complex arrays (VS Code).
// Extract the text string for logging purposes
const otelPromptText = typeof input === 'string'
? input
: input.findLast(block => block.type === 'text')?.text || ''
// Log to OpenTelemetry (standardized tracking)
if (otelPromptText) {
void logOTelEvent('user_prompt', {
prompt_length: String(otelPromptText.length),
'prompt.id': promptId, // The ID we generated earlier
})
}
Explanation: We calculate the length of the prompt and attach the ID. logOTelEvent sends this data to our monitoring system. Note that we try to find the text even if the input is a complex array.
The system quickly scans the text to see if the user is trying to steer the AI's behavior with keywords.
// Check for specific keywords
const isNegative = matchesNegativeKeyword(userPromptText) // e.g., "stop"
const isKeepGoing = matchesKeepGoingKeyword(userPromptText) // e.g., "continue"
// Log these intents for analytics
logEvent('tengu_input_prompt', {
is_negative: isNegative,
is_keep_going: isKeepGoing,
})
Explanation: If a user is getting frustrated and typing "No, stop!", we want to track that metric. This doesn't stop the code here, but it tags the message with extra information.
Sometimes a text prompt comes with an image. We have to check for that.
// If there are images attached to this text
if (imageContentBlocks.length > 0) {
// Combine text and images into one message
const userMessage = createUserMessage({
content: [...textContent, ...imageContentBlocks],
uuid: uuid,
// ...
})
return { messages: [userMessage], shouldQuery: true }
}
Explanation: If images are present, we bundle them with the text. The specific logic for preparing these images happened before this function, which is covered in Chapter 3: Media and Attachment Preprocessing.
Finally, if it's just text, we wrap it up and return it.
// Create the standardized message object
const userMessage = createUserMessage({
content: input,
uuid, // The ID passed in or generated
permissionMode,
})
// Return the package ready for the AI
return {
messages: [userMessage, ...attachmentMessages],
shouldQuery: true
}
}
Explanation: createUserMessage is a helper that ensures our object matches exactly what the AI API expects. We return shouldQuery: true to tell the system, "Yes, please send this to the AI now."
You've learned how Standard Prompt Processing turns a simple string of text into a robust, tracked system event.
By using this formal process, we ensure that:
But what if the user didn't just type text? What if they dragged and dropped a screenshot of an error message?
To handle that, we need to step back and look at how we prepared the data before it reached this processor.
Next Chapter: Media and Attachment Preprocessing
Generated by Code IQ