Files
Project-Thoth/codex/chatgpt-capture-mvp/implementation/0003-dom-extractor.md
T

124 lines
4.8 KiB
Markdown

Implement Task 3 — ChatGPT DOM Extractor for the Project Thoth ChatGPT Capture Connector MVP.
Context:
- This is a Manifest V3 Chrome/Edge extension.
- Task 1 extension skeleton is complete.
- Task 2 activeTab capture flow is complete.
- The service worker can inject or invoke a content script and receive a placeholder payload.
- This task replaces the placeholder capture logic with a ChatGPT-specific DOM extractor.
- Capture Connectors must only capture source material. Do not reason, summarize, classify, call LLMs, generate Project Thoth metadata, or write to the vault.
Goal:
Create a ChatGPT-specific DOM extractor module that returns an ordered conversation capture payload with title, URL, capture timestamp, and messages.
Files to update or create:
- src/chatgptExtractor.js
- src/background.js only if needed to integrate the extractor result
- README.md only if testing instructions need updating
Expected output shape:
{
sourcePlatform: "ChatGPT",
title: "Detected conversation title",
url: "https://chatgpt.com/...",
capturedAt: "2026-07-08T...",
messages: [
{
role: "user",
content: "..."
},
{
role: "assistant",
content: "..."
}
]
}
Extractor requirements:
1. Extract the conversation title if available.
- Prefer a visible conversation title if one exists.
- Fall back to document.title.
- Fall back to "ChatGPT Conversation".
2. Extract ordered message blocks.
- Preserve the page order of messages.
- Return messages in the same order they appear in the conversation.
- Ignore navigation, sidebar, composer/input box, buttons, menus, and unrelated UI chrome.
3. Detect speaker role when possible.
- Detect user messages as role: "user".
- Detect assistant messages as role: "assistant".
- If role cannot be determined, use role: "unknown" rather than guessing too aggressively.
- Keep role detection logic isolated and easy to revise because ChatGPT DOM structure may change.
4. Extract text content.
- Extract the readable content of each message.
- Trim leading/trailing whitespace.
- Collapse excessive blank lines where appropriate.
- Do not include copy buttons, feedback controls, model labels, timestamps, or hidden UI text.
5. Preserve basic formatting where practical.
- Preserve paragraph breaks.
- Preserve markdown-like headings.
- Preserve bullet and numbered lists as readable text.
- Preserve code blocks using fenced markdown when detectable.
- Preserve inline code as readable text when detectable.
- Do not attempt perfect HTML-to-Markdown conversion in this task.
6. Handle code blocks.
- Detect pre/code blocks inside assistant messages.
- Output fenced code blocks.
- Include a language tag if available from the DOM; otherwise use a plain triple-backtick fence.
- Avoid duplicating code block content in the surrounding extracted text.
7. Be defensive against ChatGPT DOM instability.
- Use multiple selector strategies where reasonable.
- Prefer semantic attributes when available, such as data-testid, role, aria-label, or known message container patterns.
- Keep selectors centralized near the top of the extractor.
- Add comments explaining selector assumptions.
8. Return useful failure states.
- If no messages are found, return a structured payload with messages: [] and an error field such as:
{
error: "No ChatGPT conversation messages were detected."
}
- Do not throw unhandled exceptions from normal extraction failure.
9. No browser download logic in this task.
10. No markdown normalizer in this task.
11. No Project Thoth application dependency.
12. No LLM calls.
Suggested module API:
export function extractChatGPTConversation() {
return {
sourcePlatform: "ChatGPT",
title,
url: window.location.href,
capturedAt: new Date().toISOString(),
messages
};
}
Suggested helper functions:
- getConversationTitle()
- findMessageElements()
- detectMessageRole(element)
- extractMessageContent(element)
- extractNodeAsMarkdown(node)
- normalizeWhitespace(text)
Integration:
- The activeTab capture flow should invoke extractChatGPTConversation() from the injected content context.
- The service worker should receive and log the returned payload.
- Existing Task 2 message passing should remain intact.
Acceptance criteria:
- On an open ChatGPT conversation, clicking the extension button returns a payload with title, URL, capturedAt, and ordered messages.
- User and assistant roles are detected when possible.
- Message content is readable and excludes obvious UI chrome.
- Paragraphs, lists, headings, and code blocks remain usable in the extracted content.
- If no conversation is detected, the payload clearly reports that no messages were found.
- The implementation remains modular so Task 4 can consume the payload and convert it into canonical conversation.md format.