fable-engine 1.3.1__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.
Files changed (104) hide show
  1. fable_compressor.py +356 -0
  2. fable_engine/__init__.py +1 -0
  3. fable_engine/actions/__init__.py +291 -0
  4. fable_engine/actions/cas.py +182 -0
  5. fable_engine/actions/deliberation.py +523 -0
  6. fable_engine/actions/fleet.py +807 -0
  7. fable_engine/actions/lifecycle.py +298 -0
  8. fable_engine/actions/scrapers.py +116 -0
  9. fable_engine/actions/system3.py +815 -0
  10. fable_engine/browser.py +824 -0
  11. fable_engine/cas.py +974 -0
  12. fable_engine/fable_session.json +510 -0
  13. fable_engine/guards.py +283 -0
  14. fable_engine/schema.py +714 -0
  15. fable_engine/scrapers/__init__.py +32 -0
  16. fable_engine/scrapers/arxiv.py +115 -0
  17. fable_engine/scrapers/base.py +386 -0
  18. fable_engine/scrapers/github.py +129 -0
  19. fable_engine/scrapers/reddit.py +154 -0
  20. fable_engine/scrapers/web.py +120 -0
  21. fable_engine/scrapers/x.py +125 -0
  22. fable_engine/scrapers/youtube.py +132 -0
  23. fable_engine/server.py +414 -0
  24. fable_engine/session.py +1819 -0
  25. fable_engine/test_server.py +1362 -0
  26. fable_engine/updater.py +541 -0
  27. fable_engine-1.3.1.dist-info/LICENSE +22 -0
  28. fable_engine-1.3.1.dist-info/METADATA +173 -0
  29. fable_engine-1.3.1.dist-info/RECORD +104 -0
  30. fable_engine-1.3.1.dist-info/WHEEL +5 -0
  31. fable_engine-1.3.1.dist-info/entry_points.txt +5 -0
  32. fable_engine-1.3.1.dist-info/top_level.txt +6 -0
  33. fable_mode/__init__.py +3 -0
  34. fable_mode/__main__.py +4 -0
  35. fable_mode/adapters.py +1014 -0
  36. fable_mode/installer.py +553 -0
  37. fable_mode/launcher.py +437 -0
  38. fable_mode/manifest.py +142 -0
  39. fable_mode/resources.json +114 -0
  40. fable_mode/safety.py +103 -0
  41. fable_mode_entry.py +10 -0
  42. fable_v2/__init__.py +146 -0
  43. fable_v2/adapters.py +151 -0
  44. fable_v2/coder_fleet/__init__.py +100 -0
  45. fable_v2/coder_fleet/ast_tools.py +158 -0
  46. fable_v2/coder_fleet/compute.py +199 -0
  47. fable_v2/coder_fleet/design_engine.py +1316 -0
  48. fable_v2/coder_fleet/diagnostics.py +293 -0
  49. fable_v2/coder_fleet/fleet_dispatcher.py +214 -0
  50. fable_v2/coder_fleet/mock_auditor.py +306 -0
  51. fable_v2/coder_fleet/mutation.py +216 -0
  52. fable_v2/coder_fleet/property_oracle.py +260 -0
  53. fable_v2/coder_fleet/receipt_attestor.py +122 -0
  54. fable_v2/coder_fleet/red_team_swarm.py +908 -0
  55. fable_v2/coder_fleet/test_harness.py +198 -0
  56. fable_v2/coder_fleet/vector_engine.py +1287 -0
  57. fable_v2/coder_fleet/visual.py +357 -0
  58. fable_v2/coder_fleet/workspace.py +153 -0
  59. fable_v2/cortical/__init__.py +20 -0
  60. fable_v2/cortical/plasticity_engine.py +992 -0
  61. fable_v2/execution_broker.py +811 -0
  62. fable_v2/proof_engine.py +1141 -0
  63. fable_v2/protocol.py +485 -0
  64. fable_v2/runtime.py +1010 -0
  65. fable_v2/system3/__init__.py +204 -0
  66. fable_v2/system3/causal.py +558 -0
  67. fable_v2/system3/dialectical.py +577 -0
  68. fable_v2/system3/evolution.py +503 -0
  69. fable_v2/system3/executive.py +338 -0
  70. fable_v2/system3/free_energy.py +479 -0
  71. fable_v2/system3/hyperbolic.py +555 -0
  72. fable_v2/system3/induction.py +336 -0
  73. fable_v2/system3/kripke.py +548 -0
  74. fable_v2/system3/oracle.py +745 -0
  75. fable_v2/verifiers.py +72 -0
  76. tests/__init__.py +1 -0
  77. tests/test_anti_loop_circuit_breaker.py +64 -0
  78. tests/test_auto_updater.py +407 -0
  79. tests/test_coder_fleet.py +535 -0
  80. tests/test_delegation_compiler.py +54 -0
  81. tests/test_descriptor_boundaries.py +126 -0
  82. tests/test_design_engine.py +603 -0
  83. tests/test_epistemic_evidence_validator.py +66 -0
  84. tests/test_execution_broker.py +233 -0
  85. tests/test_fable_v2.py +406 -0
  86. tests/test_fleet_transitions.py +116 -0
  87. tests/test_fsm_redteam_evolution.py +406 -0
  88. tests/test_goal_rubric_and_pipeline.py +367 -0
  89. tests/test_hebbian_plasticity.py +585 -0
  90. tests/test_packaging_runtime.py +194 -0
  91. tests/test_proof_engine.py +259 -0
  92. tests/test_red_team_swarm.py +645 -0
  93. tests/test_redteam_remediation.py +169 -0
  94. tests/test_registration_transaction.py +375 -0
  95. tests/test_requested_regressions.py +467 -0
  96. tests/test_scrapers.py +370 -0
  97. tests/test_server_actions.py +93 -0
  98. tests/test_server_frontier_actions.py +269 -0
  99. tests/test_server_protocol.py +88 -0
  100. tests/test_stealth_browser.py +970 -0
  101. tests/test_system3.py +381 -0
  102. tests/test_system3_deep_integration.py +385 -0
  103. tests/test_system3_frontier.py +436 -0
  104. tests/test_vector_engine.py +608 -0
