codent 0.2.0__tar.gz → 0.3.1__tar.gz

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 (133) hide show
  1. codent-0.3.1/PKG-INFO +28 -0
  2. codent-0.3.1/codent.egg-info/PKG-INFO +28 -0
  3. {codent-0.2.0 → codent-0.3.1}/codent.egg-info/SOURCES.txt +36 -0
  4. codent-0.3.1/codent.egg-info/requires.txt +29 -0
  5. {codent-0.2.0 → codent-0.3.1}/cont.py +54 -3
  6. {codent-0.2.0 → codent-0.3.1}/core/adaptive_prompt.py +8 -15
  7. codent-0.3.1/core/advanced_overnight.py +310 -0
  8. codent-0.3.1/core/anomaly_tools.py +304 -0
  9. {codent-0.2.0 → codent-0.3.1}/core/app.py +58 -0
  10. codent-0.3.1/core/benchmark.py +543 -0
  11. codent-0.3.1/core/budget_committee.py +122 -0
  12. codent-0.3.1/core/cc_auditor.py +294 -0
  13. codent-0.3.1/core/cleaning_tools.py +356 -0
  14. {codent-0.2.0 → codent-0.3.1}/core/cli.py +53 -3
  15. codent-0.3.1/core/context_utils.py +110 -0
  16. codent-0.3.1/core/curriculum_runner.py +292 -0
  17. codent-0.3.1/core/daemon.py +648 -0
  18. codent-0.3.1/core/data_tools.py +242 -0
  19. {codent-0.2.0 → codent-0.3.1}/core/decomposer.py +11 -7
  20. codent-0.3.1/core/domain_tools.py +230 -0
  21. {codent-0.2.0 → codent-0.3.1}/core/endpoint_discovery.py +37 -19
  22. codent-0.3.1/core/feedback_training.py +270 -0
  23. codent-0.3.1/core/fitness.py +96 -0
  24. {codent-0.2.0 → codent-0.3.1}/core/formatters.py +5 -5
  25. codent-0.3.1/core/genesis.py +91 -0
  26. codent-0.3.1/core/golden_test_runner.py +590 -0
  27. codent-0.3.1/core/guardian.py +1418 -0
  28. codent-0.3.1/core/hive_recall.py +279 -0
  29. codent-0.3.1/core/learning_loop.py +184 -0
  30. codent-0.3.1/core/lmstudio.py +124 -0
  31. codent-0.3.1/core/local_llm.py +263 -0
  32. {codent-0.2.0 → codent-0.3.1}/core/memory_store.py +5 -0
  33. codent-0.3.1/core/ml_tools.py +344 -0
  34. {codent-0.2.0 → codent-0.3.1}/core/model.py +24 -2
  35. codent-0.3.1/core/network_audit.py +160 -0
  36. codent-0.3.1/core/overfit_test.py +283 -0
  37. codent-0.3.1/core/overnight_training.py +442 -0
  38. codent-0.3.1/core/postprocess.py +213 -0
  39. codent-0.3.1/core/provider_router.py +136 -0
  40. codent-0.3.1/core/quick_overfit_test.py +129 -0
  41. codent-0.3.1/core/recipe_factory.py +214 -0
  42. codent-0.3.1/core/recipe_feedback.py +85 -0
  43. codent-0.3.1/core/recipe_learner.py +377 -0
  44. codent-0.3.1/core/relation_discovery.py +480 -0
  45. {codent-0.2.0 → codent-0.3.1}/core/repl.py +38 -5
  46. codent-0.3.1/core/rpc.py +282 -0
  47. {codent-0.2.0 → codent-0.3.1}/core/run_logger.py +42 -0
  48. {codent-0.2.0 → codent-0.3.1}/core/runtime.py +232 -1375
  49. {codent-0.2.0 → codent-0.3.1}/core/self_improve.py +11 -42
  50. codent-0.3.1/core/spreading_activation.py +366 -0
  51. codent-0.3.1/core/sql_guard.py +113 -0
  52. {codent-0.2.0 → codent-0.3.1}/core/system_executor.py +12 -14
  53. {codent-0.2.0 → codent-0.3.1}/core/task_classifier.py +21 -26
  54. codent-0.3.1/core/task_utils.py +604 -0
  55. codent-0.3.1/core/tool_helpers.py +516 -0
  56. {codent-0.2.0 → codent-0.3.1}/core/tools.py +28 -23
  57. codent-0.3.1/core/verify_minions.py +148 -0
  58. codent-0.3.1/core/yis_deep_training.py +231 -0
  59. {codent-0.2.0 → codent-0.3.1}/pyproject.toml +6 -2
  60. codent-0.2.0/PKG-INFO +0 -15
  61. codent-0.2.0/codent.egg-info/PKG-INFO +0 -15
  62. codent-0.2.0/codent.egg-info/requires.txt +0 -13
  63. codent-0.2.0/core/lmstudio.py +0 -85
  64. codent-0.2.0/core/provider_router.py +0 -97
  65. {codent-0.2.0 → codent-0.3.1}/codent.egg-info/dependency_links.txt +0 -0
  66. {codent-0.2.0 → codent-0.3.1}/codent.egg-info/entry_points.txt +0 -0
  67. {codent-0.2.0 → codent-0.3.1}/codent.egg-info/top_level.txt +0 -0
  68. {codent-0.2.0 → codent-0.3.1}/cont_ui/__init__.py +0 -0
  69. {codent-0.2.0 → codent-0.3.1}/cont_ui/frontend.html +0 -0
  70. {codent-0.2.0 → codent-0.3.1}/cont_ui/server.py +0 -0
  71. {codent-0.2.0 → codent-0.3.1}/cont_watcher.py +0 -0
  72. {codent-0.2.0 → codent-0.3.1}/core/__init__.py +0 -0
  73. {codent-0.2.0 → codent-0.3.1}/core/auto_eval.py +0 -0
  74. {codent-0.2.0 → codent-0.3.1}/core/automations.py +0 -0
  75. {codent-0.2.0 → codent-0.3.1}/core/bridge_server.py +0 -0
  76. {codent-0.2.0 → codent-0.3.1}/core/browser.py +0 -0
  77. {codent-0.2.0 → codent-0.3.1}/core/browser_agent.py +0 -0
  78. {codent-0.2.0 → codent-0.3.1}/core/env_snapshot.py +0 -0
  79. {codent-0.2.0 → codent-0.3.1}/core/episodic.py +0 -0
  80. {codent-0.2.0 → codent-0.3.1}/core/escalation.py +0 -0
  81. {codent-0.2.0 → codent-0.3.1}/core/events.py +0 -0
  82. {codent-0.2.0 → codent-0.3.1}/core/file_context.py +0 -0
  83. {codent-0.2.0 → codent-0.3.1}/core/identity.py +0 -0
  84. {codent-0.2.0 → codent-0.3.1}/core/intent_detection.py +0 -0
  85. {codent-0.2.0 → codent-0.3.1}/core/intent_gate.py +0 -0
  86. {codent-0.2.0 → codent-0.3.1}/core/memory_eviction.py +0 -0
  87. {codent-0.2.0 → codent-0.3.1}/core/memory_gate.py +0 -0
  88. {codent-0.2.0 → codent-0.3.1}/core/model_routing.py +0 -0
  89. {codent-0.2.0 → codent-0.3.1}/core/ocr.py +0 -0
  90. {codent-0.2.0 → codent-0.3.1}/core/path_resolution.py +0 -0
  91. {codent-0.2.0 → codent-0.3.1}/core/prefetch.py +0 -0
  92. {codent-0.2.0 → codent-0.3.1}/core/prompt_patches.py +0 -0
  93. {codent-0.2.0 → codent-0.3.1}/core/prompts.py +0 -0
  94. {codent-0.2.0 → codent-0.3.1}/core/recipes.py +0 -0
  95. {codent-0.2.0 → codent-0.3.1}/core/relay.py +0 -0
  96. {codent-0.2.0 → codent-0.3.1}/core/router.py +0 -0
  97. {codent-0.2.0 → codent-0.3.1}/core/safety.py +0 -0
  98. {codent-0.2.0 → codent-0.3.1}/core/scheduler.py +0 -0
  99. {codent-0.2.0 → codent-0.3.1}/core/scratchpad.py +0 -0
  100. {codent-0.2.0 → codent-0.3.1}/core/sticky_config.py +0 -0
  101. {codent-0.2.0 → codent-0.3.1}/core/structured_output.py +0 -0
  102. {codent-0.2.0 → codent-0.3.1}/core/system_map.py +0 -0
  103. {codent-0.2.0 → codent-0.3.1}/core/teacher.py +0 -0
  104. {codent-0.2.0 → codent-0.3.1}/core/tool_budget.py +0 -0
  105. {codent-0.2.0 → codent-0.3.1}/core/tool_schemas.py +0 -0
  106. {codent-0.2.0 → codent-0.3.1}/core/trace.py +0 -0
  107. {codent-0.2.0 → codent-0.3.1}/core/types.py +0 -0
  108. {codent-0.2.0 → codent-0.3.1}/core/utils.py +0 -0
  109. {codent-0.2.0 → codent-0.3.1}/core/verification.py +0 -0
  110. {codent-0.2.0 → codent-0.3.1}/core/vocabulary.py +0 -0
  111. {codent-0.2.0 → codent-0.3.1}/core/voice.py +0 -0
  112. {codent-0.2.0 → codent-0.3.1}/core/web.py +0 -0
  113. {codent-0.2.0 → codent-0.3.1}/setup.cfg +0 -0
  114. {codent-0.2.0 → codent-0.3.1}/tests/test_auto_eval.py +0 -0
  115. {codent-0.2.0 → codent-0.3.1}/tests/test_browser.py +0 -0
  116. {codent-0.2.0 → codent-0.3.1}/tests/test_browser_agent.py +0 -0
  117. {codent-0.2.0 → codent-0.3.1}/tests/test_commands_and_teach.py +0 -0
  118. {codent-0.2.0 → codent-0.3.1}/tests/test_cont.py +0 -0
  119. {codent-0.2.0 → codent-0.3.1}/tests/test_corpus_parser.py +0 -0
  120. {codent-0.2.0 → codent-0.3.1}/tests/test_episodic.py +0 -0
  121. {codent-0.2.0 → codent-0.3.1}/tests/test_eviction.py +0 -0
  122. {codent-0.2.0 → codent-0.3.1}/tests/test_formatters.py +0 -0
  123. {codent-0.2.0 → codent-0.3.1}/tests/test_golden.py +0 -0
  124. {codent-0.2.0 → codent-0.3.1}/tests/test_health_report_valid_json.py +0 -0
  125. {codent-0.2.0 → codent-0.3.1}/tests/test_integrity_and_memory_gate.py +0 -0
  126. {codent-0.2.0 → codent-0.3.1}/tests/test_known_bugs.py +0 -0
  127. {codent-0.2.0 → codent-0.3.1}/tests/test_model_agnostic.py +0 -0
  128. {codent-0.2.0 → codent-0.3.1}/tests/test_new_tools.py +0 -0
  129. {codent-0.2.0 → codent-0.3.1}/tests/test_provider_router.py +0 -0
  130. {codent-0.2.0 → codent-0.3.1}/tests/test_recipes.py +0 -0
  131. {codent-0.2.0 → codent-0.3.1}/tests/test_teacher.py +0 -0
  132. {codent-0.2.0 → codent-0.3.1}/tests/test_verification.py +0 -0
  133. {codent-0.2.0 → codent-0.3.1}/tests/test_web_fetch.py +0 -0
