emergent-translator 1.1.0__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.
@@ -0,0 +1,903 @@
1
+ # eudaimonia/translator/client_sdk.py
2
+
3
+ """
4
+ Emergent Language Translator Client SDK
5
+
6
+ Python and JavaScript SDKs for easy integration with the Emergent Language
7
+ Translator API. Provides simple, high-level interfaces for external AI systems
8
+ to compress their data using Eudaimonia's native θ symbol format.
9
+
10
+ Features:
11
+ - Simple async/sync Python client
12
+ - Batch translation support
13
+ - WebSocket streaming
14
+ - Automatic retries and error handling
15
+ - Compression statistics
16
+ - TypeScript definitions for JavaScript
17
+ """
18
+
19
+ import asyncio
20
+ import json
21
+ import logging
22
+ import time
23
+ from typing import Dict, List, Optional, Union, Any, AsyncGenerator, Tuple
24
+ from dataclasses import dataclass
25
+ import base64
26
+
27
+ import httpx
28
+ import websockets
29
+
30
+ logger = logging.getLogger(__name__)
31
+
32
+
33
+ @dataclass
34
+ class TranslationConfig:
35
+ """Configuration for translator client."""
36
+ api_base_url: str = "http://localhost:8000"
37
+ auth_token: Optional[str] = None
38
+ timeout: float = 30.0
39
+ max_retries: int = 3
40
+ retry_delay: float = 1.0
41
+
42
+
43
+ @dataclass
44
+ class ClientTranslationResult:
45
+ """Client-side translation result."""
46
+ success: bool
47
+ translated_data: Optional[bytes] = None
48
+ original_size: int = 0
49
+ translated_size: int = 0
50
+ compression_ratio: float = 0.0
51
+ efficiency_gain: float = 0.0
52
+ translation_time_ms: float = 0.0
53
+ symbol_count: int = 0
54
+ symbol_families: List[str] = None
55
+ metadata: Dict[str, Any] = None
56
+ errors: List[str] = None
57
+
58
+ def __post_init__(self):
59
+ if self.symbol_families is None:
60
+ self.symbol_families = []
61
+ if self.metadata is None:
62
+ self.metadata = {}
63
+ if self.errors is None:
64
+ self.errors = []
65
+
66
+
67
+ class EmergentTranslatorClient:
68
+ """
69
+ Async client for Emergent Language Translator API.
70
+
71
+ Provides high-level interface for translating data to Eudaimonia's
72
+ emergent language format with automatic retries and error handling.
73
+
74
+ Example:
75
+ async with EmergentTranslatorClient() as client:
76
+ result = await client.translate_json({"task": "analyze data"})
77
+ print(f"Compression: {result.efficiency_gain:.1f}%")
78
+ """
79
+
80
+ def __init__(self, config: Optional[TranslationConfig] = None):
81
+ """Initialize client with configuration."""
82
+ self.config = config or TranslationConfig()
83
+ self._client: Optional[httpx.AsyncClient] = None
84
+ self._websocket: Optional[websockets.WebSocketServerProtocol] = None
85
+
86
+ async def __aenter__(self):
87
+ """Async context manager entry."""
88
+ await self._ensure_client()
89
+ return self
90
+
91
+ async def __aexit__(self, exc_type, exc_val, exc_tb):
92
+ """Async context manager exit."""
93
+ await self.close()
94
+
95
+ async def _ensure_client(self):
96
+ """Ensure HTTP client is initialized."""
97
+ if self._client is None:
98
+ headers = {}
99
+ if self.config.auth_token:
100
+ headers["Authorization"] = f"Bearer {self.config.auth_token}"
101
+
102
+ self._client = httpx.AsyncClient(
103
+ base_url=self.config.api_base_url,
104
+ headers=headers,
105
+ timeout=self.config.timeout
106
+ )
107
+
108
+ async def close(self):
109
+ """Close client connections."""
110
+ if self._client:
111
+ await self._client.aclose()
112
+ self._client = None
113
+
114
+ if self._websocket:
115
+ await self._websocket.close()
116
+ self._websocket = None
117
+
118
+ # Core translation methods
119
+
120
+ async def translate_json(
121
+ self,
122
+ data: Union[dict, str],
123
+ intent_type: str = "general",
124
+ epoch: int = 0,
125
+ enable_validation: bool = True
126
+ ) -> ClientTranslationResult:
127
+ """
128
+ Translate JSON data to emergent language symbols.
129
+
130
+ Args:
131
+ data: JSON data (dict or string)
132
+ intent_type: Intent type for better symbol selection
133
+ epoch: Emergent language epoch version
134
+ enable_validation: Enable symbol validation
135
+
136
+ Returns:
137
+ Translation result with compressed data and statistics
138
+ """
139
+ await self._ensure_client()
140
+
141
+ request_data = {
142
+ "data": data,
143
+ "source_format": "json",
144
+ "target_format": "emergent",
145
+ "intent_type": intent_type,
146
+ "epoch": epoch,
147
+ "enable_validation": enable_validation
148
+ }
149
+
150
+ return await self._make_translation_request(request_data)
151
+
152
+ async def translate_text(
153
+ self,
154
+ text: str,
155
+ intent_type: str = "general",
156
+ epoch: int = 0,
157
+ enable_validation: bool = True
158
+ ) -> ClientTranslationResult:
159
+ """
160
+ Translate natural language text to emergent symbols.
161
+
162
+ Args:
163
+ text: Natural language text
164
+ intent_type: Intent type (general, work, governance, social, resource)
165
+ epoch: Emergent language epoch version
166
+ enable_validation: Enable symbol validation
167
+
168
+ Returns:
169
+ Translation result with compressed data and statistics
170
+ """
171
+ await self._ensure_client()
172
+
173
+ request_data = {
174
+ "data": text,
175
+ "source_format": "text",
176
+ "target_format": "emergent",
177
+ "intent_type": intent_type,
178
+ "epoch": epoch,
179
+ "enable_validation": enable_validation
180
+ }
181
+
182
+ return await self._make_translation_request(request_data)
183
+
184
+ async def translate_from_emergent(
185
+ self,
186
+ symbol_data: bytes,
187
+ target_format: str = "json",
188
+ epoch: int = 0
189
+ ) -> ClientTranslationResult:
190
+ """
191
+ Translate emergent language symbols back to readable format.
192
+
193
+ Args:
194
+ symbol_data: Emergent language symbol bytes
195
+ target_format: Target format (json, text, etc.)
196
+ epoch: Emergent language epoch version
197
+
198
+ Returns:
199
+ Translation result with decompressed data
200
+ """
201
+ await self._ensure_client()
202
+
203
+ # Encode binary data as base64 for JSON transport
204
+ encoded_data = base64.b64encode(symbol_data).decode('utf-8')
205
+
206
+ request_data = {
207
+ "data": encoded_data,
208
+ "source_format": "binary",
209
+ "target_format": target_format,
210
+ "epoch": epoch
211
+ }
212
+
213
+ return await self._make_translation_request(request_data)
214
+
215
+ async def translate_batch(
216
+ self,
217
+ requests: List[Dict[str, Any]],
218
+ parallel: bool = True
219
+ ) -> List[ClientTranslationResult]:
220
+ """
221
+ Translate multiple data items in batch.
222
+
223
+ Args:
224
+ requests: List of translation request dictionaries
225
+ parallel: Process requests in parallel
226
+
227
+ Returns:
228
+ List of translation results
229
+ """
230
+ await self._ensure_client()
231
+
232
+ request_data = {
233
+ "requests": requests,
234
+ "parallel": parallel
235
+ }
236
+
237
+ try:
238
+ response = await self._client.post("/translate/batch", json=request_data)
239
+ response.raise_for_status()
240
+
241
+ result_data = response.json()
242
+
243
+ results = []
244
+ for result in result_data.get("results", []):
245
+ translated_data = None
246
+ if result.get("translated_data"):
247
+ try:
248
+ translated_data = base64.b64decode(result["translated_data"])
249
+ except:
250
+ translated_data = result["translated_data"].encode('utf-8')
251
+
252
+ results.append(ClientTranslationResult(
253
+ success=result.get("success", False),
254
+ translated_data=translated_data,
255
+ original_size=result.get("original_size", 0),
256
+ translated_size=result.get("translated_size", 0),
257
+ compression_ratio=result.get("compression_ratio", 0.0),
258
+ efficiency_gain=result.get("efficiency_gain", 0.0),
259
+ translation_time_ms=result.get("translation_time_ms", 0.0),
260
+ symbol_count=result.get("symbol_count", 0),
261
+ symbol_families=result.get("symbol_families", []),
262
+ metadata=result.get("metadata", {}),
263
+ errors=result.get("errors", [])
264
+ ))
265
+
266
+ return results
267
+
268
+ except httpx.HTTPError as e:
269
+ logger.error(f"Batch translation HTTP error: {e}")
270
+ return [ClientTranslationResult(success=False, errors=[str(e)])]
271
+ except Exception as e:
272
+ logger.error(f"Batch translation error: {e}")
273
+ return [ClientTranslationResult(success=False, errors=[str(e)])]
274
+
275
+ # WebSocket streaming interface
276
+
277
+ async def stream_translations(
278
+ self
279
+ ) -> AsyncGenerator[ClientTranslationResult, None]:
280
+ """
281
+ Open WebSocket connection for streaming translations.
282
+
283
+ Yields:
284
+ Translation results as they are processed
285
+ """
286
+ ws_url = self.config.api_base_url.replace("http://", "ws://").replace("https://", "wss://")
287
+ ws_url += "/ws/translate"
288
+
289
+ try:
290
+ async with websockets.connect(ws_url) as websocket:
291
+ self._websocket = websocket
292
+
293
+ while True:
294
+ try:
295
+ # Wait for incoming message
296
+ message = await websocket.recv()
297
+ result_data = json.loads(message)
298
+
299
+ # Convert to client result
300
+ translated_data = None
301
+ if result_data.get("translated_data"):
302
+ try:
303
+ translated_data = base64.b64decode(result_data["translated_data"])
304
+ except:
305
+ pass
306
+
307
+ result = ClientTranslationResult(
308
+ success=result_data.get("success", False),
309
+ translated_data=translated_data,
310
+ symbol_families=result_data.get("symbol_families", []),
311
+ errors=result_data.get("errors", [])
312
+ )
313
+
314
+ # Add stats if available
315
+ if "stats" in result_data:
316
+ stats = result_data["stats"]
317
+ result.original_size = stats.get("original_size", 0)
318
+ result.translated_size = stats.get("translated_size", 0)
319
+ result.compression_ratio = stats.get("compression_ratio", 0.0)
320
+ result.efficiency_gain = stats.get("efficiency_gain", 0.0)
321
+ result.symbol_count = stats.get("symbol_count", 0)
322
+
323
+ yield result
324
+
325
+ except websockets.exceptions.ConnectionClosed:
326
+ break
327
+ except json.JSONDecodeError as e:
328
+ yield ClientTranslationResult(success=False, errors=[f"JSON decode error: {e}"])
329
+ except Exception as e:
330
+ yield ClientTranslationResult(success=False, errors=[str(e)])
331
+
332
+ except Exception as e:
333
+ logger.error(f"WebSocket connection error: {e}")
334
+ yield ClientTranslationResult(success=False, errors=[str(e)])
335
+
336
+ async def send_streaming_request(self, request_data: Dict[str, Any]):
337
+ """
338
+ Send translation request via WebSocket.
339
+
340
+ Args:
341
+ request_data: Translation request data
342
+ """
343
+ if self._websocket:
344
+ await self._websocket.send(json.dumps(request_data))
345
+ else:
346
+ raise RuntimeError("WebSocket not connected. Use stream_translations() context manager.")
347
+
348
+ # Statistics and service info
349
+
350
+ async def get_compression_stats(self) -> Dict[str, Any]:
351
+ """Get compression and usage statistics from server."""
352
+ await self._ensure_client()
353
+
354
+ try:
355
+ response = await self._client.get("/stats")
356
+ response.raise_for_status()
357
+ return response.json()
358
+ except httpx.HTTPError as e:
359
+ logger.error(f"Stats request error: {e}")
360
+ return {"error": str(e)}
361
+
362
+ async def get_service_health(self) -> Dict[str, Any]:
363
+ """Get service health status."""
364
+ await self._ensure_client()
365
+
366
+ try:
367
+ response = await self._client.get("/health")
368
+ response.raise_for_status()
369
+ return response.json()
370
+ except httpx.HTTPError as e:
371
+ logger.error(f"Health check error: {e}")
372
+ return {"status": "unhealthy", "error": str(e)}
373
+
374
+ async def get_supported_formats(self) -> Dict[str, List[str]]:
375
+ """Get list of supported translation formats."""
376
+ await self._ensure_client()
377
+
378
+ try:
379
+ response = await self._client.get("/formats")
380
+ response.raise_for_status()
381
+ return response.json()
382
+ except httpx.HTTPError as e:
383
+ logger.error(f"Formats request error: {e}")
384
+ return {"error": str(e)}
385
+
386
+ async def get_symbol_families(self) -> Dict[str, Any]:
387
+ """Get information about emergent language symbol families."""
388
+ await self._ensure_client()
389
+
390
+ try:
391
+ response = await self._client.get("/symbols")
392
+ response.raise_for_status()
393
+ return response.json()
394
+ except httpx.HTTPError as e:
395
+ logger.error(f"Symbols request error: {e}")
396
+ return {"error": str(e)}
397
+
398
+ # Oracle-Enhanced Methods
399
+
400
+ async def explain_emergent_message(
401
+ self,
402
+ emergent_data: bytes,
403
+ mode: str = "verbose"
404
+ ) -> Dict[str, Any]:
405
+ """
406
+ Get human-readable explanation of emergent language symbols using Oracle.
407
+
408
+ Args:
409
+ emergent_data: Emergent language symbol bytes
410
+ mode: Explanation mode ("glyph", "verbose", "json")
411
+
412
+ Returns:
413
+ Oracle explanation with human-readable description
414
+ """
415
+ await self._ensure_client()
416
+
417
+ try:
418
+ # Encode as base64 for transport
419
+ encoded_data = base64.b64encode(emergent_data).decode('utf-8')
420
+
421
+ request_data = {
422
+ "emergent_data": encoded_data,
423
+ "mode": mode
424
+ }
425
+
426
+ response = await self._client.post("/oracle/explain", json=request_data)
427
+ response.raise_for_status()
428
+ return response.json()
429
+
430
+ except httpx.HTTPError as e:
431
+ logger.error(f"Oracle explanation error: {e}")
432
+ return {"success": False, "error": str(e)}
433
+
434
+ async def validate_translation(
435
+ self,
436
+ original_data: Union[dict, str],
437
+ emergent_data: bytes
438
+ ) -> Dict[str, Any]:
439
+ """
440
+ Validate translation accuracy using Oracle confidence scoring.
441
+
442
+ Args:
443
+ original_data: Original data that was translated
444
+ emergent_data: Resulting emergent language bytes
445
+
446
+ Returns:
447
+ Validation result with confidence score and Oracle explanation
448
+ """
449
+ await self._ensure_client()
450
+
451
+ try:
452
+ # Encode as base64 for transport
453
+ encoded_data = base64.b64encode(emergent_data).decode('utf-8')
454
+
455
+ request_data = {
456
+ "original_data": original_data,
457
+ "emergent_data": encoded_data
458
+ }
459
+
460
+ response = await self._client.post("/oracle/validate", json=request_data)
461
+ response.raise_for_status()
462
+ return response.json()
463
+
464
+ except httpx.HTTPError as e:
465
+ logger.error(f"Oracle validation error: {e}")
466
+ return {"success": False, "error": str(e)}
467
+
468
+ async def explain_symbol_families(
469
+ self,
470
+ emergent_data: bytes
471
+ ) -> Dict[str, Any]:
472
+ """
473
+ Get Oracle explanations for symbol families in emergent message.
474
+
475
+ Args:
476
+ emergent_data: Emergent language symbol bytes
477
+
478
+ Returns:
479
+ Dictionary with symbol family explanations and contexts
480
+ """
481
+ await self._ensure_client()
482
+
483
+ try:
484
+ # Encode as base64 for URL path
485
+ encoded_data = base64.b64encode(emergent_data).decode('utf-8')
486
+
487
+ response = await self._client.get(f"/oracle/symbols/{encoded_data}")
488
+ response.raise_for_status()
489
+ return response.json()
490
+
491
+ except httpx.HTTPError as e:
492
+ logger.error(f"Symbol family explanation error: {e}")
493
+ return {"success": False, "error": str(e)}
494
+
495
+ # Internal helper methods
496
+
497
+ async def _make_translation_request(self, request_data: Dict[str, Any]) -> ClientTranslationResult:
498
+ """Make translation request with retry logic."""
499
+ last_error = None
500
+
501
+ for attempt in range(self.config.max_retries):
502
+ try:
503
+ response = await self._client.post("/translate", json=request_data)
504
+ response.raise_for_status()
505
+
506
+ result_data = response.json()
507
+
508
+ # Decode translated data if present
509
+ translated_data = None
510
+ if result_data.get("translated_data"):
511
+ try:
512
+ translated_data = base64.b64decode(result_data["translated_data"])
513
+ except:
514
+ # Fallback to string encoding if base64 decode fails
515
+ translated_data = result_data["translated_data"].encode('utf-8')
516
+
517
+ return ClientTranslationResult(
518
+ success=result_data.get("success", False),
519
+ translated_data=translated_data,
520
+ original_size=result_data.get("original_size", 0),
521
+ translated_size=result_data.get("translated_size", 0),
522
+ compression_ratio=result_data.get("compression_ratio", 0.0),
523
+ efficiency_gain=result_data.get("efficiency_gain", 0.0),
524
+ translation_time_ms=result_data.get("translation_time_ms", 0.0),
525
+ symbol_count=result_data.get("symbol_count", 0),
526
+ symbol_families=result_data.get("symbol_families", []),
527
+ metadata=result_data.get("metadata", {}),
528
+ errors=result_data.get("errors", [])
529
+ )
530
+
531
+ except httpx.HTTPError as e:
532
+ last_error = e
533
+ if attempt < self.config.max_retries - 1:
534
+ await asyncio.sleep(self.config.retry_delay)
535
+ continue
536
+ else:
537
+ logger.error(f"Translation request failed after {self.config.max_retries} attempts: {e}")
538
+ break
539
+
540
+ except Exception as e:
541
+ last_error = e
542
+ logger.error(f"Unexpected translation error: {e}")
543
+ break
544
+
545
+ return ClientTranslationResult(
546
+ success=False,
547
+ errors=[str(last_error)] if last_error else ["Unknown error"]
548
+ )
549
+
550
+
551
+ class SyncEmergentTranslatorClient:
552
+ """
553
+ Synchronous client for Emergent Language Translator API.
554
+
555
+ Wrapper around async client for synchronous usage.
556
+ """
557
+
558
+ def __init__(self, config: Optional[TranslationConfig] = None):
559
+ """Initialize sync client."""
560
+ self.config = config or TranslationConfig()
561
+ self._async_client = EmergentTranslatorClient(config)
562
+
563
+ def __enter__(self):
564
+ """Sync context manager entry."""
565
+ return self
566
+
567
+ def __exit__(self, exc_type, exc_val, exc_tb):
568
+ """Sync context manager exit."""
569
+ asyncio.run(self._async_client.close())
570
+
571
+ def translate_json(self, data: Union[dict, str], **kwargs) -> ClientTranslationResult:
572
+ """Sync version of translate_json."""
573
+ return asyncio.run(self._async_client.translate_json(data, **kwargs))
574
+
575
+ def translate_text(self, text: str, **kwargs) -> ClientTranslationResult:
576
+ """Sync version of translate_text."""
577
+ return asyncio.run(self._async_client.translate_text(text, **kwargs))
578
+
579
+ def translate_from_emergent(self, symbol_data: bytes, **kwargs) -> ClientTranslationResult:
580
+ """Sync version of translate_from_emergent."""
581
+ return asyncio.run(self._async_client.translate_from_emergent(symbol_data, **kwargs))
582
+
583
+ def translate_batch(self, requests: List[Dict[str, Any]], **kwargs) -> List[ClientTranslationResult]:
584
+ """Sync version of translate_batch."""
585
+ return asyncio.run(self._async_client.translate_batch(requests, **kwargs))
586
+
587
+ def get_compression_stats(self) -> Dict[str, Any]:
588
+ """Sync version of get_compression_stats."""
589
+ return asyncio.run(self._async_client.get_compression_stats())
590
+
591
+ def get_service_health(self) -> Dict[str, Any]:
592
+ """Sync version of get_service_health."""
593
+ return asyncio.run(self._async_client.get_service_health())
594
+
595
+ # Oracle-Enhanced Sync Methods
596
+
597
+ def explain_emergent_message(self, emergent_data: bytes, mode: str = "verbose") -> Dict[str, Any]:
598
+ """Sync version of explain_emergent_message."""
599
+ return asyncio.run(self._async_client.explain_emergent_message(emergent_data, mode))
600
+
601
+ def validate_translation(self, original_data: Union[dict, str], emergent_data: bytes) -> Dict[str, Any]:
602
+ """Sync version of validate_translation."""
603
+ return asyncio.run(self._async_client.validate_translation(original_data, emergent_data))
604
+
605
+ def explain_symbol_families(self, emergent_data: bytes) -> Dict[str, Any]:
606
+ """Sync version of explain_symbol_families."""
607
+ return asyncio.run(self._async_client.explain_symbol_families(emergent_data))
608
+
609
+
610
+ # High-level SDK class
611
+
612
+ class TranslatorSDK:
613
+ """
614
+ High-level SDK for Emergent Language Translation.
615
+
616
+ Provides the simplest possible interface for external AIs to integrate
617
+ with Eudaimonia's emergent language system.
618
+
619
+ Example:
620
+ sdk = TranslatorSDK(api_url="https://translator.eudaimonia.ai")
621
+
622
+ # Compress JSON data
623
+ compressed = sdk.compress({"task": "analyze market"})
624
+ print(f"60x smaller: {len(compressed)} bytes")
625
+
626
+ # Decompress back to JSON
627
+ original = sdk.decompress(compressed, format="json")
628
+ """
629
+
630
+ def __init__(self, api_url: str = "http://localhost:8000", auth_token: Optional[str] = None, api_key: Optional[str] = None):
631
+ """
632
+ Initialize SDK with API configuration.
633
+
634
+ Args:
635
+ api_url: Base URL of the translator API
636
+ auth_token: Optional authentication token
637
+ api_key: Alias for auth_token (for CLI compatibility)
638
+ """
639
+ token = auth_token or api_key
640
+ self.api_url = api_url
641
+ config = TranslationConfig(api_base_url=api_url, auth_token=token)
642
+ self.client = SyncEmergentTranslatorClient(config)
643
+
644
+ def compress(
645
+ self,
646
+ data: Union[dict, str],
647
+ intent: str = "general"
648
+ ) -> bytes:
649
+ """
650
+ Compress data to emergent language symbols.
651
+
652
+ Args:
653
+ data: JSON data or text string to compress
654
+ intent: Intent type for better compression
655
+
656
+ Returns:
657
+ Compressed emergent language bytes (typically 60x smaller)
658
+ """
659
+ if isinstance(data, dict):
660
+ result = self.client.translate_json(data, intent_type=intent)
661
+ elif isinstance(data, str):
662
+ result = self.client.translate_text(data, intent_type=intent)
663
+ else:
664
+ raise ValueError("Data must be dict or str")
665
+
666
+ if not result.success:
667
+ raise RuntimeError(f"Compression failed: {', '.join(result.errors)}")
668
+
669
+ return result.translated_data
670
+
671
+ def decompress(self, compressed_data: bytes, format: str = "json") -> Union[dict, str]:
672
+ """
673
+ Decompress emergent language symbols back to readable format.
674
+
675
+ Args:
676
+ compressed_data: Emergent language symbol bytes
677
+ format: Target format (json, text)
678
+
679
+ Returns:
680
+ Decompressed data
681
+ """
682
+ result = self.client.translate_from_emergent(compressed_data, target_format=format)
683
+
684
+ if not result.success:
685
+ raise RuntimeError(f"Decompression failed: {', '.join(result.errors)}")
686
+
687
+ if format == "json":
688
+ try:
689
+ return json.loads(result.translated_data.decode('utf-8'))
690
+ except:
691
+ return {"data": result.translated_data.decode('utf-8', errors='ignore')}
692
+ else:
693
+ return result.translated_data.decode('utf-8', errors='ignore')
694
+
695
+ def get_compression_ratio(self, data: Union[dict, str]) -> float:
696
+ """
697
+ Get compression ratio without actually compressing (estimate).
698
+
699
+ Args:
700
+ data: Data to analyze
701
+
702
+ Returns:
703
+ Estimated compression ratio (e.g., 0.016 for 60x compression)
704
+ """
705
+ if isinstance(data, dict):
706
+ original_size = len(json.dumps(data))
707
+ else:
708
+ original_size = len(data.encode('utf-8'))
709
+
710
+ # Typical emergent language message is 8-16 bytes
711
+ estimated_compressed_size = 12
712
+
713
+ return estimated_compressed_size / original_size
714
+
715
+ def get_stats(self) -> Dict[str, Any]:
716
+ """Get compression statistics from the service."""
717
+ return self.client.get_compression_stats()
718
+
719
+ def get_health(self) -> Dict[str, Any]:
720
+ """Get full health status from the service."""
721
+ return self.client.get_service_health()
722
+
723
+ def is_healthy(self) -> bool:
724
+ """Check if the translator service is healthy."""
725
+ health = self.get_health()
726
+ return health.get("status") == "healthy"
727
+
728
+ # Oracle-Powered Methods
729
+
730
+ def explain(self, compressed_data: bytes, mode: str = "verbose") -> str:
731
+ """
732
+ Get human explanation of compressed emergent data.
733
+
734
+ Args:
735
+ compressed_data: Emergent language bytes
736
+ mode: Explanation mode ("glyph", "verbose", "json")
737
+
738
+ Returns:
739
+ Human-readable explanation of what the symbols mean
740
+ """
741
+ result = self.client.explain_emergent_message(compressed_data, mode)
742
+ if result.get("success"):
743
+ return result.get("explanation", "No explanation available")
744
+ else:
745
+ raise RuntimeError(f"Oracle explanation failed: {result.get('error', 'Unknown error')}")
746
+
747
+ def validate(self, original_data: Union[dict, str], compressed_data: bytes) -> float:
748
+ """
749
+ Validate that compressed data preserves the meaning of original data.
750
+
751
+ Args:
752
+ original_data: Original data before compression
753
+ compressed_data: Compressed emergent language bytes
754
+
755
+ Returns:
756
+ Confidence score (0.0-1.0) indicating translation accuracy
757
+ """
758
+ result = self.client.validate_translation(original_data, compressed_data)
759
+ if result.get("success") and result.get("validation_available"):
760
+ return result.get("confidence_score", 0.0)
761
+ else:
762
+ raise RuntimeError(f"Oracle validation failed: {result.get('error', 'Unknown error')}")
763
+
764
+ def get_symbol_info(self, compressed_data: bytes) -> Dict[str, str]:
765
+ """
766
+ Get detailed information about symbol families in compressed data.
767
+
768
+ Args:
769
+ compressed_data: Emergent language bytes
770
+
771
+ Returns:
772
+ Dictionary mapping symbol families to their explanations
773
+ """
774
+ result = self.client.explain_symbol_families(compressed_data)
775
+ if result.get("success"):
776
+ return result.get("symbol_families", {})
777
+ else:
778
+ raise RuntimeError(f"Symbol explanation failed: {result.get('error', 'Unknown error')}")
779
+
780
+ def compress_with_explanation(
781
+ self,
782
+ data: Union[dict, str],
783
+ intent: str = "general"
784
+ ) -> Tuple[bytes, str]:
785
+ """
786
+ Compress data and get Oracle explanation in one call.
787
+
788
+ Args:
789
+ data: Data to compress
790
+ intent: Intent type for optimization
791
+
792
+ Returns:
793
+ Tuple of (compressed_bytes, human_explanation)
794
+ """
795
+ # Compress the data
796
+ compressed = self.compress(data, intent)
797
+
798
+ # Get Oracle explanation
799
+ explanation = self.explain(compressed)
800
+
801
+ return compressed, explanation
802
+
803
+
804
+ # Convenience functions for quick usage
805
+
806
+ def compress_json(data: dict, api_url: str = "http://localhost:8000") -> bytes:
807
+ """
808
+ Quick function to compress JSON data.
809
+
810
+ Args:
811
+ data: JSON data to compress
812
+ api_url: Translator API URL
813
+
814
+ Returns:
815
+ Compressed emergent language bytes
816
+ """
817
+ sdk = TranslatorSDK(api_url)
818
+ return sdk.compress(data)
819
+
820
+
821
+ def decompress_to_json(compressed_data: bytes, api_url: str = "http://localhost:8000") -> dict:
822
+ """
823
+ Quick function to decompress to JSON.
824
+
825
+ Args:
826
+ compressed_data: Emergent language bytes
827
+ api_url: Translator API URL
828
+
829
+ Returns:
830
+ Decompressed JSON data
831
+ """
832
+ sdk = TranslatorSDK(api_url)
833
+ return sdk.decompress(compressed_data, format="json")
834
+
835
+
836
+ # Oracle-Enhanced Convenience Functions
837
+
838
+ def explain_emergent(compressed_data: bytes, api_url: str = "http://localhost:8000") -> str:
839
+ """
840
+ Quick function to get Oracle explanation of emergent data.
841
+
842
+ Args:
843
+ compressed_data: Emergent language bytes
844
+ api_url: Translator API URL
845
+
846
+ Returns:
847
+ Human-readable explanation
848
+ """
849
+ sdk = TranslatorSDK(api_url)
850
+ return sdk.explain(compressed_data)
851
+
852
+
853
+ def validate_compression(
854
+ original_data: Union[dict, str],
855
+ compressed_data: bytes,
856
+ api_url: str = "http://localhost:8000"
857
+ ) -> float:
858
+ """
859
+ Quick function to validate compression accuracy.
860
+
861
+ Args:
862
+ original_data: Original data
863
+ compressed_data: Compressed bytes
864
+ api_url: Translator API URL
865
+
866
+ Returns:
867
+ Confidence score (0.0-1.0)
868
+ """
869
+ sdk = TranslatorSDK(api_url)
870
+ return sdk.validate(original_data, compressed_data)
871
+
872
+
873
+ def compress_with_oracle(
874
+ data: Union[dict, str],
875
+ api_url: str = "http://localhost:8000"
876
+ ) -> Tuple[bytes, str]:
877
+ """
878
+ Quick function to compress data and get Oracle explanation.
879
+
880
+ Args:
881
+ data: Data to compress
882
+ api_url: Translator API URL
883
+
884
+ Returns:
885
+ Tuple of (compressed_bytes, explanation)
886
+ """
887
+ sdk = TranslatorSDK(api_url)
888
+ return sdk.compress_with_explanation(data)
889
+
890
+
891
+ # Export main classes
892
+ __all__ = [
893
+ 'EmergentTranslatorClient',
894
+ 'SyncEmergentTranslatorClient',
895
+ 'TranslatorSDK',
896
+ 'TranslationConfig',
897
+ 'ClientTranslationResult',
898
+ 'compress_json',
899
+ 'decompress_to_json',
900
+ 'explain_emergent',
901
+ 'validate_compression',
902
+ 'compress_with_oracle'
903
+ ]