tzero-mcp 10.7.0 → 10.7.1
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.
- package/bin/tzero-mcp.js +9 -16
- package/bin/tzero.js +9 -16
- package/index.js +7 -2
- package/package.json +2 -1
- package/src/addmcp.py +1194 -0
- package/src/main.py +60 -0
- package/src/siber_akademi_icon.py +77 -0
- package/src/tzero/jarvis/semantic_compressor.py +373 -0
- package/src/tzero.py +58 -0
- package/src/tzero_benchmark.py +475 -0
- package/src/tzero_bridge.py +362 -0
- package/src/tzero_ci.py +153 -0
- package/src/tzero_commit.py +192 -0
- package/src/tzero_cost.py +163 -0
- package/src/tzero_dashboard.py +1448 -0
- package/src/tzero_deps.py +287 -0
- package/src/tzero_drift.py +208 -0
- package/src/tzero_explain.py +240 -0
- package/src/tzero_features.py +3022 -0
- package/src/tzero_fix.py +228 -0
- package/src/tzero_fixer/__init__.py +63 -0
- package/src/tzero_fixer/amalgamation.py +334 -0
- package/src/tzero_fixer/ast_syntax_healer.py +464 -0
- package/src/tzero_fixer/ast_type_modernizer.py +288 -0
- package/src/tzero_fixer/async_io_modernizer.py +127 -0
- package/src/tzero_fixer/automated_regression_suite.py +600 -0
- package/src/tzero_fixer/benchmarks_and_diagnostics.py +174 -0
- package/src/tzero_fixer/ci_cd_self_healing_gate.py +246 -0
- package/src/tzero_fixer/code_duplicity_and_refactorer.py +151 -0
- package/src/tzero_fixer/code_smells_healer.py +260 -0
- package/src/tzero_fixer/cwe_remediator.py +171 -0
- package/src/tzero_fixer/dead_code_eliminator.py +150 -0
- package/src/tzero_fixer/dependency_vulnerability_auditor.py +309 -0
- package/src/tzero_fixer/git_advanced_surgeon.py +280 -0
- package/src/tzero_fixer/hardware_and_disk_doctor.py +325 -0
- package/src/tzero_fixer/import_graph_healer.py +412 -0
- package/src/tzero_fixer/interactive_tui.py +91 -0
- package/src/tzero_fixer/knowledge_base.py +295 -0
- package/src/tzero_fixer/knowledge_base_extended.py +940 -0
- package/src/tzero_fixer/linters_and_static_analyzer.py +307 -0
- package/src/tzero_fixer/mcp_server.py +447 -0
- package/src/tzero_fixer/models.py +385 -0
- package/src/tzero_fixer/orchestrator.py +375 -0
- package/src/tzero_fixer/os_doctor.py +502 -0
- package/src/tzero_fixer/packaging_abi_surgeon.py +323 -0
- package/src/tzero_fixer/pc_fixer_doctor.py +599 -0
- package/src/tzero_fixer/performance_and_memory_profiler.py +274 -0
- package/src/tzero_fixer/polyglot_ast_parsers.py +313 -0
- package/src/tzero_fixer/polyglot_build_healer.py +364 -0
- package/src/tzero_fixer/polyglot_config_healer.py +318 -0
- package/src/tzero_fixer/polyglot_doctor.py +372 -0
- package/src/tzero_fixer/polyglot_linters.py +619 -0
- package/src/tzero_fixer/polyglot_schema_validator.py +305 -0
- package/src/tzero_fixer/security_cwe_database.py +444 -0
- package/src/tzero_fixer/security_deep_rules.py +114 -0
- package/src/tzero_fixer/security_rules_catalog.py +110 -0
- package/src/tzero_fixer/security_zero_leak.py +326 -0
- package/src/tzero_fixer/smart_patch_recommender.py +223 -0
- package/src/tzero_fixer/synthetic_workspace_generator.py +220 -0
- package/src/tzero_fixer/system_diagnostics_extended.py +493 -0
- package/src/tzero_fixer/system_repair_recipes.py +447 -0
- package/src/tzero_fixer/venv_doctor.py +309 -0
- package/src/tzero_gateway.py +885 -0
- package/src/tzero_guard.py +243 -0
- package/src/tzero_infra.py +274 -0
- package/src/tzero_jarvis/__init__.py +124 -0
- package/src/tzero_jarvis/causal_graph.py +310 -0
- package/src/tzero_jarvis/graph_visualizer.py +395 -0
- package/src/tzero_jarvis/hybrid_search.py +214 -0
- package/src/tzero_jarvis/latent_press.py +137 -0
- package/src/tzero_jarvis/memory_consolidation.py +212 -0
- package/src/tzero_jarvis/minhash_lsh.py +184 -0
- package/src/tzero_jarvis/orchestrator.py +335 -0
- package/src/tzero_jarvis/self_healing.py +308 -0
- package/src/tzero_jarvis/semantic_compressor.py +887 -0
- package/src/tzero_jarvis/swarm.py +261 -0
- package/src/tzero_jarvis/swarm_bft.py +144 -0
- package/src/tzero_jarvis/workspace_orchestrator.py +1167 -0
- package/src/tzero_jarvis/zero_key_router.py +173 -0
- package/src/tzero_mcp.py +4858 -0
- package/src/tzero_neural_cortex.py +1425 -0
- package/src/tzero_packer.py +370 -0
- package/src/tzero_patch.py +624 -0
- package/src/tzero_pc_fixer.py +12657 -0
- package/src/tzero_pipe.py +95 -0
- package/src/tzero_polyglot.py +422 -0
- package/src/tzero_reachability.py +272 -0
- package/src/tzero_replay.py +141 -0
- package/src/tzero_security.py +570 -0
- package/src/tzero_snapshot.py +258 -0
- package/src/tzero_stubs.py +313 -0
- package/src/tzero_superdesign.py +774 -0
- package/src/tzero_sync.py +241 -0
- package/src/tzero_task_benchmark.py +363 -0
- package/src/tzero_tui.py +244 -0
- 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
|