codent-0.3.1/PKG-INFO ADDED
@@ -0,0 +1,28 @@
1
+ Metadata-Version: 2.4
2
+ Name: codent
3
+ Version: 0.3.1
4
+ Requires-Python: >=3.10
5
+ Requires-Dist: rich>=13.0
6
+ Requires-Dist: openai>=1.0
7
+ Requires-Dist: httpx>=0.24
8
+ Requires-Dist: requests>=2.28
9
+ Requires-Dist: pyyaml>=6.0
10
+ Provides-Extra: ocr
11
+ Requires-Dist: easyocr; extra == "ocr"
12
+ Requires-Dist: surya-ocr; extra == "ocr"
13
+ Requires-Dist: pillow; extra == "ocr"
14
+ Provides-Extra: ml
15
+ Requires-Dist: lightgbm; extra == "ml"
16
+ Requires-Dist: scikit-learn; extra == "ml"
17
+ Requires-Dist: pandas; extra == "ml"
18
+ Requires-Dist: numpy; extra == "ml"
19
+ Requires-Dist: duckdb; extra == "ml"
20
+ Provides-Extra: bank
21
+ Requires-Dist: duckdb; extra == "bank"
22
+ Provides-Extra: ui
23
+ Requires-Dist: fastapi; extra == "ui"
24
+ Requires-Dist: uvicorn; extra == "ui"
25
+ Provides-Extra: all
26
+ Requires-Dist: codent[ocr]; extra == "all"
27
+ Requires-Dist: codent[ml]; extra == "all"
28
+ Requires-Dist: codent[ui]; extra == "all"
@@ -0,0 +1,28 @@
1
+ Metadata-Version: 2.4
2
+ Name: codent
3
+ Version: 0.3.1
4
+ Requires-Python: >=3.10
5
+ Requires-Dist: rich>=13.0
6
+ Requires-Dist: openai>=1.0
7
+ Requires-Dist: httpx>=0.24
8
+ Requires-Dist: requests>=2.28
9
+ Requires-Dist: pyyaml>=6.0
10
+ Provides-Extra: ocr
11
+ Requires-Dist: easyocr; extra == "ocr"
12
+ Requires-Dist: surya-ocr; extra == "ocr"
13
+ Requires-Dist: pillow; extra == "ocr"
14
+ Provides-Extra: ml
15
+ Requires-Dist: lightgbm; extra == "ml"
16
+ Requires-Dist: scikit-learn; extra == "ml"
17
+ Requires-Dist: pandas; extra == "ml"
18
+ Requires-Dist: numpy; extra == "ml"
19
+ Requires-Dist: duckdb; extra == "ml"
20
+ Provides-Extra: bank
21
+ Requires-Dist: duckdb; extra == "bank"
22
+ Provides-Extra: ui
23
+ Requires-Dist: fastapi; extra == "ui"
24
+ Requires-Dist: uvicorn; extra == "ui"
25
+ Provides-Extra: all
26
+ Requires-Dist: codent[ocr]; extra == "all"
27
+ Requires-Dist: codent[ml]; extra == "all"
28
+ Requires-Dist: codent[ui]; extra == "all"
@@ -12,62 +12,98 @@ cont_ui/frontend.html
12
12
  cont_ui/server.py
