tzero-mcp 10.7.0 → 10.7.2

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 (101) hide show
  1. package/CHANGELOG.md +589 -0
  2. package/CONTRIBUTING.md +71 -0
  3. package/README.md +25 -17
  4. package/bin/postinstall.js +34 -0
  5. package/bin/tzero-mcp.js +16 -19
  6. package/bin/tzero.js +14 -19
  7. package/index.d.ts +24 -0
  8. package/index.js +7 -3
  9. package/package.json +24 -2
  10. package/src/addmcp.py +1194 -0
  11. package/src/main.py +60 -0
  12. package/src/siber_akademi_icon.py +77 -0
  13. package/src/tzero/jarvis/semantic_compressor.py +373 -0
  14. package/src/tzero.py +58 -0
  15. package/src/tzero_benchmark.py +475 -0
  16. package/src/tzero_bridge.py +362 -0
  17. package/src/tzero_ci.py +153 -0
  18. package/src/tzero_commit.py +192 -0
  19. package/src/tzero_cost.py +163 -0
  20. package/src/tzero_dashboard.py +1448 -0
  21. package/src/tzero_deps.py +287 -0
  22. package/src/tzero_drift.py +208 -0
  23. package/src/tzero_explain.py +240 -0
  24. package/src/tzero_features.py +3022 -0
  25. package/src/tzero_fix.py +228 -0
  26. package/src/tzero_fixer/__init__.py +63 -0
  27. package/src/tzero_fixer/amalgamation.py +334 -0
  28. package/src/tzero_fixer/ast_syntax_healer.py +464 -0
  29. package/src/tzero_fixer/ast_type_modernizer.py +288 -0
  30. package/src/tzero_fixer/async_io_modernizer.py +127 -0
  31. package/src/tzero_fixer/automated_regression_suite.py +600 -0
  32. package/src/tzero_fixer/benchmarks_and_diagnostics.py +174 -0
  33. package/src/tzero_fixer/ci_cd_self_healing_gate.py +246 -0
  34. package/src/tzero_fixer/code_duplicity_and_refactorer.py +151 -0
  35. package/src/tzero_fixer/code_smells_healer.py +260 -0
  36. package/src/tzero_fixer/cwe_remediator.py +171 -0
  37. package/src/tzero_fixer/dead_code_eliminator.py +150 -0
  38. package/src/tzero_fixer/dependency_vulnerability_auditor.py +309 -0
  39. package/src/tzero_fixer/git_advanced_surgeon.py +280 -0
  40. package/src/tzero_fixer/hardware_and_disk_doctor.py +325 -0
  41. package/src/tzero_fixer/import_graph_healer.py +412 -0
  42. package/src/tzero_fixer/interactive_tui.py +91 -0
  43. package/src/tzero_fixer/knowledge_base.py +295 -0
  44. package/src/tzero_fixer/knowledge_base_extended.py +940 -0
  45. package/src/tzero_fixer/linters_and_static_analyzer.py +307 -0
  46. package/src/tzero_fixer/mcp_server.py +447 -0
  47. package/src/tzero_fixer/models.py +385 -0
  48. package/src/tzero_fixer/orchestrator.py +375 -0
  49. package/src/tzero_fixer/os_doctor.py +502 -0
  50. package/src/tzero_fixer/packaging_abi_surgeon.py +323 -0
  51. package/src/tzero_fixer/pc_fixer_doctor.py +599 -0
  52. package/src/tzero_fixer/performance_and_memory_profiler.py +274 -0
  53. package/src/tzero_fixer/polyglot_ast_parsers.py +313 -0
  54. package/src/tzero_fixer/polyglot_build_healer.py +364 -0
  55. package/src/tzero_fixer/polyglot_config_healer.py +318 -0
  56. package/src/tzero_fixer/polyglot_doctor.py +372 -0
  57. package/src/tzero_fixer/polyglot_linters.py +619 -0
  58. package/src/tzero_fixer/polyglot_schema_validator.py +305 -0
  59. package/src/tzero_fixer/security_cwe_database.py +444 -0
  60. package/src/tzero_fixer/security_deep_rules.py +114 -0
  61. package/src/tzero_fixer/security_rules_catalog.py +110 -0
  62. package/src/tzero_fixer/security_zero_leak.py +326 -0
  63. package/src/tzero_fixer/smart_patch_recommender.py +223 -0
  64. package/src/tzero_fixer/synthetic_workspace_generator.py +220 -0
  65. package/src/tzero_fixer/system_diagnostics_extended.py +493 -0
  66. package/src/tzero_fixer/system_repair_recipes.py +447 -0
  67. package/src/tzero_fixer/venv_doctor.py +309 -0
  68. package/src/tzero_gateway.py +885 -0
  69. package/src/tzero_guard.py +243 -0
  70. package/src/tzero_infra.py +274 -0
  71. package/src/tzero_jarvis/__init__.py +124 -0
  72. package/src/tzero_jarvis/causal_graph.py +310 -0
  73. package/src/tzero_jarvis/graph_visualizer.py +395 -0
  74. package/src/tzero_jarvis/hybrid_search.py +214 -0
  75. package/src/tzero_jarvis/latent_press.py +137 -0
  76. package/src/tzero_jarvis/memory_consolidation.py +212 -0
  77. package/src/tzero_jarvis/minhash_lsh.py +184 -0
  78. package/src/tzero_jarvis/orchestrator.py +335 -0
  79. package/src/tzero_jarvis/self_healing.py +308 -0
  80. package/src/tzero_jarvis/semantic_compressor.py +887 -0
  81. package/src/tzero_jarvis/swarm.py +261 -0
  82. package/src/tzero_jarvis/swarm_bft.py +144 -0
  83. package/src/tzero_jarvis/workspace_orchestrator.py +1167 -0
  84. package/src/tzero_jarvis/zero_key_router.py +173 -0
  85. package/src/tzero_mcp.py +4858 -0
  86. package/src/tzero_neural_cortex.py +1425 -0
  87. package/src/tzero_packer.py +370 -0
  88. package/src/tzero_patch.py +624 -0
  89. package/src/tzero_pc_fixer.py +12657 -0
  90. package/src/tzero_pipe.py +95 -0
  91. package/src/tzero_polyglot.py +422 -0
  92. package/src/tzero_reachability.py +272 -0
  93. package/src/tzero_replay.py +141 -0
  94. package/src/tzero_security.py +570 -0
  95. package/src/tzero_snapshot.py +258 -0
  96. package/src/tzero_stubs.py +313 -0
  97. package/src/tzero_superdesign.py +774 -0
  98. package/src/tzero_sync.py +241 -0
  99. package/src/tzero_task_benchmark.py +363 -0
  100. package/src/tzero_tui.py +244 -0
  101. package/src/tzero_v3.py +9435 -0
