In Chapter 3: Content Serialization, we successfully turned our complex conversation data into a readable text string (our "content").
However, if the user didn't specify a filename (e.g., they just typed export instead of export my-file.txt), we have a problem. We can't just save it as file.txt every time, or we would overwrite previous work. We also don't want to use boring names like export_001.txt because nobody remembers what those contain.
This chapter is about building a Smart Filing Assistant that names files automatically based on what you were talking about.
Imagine you are dictating notes to a secretary.
2023-10-27-chocolate-chip-recipe.txt.The Central Use Case: We want our tool to scan the conversation, find the first thing the user said (the "Topic"), clean it up so computers can read it, and use that as the filename.
To build this Smart Secretary, we need three specific skills:
?, :, or / in filenames. We need to clean the text.
We will implement this logic using three small helper functions inside export.tsx.
First, let's make sure we can always generate a unique name based on the current time.
// File: export.tsx
function formatTimestamp(date: Date): string {
const year = date.getFullYear();
// Add +1 because months are 0-indexed (0 = January)
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
// Return format: 2023-10-27-143005
// (Year-Month-Day-HourMinuteSecond)
return `${year}-${month}-${day}-${date.getHours()}...`;
}
Explanation:
2023-11-04.padStart(2, '0') ensures that "January" becomes 01 instead of just 1, keeping our filenames neatly sorted alphabetically.Next, we need to find out what the conversation is about. We assume the first message from the user sets the topic.
// File: export.tsx
export function extractFirstPrompt(messages: Message[]): string {
// Find the very first message sent by the 'user'
const firstUserMessage = messages.find(msg => msg.type === 'user');
if (!firstUserMessage) return ''; // No user message found? Return empty.
// Get the text content (simplifying complex objects if needed)
let result = extractTextFromMessage(firstUserMessage);
// Take only the first line and limit it to 50 characters
return result.split('\n')[0].substring(0, 49);
}
Explanation:
Users type things like "How do I fix my CPU?" or "Project: Alpha/Beta".
Operating systems forbid ? and / in filenames. We need to clean this up.
// File: export.tsx
export function sanitizeFilename(text: string): string {
return text.toLowerCase()
// 1. Remove anything that isn't a letter, number, or space
.replace(/[^a-z0-9\s-]/g, '')
// 2. Turn spaces into hyphens (project alpha -> project-alpha)
.replace(/\s+/g, '-')
// 3. Remove accidental double hyphens
.replace(/-+/g, '-');
}
Explanation:
project-alpha-betaNow, let's see how these three functions work together in a sequence when the command is run.
Finally, let's look at the call function in export.tsx where these pieces are glued together. This happens immediately after we generate the content (from the previous chapter) but before we show the dialog.
// File: export.tsx (Inside the call function)
// 1. Get the raw text of the first user message
const firstPrompt = extractFirstPrompt(context.messages);
// 2. Get the current time
const timestamp = formatTimestamp(new Date());
let defaultFilename: string;
// 3. Decide the name
if (firstPrompt) {
const sanitized = sanitizeFilename(firstPrompt);
// Combine: Timestamp + Context.txt
defaultFilename = `${timestamp}-${sanitized}.txt`;
} else {
// Fallback: Context was empty or invalid? Just use timestamp.
defaultFilename = `conversation-${timestamp}.txt`;
}
Walkthrough:
if (firstPrompt)), we sanitize it and append the timestamp.2023-10-27-how-to-code.txtconversation-2023-10-27.txtIn this chapter, we built the Contextual Filename Generation logic.
We now have the Content (from Chapter 3) and the Default Filename (from Chapter 4). But we still haven't actually saved the file if the user didn't provide an argument!
It is time to present these options to the user nicely.
Next Chapter: Interactive Export Fallback
Generated by Code IQ