3.8 KiB
Implement Task 5 — Download Writer for the Project Thoth ChatGPT Capture Connector MVP.
Context:
- Task 3 extracts a ChatGPT conversation payload.
- Task 4 converts that payload into canonical Project Thoth Markdown.
- This task saves the Markdown file to the user’s Downloads folder.
- Capture Connectors still only capture and transmit source material.
- Do not reason, summarize, classify, call LLMs, generate Source Metadata, generate Manifests, generate Harvests, or write directly to the vault.
Goal: Implement Markdown download using the browser downloads API with safe filename generation.
Files to create or update:
- src/filename.js
- src/background.js
- manifest.json if the downloads permission is not already present
- README.md only if testing instructions need updating
Manifest requirement: Ensure manifest.json includes:
"permissions": [ "activeTab", "scripting", "downloads" ]
Filename requirements:
-
Generate a safe filename using:
- capture date
- source platform
- conversation title
-
Preferred format:
YYYY-MM-DD - ChatGPT - Conversation Title.md
- If title is missing, use:
YYYY-MM-DD - ChatGPT - Conversation.md
-
Sanitize invalid filename characters:
- < > : " / \ | ? *
- control characters
- excessive whitespace
- leading/trailing dots or spaces
-
Keep filename length reasonable.
- Limit final filename to approximately 180 characters including
.md. - Preserve the date, platform, and extension.
- Truncate the title portion if needed.
- Limit final filename to approximately 180 characters including
-
If capturedAt is invalid or missing:
- Use the current date.
-
Add a timestamp suffix only when needed to reduce collision risk or when using downloads API conflict handling.
Suggested module API:
export function createConversationFilename(capturePayload) { return "2026-07-08 - ChatGPT - Conversation Title.md"; }
Suggested helpers:
- formatDateForFilename(dateValue)
- sanitizeFilenamePart(value)
- truncateFilename(filename, maxLength)
Download requirements:
- Export or implement a function that downloads Markdown as a
.mdfile. - Use chrome.downloads.download.
- Create a Blob from the Markdown content.
- Create an object URL using URL.createObjectURL(blob).
- Pass the object URL to chrome.downloads.download.
- Use the generated filename.
- Save to Downloads by using only the filename, not an absolute path.
- Use conflictAction: "uniquify" to avoid overwriting existing captures.
- Revoke the object URL after download is started or after the callback returns.
Suggested implementation shape in background.js:
const blob = new Blob([markdown], { type: "text/markdown;charset=utf-8" }); const url = URL.createObjectURL(blob);
chrome.downloads.download( { url, filename, saveAs: false, conflictAction: "uniquify" }, (downloadId) => { URL.revokeObjectURL(url);
if (chrome.runtime.lastError || !downloadId) {
// Handle download failure
}
// Handle success
} );
Integration:
- After activeTab capture succeeds, call normalizeConversationToMarkdown(payload).
- Generate filename from the same payload.
- Download the Markdown file.
- Log success/failure clearly.
- Do not add complex UI yet unless already present.
- Task 6 will handle user-facing feedback.
Error handling:
- If Markdown generation succeeds but download fails, report or log: "The conversation was captured, but the file could not be saved."
- If filename generation fails, fall back to: conversation.md
Acceptance criteria:
- Clicking the extension button on a ChatGPT conversation downloads a
.mdfile. - File is saved to the browser’s default Downloads folder.
- Filename is human-readable and safe.
- Invalid filename characters are removed or replaced.
- Existing files are not overwritten.
- Markdown content matches Task 4 output.
- No LLM calls.
- No Project Thoth application dependency.
- No vault writes.