@@ -0,0 +1,310 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ T-ZERO CAUSAL & TEMPORAL KNOWLEDGE GRAPH ENGINE (4D GRAPH)
4
+ Developer: Toprak Ahmet Aydoğmuş (Siber Akademi)
5
+ Version: 4.4.0
6
+
7
+ Bu modül, anlamsal üçlüleri (Semantic Triplet) 4 boyutlu uzayda (zaman + nedensellik)
8
+ birleştiren akıllı çizge motorudur.
9
+
10
+ Temel Yetenekler:
11
+ 1. Zamansal Sıralama (Temporal Sequencing): precedes, follows, simultaneous, timestamping
12
+ 2. Nedensellik Bağları (Causal Edges): causes, triggered_by, fixes, resolves, mitigates, fails_with
13
+ 3. Kök Neden Analizi (Root-Cause Analysis via Causal DAG Traversal)
14
+ 4. Geri Alma Sıralaması (Rollback Order Planning)
15
+ 5. Döngü Tespiti (Causal Cycle Detection)
16
+ """
17
+
18
+ from __future__ import annotations
19
+ import time
20
+ import json
21
+ from typing import Dict, List, Optional, Set, Tuple, Any
22
+ from dataclasses import dataclass, field, asdict
23
+ from tzero_jarvis.semantic_compressor import SemanticTriplet, TypedEntity, EntityType, VectorQuantizedCodebook
24
+
25
+
26
+ class CausalRelationType:
27
+ CAUSES = "causes" # A -> B (A, B'ye sebep oldu)
28
+ TRIGGERED_BY = "triggered_by" # B <- A (B, A tarafından tetiklendi)
29
+ FIXES = "fixes" # A -> B (A, B hatasını/sorununu çözdü)
30
+ RESOLVES = "resolves" # Eş anlamlı: çözüme kavuşturdu
31
+ MITIGATES = "mitigates" # A, B'nin etkisini hafifletti
32
+ FAILS_WITH = "fails_with" # A eylemi B hatasıyla sonuçlandı
33
+ PRECEDES = "precedes" # A zaman olarak B'den önce gerçekleşti
34
+ FOLLOWS = "follows" # A zaman olarak B'den sonra gerçekleşti
35
+ CORRELATED_WITH = "correlated_with" # İstatistiki ilişki
36
+
37
+
38
+ @dataclass
39
+ class CausalEdge:
40
+ source_id: str
41
+ target_id: str
42
+ relation: str
43
+ weight: float = 1.0
44
+ timestamp: float = field(default_factory=time.time)
45
+ metadata: Dict[str, Any] = field(default_factory=dict)
46
+
47
+ def to_dict(self) -> Dict[str, Any]:
48
+ return asdict(self)
49
+
50
+
51
+ @dataclass
52
+ class CausalNode:
53
+ node_id: str
54
+ label: str
55
+ entity_type: str = "GENERIC"
56
+ triplet_code: Optional[int] = None
57
+ timestamp: float = field(default_factory=time.time)
58
+ attributes: Dict[str, Any] = field(default_factory=dict)
59
+
60
+ def to_dict(self) -> Dict[str, Any]:
61
+ return asdict(self)
62
+
63
+
64
+ class CausalTemporalGraph:
65
+ """
66
+ 4 Boyutlu Nedensellik ve Zaman Çizgesi Motoru.
67
+ Gelişmiş DAG algoritmaları ile kök neden ve geri alma zincirlerini hesaplar.
68
+ """
69
+
70
+ def __init__(self, codebook: Optional[VectorQuantizedCodebook] = None):
71
+ self.codebook = codebook or VectorQuantizedCodebook()
72
+ self.nodes: Dict[str, CausalNode] = {}
73
+ self.outgoing_edges: Dict[str, List[CausalEdge]] = {}
74
+ self.incoming_edges: Dict[str, List[CausalEdge]] = {}
75
+ self.chronological_timeline: List[str] = [] # node_id list in temporal order
76
+
77
+ def add_node(self, node_id: str, label: str, entity_type: str = "GENERIC",
78
+ triplet_code: Optional[int] = None, timestamp: Optional[float] = None,
79
+ attributes: Optional[Dict[str, Any]] = None) -> CausalNode:
80
+ ts = timestamp if timestamp is not None else time.time()
81
+ node = CausalNode(
82
+ node_id=node_id,
83
+ label=label,
84
+ entity_type=entity_type,
85
+ triplet_code=triplet_code,
86
+ timestamp=ts,
87
+ attributes=attributes or {}
88
+ )
89
+ self.nodes[node_id] = node
90
+ if node_id not in self.outgoing_edges:
91
+ self.outgoing_edges[node_id] = []
92
+ if node_id not in self.incoming_edges:
93
+ self.incoming_edges[node_id] = []
94
+
95
+ # Zaman çizgisine ekle
96
+ self.chronological_timeline.append(node_id)
97
+ self.chronological_timeline.sort(key=lambda nid: self.nodes[nid].timestamp)
98
+ return node
99
+
100
+ def add_edge(self, source_id: str, target_id: str, relation: str = CausalRelationType.CAUSES,
101
+ weight: float = 1.0, metadata: Optional[Dict[str, Any]] = None) -> CausalEdge:
102
+ if source_id not in self.nodes:
103
+ self.add_node(source_id, source_id)
104
+ if target_id not in self.nodes:
105
+ self.add_node(target_id, target_id)
106
+
107
+ edge = CausalEdge(
108
+ source_id=source_id,
109
+ target_id=target_id,
110
+ relation=relation,
111
+ weight=weight,
112
+ timestamp=time.time(),
113
+ metadata=metadata or {}
114
+ )
115
+ self.outgoing_edges[source_id].append(edge)
116
+ self.incoming_edges[target_id].append(edge)
117
+ return edge
118
+
119
+ def record_triplet_event(self, triplet: SemanticTriplet,
120
+ preceding_triplet_code: Optional[int] = None,
121
+ causes_triplet_code: Optional[int] = None) -> Tuple[int, str]:
122
+ """
123
+ Bir semantik üçlüyü çizgeye zamansal düğüm olarak ekler ve nedensellik bağlarını kurar.
124
+ """
125
+ code = self.codebook.encode(triplet)
126
+ node_id = f"node_{code}_{int(time.time() * 1000) % 100000}"
127
+ label = f"({triplet.subject})->[{triplet.predicate}]->({','.join(o.name for o in triplet.objects)})"
128
+
129
+ # Ana entity domain belirle
130
+ primary_domain = "GENERIC"
131
+ if triplet.objects:
132
+ primary_domain = triplet.objects[0].entity_type.value
133
+ elif triplet.contexts:
134
+ primary_domain = triplet.contexts[0].entity_type.value
135
+
136
+ self.add_node(
137
+ node_id=node_id,
138
+ label=label,
139
+ entity_type=primary_domain,
140
+ triplet_code=code,
141
+ attributes={"subject": triplet.subject, "predicate": triplet.predicate}
142
+ )
143
+
144
+ # Önceki olayla zamansal bağ
145
+ if preceding_triplet_code is not None:
146
+ prev_nodes = [nid for nid, n in self.nodes.items() if n.triplet_code == preceding_triplet_code]
147
+ if prev_nodes:
148
+ latest_prev = prev_nodes[-1]
149
+ self.add_edge(latest_prev, node_id, relation=CausalRelationType.PRECEDES)
150
+
151
+ # Neden-sonuç bağı
152
+ if causes_triplet_code is not None:
153
+ cause_nodes = [nid for nid, n in self.nodes.items() if n.triplet_code == causes_triplet_code]
154
+ if cause_nodes:
155
+ latest_cause = cause_nodes[-1]
156
+ self.add_edge(latest_cause, node_id, relation=CausalRelationType.CAUSES)
157
+
158
+ return code, node_id
159
+
160
+ def get_root_causes(self, target_node_id: str, max_depth: int = 10) -> List[Dict[str, Any]]:
161
+ """
162
+ Hedef düğümün (örn: bir hata veya arıza durumu) tüm kök nedenlerini (Root Causes)
163
+ nedensellik çizgisi boyunca geriye doğru izleyerek bulur.
164
+ """
165
+ if target_node_id not in self.nodes:
166
+ return []
167
+
168
+ visited: Set[str] = set()
169
+ root_causes: List[Dict[str, Any]] = []
170
+
171
+ def dfs(curr_id: str, depth: int, path: List[str]):
172
+ if depth >= max_depth or curr_id in visited:
173
+ return
174
+ visited.add(curr_id)
175
+
176
+ incoming = self.incoming_edges.get(curr_id, [])
177
+ causal_incoming = [
178
+ e for e in incoming
179
+ if e.relation in (CausalRelationType.CAUSES, CausalRelationType.TRIGGERED_BY, CausalRelationType.PRECEDES)
180
+ ]
181
+
182
+ if not causal_incoming and depth > 0:
183
+ # Kök nedene ulaşıldı
184
+ node = self.nodes[curr_id]
185
+ root_causes.append({
186
+ "root_node_id": curr_id,
187
+ "label": node.label,
188
+ "entity_type": node.entity_type,
189
+ "triplet_code": node.triplet_code,
190
+ "causal_path": list(reversed(path + [curr_id])),
191
+ "depth": depth
192
+ })
193
+ return
194
+
195
+ for edge in causal_incoming:
196
+ dfs(edge.source_id, depth + 1, path + [curr_id])
197
+
198
+ dfs(target_node_id, 0, [])
199
+ return root_causes
200
+
201
+ def trace_effect_chain(self, start_node_id: str, max_depth: int = 10) -> List[Dict[str, Any]]:
202
+ """
203
+ Başlangıç düğümünün tetiklediği tüm zincirleme sonuçları (Downstream Effects) çıkarır.
204
+ """
205
+ if start_node_id not in self.nodes:
206
+ return []
207
+
208
+ chain: List[Dict[str, Any]] = []
209
+ queue: List[Tuple[str, int, List[str]]] = [(start_node_id, 0, [start_node_id])]
210
+ visited: Set[str] = {start_node_id}
211
+
212
+ while queue:
213
+ curr_id, depth, path = queue.pop(0)
214
+ if depth >= max_depth:
215
+ continue
216
+
217
+ for edge in self.outgoing_edges.get(curr_id, []):
218
+ next_id = edge.target_id
219
+ if next_id not in visited:
220
+ visited.add(next_id)
221
+ next_node = self.nodes.get(next_id)
222
+ if next_node:
223
+ chain.append({
224
+ "node_id": next_id,
225
+ "label": next_node.label,
226
+ "relation": edge.relation,
227
+ "depth": depth + 1,
228
+ "path": path + [next_id]
229
+ })
230
+ queue.append((next_id, depth + 1, path + [next_id]))
231
+
232
+ return chain
233
+
234
+ def compute_rollback_order(self, target_node_id: str) -> List[Dict[str, Any]]:
235
+ """
236
+ Bir hata durumunda veya işlemin geri alınması gerektiğinde,
237
+ ters topolojik sıralama (Reverse Topological Order) ile güvenli geri alma adımlarını hesaplar.
238
+ """
239
+ effects = self.trace_effect_chain(target_node_id)
240
+ # En derin/en son etkilenen düğümden başlayarak geri alma planı
241
+ rollback_steps = []
242
+ for item in reversed(effects):
243
+ rollback_steps.append({
244
+ "step": len(rollback_steps) + 1,
245
+ "action": f"Rollback: {item['label']}",
246
+ "node_id": item["node_id"],
247
+ "relation_to_reverse": item["relation"]
248
+ })
249
+
250
+ target_node = self.nodes.get(target_node_id)
251
+ if target_node:
252
+ rollback_steps.append({
253
+ "step": len(rollback_steps) + 1,
254
+ "action": f"Revert Base: {target_node.label}",
255
+ "node_id": target_node_id,
256
+ "relation_to_reverse": "initial_trigger"
257
+ })
258
+ return rollback_steps
259
+
260
+ def get_timeline(self, limit: int = 50) -> List[Dict[str, Any]]:
261
+ """
262
+ Kronolojik olay akışını döndürür.
263
+ """
264
+ results = []
265
+ for nid in self.chronological_timeline[-limit:]:
266
+ node = self.nodes[nid]
267
+ results.append({
268
+ "node_id": nid,
269
+ "label": node.label,
270
+ "entity_type": node.entity_type,
271
+ "triplet_code": node.triplet_code,
272
+ "timestamp": node.timestamp,
273
+ "outgoing_count": len(self.outgoing_edges.get(nid, [])),
274
+ "incoming_count": len(self.incoming_edges.get(nid, []))
275
+ })
276
+ return results
277
+
278
+ def to_graph_data(self) -> Dict[str, Any]:
279
+ """
280
+ Görselleştirme için nodes ve links JSON verisi üretir.
281
+ """
282
+ nodes_data = []
283
+ for nid, node in self.nodes.items():
284
+ nodes_data.append({
285
+ "id": nid,
286
+ "label": node.label,
287
+ "group": node.entity_type,
288
+ "code": node.triplet_code,
289
+ "timestamp": node.timestamp
290
+ })
291
+
292
+ links_data = []
293
+ for src, edges in self.outgoing_edges.items():
294
+ for e in edges:
295
+ links_data.append({
296
+ "source": e.source_id,
297
+ "target": e.target_id,
298
+ "relation": e.relation,
299
+ "weight": e.weight
300
+ })
301
+
302
+ return {
303
+ "nodes": nodes_data,
304
+ "links": links_data,
305
+ "stats": {
306
+ "total_nodes": len(self.nodes),
307
+ "total_edges": sum(len(el) for el in self.outgoing_edges.values()),
308
+ "timeline_events": len(self.chronological_timeline)
309
+ }
310
+ }
@@ -0,0 +1,395 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ T-ZERO CYBERPUNK KNOWLEDGE & CAUSAL GRAPH VISUALIZER
4
+ Developer: Toprak Ahmet Aydoğmuş (Siber Akademi)
5
+ Version: 4.4.0
6
+
7
+ Bu modül, T-Zero 4D Nedensellik ve Bilgi Çizgesini tamamen bağımsız (Offline),
8
+ neon siberpunk estetiğine sahip interaktif bir HTML5 / SVG Force-Directed Graph
9
+ olarak render eder ve dışa aktarır.
10
+ """
11
+
12
+ from __future__ import annotations
13
+ import os
14
+ import json
15
+ from typing import Dict, List, Optional, Any
16
+ from tzero_jarvis.causal_graph import CausalTemporalGraph
17
+
18
+
19
+ DOMAIN_COLORS = {
20
+ "HARDWARE": "#38bdf8",
21
+ "PROTOCOL": "#818cf8",
22
+ "SOFTWARE": "#60a5fa",
23
+ "VULN": "#f43f5e",
24
+ "BIO": "#34d399",
25
+ "CRYPTO": "#fbbf24",
26
+ "QUANTUM": "#a78bfa",
27
+ "AEROSPACE": "#fb923c",
28
+ "AUTOMOTIVE": "#38bdf8",
29
+ "FINANCE": "#4ade80",
30
+ "ROBOTICS": "#f87171",
31
+ "GENERIC": "#94a3b8"
32
+ }
33
+
34
+
35
+ class CyberpunkGraphVisualizer:
36
+ """
37
+ Siberpunk Temalı Çizge Görselleştirici.
38
+ Hiçbir CDN veya internet bağlantısına ihtiyaç duymadan saf HTML5/SVG/Canvas üretir.
39
+ """
40
+
41
+ def __init__(self, causal_graph: Optional[CausalTemporalGraph] = None):
42
+ self.causal_graph = causal_graph or CausalTemporalGraph()
43
+
44
+ def generate_html(self, title: str = "T-ZERO JARVIS KNOWLEDGE & CAUSAL GRAPH") -> str:
45
+ graph_data = self.causal_graph.to_graph_data()
46
+ json_payload = json.dumps(graph_data, ensure_ascii=False)
47
+ colors_payload = json.dumps(DOMAIN_COLORS, ensure_ascii=False)
48
+
49
+ html = f"""<!DOCTYPE html>
50
+ <html lang="tr">
51
+ <head>
52
+ <meta charset="UTF-8">
53
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
54
+ <title>{title}</title>
55
+ <style>
56
+ * {{ margin: 0; padding: 0; box-sizing: border-box; }}
57
+ body {{
58
+ background: #090d16;
59
+ color: #f8fafc;
60
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
61
+ overflow: hidden;
62
+ height: 100vh;
63
+ width: 100vw;
64
+ }}
65
+ #header {{
66
+ position: absolute;
67
+ top: 15px;
68
+ left: 20px;
69
+ z-index: 100;
70
+ background: rgba(15, 23, 42, 0.88);
71
+ backdrop-filter: blur(8px);
72
+ padding: 12px 20px;
73
+ border: 1px solid #1e293b;
74
+ border-radius: 8px;
75
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4);
76
+ pointer-events: auto;
77
+ }}
78
+ #header h1 {{ font-size: 15px; font-weight: 600; letter-spacing: 0.5px; color: #f8fafc; }}
79
+ #header p {{ font-size: 12px; color: #94a3b8; margin-top: 4px; }}
80
+ #controls {{
81
+ position: absolute;
82
+ top: 15px;
83
+ right: 20px;
84
+ z-index: 100;
85
+ background: rgba(15, 23, 42, 0.88);
86
+ backdrop-filter: blur(8px);
87
+ padding: 10px 15px;
88
+ border: 1px solid #1e293b;
89
+ border-radius: 8px;
90
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4);
91
+ }}
92
+ input[type="text"] {{
93
+ background: #0b1120;
94
+ border: 1px solid #334155;
95
+ color: #f8fafc;
96
+ padding: 7px 12px;
97
+ border-radius: 6px;
98
+ font-family: monospace;
99
+ font-size: 12px;
100
+ outline: none;
101
+ transition: border-color 0.15s ease;
102
+ }}
103
+ input[type="text"]:focus {{
104
+ border-color: #38bdf8;
105
+ }}
106
+ #stats-bar {{
107
+ position: absolute;
108
+ bottom: 15px;
109
+ left: 20px;
110
+ z-index: 100;
111
+ background: rgba(15, 23, 42, 0.88);
112
+ backdrop-filter: blur(8px);
113
+ padding: 8px 16px;
114
+ border: 1px solid #1e293b;
115
+ font-size: 12px;
116
+ color: #94a3b8;
117
+ border-radius: 6px;
118
+ }}
119
+ #inspector {{
120
+ position: absolute;
121
+ bottom: 15px;
122
+ right: 20px;
123
+ z-index: 100;
124
+ width: 320px;
125
+ max-height: 250px;
126
+ overflow-y: auto;
127
+ background: rgba(15, 23, 42, 0.95);
128
+ backdrop-filter: blur(10px);
129
+ border: 1px solid #334155;
130
+ padding: 14px;
131
+ font-size: 12px;
132
+ border-radius: 8px;
133
+ display: none;
134
+ box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5);
135
+ }}
136
+ canvas {{ display: block; width: 100%; height: 100%; }}
137
+ </style>
138
+ </head>
139
+ <body>
140
+ <div id="header">
141
+ <h1>⚡ T-ZERO 4D KNOWLEDGE & CAUSAL GRAPH</h1>
142
+ <p>Developer: Toprak Ahmet Aydoğmuş | Zero-Cost Neural Engine</p>
143
+ </div>
144
+
145
+ <div id="controls">
146
+ <input type="text" id="searchInput" placeholder="Düğüm / Kod ara (örn: ESP32, #8421)..." oninput="filterGraph()">
147
+ </div>
148
+
149
+ <div id="stats-bar">
150
+ Düğümler: <span id="nodeCount" style="color:#38bdf8">0</span> |
151
+ Bağlar: <span id="edgeCount" style="color:#818cf8">0</span> |
152
+ FPS: <span id="fpsCount" style="color:#fbbf24">60</span>
153
+ </div>
154
+
155
+ <div id="inspector">
156
+ <h3 id="insTitle" style="color:#38bdf8; margin-bottom:6px;">Detay</h3>
157
+ <p id="insBody" style="color:#cbd5e1; line-height:1.5;"></p>
158
+ </div>
159
+
160
+ <canvas id="graphCanvas"></canvas>
161
+
162
+ <script>
163
+ const graphData = {json_payload};
164
+ const domainColors = {colors_payload};
165
+
166
+ const canvas = document.getElementById('graphCanvas');
167
+ const ctx = canvas.getContext('2d');
168
+ let width = canvas.width = window.innerWidth;
169
+ let height = canvas.height = window.innerHeight;
170
+
171
+ window.addEventListener('resize', () => {{
172
+ width = canvas.width = window.innerWidth;
173
+ height = canvas.height = window.innerHeight;
174
+ }});
175
+
176
+ document.getElementById('nodeCount').innerText = graphData.nodes.length;
177
+ document.getElementById('edgeCount').innerText = graphData.links.length;
178
+
179
+ // Düğümleri rastgele pozisyonlara yerleştir
180
+ const nodes = graphData.nodes.map((n, i) => {{
181
+ const angle = (i / Math.max(1, graphData.nodes.length)) * 2 * Math.PI;
182
+ const radius = 150 + Math.random() * 200;
183
+ return {{
184
+ ...n,
185
+ x: width / 2 + Math.cos(angle) * radius,
186
+ y: height / 2 + Math.sin(angle) * radius,
187
+ vx: 0,
188
+ vy: 0,
189
+ radius: n.code ? 18 : 12,
190
+ color: domainColors[n.group] || '#00ffcc'
191
+ }};
192
+ }});
193
+
194
+ const nodeMap = new Map();
195
+ nodes.forEach(n => nodeMap.set(n.id, n));
196
+
197
+ const links = graphData.links.map(l => ({{
198
+ ...l,
199
+ sourceNode: nodeMap.get(l.source),
200
+ targetNode: nodeMap.get(l.target)
201
+ }})).filter(l => l.sourceNode && l.targetNode);
202
+
203
+ // Basit Force-Directed Fizik Simülasyonu
204
+ let zoom = 1.0;
205
+ let panX = 0, panY = 0;
206
+ let selectedNode = null;
207
+ let isDragging = false;
208
+ let dragNode = null;
209
+
210
+ function simulate() {{
211
+ // İtme kuvveti
212
+ for (let i = 0; i < nodes.length; i++) {{
213
+ for (let j = i + 1; j < nodes.length; j++) {{
214
+ const dx = nodes[j].x - nodes[i].x;
215
+ const dy = nodes[j].y - nodes[i].y;
216
+ const dist = Math.sqrt(dx * dx + dy * dy) || 1;
217
+ if (dist < 300) {{
218
+ const force = (300 - dist) / (dist * 15);
219
+ nodes[i].vx -= dx * force;
220
+ nodes[i].vy -= dy * force;
221
+ nodes[j].vx += dx * force;
222
+ nodes[j].vy += dy * force;
223
+ }}
224
+ }}
225
+ }}
226
+
227
+ // Bağ çekme kuvveti
228
+ links.forEach(l => {{
229
+ const dx = l.targetNode.x - l.sourceNode.x;
230
+ const dy = l.targetNode.y - l.sourceNode.y;
231
+ const dist = Math.sqrt(dx * dx + dy * dy) || 1;
232
+ const force = (dist - 120) * 0.02;
233
+ l.sourceNode.vx += dx * force;
234
+ l.sourceNode.vy += dy * force;
235
+ l.targetNode.vx -= dx * force;
236
+ l.targetNode.vy -= dy * force;
237
+ }});
238
+
239
+ // Merkeze çekim ve sürtünme
240
+ nodes.forEach(n => {{
241
+ if (n === dragNode) return;
242
+ n.vx += (width / 2 - n.x) * 0.002;
243
+ n.vy += (height / 2 - n.y) * 0.002;
244
+ n.vx *= 0.85;
245
+ n.vy *= 0.85;
246
+ n.x += n.vx;
247
+ n.y += n.vy;
248
+ }});
249
+ }}
250
+
251
+ let lastFrameTime = performance.now();
252
+ let frameCount = 0;
253
+
254
+ function render() {{
255
+ simulate();
256
+
257
+ ctx.clearRect(0, 0, width, height);
258
+ ctx.save();
259
+ ctx.translate(panX, panY);
260
+ ctx.scale(zoom, zoom);
261
+
262
+ // Bağları çiz
263
+ links.forEach(l => {{
264
+ ctx.beginPath();
265
+ ctx.moveTo(l.sourceNode.x, l.sourceNode.y);
266
+ ctx.lineTo(l.targetNode.x, l.targetNode.y);
267
+ ctx.strokeStyle = l.relation === 'causes' ? 'rgba(255, 0, 85, 0.6)' : 'rgba(0, 229, 255, 0.4)';
268
+ ctx.lineWidth = l.relation === 'causes' ? 2 : 1;
269
+ ctx.stroke();
270
+
271
+ // İlişki etiketi
272
+ const midX = (l.sourceNode.x + l.targetNode.x) / 2;
273
+ const midY = (l.sourceNode.y + l.targetNode.y) / 2;
274
+ ctx.font = '9px monospace';
275
+ ctx.fillStyle = '#80d8ff';
276
+ ctx.fillText(l.relation, midX, midY);
277
+ }});
278
+
279
+ // Düğümleri çiz
280
+ nodes.forEach(n => {{
281
+ ctx.save();
282
+ ctx.shadowColor = n.color;
283
+ ctx.shadowBlur = 12;
284
+
285
+ ctx.beginPath();
286
+ ctx.arc(n.x, n.y, n.radius, 0, 2 * Math.PI);
287
+ ctx.fillStyle = n.color;
288
+ ctx.fill();
289
+
290
+ ctx.restore();
291
+
292
+ // Düğüm halkası
293
+ ctx.beginPath();
294
+ ctx.arc(n.x, n.y, n.radius + 3, 0, 2 * Math.PI);
295
+ ctx.strokeStyle = '#ffffff';
296
+ ctx.lineWidth = 1;
297
+ ctx.stroke();
298
+
299
+ // Metin etiketi
300
+ ctx.font = '10px Consolas, monospace';
301
+ ctx.fillStyle = '#ffffff';
302
+ ctx.textAlign = 'center';
303
+ const labelText = n.code ? `[#${{n.code}}] ${{n.label}}` : n.label;
304
+ ctx.fillText(labelText, n.x, n.y + n.radius + 14);
305
+ }});
306
+
307
+ ctx.restore();
308
+
309
+ // FPS sayacı
310
+ frameCount++;
311
+ const now = performance.now();
312
+ if (now - lastFrameTime >= 1000) {{
313
+ document.getElementById('fpsCount').innerText = frameCount;
314
+ frameCount = 0;
315
+ lastFrameTime = now;
316
+ }}
317
+
318
+ requestAnimationFrame(render);
319
+ }}
320
+
321
+ // Mouse Etkileşimi
322
+ canvas.addEventListener('mousedown', e => {{
323
+ const mx = (e.clientX - panX) / zoom;
324
+ const my = (e.clientY - panY) / zoom;
325
+ for (let n of nodes) {{
326
+ const dx = n.x - mx;
327
+ const dy = n.y - my;
328
+ if (Math.sqrt(dx * dx + dy * dy) < n.radius + 5) {{
329
+ dragNode = n;
330
+ selectedNode = n;
331
+ showInspector(n);
332
+ return;
333
+ }}
334
+ }}
335
+ isDragging = true;
336
+ dragStartX = e.clientX - panX;
337
+ dragStartY = e.clientY - panY;
338
+ }});
339
+
340
+ canvas.addEventListener('mousemove', e => {{
341
+ if (dragNode) {{
342
+ dragNode.x = (e.clientX - panX) / zoom;
343
+ dragNode.y = (e.clientY - panY) / zoom;
344
+ }} else if (isDragging) {{
345
+ panX = e.clientX - dragStartX;
346
+ panY = e.clientY - dragStartY;
347
+ }}
348
+ }});
349
+
350
+ canvas.addEventListener('mouseup', () => {{
351
+ dragNode = null;
352
+ isDragging = false;
353
+ }});
354
+
355
+ canvas.addEventListener('wheel', e => {{
356
+ e.preventDefault();
357
+ const factor = e.deltaY < 0 ? 1.1 : 0.9;
358
+ zoom *= factor;
359
+ zoom = Math.min(Math.max(0.2, zoom), 4.0);
360
+ }});
361
+
362
+ function showInspector(node) {{
363
+ const ins = document.getElementById('inspector');
364
+ ins.style.display = 'block';
365
+ document.getElementById('insTitle').innerText = `${{node.group}}: ${{node.label}}`;
366
+ document.getElementById('insBody').innerHTML = `
367
+ <b>ID:</b> ${{node.id}}<br>
368
+ <b>Latent Code:</b> ${{node.code ? '#' + node.code : 'None'}}<br>
369
+ <b>Domain:</b> ${{node.group}}<br>
370
+ <b>Timestamp:</b> ${{new Date(node.timestamp * 1000).toLocaleTimeString()}}
371
+ `;
372
+ }}
373
+
374
+ function filterGraph() {{
375
+ const query = document.getElementById('searchInput').value.toLowerCase();
376
+ nodes.forEach(n => {{
377
+ const match = n.label.toLowerCase().includes(query) || (n.code && n.code.toString().includes(query));
378
+ n.color = match ? (domainColors[n.group] || '#00ffcc') : '#334155';
379
+ n.radius = match ? (n.code ? 20 : 14) : 8;
380
+ }});
381
+ }}
382
+
383
+ requestAnimationFrame(render);
384
+ </script>
385
+ </body>
386
+ </html>
387
+ """
388
+ return html
389
+
390
+ def export_to_file(self, target_path: str, title: str = "T-ZERO JARVIS KNOWLEDGE & CAUSAL GRAPH") -> str:
391
+ html = self.generate_html(title)
392
+ os.makedirs(os.path.dirname(os.path.abspath(target_path)), exist_ok=True)
393
+ with open(target_path, "w", encoding="utf-8") as f:
394
+ f.write(html)
395
+ return target_path