13
13
  core/__init__.py
14
14
  core/adaptive_prompt.py
15
+ core/advanced_overnight.py
16
+ core/anomaly_tools.py
15
17
  core/app.py
16
18
  core/auto_eval.py
17
19
  core/automations.py
20
+ core/benchmark.py
18
21
  core/bridge_server.py
19
22
  core/browser.py
20
23
  core/browser_agent.py
24
+ core/budget_committee.py
25
+ core/cc_auditor.py
26
+ core/cleaning_tools.py
21
27
  core/cli.py
28
+ core/context_utils.py
29
+ core/curriculum_runner.py
30
+ core/daemon.py
31
+ core/data_tools.py
22
32
  core/decomposer.py
33
+ core/domain_tools.py
23
34
  core/endpoint_discovery.py
24
35
  core/env_snapshot.py
25
36
  core/episodic.py
26
37
  core/escalation.py
27
38
  core/events.py
39
+ core/feedback_training.py
28
40
  core/file_context.py
41
+ core/fitness.py
29
42
  core/formatters.py
43
+ core/genesis.py
44
+ core/golden_test_runner.py
45
+ core/guardian.py
46
+ core/hive_recall.py
30
47
  core/identity.py
31
48
  core/intent_detection.py
32
49
  core/intent_gate.py
50
+ core/learning_loop.py
33
51
  core/lmstudio.py
52
+ core/local_llm.py
34
53
  core/memory_eviction.py
35
54
  core/memory_gate.py
36
55
  core/memory_store.py
56
+ core/ml_tools.py
37
57
  core/model.py
38
58
  core/model_routing.py
59
+ core/network_audit.py
39
60
  core/ocr.py
61
+ core/overfit_test.py
62
+ core/overnight_training.py
40
63
  core/path_resolution.py
64
+ core/postprocess.py
41
65
  core/prefetch.py
42
66
  core/prompt_patches.py
43
67
  core/prompts.py
44
68
  core/provider_router.py
69
+ core/quick_overfit_test.py
70
+ core/recipe_factory.py
71
+ core/recipe_feedback.py
72
+ core/recipe_learner.py
45
73
  core/recipes.py
74
+ core/relation_discovery.py
46
75
  core/relay.py
47
76
  core/repl.py
48
77
  core/router.py
78
+ core/rpc.py
49
79
  core/run_logger.py
50
80
  core/runtime.py
51
81
  core/safety.py
52
82
  core/scheduler.py
53
83
  core/scratchpad.py
54
84
  core/self_improve.py
85
+ core/spreading_activation.py
86
+ core/sql_guard.py
55
87
  core/sticky_config.py
56
88
  core/structured_output.py
57
89
  core/system_executor.py
58
90
  core/system_map.py
59
91
  core/task_classifier.py
92
+ core/task_utils.py
60
93
  core/teacher.py
