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,87 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Type validator.
|
|
3
|
+
|
|
4
|
+
Validates roles and content block types against known values.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import List, Set
|
|
8
|
+
|
|
9
|
+
from ..base import NormalizedMessage
|
|
10
|
+
from .base import BaseValidator, ValidationContext, ValidationSeverity
|
|
11
|
+
|
|
12
|
+
# Universal known block types across all providers
|
|
13
|
+
KNOWN_BLOCK_TYPES: Set[str] = {
|
|
14
|
+
"text",
|
|
15
|
+
"thinking",
|
|
16
|
+
"tool_use",
|
|
17
|
+
"tool_result",
|
|
18
|
+
"image",
|
|
19
|
+
"file",
|
|
20
|
+
"code",
|
|
21
|
+
"system_context",
|
|
22
|
+
"parse_error",
|
|
23
|
+
"file_snapshot",
|
|
24
|
+
"context_summary",
|
|
25
|
+
"system_metadata",
|
|
26
|
+
"ide_context",
|
|
27
|
+
"queue_operation",
|
|
28
|
+
"progress",
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class TypeValidator(BaseValidator):
|
|
33
|
+
"""Validates message roles and content block types.
|
|
34
|
+
|
|
35
|
+
Unknown types get warnings (not errors) because:
|
|
36
|
+
- Provider may have added new features
|
|
37
|
+
- We want to preserve unknown data, not reject it
|
|
38
|
+
|
|
39
|
+
This helps detect format changes in provider exports.
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
def validate(
|
|
43
|
+
self, messages: List[NormalizedMessage], context: ValidationContext
|
|
44
|
+
) -> None:
|
|
45
|
+
"""Validate types across all messages."""
|
|
46
|
+
unknown_roles: Set[str] = set()
|
|
47
|
+
unknown_block_types: Set[str] = set()
|
|
48
|
+
|
|
49
|
+
for msg in messages:
|
|
50
|
+
role = msg.get("role", "")
|
|
51
|
+
|
|
52
|
+
# Check role against provider's expected roles
|
|
53
|
+
if role and self.config.expected_roles:
|
|
54
|
+
if role not in self.config.expected_roles:
|
|
55
|
+
unknown_roles.add(role)
|
|
56
|
+
|
|
57
|
+
# Check content block types
|
|
58
|
+
for block in msg.get("content_blocks", []):
|
|
59
|
+
block_type = block.get("type", "")
|
|
60
|
+
if block_type:
|
|
61
|
+
# Check against universal known types
|
|
62
|
+
if block_type not in KNOWN_BLOCK_TYPES:
|
|
63
|
+
unknown_block_types.add(block_type)
|
|
64
|
+
# Optionally check against provider-specific expected types
|
|
65
|
+
elif (
|
|
66
|
+
self.config.expected_block_types
|
|
67
|
+
and block_type not in self.config.expected_block_types
|
|
68
|
+
):
|
|
69
|
+
# Provider has restricted set - warn about unexpected
|
|
70
|
+
unknown_block_types.add(block_type)
|
|
71
|
+
|
|
72
|
+
# Report unknown types
|
|
73
|
+
for role in sorted(unknown_roles):
|
|
74
|
+
self._add_issue(
|
|
75
|
+
context,
|
|
76
|
+
f"Unknown message role '{role}' from provider {self.config.provider_name} - "
|
|
77
|
+
f"possible format change or new feature",
|
|
78
|
+
ValidationSeverity.warning,
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
for block_type in sorted(unknown_block_types):
|
|
82
|
+
self._add_issue(
|
|
83
|
+
context,
|
|
84
|
+
f"Unknown content block type '{block_type}' - "
|
|
85
|
+
f"possible format change or new feature",
|
|
86
|
+
ValidationSeverity.warning,
|
|
87
|
+
)
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
"""
|
|
2
|
+
JSON Schema validation for provider export formats.
|
|
3
|
+
|
|
4
|
+
Provides versioned schema validation with automatic version detection.
|
|
5
|
+
Schemas are stored as JSON files in provider-specific subdirectories.
|
|
6
|
+
|
|
7
|
+
Usage:
|
|
8
|
+
from apps.chat_import.schemas import validate_export, detect_schema_version
|
|
9
|
+
|
|
10
|
+
# Auto-detect and validate
|
|
11
|
+
errors, warnings = validate_export(data, provider="chatgpt")
|
|
12
|
+
|
|
13
|
+
# Or detect version explicitly
|
|
14
|
+
version = detect_schema_version(data, provider="chatgpt")
|
|
15
|
+
errors, warnings = validate_export(data, provider="chatgpt", version=version)
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
import json
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
from typing import Any, Dict, List, Optional, Tuple
|
|
21
|
+
|
|
22
|
+
try:
|
|
23
|
+
import jsonschema
|
|
24
|
+
HAS_JSONSCHEMA = True
|
|
25
|
+
except ImportError:
|
|
26
|
+
HAS_JSONSCHEMA = False
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
SCHEMA_DIR = Path(__file__).parent
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def get_available_versions(provider: str) -> List[str]:
|
|
33
|
+
"""Get list of available schema versions for a provider."""
|
|
34
|
+
provider_dir = SCHEMA_DIR / provider
|
|
35
|
+
if not provider_dir.exists():
|
|
36
|
+
return []
|
|
37
|
+
|
|
38
|
+
versions = []
|
|
39
|
+
for schema_file in provider_dir.glob("v*.json"):
|
|
40
|
+
versions.append(schema_file.stem) # e.g., "v1", "v2"
|
|
41
|
+
|
|
42
|
+
return sorted(versions)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def load_schema(provider: str, version: str) -> Optional[Dict[str, Any]]:
|
|
46
|
+
"""Load a specific schema version."""
|
|
47
|
+
schema_path = SCHEMA_DIR / provider / f"{version}.json"
|
|
48
|
+
if not schema_path.exists():
|
|
49
|
+
return None
|
|
50
|
+
|
|
51
|
+
with open(schema_path) as f:
|
|
52
|
+
return json.load(f)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def detect_schema_version(data: Any, provider: str) -> str:
|
|
56
|
+
"""
|
|
57
|
+
Auto-detect schema version from data structure.
|
|
58
|
+
|
|
59
|
+
Uses heuristics specific to each provider to determine which
|
|
60
|
+
schema version the data matches.
|
|
61
|
+
|
|
62
|
+
Returns the detected version string (e.g., "v1", "v2") or "v1" as default.
|
|
63
|
+
"""
|
|
64
|
+
if provider == "chatgpt":
|
|
65
|
+
return _detect_chatgpt_version(data)
|
|
66
|
+
elif provider == "claude":
|
|
67
|
+
return _detect_claude_version(data)
|
|
68
|
+
elif provider == "claude-code":
|
|
69
|
+
return _detect_claude_code_version(data)
|
|
70
|
+
elif provider == "cursor":
|
|
71
|
+
return _detect_cursor_version(data)
|
|
72
|
+
|
|
73
|
+
return "v1"
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def _detect_chatgpt_version(data: Any) -> str:
|
|
77
|
+
"""Detect ChatGPT export version.
|
|
78
|
+
|
|
79
|
+
v2: Has thinking blocks (content_type: "thoughts")
|
|
80
|
+
v1: Original format
|
|
81
|
+
"""
|
|
82
|
+
if not isinstance(data, list):
|
|
83
|
+
data = [data]
|
|
84
|
+
|
|
85
|
+
for conv in data:
|
|
86
|
+
mapping = conv.get("mapping", {})
|
|
87
|
+
for node in mapping.values():
|
|
88
|
+
msg = node.get("message")
|
|
89
|
+
if msg:
|
|
90
|
+
metadata = msg.get("metadata", {})
|
|
91
|
+
content_type = metadata.get("content_type")
|
|
92
|
+
if content_type in ("thoughts", "analysis", "reasoning_recap"):
|
|
93
|
+
return "v2"
|
|
94
|
+
|
|
95
|
+
return "v1"
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def _detect_claude_version(data: Any) -> str:
|
|
99
|
+
"""Detect Claude export version.
|
|
100
|
+
|
|
101
|
+
v1: Current format (only version so far)
|
|
102
|
+
"""
|
|
103
|
+
return "v1"
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def _detect_claude_code_version(data: Any) -> str:
|
|
107
|
+
"""Detect Claude Code session version.
|
|
108
|
+
|
|
109
|
+
v1: Current JSONL format (only version so far)
|
|
110
|
+
"""
|
|
111
|
+
return "v1"
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def _detect_cursor_version(data: Any) -> str:
|
|
115
|
+
"""Detect Cursor export version.
|
|
116
|
+
|
|
117
|
+
v2: Has toolFormerData field
|
|
118
|
+
v1: Original format
|
|
119
|
+
"""
|
|
120
|
+
if isinstance(data, dict):
|
|
121
|
+
bubbles = data.get("bubbles", [])
|
|
122
|
+
elif isinstance(data, list):
|
|
123
|
+
bubbles = data
|
|
124
|
+
else:
|
|
125
|
+
return "v1"
|
|
126
|
+
|
|
127
|
+
for bubble in bubbles:
|
|
128
|
+
if bubble.get("toolFormerData"):
|
|
129
|
+
return "v2"
|
|
130
|
+
|
|
131
|
+
return "v1"
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def validate_export(
|
|
135
|
+
data: Any,
|
|
136
|
+
provider: str,
|
|
137
|
+
version: Optional[str] = None,
|
|
138
|
+
) -> Tuple[List[str], List[str]]:
|
|
139
|
+
"""
|
|
140
|
+
Validate export data against JSON Schema.
|
|
141
|
+
|
|
142
|
+
Args:
|
|
143
|
+
data: The export data to validate
|
|
144
|
+
provider: Provider name (chatgpt, claude, claude-code, cursor)
|
|
145
|
+
version: Schema version (auto-detected if not specified)
|
|
146
|
+
|
|
147
|
+
Returns:
|
|
148
|
+
Tuple of (errors, warnings) where:
|
|
149
|
+
- errors: List of validation error messages
|
|
150
|
+
- warnings: List of validation warning messages (unknown fields, etc.)
|
|
151
|
+
"""
|
|
152
|
+
if not HAS_JSONSCHEMA:
|
|
153
|
+
# Return empty if jsonschema not installed
|
|
154
|
+
return [], ["jsonschema library not installed, skipping validation"]
|
|
155
|
+
|
|
156
|
+
if version is None:
|
|
157
|
+
version = detect_schema_version(data, provider)
|
|
158
|
+
|
|
159
|
+
schema = load_schema(provider, version)
|
|
160
|
+
if schema is None:
|
|
161
|
+
# No schema file for this version - not an error, just a warning
|
|
162
|
+
available = get_available_versions(provider)
|
|
163
|
+
if available:
|
|
164
|
+
return [], [f"No schema for {provider} {version}, available: {available}"]
|
|
165
|
+
else:
|
|
166
|
+
return [], [f"No schemas defined for provider {provider}"]
|
|
167
|
+
|
|
168
|
+
errors: List[str] = []
|
|
169
|
+
warnings: List[str] = []
|
|
170
|
+
|
|
171
|
+
try:
|
|
172
|
+
# Validate against schema
|
|
173
|
+
validator = jsonschema.Draft7Validator(schema)
|
|
174
|
+
|
|
175
|
+
for error in validator.iter_errors(data):
|
|
176
|
+
# Categorize errors
|
|
177
|
+
if error.validator == "additionalProperties":
|
|
178
|
+
# Unknown field - warning not error
|
|
179
|
+
warnings.append(f"Unknown field at {_format_path(error.path)}: {error.message}")
|
|
180
|
+
elif error.validator == "required":
|
|
181
|
+
# Missing required field - error
|
|
182
|
+
errors.append(f"Missing required field at {_format_path(error.path)}: {error.message}")
|
|
183
|
+
elif error.validator == "type":
|
|
184
|
+
# Type mismatch - error
|
|
185
|
+
errors.append(f"Type mismatch at {_format_path(error.path)}: {error.message}")
|
|
186
|
+
else:
|
|
187
|
+
# Other validation errors
|
|
188
|
+
errors.append(f"Validation error at {_format_path(error.path)}: {error.message}")
|
|
189
|
+
|
|
190
|
+
except Exception as e:
|
|
191
|
+
errors.append(f"Schema validation failed: {str(e)}")
|
|
192
|
+
|
|
193
|
+
return errors, warnings
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
def _format_path(path) -> str:
|
|
197
|
+
"""Format a JSON path for display."""
|
|
198
|
+
if not path:
|
|
199
|
+
return "root"
|
|
200
|
+
parts = []
|
|
201
|
+
for p in path:
|
|
202
|
+
if isinstance(p, int):
|
|
203
|
+
parts.append(f"[{p}]")
|
|
204
|
+
else:
|
|
205
|
+
parts.append(f".{p}")
|
|
206
|
+
return "".join(parts).lstrip(".")
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
def get_schema_violations(
|
|
210
|
+
data: Any,
|
|
211
|
+
provider: str,
|
|
212
|
+
version: Optional[str] = None,
|
|
213
|
+
) -> Dict[str, List[str]]:
|
|
214
|
+
"""
|
|
215
|
+
Get detailed schema violations.
|
|
216
|
+
|
|
217
|
+
Returns:
|
|
218
|
+
Dict with keys:
|
|
219
|
+
- unknown_fields: Fields not in schema
|
|
220
|
+
- missing_fields: Required fields that are missing
|
|
221
|
+
- type_mismatches: Fields with wrong types
|
|
222
|
+
- other_errors: Other validation errors
|
|
223
|
+
"""
|
|
224
|
+
errors, warnings = validate_export(data, provider, version)
|
|
225
|
+
|
|
226
|
+
return {
|
|
227
|
+
"unknown_fields": [w for w in warnings if "Unknown field" in w],
|
|
228
|
+
"missing_fields": [e for e in errors if "Missing required" in e],
|
|
229
|
+
"type_mismatches": [e for e in errors if "Type mismatch" in e],
|
|
230
|
+
"other_errors": [e for e in errors if "Missing required" not in e and "Type mismatch" not in e],
|
|
231
|
+
}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "chatgpt_export_v1",
|
|
4
|
+
"title": "ChatGPT Export v1",
|
|
5
|
+
"description": "Original ChatGPT conversation export format",
|
|
6
|
+
"type": "array",
|
|
7
|
+
"items": {
|
|
8
|
+
"$ref": "#/definitions/conversation"
|
|
9
|
+
},
|
|
10
|
+
"definitions": {
|
|
11
|
+
"conversation": {
|
|
12
|
+
"type": "object",
|
|
13
|
+
"required": ["title", "mapping"],
|
|
14
|
+
"properties": {
|
|
15
|
+
"title": {
|
|
16
|
+
"type": ["string", "null"],
|
|
17
|
+
"description": "Conversation title"
|
|
18
|
+
},
|
|
19
|
+
"create_time": {
|
|
20
|
+
"type": ["number", "null"],
|
|
21
|
+
"description": "Unix timestamp when conversation was created"
|
|
22
|
+
},
|
|
23
|
+
"update_time": {
|
|
24
|
+
"type": ["number", "null"],
|
|
25
|
+
"description": "Unix timestamp when conversation was last updated"
|
|
26
|
+
},
|
|
27
|
+
"mapping": {
|
|
28
|
+
"type": "object",
|
|
29
|
+
"additionalProperties": {
|
|
30
|
+
"$ref": "#/definitions/mappingNode"
|
|
31
|
+
},
|
|
32
|
+
"description": "Tree structure of messages"
|
|
33
|
+
},
|
|
34
|
+
"current_node": {
|
|
35
|
+
"type": ["string", "null"],
|
|
36
|
+
"description": "ID of the currently active message node"
|
|
37
|
+
},
|
|
38
|
+
"conversation_template_id": {
|
|
39
|
+
"type": ["string", "null"]
|
|
40
|
+
},
|
|
41
|
+
"gizmo_id": {
|
|
42
|
+
"type": ["string", "null"]
|
|
43
|
+
},
|
|
44
|
+
"id": {
|
|
45
|
+
"type": "string"
|
|
46
|
+
},
|
|
47
|
+
"moderation_results": {
|
|
48
|
+
"type": "array"
|
|
49
|
+
},
|
|
50
|
+
"safe_urls": {
|
|
51
|
+
"type": "array"
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
"mappingNode": {
|
|
56
|
+
"type": "object",
|
|
57
|
+
"properties": {
|
|
58
|
+
"id": {
|
|
59
|
+
"type": "string",
|
|
60
|
+
"description": "Node/message ID"
|
|
61
|
+
},
|
|
62
|
+
"parent": {
|
|
63
|
+
"type": ["string", "null"],
|
|
64
|
+
"description": "Parent node ID (null for root)"
|
|
65
|
+
},
|
|
66
|
+
"children": {
|
|
67
|
+
"type": "array",
|
|
68
|
+
"items": {
|
|
69
|
+
"type": "string"
|
|
70
|
+
},
|
|
71
|
+
"description": "Child node IDs"
|
|
72
|
+
},
|
|
73
|
+
"message": {
|
|
74
|
+
"oneOf": [
|
|
75
|
+
{"$ref": "#/definitions/message"},
|
|
76
|
+
{"type": "null"}
|
|
77
|
+
],
|
|
78
|
+
"description": "Message content (null for structural nodes)"
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
"message": {
|
|
83
|
+
"type": "object",
|
|
84
|
+
"required": ["id", "author", "content"],
|
|
85
|
+
"properties": {
|
|
86
|
+
"id": {
|
|
87
|
+
"type": "string",
|
|
88
|
+
"description": "Message ID"
|
|
89
|
+
},
|
|
90
|
+
"author": {
|
|
91
|
+
"$ref": "#/definitions/author"
|
|
92
|
+
},
|
|
93
|
+
"content": {
|
|
94
|
+
"$ref": "#/definitions/content"
|
|
95
|
+
},
|
|
96
|
+
"create_time": {
|
|
97
|
+
"type": ["number", "null"],
|
|
98
|
+
"description": "Unix timestamp when message was created"
|
|
99
|
+
},
|
|
100
|
+
"update_time": {
|
|
101
|
+
"type": ["number", "null"]
|
|
102
|
+
},
|
|
103
|
+
"status": {
|
|
104
|
+
"type": "string",
|
|
105
|
+
"enum": ["finished_successfully", "in_progress", "finished_partial_completion"]
|
|
106
|
+
},
|
|
107
|
+
"end_turn": {
|
|
108
|
+
"type": ["boolean", "null"]
|
|
109
|
+
},
|
|
110
|
+
"weight": {
|
|
111
|
+
"type": "number"
|
|
112
|
+
},
|
|
113
|
+
"metadata": {
|
|
114
|
+
"$ref": "#/definitions/metadata"
|
|
115
|
+
},
|
|
116
|
+
"recipient": {
|
|
117
|
+
"type": "string"
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
"author": {
|
|
122
|
+
"type": "object",
|
|
123
|
+
"required": ["role"],
|
|
124
|
+
"properties": {
|
|
125
|
+
"role": {
|
|
126
|
+
"type": "string",
|
|
127
|
+
"enum": ["user", "assistant", "system", "tool"],
|
|
128
|
+
"description": "Message author role"
|
|
129
|
+
},
|
|
130
|
+
"name": {
|
|
131
|
+
"type": ["string", "null"]
|
|
132
|
+
},
|
|
133
|
+
"metadata": {
|
|
134
|
+
"type": "object"
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
"content": {
|
|
139
|
+
"type": "object",
|
|
140
|
+
"properties": {
|
|
141
|
+
"content_type": {
|
|
142
|
+
"type": "string",
|
|
143
|
+
"enum": ["text", "code", "execution_output", "tether_browsing_display", "tether_quote", "multimodal_text", "system_error"]
|
|
144
|
+
},
|
|
145
|
+
"parts": {
|
|
146
|
+
"type": "array",
|
|
147
|
+
"description": "Content parts (text strings or objects)"
|
|
148
|
+
},
|
|
149
|
+
"language": {
|
|
150
|
+
"type": "string"
|
|
151
|
+
},
|
|
152
|
+
"text": {
|
|
153
|
+
"type": "string"
|
|
154
|
+
},
|
|
155
|
+
"result": {
|
|
156
|
+
"type": "string"
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
"metadata": {
|
|
161
|
+
"type": "object",
|
|
162
|
+
"properties": {
|
|
163
|
+
"is_user_system_message": {
|
|
164
|
+
"type": "boolean",
|
|
165
|
+
"description": "True if this is user's custom instructions"
|
|
166
|
+
},
|
|
167
|
+
"user_context_message_data": {
|
|
168
|
+
"type": "object"
|
|
169
|
+
},
|
|
170
|
+
"model_slug": {
|
|
171
|
+
"type": "string"
|
|
172
|
+
},
|
|
173
|
+
"default_model_slug": {
|
|
174
|
+
"type": "string"
|
|
175
|
+
},
|
|
176
|
+
"finish_details": {
|
|
177
|
+
"type": "object"
|
|
178
|
+
},
|
|
179
|
+
"citations": {
|
|
180
|
+
"type": "array"
|
|
181
|
+
},
|
|
182
|
+
"gizmo_id": {
|
|
183
|
+
"type": ["string", "null"]
|
|
184
|
+
},
|
|
185
|
+
"message_type": {
|
|
186
|
+
"type": ["string", "null"]
|
|
187
|
+
},
|
|
188
|
+
"request_id": {
|
|
189
|
+
"type": "string"
|
|
190
|
+
},
|
|
191
|
+
"timestamp_": {
|
|
192
|
+
"type": "string"
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|