thread-archive 0.0.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- thread_archive/__init__.py +34 -0
- thread_archive/_api.py +2235 -0
- thread_archive/_config.py +126 -0
- thread_archive/_importers/__init__.py +81 -0
- thread_archive/_importers/_continuation.py +136 -0
- thread_archive/_importers/_cursor.py +103 -0
- thread_archive/_importers/_events.py +244 -0
- thread_archive/_importers/_line_stream.py +193 -0
- thread_archive/_importers/_read.py +82 -0
- thread_archive/_importers/_result.py +17 -0
- thread_archive/_importers/_sidecar.py +113 -0
- thread_archive/_importers/_state.py +240 -0
- thread_archive/_importers/_titles.py +179 -0
- thread_archive/_importers/antigravity.py +254 -0
- thread_archive/_importers/claude_code.py +293 -0
- thread_archive/_importers/claude_science.py +330 -0
- thread_archive/_importers/cloth.py +20 -0
- thread_archive/_importers/codex.py +324 -0
- thread_archive/_importers/cowork.py +107 -0
- thread_archive/_importers/cursor.py +432 -0
- thread_archive/_importers/exports.py +389 -0
- thread_archive/_importers/grok.py +600 -0
- thread_archive/_importers/opencode.py +538 -0
- thread_archive/_knowledge/__init__.py +67 -0
- thread_archive/_knowledge/_claims.py +116 -0
- thread_archive/_knowledge/_community.py +75 -0
- thread_archive/_knowledge/graph.py +208 -0
- thread_archive/_knowledge/materialize.py +212 -0
- thread_archive/_knowledge/write.py +438 -0
- thread_archive/_launchd.py +167 -0
- thread_archive/_mcp/__init__.py +1 -0
- thread_archive/_mcp/librarian.py +151 -0
- thread_archive/_mcp/server.py +307 -0
- thread_archive/_retrieval/__init__.py +280 -0
- thread_archive/_retrieval/_classify.py +80 -0
- thread_archive/_retrieval/_codex.py +157 -0
- thread_archive/_retrieval/_context.py +123 -0
- thread_archive/_retrieval/_extract.py +184 -0
- thread_archive/_retrieval/embed.py +186 -0
- thread_archive/_retrieval/format.py +149 -0
- thread_archive/_retrieval/fts.py +538 -0
- thread_archive/_retrieval/rank.py +228 -0
- thread_archive/_retrieval/read.py +908 -0
- thread_archive/_retrieval/rerank.py +143 -0
- thread_archive/_retrieval/vectors.py +611 -0
- thread_archive/_scripts/__init__.py +1 -0
- thread_archive/_scripts/backfill_recompute.py +328 -0
- thread_archive/_scripts/backfill_reconcile.py +296 -0
- thread_archive/_scripts/denamespace_dedup_keys.py +120 -0
- thread_archive/_scripts/recover_dropped_events.py +190 -0
- thread_archive/_scripts/repair_grok_tool_names.py +118 -0
- thread_archive/_scripts/repair_grok_tool_names_backup_20260704T155625Z.json +275 -0
- thread_archive/_scripts/repair_grok_tool_names_plan_20260704.json +435 -0
- thread_archive/_setup/__init__.py +12 -0
- thread_archive/_setup/clients.py +89 -0
- thread_archive/_setup/wizard.py +474 -0
- thread_archive/_store/__init__.py +45 -0
- thread_archive/_store/_base.py +173 -0
- thread_archive/_store/_defaults.py +57 -0
- thread_archive/_store/_types.py +38 -0
- thread_archive/_store/models.py +370 -0
- thread_archive/_store/schema.py +84 -0
- thread_archive/_thread_import/__init__.py +40 -0
- thread_archive/_thread_import/api.py +78 -0
- thread_archive/_thread_import/event_builder.py +810 -0
- thread_archive/_thread_import/exporters/__init__.py +9 -0
- thread_archive/_thread_import/exporters/_cursor_kv_mixin.py +166 -0
- thread_archive/_thread_import/exporters/_cursor_parse_mixin.py +149 -0
- thread_archive/_thread_import/exporters/cursor.py +582 -0
- thread_archive/_thread_import/exporters/cursor_parse.py +145 -0
- thread_archive/_thread_import/parsers/__init__.py +191 -0
- thread_archive/_thread_import/parsers/base.py +698 -0
- thread_archive/_thread_import/parsers/chatgpt.py +722 -0
- thread_archive/_thread_import/parsers/chatgpt_content.py +332 -0
- thread_archive/_thread_import/parsers/claude.py +443 -0
- thread_archive/_thread_import/parsers/claude_code.py +1035 -0
- thread_archive/_thread_import/parsers/claude_code_blocks.py +415 -0
- thread_archive/_thread_import/parsers/claude_code_ide.py +122 -0
- thread_archive/_thread_import/parsers/claude_code_sessions.py +90 -0
- thread_archive/_thread_import/parsers/config/__init__.py +26 -0
- thread_archive/_thread_import/parsers/config/base.py +220 -0
- thread_archive/_thread_import/parsers/cursor.py +538 -0
- thread_archive/_thread_import/parsers/cursor_blocks.py +365 -0
- thread_archive/_thread_import/parsers/pipeline/__init__.py +29 -0
- thread_archive/_thread_import/parsers/pipeline/base.py +251 -0
- thread_archive/_thread_import/parsers/pipeline/interfaces.py +191 -0
- thread_archive/_thread_import/parsers/transformers/__init__.py +22 -0
- thread_archive/_thread_import/parsers/transformers/active_path.py +87 -0
- thread_archive/_thread_import/parsers/transformers/coalescing.py +389 -0
- thread_archive/_thread_import/parsers/transformers/ide_context.py +158 -0
- thread_archive/_thread_import/parsers/transformers/thinking_merge.py +68 -0
- thread_archive/_thread_import/parsers/types/__init__.py +56 -0
- thread_archive/_thread_import/parsers/types/chatgpt.py +99 -0
- thread_archive/_thread_import/parsers/types/claude.py +120 -0
- thread_archive/_thread_import/parsers/types/claude_code.py +139 -0
- thread_archive/_thread_import/parsers/types/cursor.py +109 -0
- thread_archive/_thread_import/parsers/validators/__init__.py +83 -0
- thread_archive/_thread_import/parsers/validators/base.py +168 -0
- thread_archive/_thread_import/parsers/validators/content.py +80 -0
- thread_archive/_thread_import/parsers/validators/referential.py +57 -0
- thread_archive/_thread_import/parsers/validators/thinking.py +143 -0
- thread_archive/_thread_import/parsers/validators/types.py +87 -0
- thread_archive/_thread_import/schemas/__init__.py +231 -0
- thread_archive/_thread_import/schemas/chatgpt/v1.json +197 -0
- thread_archive/_thread_import/schemas/chatgpt/v2.json +203 -0
- thread_archive/_thread_import/schemas/claude/v1.json +188 -0
- thread_archive/_thread_import/schemas/claude_code/v1.json +183 -0
- thread_archive/_thread_import/schemas/cursor/v1.json +143 -0
- thread_archive/_thread_import/schemas/cursor/v2.json +200 -0
- thread_archive/_thread_import/timestamps.py +57 -0
- thread_archive/_thread_import/tool_names.py +48 -0
- thread_archive/_truth/__init__.py +40 -0
- thread_archive/_truth/jsonl_log.py +2340 -0
- thread_archive/_truth/repair.py +322 -0
- thread_archive/_watcher/__init__.py +57 -0
- thread_archive/_watcher/base.py +65 -0
- thread_archive/_watcher/daemon.py +289 -0
- thread_archive/_watcher/export_drop.py +203 -0
- thread_archive/_watcher/exthost.py +316 -0
- thread_archive/_watcher/lazy.py +117 -0
- thread_archive/_watcher/sources.py +616 -0
- thread_archive/_web/__init__.py +15 -0
- thread_archive/_web/server.py +299 -0
- thread_archive/_web/static/assets/index-DECSH1Mz.css +10 -0
- thread_archive/_web/static/assets/index-Djq0FK0y.js +101 -0
- thread_archive/_web/static/index.html +13 -0
- thread_archive/cli.py +746 -0
- thread_archive-0.0.2.dist-info/METADATA +296 -0
- thread_archive-0.0.2.dist-info/RECORD +132 -0
- thread_archive-0.0.2.dist-info/WHEEL +4 -0
- thread_archive-0.0.2.dist-info/entry_points.txt +6 -0
- thread_archive-0.0.2.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
"""Pure per-message-shape parsing helpers for the Cursor exporter.
|
|
2
|
+
|
|
3
|
+
Stateless functions that keep ``CursorExporter`` thin. The emitted dict/list
|
|
4
|
+
shapes are an import contract and must stay byte-for-byte stable.
|
|
5
|
+
|
|
6
|
+
No filesystem, no SQLite, no instance state — pure transforms over the raw
|
|
7
|
+
composer/bubble/message blobs that Cursor stores. ``CursorExporter``'s pinned
|
|
8
|
+
methods delegate here.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from typing import Any, Dict, List, Optional
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def kv_role(bubble: Dict[str, Any], header: Dict[str, Any]) -> str:
|
|
15
|
+
"""Map a Cursor bubble/header ``type`` (1/2) onto a canonical role."""
|
|
16
|
+
bubble_type = bubble.get("type") or header.get("type")
|
|
17
|
+
if bubble_type == 1:
|
|
18
|
+
return "user"
|
|
19
|
+
if bubble_type == 2:
|
|
20
|
+
return "assistant"
|
|
21
|
+
return "unknown"
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def build_kv_message(
|
|
25
|
+
bubble_id: str,
|
|
26
|
+
bubble: Dict[str, Any],
|
|
27
|
+
header: Dict[str, Any],
|
|
28
|
+
idx: int,
|
|
29
|
+
) -> Dict[str, Any]:
|
|
30
|
+
"""Build one conversation message from a composer header + its bubble."""
|
|
31
|
+
message = {
|
|
32
|
+
"id": bubble_id,
|
|
33
|
+
"role": kv_role(bubble, header),
|
|
34
|
+
"content": bubble.get("text", ""),
|
|
35
|
+
"created_at": bubble.get("createdAt"),
|
|
36
|
+
"index": idx,
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
tool_data = bubble.get("toolFormerData")
|
|
40
|
+
if tool_data and isinstance(tool_data, dict):
|
|
41
|
+
message["tool_call"] = {
|
|
42
|
+
"name": tool_data.get("name", "unknown"),
|
|
43
|
+
"tool_id": tool_data.get("tool"),
|
|
44
|
+
"call_id": tool_data.get("toolCallId"),
|
|
45
|
+
"status": tool_data.get("status"),
|
|
46
|
+
"args": tool_data.get("rawArgs"),
|
|
47
|
+
"params": tool_data.get("params"),
|
|
48
|
+
"result": tool_data.get("result"),
|
|
49
|
+
"user_decision": tool_data.get("userDecision"),
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
code_blocks = bubble.get("codeBlocks", [])
|
|
53
|
+
if code_blocks:
|
|
54
|
+
message["code_blocks"] = code_blocks
|
|
55
|
+
|
|
56
|
+
thinking = bubble.get("thinking")
|
|
57
|
+
if thinking and isinstance(thinking, dict):
|
|
58
|
+
thinking_text = thinking.get("text", "")
|
|
59
|
+
if thinking_text:
|
|
60
|
+
message["thinking"] = thinking_text
|
|
61
|
+
message["thinking_duration_ms"] = bubble.get("thinkingDurationMs")
|
|
62
|
+
|
|
63
|
+
if bubble.get("serverBubbleId"):
|
|
64
|
+
message["server_bubble_id"] = bubble["serverBubbleId"]
|
|
65
|
+
|
|
66
|
+
return message
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def build_kv_metadata(composer: Dict[str, Any]) -> Dict[str, Any]:
|
|
70
|
+
"""Extract the conversation metadata block from a composer record."""
|
|
71
|
+
return {
|
|
72
|
+
"mode": composer.get("unifiedMode"),
|
|
73
|
+
"status": composer.get("status"),
|
|
74
|
+
"is_agentic": composer.get("isAgentic"),
|
|
75
|
+
"context_tokens": composer.get("contextTokensUsed"),
|
|
76
|
+
"lines_added": composer.get("totalLinesAdded"),
|
|
77
|
+
"lines_removed": composer.get("totalLinesRemoved"),
|
|
78
|
+
"branch": composer.get("createdOnBranch"),
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def normalize_role(msg: Dict[str, Any]) -> Optional[str]:
|
|
83
|
+
"""Map Cursor's role/type/sender aliases onto canonical role names."""
|
|
84
|
+
role = msg.get("role") or msg.get("type") or msg.get("sender")
|
|
85
|
+
if role:
|
|
86
|
+
role = role.lower()
|
|
87
|
+
if role in ("human", "user"):
|
|
88
|
+
role = "user"
|
|
89
|
+
elif role in ("assistant", "ai", "bot"):
|
|
90
|
+
role = "assistant"
|
|
91
|
+
elif role in ("system",):
|
|
92
|
+
role = "system"
|
|
93
|
+
elif role in ("tool", "function"):
|
|
94
|
+
role = "tool"
|
|
95
|
+
return role
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def content_blocks_from_content(raw_content: Any) -> List[Dict[str, Any]]:
|
|
99
|
+
"""Build text content blocks from a message's raw ``content`` field."""
|
|
100
|
+
content_blocks: List[Dict[str, Any]] = []
|
|
101
|
+
if isinstance(raw_content, list):
|
|
102
|
+
for block in raw_content:
|
|
103
|
+
if isinstance(block, dict):
|
|
104
|
+
content_blocks.append(block)
|
|
105
|
+
elif isinstance(block, str):
|
|
106
|
+
content_blocks.append({"type": "text", "text": block})
|
|
107
|
+
elif isinstance(raw_content, str):
|
|
108
|
+
content_blocks.append({"type": "text", "text": raw_content})
|
|
109
|
+
return content_blocks
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def parse_message(msg: Any, index: int = 0) -> Optional[Dict[str, Any]]:
|
|
113
|
+
"""Parse a single message from Cursor's format."""
|
|
114
|
+
if not isinstance(msg, dict):
|
|
115
|
+
return None
|
|
116
|
+
|
|
117
|
+
role = normalize_role(msg)
|
|
118
|
+
content = msg.get("content") or msg.get("text") or msg.get("message") or ""
|
|
119
|
+
content_blocks = content_blocks_from_content(msg.get("content"))
|
|
120
|
+
|
|
121
|
+
tool_calls = msg.get("tool_calls") or msg.get("toolCalls") or msg.get("function_call")
|
|
122
|
+
tool_results = msg.get("tool_results") or msg.get("toolResults")
|
|
123
|
+
thinking = msg.get("thinking") or msg.get("reasoning")
|
|
124
|
+
|
|
125
|
+
parsed = {
|
|
126
|
+
"id": msg.get("id") or msg.get("messageId") or f"msg_{index}",
|
|
127
|
+
"role": role or "unknown",
|
|
128
|
+
"content": content if isinstance(content, str) else "",
|
|
129
|
+
"content_blocks": content_blocks,
|
|
130
|
+
"created_at": msg.get("createdAt") or msg.get("created_at") or msg.get("timestamp"),
|
|
131
|
+
"index": index,
|
|
132
|
+
"raw_data": msg,
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if tool_calls:
|
|
136
|
+
parsed["tool_calls"] = tool_calls
|
|
137
|
+
if tool_results:
|
|
138
|
+
parsed["tool_results"] = tool_results
|
|
139
|
+
if thinking:
|
|
140
|
+
parsed["thinking"] = thinking
|
|
141
|
+
|
|
142
|
+
if msg.get("model"):
|
|
143
|
+
parsed["model"] = msg["model"]
|
|
144
|
+
|
|
145
|
+
return parsed
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Provider-specific parsers for chat export files.
|
|
3
|
+
|
|
4
|
+
Each parser transforms a provider's export format into a standardized
|
|
5
|
+
message format with unified content_blocks schema.
|
|
6
|
+
|
|
7
|
+
## Architecture
|
|
8
|
+
|
|
9
|
+
The parser system uses a pipeline pattern with clear boundaries:
|
|
10
|
+
|
|
11
|
+
1. **Types** (`types/`): TypedDict schemas for provider input formats
|
|
12
|
+
2. **Config** (`config/`): Provider-specific configuration (ProviderConfig)
|
|
13
|
+
3. **Pipeline** (`pipeline/`): Composable parse -> transform -> normalize -> validate
|
|
14
|
+
4. **Validators** (`validators/`): Pluggable validation rules
|
|
15
|
+
5. **Transformers** (`transformers/`): Message transformations (coalescing, etc.)
|
|
16
|
+
|
|
17
|
+
## Content Block Types
|
|
18
|
+
|
|
19
|
+
- text: Plain text content
|
|
20
|
+
- thinking: Model thinking/reasoning
|
|
21
|
+
- tool_use: Tool/function call
|
|
22
|
+
- tool_result: Tool/function result
|
|
23
|
+
- image: Image content
|
|
24
|
+
- file: File attachment
|
|
25
|
+
- code: Code execution
|
|
26
|
+
- system_context: System/user context
|
|
27
|
+
- ide_context: IDE state (opened files, selections)
|
|
28
|
+
- file_snapshot: File state snapshots
|
|
29
|
+
- context_summary: Conversation summaries
|
|
30
|
+
- parse_error: Preserved malformed data
|
|
31
|
+
|
|
32
|
+
## Field Mapping
|
|
33
|
+
|
|
34
|
+
- Each parser uses explicit FieldMapping declarations
|
|
35
|
+
- Maps provider JSON fields to our semantic model
|
|
36
|
+
- Documents what each field MEANS, not just where it comes from
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
from typing import Type
|
|
40
|
+
|
|
41
|
+
# Base types and infrastructure
|
|
42
|
+
from .base import (
|
|
43
|
+
CodeBlock,
|
|
44
|
+
ContentBlock,
|
|
45
|
+
FieldMapping,
|
|
46
|
+
FileBlock,
|
|
47
|
+
ImageBlock,
|
|
48
|
+
ImportResult,
|
|
49
|
+
NormalizedMessage,
|
|
50
|
+
ProviderParser,
|
|
51
|
+
SemanticCheck,
|
|
52
|
+
SystemContextBlock,
|
|
53
|
+
TextBlock,
|
|
54
|
+
ThinkingBlock,
|
|
55
|
+
ToolResultBlock,
|
|
56
|
+
ToolUseBlock,
|
|
57
|
+
ValidationContext,
|
|
58
|
+
ValidationSeverity,
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
# Existing parsers (legacy interface, still functional)
|
|
62
|
+
from .chatgpt import ChatGPTParser
|
|
63
|
+
from .claude import ClaudeParser
|
|
64
|
+
from .claude_code import ClaudeCodeParser
|
|
65
|
+
|
|
66
|
+
# Provider configurations
|
|
67
|
+
from .config import (
|
|
68
|
+
CHATGPT_CONFIG,
|
|
69
|
+
CLAUDE_CODE_CONFIG,
|
|
70
|
+
CLAUDE_CONFIG,
|
|
71
|
+
CURSOR_CONFIG,
|
|
72
|
+
ProviderConfig,
|
|
73
|
+
ThinkingExpectation,
|
|
74
|
+
get_provider_config,
|
|
75
|
+
)
|
|
76
|
+
from .cursor import CursorParser
|
|
77
|
+
|
|
78
|
+
# Pipeline infrastructure
|
|
79
|
+
from .pipeline import (
|
|
80
|
+
Normalizer,
|
|
81
|
+
Parser,
|
|
82
|
+
ParserPipeline,
|
|
83
|
+
RawMessage,
|
|
84
|
+
Transformer,
|
|
85
|
+
Validator,
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
# Transformers
|
|
89
|
+
from .transformers import (
|
|
90
|
+
ActivePathTransformer,
|
|
91
|
+
IDEContextTransformer,
|
|
92
|
+
ThinkingMergeTransformer,
|
|
93
|
+
ToolCoalescingTransformer,
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
# Validators
|
|
97
|
+
from .validators import (
|
|
98
|
+
BaseValidator,
|
|
99
|
+
ContentValidator,
|
|
100
|
+
ReferentialIntegrityValidator,
|
|
101
|
+
ThinkingBlockValidator,
|
|
102
|
+
TypeValidator,
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
# Registry of parser classes (not instances - we create instances with config)
|
|
106
|
+
PARSER_CLASSES: dict[str, Type[ProviderParser]] = {
|
|
107
|
+
"chatgpt": ChatGPTParser,
|
|
108
|
+
"claude": ClaudeParser,
|
|
109
|
+
"claude-code": ClaudeCodeParser,
|
|
110
|
+
"cursor": CursorParser,
|
|
111
|
+
# Add more providers here:
|
|
112
|
+
# 'gemini': GeminiParser,
|
|
113
|
+
# 'copilot': CopilotParser,
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
# Available provider names
|
|
117
|
+
PROVIDERS = list(PARSER_CLASSES.keys())
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def get_parser(provider: str, strict: bool = False) -> ProviderParser:
|
|
121
|
+
"""
|
|
122
|
+
Get a parser instance for a provider.
|
|
123
|
+
|
|
124
|
+
Args:
|
|
125
|
+
provider: Provider name (chatgpt, claude, cursor)
|
|
126
|
+
strict: If True, validation warnings become errors
|
|
127
|
+
|
|
128
|
+
Returns:
|
|
129
|
+
Parser instance configured with the given strictness level
|
|
130
|
+
"""
|
|
131
|
+
if provider not in PARSER_CLASSES:
|
|
132
|
+
raise ValueError(f"Unknown provider '{provider}'. Available: {PROVIDERS}")
|
|
133
|
+
return PARSER_CLASSES[provider](strict=strict)
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
__all__ = [
|
|
137
|
+
# Base types
|
|
138
|
+
"ProviderParser",
|
|
139
|
+
"NormalizedMessage",
|
|
140
|
+
"ContentBlock",
|
|
141
|
+
"ImportResult",
|
|
142
|
+
# Field mapping infrastructure
|
|
143
|
+
"FieldMapping",
|
|
144
|
+
"SemanticCheck",
|
|
145
|
+
"ValidationContext",
|
|
146
|
+
"ValidationSeverity",
|
|
147
|
+
# Block types
|
|
148
|
+
"TextBlock",
|
|
149
|
+
"ThinkingBlock",
|
|
150
|
+
"ToolUseBlock",
|
|
151
|
+
"ToolResultBlock",
|
|
152
|
+
"ImageBlock",
|
|
153
|
+
"FileBlock",
|
|
154
|
+
"CodeBlock",
|
|
155
|
+
"SystemContextBlock",
|
|
156
|
+
# Provider configurations
|
|
157
|
+
"ProviderConfig",
|
|
158
|
+
"ThinkingExpectation",
|
|
159
|
+
"CHATGPT_CONFIG",
|
|
160
|
+
"CLAUDE_CONFIG",
|
|
161
|
+
"CLAUDE_CODE_CONFIG",
|
|
162
|
+
"CURSOR_CONFIG",
|
|
163
|
+
"get_provider_config",
|
|
164
|
+
# Pipeline infrastructure
|
|
165
|
+
"RawMessage",
|
|
166
|
+
"Parser",
|
|
167
|
+
"Transformer",
|
|
168
|
+
"Normalizer",
|
|
169
|
+
"Validator",
|
|
170
|
+
"ParserPipeline",
|
|
171
|
+
# Validators
|
|
172
|
+
"BaseValidator",
|
|
173
|
+
"ThinkingBlockValidator",
|
|
174
|
+
"ReferentialIntegrityValidator",
|
|
175
|
+
"TypeValidator",
|
|
176
|
+
"ContentValidator",
|
|
177
|
+
# Transformers
|
|
178
|
+
"ToolCoalescingTransformer",
|
|
179
|
+
"ActivePathTransformer",
|
|
180
|
+
"ThinkingMergeTransformer",
|
|
181
|
+
"IDEContextTransformer",
|
|
182
|
+
# Parsers (legacy interface)
|
|
183
|
+
"ChatGPTParser",
|
|
184
|
+
"ClaudeParser",
|
|
185
|
+
"ClaudeCodeParser",
|
|
186
|
+
"CursorParser",
|
|
187
|
+
"PARSER_CLASSES",
|
|
188
|
+
"PROVIDERS",
|
|
189
|
+
"get_parser",
|
|
190
|
+
]
|
|
191
|
+
|