124 lines
4.8 KiB
Markdown
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. |