@@ -0,0 +1,182 @@
1
+ """CAS storage, payload compression, slice viewing, and accumulation action handlers."""
2
+ from __future__ import annotations
3
+
4
+ import json
5
+ import logging
6
+ import os
7
+ import sys
8
+ import time
9
+ from pathlib import Path
10
+ from typing import Any, Dict, List, Optional, Tuple, Union
11
+
12
+ logger = logging.getLogger("fable-engine.actions.cas")
13
+
14
+ from fable_engine.cas import (
15
+ CAS_ENGINE,
16
+ AdaptiveChunkAccumulator,
17
+ CompositeFrame,
18
+ CASSliceViewer,
19
+ DATA_DIR,
20
+ MAX_CAS_OBJECT_BYTES,
21
+ MAX_SLICE_RESPONSE_BYTES,
22
+ MAX_RPC_RESPONSE_BYTES,
23
+ )
24
+ from fable_engine.session import FableSession
25
+
26
+ def _handle_compress_payload(arguments: Dict[str, Any]) -> str:
27
+ action = arguments.get("action", "").strip().lower()
28
+ session_name = arguments.get("session_name", "").strip()
29
+ session: Optional[FableSession] = None
30
+ content = arguments.get("content")
31
+ if content is None:
32
+ content = arguments.get("payload")
33
+ if content is None:
34
+ return "Error: 'content' (or 'payload') is required for action 'compress_payload'."
35
+ label = arguments.get("label", "payload")
36
+ content_text = str(content)
37
+ if len(content_text.encode("utf-8")) > MAX_CAS_OBJECT_BYTES:
38
+ return "Error: payload exceeds maximum CAS object size."
39
+
40
+ compressed_node = CAS_ENGINE.compress_payload_to_cas(content_text, label=label)
41
+ raw_len = len(content_text)
42
+ raw_tokens = CAS_ENGINE.estimate_token_count(content_text)
43
+ comp_repr = json.dumps(compressed_node, separators=(",", ":"))
44
+ comp_tokens = CAS_ENGINE.estimate_token_count(comp_repr)
45
+ ratio = CAS_ENGINE.calculate_token_ratio(content_text, comp_repr)
46
+
47
+ invariant_met = ratio <= 0.003 if raw_len >= 10000 else True
48
+ badge = "✅ PASS (<= 0.003 tokens/char)" if invariant_met else f"âš ī¸ Ratio: {ratio:.6f} tokens/char"
49
+
50
+ return (
51
+ f"### đŸ—œī¸ Fable CAS Payload Compressed\n\n"
52
+ f"- **CAS URI**: `{compressed_node['cas_ref']}`\n"
53
+ f"- **Line Count**: `{compressed_node['lines']}`\n"
54
+ f"- **Raw Size**: `{raw_len}` characters (~`{raw_tokens}` tokens)\n"
55
+ f"- **Compressed Reference Size**: `{len(comp_repr)}` characters (~`{comp_tokens}` tokens)\n"
56
+ f"- **Token Compression Ratio**: `{ratio:.6f}` tokens/char\n"
57
+ f"- **Invariant Status**: {badge}\n"
58
+ f"- **JSON Descriptor**:\n```json\n{json.dumps(compressed_node, indent=2)}\n```\n\n"
59
+ f"> [!TIP]\n"
60
+ f"> Use action `view_slice` with `cas_ref` to inspect specific line windows without loading full payload."
61
+ )
62
+
63
+
64
+ def _handle_decompress_payload(arguments: Dict[str, Any]) -> str:
65
+ action = arguments.get("action", "").strip().lower()
66
+ session_name = arguments.get("session_name", "").strip()
67
+ session: Optional[FableSession] = None
68
+ cas_ref = arguments.get("cas_ref") or arguments.get("ref_or_hash")
69
+ if not cas_ref:
70
+ return "Error: 'cas_ref' is required for action 'decompress_payload'."
71
+ try:
72
+ text = CAS_ENGINE.cas_store.get_text(cas_ref, verify=True)
73
+ if len(text.encode("utf-8")) > MAX_RPC_RESPONSE_BYTES // 2:
74
+ return "Error: decompressed response exceeds maximum size; use view_slice."
75
+ lines = CAS_ENGINE.slice_viewer.get_line_count(cas_ref)
76
+ return (
77
+ f"### đŸ“Ļ Fable CAS Payload Retrieved\n\n"
78
+ f"- **CAS URI**: `{cas_ref}`\n"
79
+ f"- **Total Length**: `{len(text)}` characters\n"
80
+ f"- **Total Lines**: `{lines}`\n\n"
81
+ f"```text\n{text}\n```"
82
+ )
83
+ except Exception as e:
84
+ return f"Error decompressing CAS payload: {e}"
85
+
86
+
87
+ def _handle_view_slice(arguments: Dict[str, Any]) -> str:
88
+ action = arguments.get("action", "").strip().lower()
89
+ session_name = arguments.get("session_name", "").strip()
90
+ session: Optional[FableSession] = None
91
+ cas_ref = arguments.get("cas_ref") or arguments.get("ref_or_hash")
92
+ if not cas_ref:
93
+ return "Error: 'cas_ref' is required for action 'view_slice'."
94
+ start_line = int(arguments.get("start_line", 1))
95
+ end_line = int(arguments.get("end_line", 100))
96
+ include_line_numbers = bool(arguments.get("include_line_numbers", False))
97
+
98
+ try:
99
+ slice_text = CAS_ENGINE.slice_viewer.view_slice(
100
+ cas_ref, start_line, end_line, include_line_numbers=include_line_numbers
101
+ )
102
+ total_lines = CAS_ENGINE.slice_viewer.get_line_count(cas_ref)
103
+ return (
104
+ f"### 🔍 Fable CAS Slice View (`{start_line}` - `{end_line}` of `{total_lines}` lines)\n\n"
105
+ f"- **CAS URI**: `{cas_ref}`\n"
106
+ f"- **Range**: Lines {start_line}..{end_line}\n\n"
107
+ f"```text\n{slice_text}\n```"
108
+ )
109
+ except Exception as e:
110
+ return f"Error reading CAS slice: {e}"
111
+
112
+
113
+ def _handle_accumulate_payload(arguments: Dict[str, Any]) -> str:
114
+ action = arguments.get("action", "").strip().lower()
115
+ session_name = arguments.get("session_name", "").strip()
116
+ session: Optional[FableSession] = None
117
+ payload = arguments.get("payload")
118
+ if payload is None:
119
+ payload = arguments.get("content")
120
+ if payload is None:
121
+ return "Error: 'payload' is required for action 'accumulate_payload'."
122
+ metadata = arguments.get("metadata")
123
+ if isinstance(metadata, str):
124
+ try:
125
+ metadata = json.loads(metadata)
126
+ except Exception:
127
+ metadata = {"raw": metadata}
128
+ force_flush = bool(arguments.get("force_flush", False))
129
+
130
+ flushed = CAS_ENGINE.accumulator.add(str(payload), metadata=metadata, force_flush=force_flush)
131
+ stats = CAS_ENGINE.accumulator.get_stats()
132
+
133
+ flushed_str = "\n".join([f"- Flushed Composite Frame: `{u}`" for u in flushed]) if flushed else "- No frame flushed yet (buffering micro-payload)."
134
+ return (
135
+ f"### đŸ“Ĩ Micro-Payload Ingested\n\n"
136
+ f"- **Buffered Items**: `{stats['currently_buffered_items']}`\n"
137
+ f"- **Buffered Chars**: `{stats['currently_buffered_chars']}` / `{CAS_ENGINE.accumulator.min_frame_size}` bytes threshold\n"
138
+ f"- **Total Ingested**: `{stats['total_payloads_ingested']}`\n"
139
+ f"- **Total Frames Flushed**: `{stats['total_frames_flushed']}`\n\n"
140
+ f"{flushed_str}"
141
+ )
142
+
143
+
144
+ def _handle_flush_accumulator(arguments: Dict[str, Any]) -> str:
145
+ action = arguments.get("action", "").strip().lower()
146
+ session_name = arguments.get("session_name", "").strip()
147
+ session: Optional[FableSession] = None
148
+ flushed = CAS_ENGINE.accumulator.flush()
149
+ stats = CAS_ENGINE.accumulator.get_stats()
150
+ if flushed:
151
+ flushed_str = "\n".join([f"- Flushed Frame: `{u}`" for u in flushed])
152
+ return (
153
+ f"### 🚀 Micro-Payload Accumulator Flushed\n\n"
154
+ f"- **Flushed Frames**: `{len(flushed)}`\n"
155
+ f"- **Total CAS Bytes Written**: `{stats['total_cas_bytes_written']}`\n\n"
156
+ f"{flushed_str}"
157
+ )
158
+ return (
159
+ f"### â„šī¸ Micro-Payload Accumulator Buffer Empty\n\n"
160
+ f"- **Currently Buffered**: `0` items\n"
161
+ f"- **Total Frames Flushed**: `{stats['total_frames_flushed']}`"
162
+ )
163
+
164
+
165
+ def _handle_get_compression_stats(arguments: Dict[str, Any]) -> str:
166
+ action = arguments.get("action", "").strip().lower()
167
+ session_name = arguments.get("session_name", "").strip()
168
+ session: Optional[FableSession] = None
169
+ stats = CAS_ENGINE.accumulator.get_stats()
170
+ return (
171
+ f"### 📊 Fable Token Compression Subsystem Telemetry\n\n"
172
+ f"- **CAS Storage Root**: `{CAS_ENGINE.cas_store.root_dir}`\n"
173
+ f"- **Memory Cache Capacity**: `{CAS_ENGINE.cas_store.cache.capacity}` entries (Current: `{len(CAS_ENGINE.cas_store.cache)}`)\n"
174
+ f"- **Micro-Payloads Ingested**: `{stats['total_payloads_ingested']}`\n"
175
+ f"- **Composite Frames Flushed**: `{stats['total_frames_flushed']}`\n"
176
+ f"- **Total Raw Characters**: `{stats['total_raw_chars']}`\n"
177
+ f"- **Total CAS Bytes Written**: `{stats['total_cas_bytes_written']}`\n"
178
+ f"- **Currently Buffered Items**: `{stats['currently_buffered_items']}` (`{stats['currently_buffered_chars']}` chars)\n"
179
+ f"- **Token Compression Invariant**: `<= 0.003 tokens/character`"
180
+ )
181
+
182
+