61
94
  core/tool_budget.py
95
+ core/tool_helpers.py
62
96
  core/tool_schemas.py
63
97
  core/tools.py
64
98
  core/trace.py
65
99
  core/types.py
66
100
  core/utils.py
67
101
  core/verification.py
102
+ core/verify_minions.py
68
103
  core/vocabulary.py
69
104
  core/voice.py
70
105
  core/web.py
106
+ core/yis_deep_training.py
71
107
  tests/test_auto_eval.py
72
108
  tests/test_browser.py
73
109
  tests/test_browser_agent.py
@@ -0,0 +1,29 @@
1
+ rich>=13.0
2
+ openai>=1.0
3
+ httpx>=0.24
4
+ requests>=2.28
5
+ pyyaml>=6.0
6
+
7
+ [all]
8
+ codent[ocr]
9
+ codent[ml]
10
+ codent[ui]
11
+
12
+ [bank]
13
+ duckdb
14
+
15
+ [ml]
16
+ lightgbm
17
+ scikit-learn
18
+ pandas
19
+ numpy
20
+ duckdb
21
+
22
+ [ocr]
23
+ easyocr
24
+ surya-ocr
25
+ pillow
26
+
27
+ [ui]
28
+ fastapi
29
+ uvicorn
@@ -415,12 +415,12 @@ from core.provider_router import (
415
415
  ProviderUnavailableError,
416
416
  )
417
417
 
418
+ # Discover working base URL at startup (LM Studio → Ollama fallback)
418
419
  # Discover working base URL at startup (LM Studio → Ollama fallback)
419
420
  _PROVIDER_NAME = "lmstudio"
420
421
  try:
421
422
  BASE_URL, _TRIED_URLS = discover_openai_base_url()
422
423
  except EndpointNotFoundError:
423
- # LM Studio not found via endpoint_discovery, try Ollama fallback
424
424
  from core.provider_router import _check_provider, OLLAMA_BASE
425
425
  _ollama_models = _check_provider(OLLAMA_BASE)
426
426
  if _ollama_models:
@@ -528,6 +528,7 @@ def resolve_model(strict=None, save=None, **kw):
528
528
  # =====================
529
529
  from core.lmstudio import (
530
530
  _probe_lmstudio_unload, _lmstudio_unload_model, _lmstudio_load_model,
531
+ _lmstudio_eject_all, _lmstudio_ensure_model, _lmstudio_get_loaded,
531
532
  )
532
533
  _NO_UNLOAD: bool = False # Set by --no-unload flag
533
534
 
@@ -727,13 +728,20 @@ def llm_complete(
727
728
  MODEL = model
728
729
  _debug(f"llm_complete: model was empty, resolved to {model}")
729
730
 
731
+ # Eject guard: LM Studio'da doğru modelin yüklü olduğunu garanti et
732
+ # (üst üste binme koruması — yanlış model VRAM'i işgal etmesin)
733
+ # Sadece ilk çağrıda kontrol et (session başına bir kez yeterli)
734
+ if not getattr(llm_complete, '_model_ensured', False):
735
+ _lmstudio_ensure_model(BASE_URL, model)
736
+ llm_complete._model_ensured = True
737
+
730
738
  # Ensure messages fit in context window before sending.
731
739
  # Tool schemas consume ~5200 tokens, so subtract that from the budget.
732
740
  # Reserve 500 tokens for response generation.
733
- ctx_tokens = (_CONTEXT_LIMIT or 8192)
741
+ ctx_tokens = (_CONTEXT_LIMIT or 32768)
734
742
  tool_overhead = 5500 if tools else 0 # tool schemas ≈ 5200 tokens
735
743
  available_tokens = ctx_tokens - tool_overhead - 500 # response headroom
736
- available_tokens = max(available_tokens, 1500) # floor
744
+ available_tokens = max(available_tokens, 4000) # floor
737
745
  context_limit = int(available_tokens * 2.5) # tokens → chars (Turkish)
738
746
  messages = _truncate_for_context(messages, max_chars=context_limit)
739
747
 
@@ -1076,6 +1084,17 @@ def capabilities_report() -> dict:
1076
1084
  # Tool schemas loaded from core/tool_schemas.py
1077
1085
  from core.tool_schemas import TOOL_SCHEMAS, BROWSER_TOOL_SCHEMAS
1078
1086
 
1087
+ # Offline mode: ağ bağlantısı gerektiren tool'ları çıkar
1088
+ if os.environ.get("CONT_OFFLINE", "0") == "1":
1089
+ _OFFLINE_BLOCKED = {"web_search", "web_fetch", "open_in_browser", "browser_open",
1090
+ "browser_click", "browser_type", "browser_text",
1091
+ "browser_screenshot", "browser_links", "browser_agent",
1092
+ "repo_fetch"}
1093
+ TOOL_SCHEMAS = [t for t in TOOL_SCHEMAS
1094
+ if t.get("function", {}).get("name") not in _OFFLINE_BLOCKED]
1095
+ BROWSER_TOOL_SCHEMAS = []
1096
+ _debug(f"[OFFLINE] {len(_OFFLINE_BLOCKED)} ağ tool'u tool listesinden çıkarıldı")
1097
+
1079
1098
  # File Context Injection (extracted to core/file_context.py)
1080
1099
  # =====================
1081
1100
  from core.file_context import (
@@ -1811,9 +1830,23 @@ def main():
1811
1830
  cont_home = get_cont_home()
1812
1831
  _debug(f"Cont home: {cont_home}")
1813
1832
 
1833
+ # Guardian — felsefe koruma uyarıları
1834
+ try:
1835
+ from core.guardian import show_guardian_warnings
1836
+ show_guardian_warnings()
1837
+ except Exception:
1838
+ pass
1839
+
1814
1840
  parser = build_parser()
1815
1841
  args = parser.parse_args()
1816
1842
 
1843
+ # Daemon hoş geldin raporu
1844
+ try:
1845
+ from core.daemon import show_welcome
1846
+ show_welcome()
1847
+ except Exception:
1848
+ pass
1849
+
1817
1850
  # Handle --debug flag (enable debug logging)
1818
1851
  if args.debug:
1819
1852
  LOG_LEVEL = "debug"
@@ -1840,6 +1873,12 @@ def main():
1840
1873
  else:
1841
1874
  run_task._dry_run = False
1842
1875
 
1876
+ # Handle --local-list (show available GGUF presets)
1877
+ if getattr(args, 'local_list', False):
1878
+ from core.local_llm import list_presets
1879
+ list_presets()
1880
+ sys.exit(0)
1881
+
1843
1882
  # Handle all exit flags (--set-home, --show-home, --self-report, --memory-*, etc.)
1844
1883
  handle_exit_flags(args)
1845
1884
 
@@ -1905,6 +1944,18 @@ def main():
1905
1944
  security.enabled = False
1906
1945
  console.print("[yellow]Write protection disabled via --no-write-protect[/yellow]")
1907
1946
 
1947
+ # Handle --unattended (auto-approve TIER_2, for overnight training)
1948
+ if getattr(args, 'unattended', False):
1949
+ wp = get_write_protection()
1950
+ wp.write_confirmed = True
1951
+ security = get_security_manager()
1952
+ if security:
1953
+ # Pre-approve common tools so no prompts appear
1954
+ security.session.approve_tool("run_shell")
1955
+ security.session.approve_tool("write_file")
1956
+ security.session.approve_tool("apply_patch")
1957
+ console.print("[yellow]Unattended mode: TIER_2 auto-approved[/yellow]")
1958
+
1908
1959
  # Handle --model flag (set model override)
1909
1960
  if args.model:
1910
1961
  _MODEL_OVERRIDE = args.model
@@ -121,23 +121,16 @@ ANTI_LOOP_SHORT = """
121
121
  ANTI-LOOP:
122
122
  - Never call same tool with same args twice
123
123
  - After 2 failures, STOP and report the issue
124
- - list_dir sonrası alt klasörlere tekrar list_dir YAPMA (kullanıcı istemediyse)
124
+ - İlk tool sonucu yeterliyse HEMEN cevap ver
125
125
 
126
126
  PATH RESOLUTION:
127
- - list_dir sonucu {"path": "/a/b", "contents": ["x.json"]} şeklindedir.
128
- - Dosya okumak için TAM YOLU kullan: read_file("/a/b/x.json")
129
- - ASLA sadece dosya adını kullanma: read_file("x.json") YANLIŞ!
130
-
131
- VERİMLİLİK:
132
- - "list dir" = SADECE list_dir {"path": "."} çağır, sonucu göster. Başka tool çağırma.
133
- - Basit komutlar (list, show, find, bul, göster) MAX 2 tool call.
134
- - İlk tool sonucu yeterliyse HEMEN cevap ver, ekstra arama yapma.
135
- - "X loglarını aç" = system_search + open_file. Başka klasörlere bakma.
136
-
137
- KISA YOLLAR (tool çağırmana gerek yok, doğrudan biliyorsun):
138
- - "cont log/logları" = cont projesinin logs/cont_runs/ klasörü → open_in_explorer ile aç.
139
- - "cont klasörü" = workspace root (yukarıda yazıyor).
140
- - "kendi logların" = logs/cont_runs/ altında."""
127
+ - list_dir sonucu {"path": "/a/b", "contents": ["x.json"]} → read_file("/a/b/x.json")
128
+ - ASLA sadece dosya adını kullanma, TAM YOLU kullan
129
+
130
+ KNOWLEDGE MAP:
131
+ - Reçeteler (nasıl yapılır): .cont/hive/recipes/
132
+ - Kısıtlar (ne yapılmaz): .cont/hive/DISCIPLINE.md
133
+ - Proje kuralları: CLAUDE.md veya CONT.md (CWD'de ara)"""
141
134
 
142
135
  CONVERSATION_CONTEXT_SHORT = """
143
136
  CONTEXT:
@@ -0,0 +1,310 @@
1
+ #!/usr/bin/env python3
2
+ """İleri muhakeme gece eğitimi — 7 bölüm, 24 görev, GPU termal yönetimi.
3
+
4
+ 3 görev → 10dk mola → 3 görev → 10dk mola → ...
5
+ GPU 70°C üstüyse ekstra 5dk bekle.
6
+ 07:30'a kadar tekrar çalıştır.
7
+ """
8
+
9
+ import json, os, re, subprocess, sys, time
10
+ from datetime import datetime, timedelta
11
+ from pathlib import Path
12
+
13
+ PROJECT_ROOT = Path(__file__).parent.parent
14
+ os.chdir(str(PROJECT_ROOT))
15
+ if str(PROJECT_ROOT) not in sys.path:
16
+ sys.path.insert(0, str(PROJECT_ROOT))
17
+
18
+ DB = "/home/sertan/projects/ews_v511/ews_dashboard/db/ews.duckdb"
19
+ RESULTS_DIR = PROJECT_ROOT / ".cont" / "hive" / "runs" / "training"
20
+ RESULTS_DIR.mkdir(parents=True, exist_ok=True)
21
+
22
+ STOP_TIME = datetime.now().replace(hour=7, minute=30, second=0)
23
+ if STOP_TIME < datetime.now():
24
+ STOP_TIME += timedelta(days=1)
25
+
26
+ SECTIONS = {
27
+ "A": {
28
+ "name": "Sayılar uymuyor",
29
+ "tasks": [
30
+ {"id": "A1", "scenario": f"Scoreboard'da 1,540,051 firma var ama dim_entity'de 4,185,053. 2.6 milyon firma nereye kayboldu? ({DB}) SQL ile araştır.",
31
+ "check": lambda r: any(w in r.lower() for w in ["filtre","katman","dim_entity","fact_periodic","scoreboard","kaybolmadı"])},
32
+ {"id": "A2", "scenario": f"Aynı firma için kombine_risk=150M, kik_risk=50M, kredi_risk=120M ({DB}). Hangisi doğru? Risk nasıl hesaplanıyor?",
33
+ "check": lambda r: any(w in r.lower() for w in ["kombine","coalesce","fallback","toplam","formül","hesaplama"])},
34
+ {"id": "A3", "scenario": f"brz_raporlama_depo'da donem=2501 ama dosya adı 1-DEPO2025. Bu tutarsızlık mı? ({DB})",
35
+ "check": lambda r: any(w in r.lower() for w in ["kaydırma","shift","konvansiyon","rapor","gecikme","dosya adı"])},
36
+ ],
37
+ },
38
+ "B": {
39
+ "name": "Neden bozuldu?",
40
+ "tasks": [
41
+ {"id": "B1", "scenario": f"Dev'de 6000 row dönen fonksiyon prod'da 0 row dönüyor. Hata yok. entity_id tipi VARCHAR vs BIGINT olabilir mi? ({DB})",
42
+ "check": lambda r: any(w in r.upper() for w in ["VARCHAR","BIGINT","CAST","NULL","TİP"]) and any(w in r.lower() for w in ["join","eşleşme","tip","uyumsuz"])},
43
+ {"id": "B2", "scenario": f"_build_diag_index prod'da boş dict döndürüyor. except bloğu hatayı yutuyor olabilir. Bellek sorunu mu? ({DB})",
44
+ "check": lambda r: any(w in r.lower() for w in ["bellek","memory","except","aggregate","sql","fetchdf","oom"])},
45
+ {"id": "B3", "scenario": f"Fonksiyon var, test geçiyor ama prod'da diag_index boş. Fonksiyon çağrılıyor mu? ({DB})",
46
+ "check": lambda r: any(w in r.lower() for w in ["çağrılmıyor","entegrasyon","return","integration","unit test"])},
47
+ {"id": "B4", "scenario": f"HTML'de çok büyük inline JavaScript var. Admin sayfası açılmıyor. Neden? ({DB})",
48
+ "check": lambda r: any(w in r.lower() for w in ["inline","json","chunk","script","boyut","mb","parse"])},
49
+ ],
50
+ },
51
+ "C": {
52
+ "name": "Tasarım kararları",
53
+ "tasks": [
54
+ {"id": "C1", "scenario": f"Diag tablosu neden 42.6M satır? Normalize edilseydi daha iyi olmaz mıydı? ({DB}) Trade-off'u açıkla.",
55
+ "check": lambda r: any(w in r.lower() for w in ["denormalize","trade-off","sorgu","hız","depolama","join"])},
56
+ {"id": "C2", "scenario": f"wsx.id_risk (EUS kapsam sorgusu) neden idempotent değil? Her çalıştırmada farklı sonuç verirse ne olur?",
57
+ "check": lambda r: any(w in r.lower() for w in ["idempotent","canlı","güncel","tekrar","tutarsız"])},
58
+ {"id": "C3", "scenario": f"EWS skoru neden VARCHAR? Integer olsa tip güvenliği olurdu. Neden string seçildi? ({DB})",
59
+ "check": lambda r: any(w in r.lower() for w in ["varchar","yi","string","integer","cast","esneklik"])},
60
+ ],
61
+ },
62
+ "D": {
63
+ "name": "Zincir muhakeme",
64
+ "tasks": [
65
+ {"id": "D1", "scenario": f"Bir firmanın 2503'te skoru 400, 2602'de 750. 12 dönemlik trajectory'sini çıkar, kırılma noktasını bul. ({DB})",
66
+ "check": lambda r: any(w in r.lower() for w in ["trajectory","kırılma","dönem","trend","geçiş","artış"])},
67
+ {"id": "D2", "scenario": f"EUS skoru hesaplanan firma seti dönemler arası neden değişiyor? Kapsam sorgusu nasıl çalışıyor? ({DB})",
68
+ "check": lambda r: any(w in r.lower() for w in ["kapsam","eus","filtre","sorgu","değişiyor","set"])},
69
+ {"id": "D3", "scenario": f"Admin sayfasında bir firmanın Neden YIS tablosu boş ama diag verisi var. _build_diag_index_full vs _slim farkı ne?",
70
+ "check": lambda r: any(w in r.lower() for w in ["slim","full","admin","diag","fark","index"])},
71
+ {"id": "D4", "scenario": f"2509'da YI sayısı aniden %30 arttı. Gerçek mi yoksa veri anomalisi mi? En az 3 alternatif açıklama ver. ({DB})",
72
+ "check": lambda r: any(w in r.lower() for w in ["alternatif","açıklama","anomali","gerçek","veri","kapsam"])},
73
+ ],
74
+ },
75
+ "E": {
76
+ "name": "Çapraz kontrol",
77
+ "tasks": [
78
+ {"id": "E1", "scenario": f"fact_periodic + dim_entity + brz_kik_izleme ({DB}): entity_id tutarlı mı? Dönem uyumu var mı? Risk tutarlı mı?",
79
+ "check": lambda r: any(w in r.lower() for w in ["tutarlı","entity_id","dönem","risk","join","tip"])},
80
+ {"id": "E2", "scenario": f"Scoreboard çıktısındaki firma sayısı ile fact_periodic'teki firma sayısı ({DB}) aynı mı? Fark varsa neden?",
81
+ "check": lambda r: any(w in r.lower() for w in ["firma","sayı","fark","filtre","scoreboard","fact"])},
82
+ {"id": "E3", "scenario": f"fact_periodic'te ews_skor='YI' olan firmalarla ykn_izl_flag=1 olan firmalar ({DB}) aynı set mi? Fark ne kadar?",
83
+ "check": lambda r: any(w in r.lower() for w in ["yi","ykn_izl","fark","aynı","set","flag"])},
84
+ ],
85
+ },
86
+ "F": {
87
+ "name": "Sistem düşüncesi",
88
+ "tasks": [
89
+ {"id": "F1", "scenario": f"brz_eus_tahmin yanlış geldi — downstream etki analizi yap. Hangi tablolar, hangi raporlar etkilenir? ({DB})",
90
+ "check": lambda r: any(w in r.lower() for w in ["downstream","etki","bağımlı","tablo","rapor","pipeline"])},
91
+ {"id": "F2", "scenario": f"EUS eşiğini 325'ten 250'ye düşürseydik ne olurdu? Kaç firma daha yakalanırdı, precision nasıl değişirdi? ({DB})",
92
+ "check": lambda r: any(w in r.lower() for w in ["eşik","threshold","precision","recall","firma","250"])},
93
+ {"id": "F3", "scenario": f"Bu pipeline'ın en kırılgan noktası neresi? Hangi adım bozulursa en çok hasar verir? ({DB})",
94
+ "check": lambda r: any(w in r.lower() for w in ["kırılgan","hasar","risk","bağımlılık","tek nokta","critical"])},
95
+ ],
96
+ },
97
+ "G": {
98
+ "name": "Meta-muhakeme",
99
+ "tasks": [
100
+ {"id": "G1", "scenario": f"Yüksek risk volatilitesi olan firmaların %80'i YI oluyor. Volatiliteyi düşürmek YI'yı azaltır mı? ({DB})",
101
+ "check": lambda r: any(w in r.lower() for w in ["korelasyon","nedensellik","causation","ters","correlation"])},
102
+ {"id": "G2", "scenario": f"0-325 bandındaki firmaların %95'i 12 dönem güvenli kalmış. Model çok iyi mi? ({DB})",
103
+ "check": lambda r: any(w in r.lower() for w in ["survivorship","bias","hayatta","kalan","seçilim","yanılgı"])},
104
+ {"id": "G3", "scenario": f"Her segmentte precision >%22 ama genel precision %18. Bu nasıl mümkün? ({DB})",
105
+ "check": lambda r: any(w in r.lower() for w in ["simpson","paradoks","ağırlık","weight","segment","boyut"])},
106
+ {"id": "G4", "scenario": f"2506'da EUS firma sayısı %5 düştü. Bu kriz mi? En az 3 alternatif açıklama ver. ({DB})",
107
+ "check": lambda r: any(w in r.lower() for w in ["alternatif","açıklama","kapsam","kriz","veri","sorgu"])},
108
+ ],
109
+ },
110
+ }
111
+
112
+
113
+ def gpu_temp():
114
+ try:
115
+ r = subprocess.run(["nvidia-smi", "--query-gpu=temperature.gpu", "--format=csv,noheader"],
116
+ capture_output=True, text=True, timeout=5)
117
+ return int(r.stdout.strip())
118
+ except Exception:
119
+ return -1
120
+
121
+
122
+ def rest(minutes=10, label="DİNLENME"):
123
+ """GPU soğutma molası."""
124
+ t = gpu_temp()
125
+ print(f"\n[{label}] {datetime.now().strftime('%H:%M')} — GPU={t}°C, {minutes}dk bekleniyor...")
126
+ time.sleep(minutes * 60)
127
+ t2 = gpu_temp()
128
+ if t2 > 70:
129
+ print(f" GPU hâlâ {t2}°C > 70°C, ekstra 5dk...")
130
+ time.sleep(300)
131
+ t3 = gpu_temp()
132
+ print(f" [{label} BİTTİ] GPU={t3}°C")
133
+
134
+
135
+ def run_cont(task):
136
+ t0 = time.time()
137
+ try:
138
+ from cont import run_task
139
+ answer, success = run_task(task)
140
+ return {"answer": answer or "", "elapsed": round(time.time()-t0, 1),
141
+ "tools": len(getattr(run_task, '_last_tools_used', []) or []),
142
+ "recipe": getattr(run_task, '_last_recipe_id', None)}
143
+ except Exception as e:
144
+ return {"answer": f"ERROR:{e}", "elapsed": round(time.time()-t0, 1), "tools": 0, "recipe": None}
145
+
146
+
147
+ def score_answer(answer, task):
148
+ """Basit otomatik puanlama."""
149
+ if not answer or "ERROR" in answer:
150
+ return {"dogruluk": 0, "zincir": 0, "derinlik": 0, "farkindalik": 0}
151
+
152
+ passed = task["check"](answer)
153
+ length = len(answer)
154
+ steps = len(re.findall(r'(?:^\d+[\.\)]|^-\s|^#{1,3}\s|Adım)', answer, re.MULTILINE))
155
+
156
+ dogruluk = 3 if passed and length > 200 else 2 if passed else 1 if length > 50 else 0
157
+ zincir = min(4, steps)
158
+ derinlik = 3 if length > 500 else 2 if length > 200 else 1
159
+ farkindalik = 2 if any(w in answer.lower() for w in ["tuzak","dikkat","uyarı","yanıltıcı","varsayım"]) else 1
160
+
161
+ return {"dogruluk": dogruluk, "zincir": zincir, "derinlik": derinlik, "farkindalik": farkindalik}
162
+
163
+
164
+ def weighted(scores):
165
+ return round(scores["dogruluk"]*0.3 + scores["zincir"]*0.3 + scores["derinlik"]*0.2 + scores["farkindalik"]*0.2, 1)
166
+
167
+
168
+ def run_section(section_key, section):
169
+ """Bir bölümü çalıştır."""
170
+ tasks = section["tasks"]
171
+ name = section["name"]
172
+ results = []
173
+
174
+ print(f"\n{'█'*60}")
175
+ print(f" BÖLÜM {section_key}: {name} ({len(tasks)} görev)")
176
+ print(f"{'█'*60}")
177
+
178
+ for ti, task in enumerate(tasks):
179
+ if datetime.now() > STOP_TIME:
180
+ print(f" ⏰ 07:30 geçti, durduruluyor")
181
+ break
182
+
183
+ print(f"\n [{task['id']}] {task['scenario'][:70]}...")
184
+ r = run_cont(task["scenario"])
185
+ scores = score_answer(r["answer"], task)
186
+ w = weighted(scores)
187
+ icon = "✓" if w >= 2.5 else "~" if w >= 1.5 else "✗"
188
+ print(f" {icon} {w}/4.0 (d={scores['dogruluk']} z={scores['zincir']} "
189
+ f"dp={scores['derinlik']} f={scores['farkindalik']}) | {r['elapsed']:.0f}s")
190
+
191
+ results.append({
192
+ "id": task["id"], "scores": scores, "weighted": w,
193
+ "elapsed": r["elapsed"], "tools": r["tools"], "recipe": r["recipe"],
194
+ "answer_len": len(r["answer"]),
195
+ })
196
+ time.sleep(2)
197
+
198
+ # Bölüm özeti
199
+ total_w = sum(r["weighted"] for r in results)
200
+ max_w = len(results) * 4
201
+ print(f"\n Bölüm {section_key}: {total_w:.1f}/{max_w:.0f}")
202
+ return results
203
+
204
+
205
+ def run_training_cycle(cycle_num=1):
206
+ """Tam bir eğitim döngüsü — 7 bölüm + molalar."""
207
+ print(f"\n{'═'*60}")
208
+ print(f" EĞİTİM DÖNGÜSÜ #{cycle_num} — {datetime.now().strftime('%H:%M')}")
209
+ print(f" Hedef bitiş: {STOP_TIME.strftime('%H:%M')}")
210
+ print(f"{'═'*60}")
211
+
212
+ all_results = {}
213
+ task_counter = 0
214
+
215
+ for section_key in sorted(SECTIONS.keys()):
216
+ if datetime.now() > STOP_TIME:
217
+ break
218
+
219
+ section = SECTIONS[section_key]
220
+ results = run_section(section_key, section)
221
+ all_results[section_key] = results
222
+ task_counter += len(results)
223
+
224
+ # Her 3 görev → mola
225
+ if task_counter % 3 == 0 and section_key != list(SECTIONS.keys())[-1]:
226
+ ml_task = section_key in ("B", "D") # ML/ağır görevler
227
+ rest(15 if ml_task else 10)
228
+
229
+ return all_results
230
+
231
+
232
+ def save_results(all_results, cycle_num):
233
+ """Sonuçları kaydet."""
234
+ total_w = sum(r["weighted"] for results in all_results.values() for r in results)
235
+ total_tasks = sum(len(results) for results in all_results.values())
236
+ max_w = total_tasks * 4
237
+
238
+ summary = {
239
+ "cycle": cycle_num,
240
+ "timestamp": datetime.now().isoformat(),
241
+ "total_score": round(total_w, 1),
242
+ "max_score": max_w,
243
+ "total_tasks": total_tasks,
244
+ "pct": round(total_w / max(max_w, 1) * 100, 1),
245
+ "gpu_temp": gpu_temp(),
246
+ "sections": {},
247
+ }
248
+
249
+ for key, results in all_results.items():
250
+ sec_w = sum(r["weighted"] for r in results)
251
+ sec_max = len(results) * 4
252
+ summary["sections"][key] = {
253
+ "name": SECTIONS[key]["name"],
254
+ "score": round(sec_w, 1),
255
+ "max": sec_max,
256
+ "tasks": results,
257
+ }
258
+
259
+ ts = datetime.now().strftime("%Y%m%d_%H%M%S")
260
+ out = RESULTS_DIR / f"advanced_cycle{cycle_num}_{ts}.json"
261
+ out.write_text(json.dumps(summary, indent=2, ensure_ascii=False, default=str))
262
+
263
+ print(f"\n{'═'*60}")
264
+ print(f" DÖNGÜ #{cycle_num} SONUCU: {total_w:.1f}/{max_w} ({summary['pct']}%)")
265
+ for key in sorted(summary["sections"].keys()):
266
+ s = summary["sections"][key]
267
+ print(f" {key}. {s['name']:<20s} {s['score']:.1f}/{s['max']}")
268
+ print(f" GPU: {summary['gpu_temp']}°C")
269
+ print(f" JSON: {out}")
270
+
271
+ return summary
272
+
273
+
274
+ def main():
275
+ cycle = 1
276
+
277
+ while datetime.now() < STOP_TIME:
278
+ results = run_training_cycle(cycle)
279
+ summary = save_results(results, cycle)
280
+
281
+ # Guardian
282
+ try:
283
+ from core.guardian import run_guardian
284
+ report = run_guardian(full=True)
285
+ g = sum(1 for r in report.results.values() if r["passed"])
286
+ print(f" Guardian: {g}/{len(report.results)}")
287
+ except Exception:
288
+ pass
289
+
290
+ # Sonraki döngü için uzun mola
291
+ if datetime.now() < STOP_TIME:
292
+ remaining = (STOP_TIME - datetime.now()).total_seconds() / 60
293
+ if remaining > 30:
294
+ print(f"\n Sonraki döngüye kadar 20dk mola (kalan: {remaining:.0f}dk)")
295
+ rest(20, "DÖNGÜ ARASI")
296
+ cycle += 1
297
+ else:
298
+ print(f"\n Kalan süre {remaining:.0f}dk — döngü yeterli değil, durduruluyor")
299
+ break
300
+
301
+ # Sabah raporu
302
+ print(f"\n{'█'*60}")
303
+ print(f" SABAH RAPORU — {datetime.now().strftime('%H:%M')}")
304
+ print(f" Toplam döngü: {cycle}")
305
+ print(f" GPU: {gpu_temp()}°C")
306
+ print(f"{'█'*60}")
307
+
308
+
309
+ if __name__ == "__main__":
310
+ main()