programgarden 1.26.0__tar.gz → 1.28.0__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.
- {programgarden-1.26.0 → programgarden-1.28.0}/PKG-INFO +2 -2
- {programgarden-1.26.0 → programgarden-1.28.0}/programgarden/__init__.py +1 -1
- {programgarden-1.26.0 → programgarden-1.28.0}/programgarden/context.py +29 -9
- {programgarden-1.26.0 → programgarden-1.28.0}/programgarden/executor.py +342 -175
- {programgarden-1.26.0 → programgarden-1.28.0}/programgarden/resolver.py +315 -0
- {programgarden-1.26.0 → programgarden-1.28.0}/pyproject.toml +2 -2
- {programgarden-1.26.0 → programgarden-1.28.0}/README.md +0 -0
- {programgarden-1.26.0 → programgarden-1.28.0}/programgarden/binding_validator.py +0 -0
- {programgarden-1.26.0 → programgarden-1.28.0}/programgarden/client.py +0 -0
- {programgarden-1.26.0 → programgarden-1.28.0}/programgarden/code_worker.py +0 -0
- {programgarden-1.26.0 → programgarden-1.28.0}/programgarden/database/__init__.py +0 -0
- {programgarden-1.26.0 → programgarden-1.28.0}/programgarden/database/checkpoint_manager.py +0 -0
- {programgarden-1.26.0 → programgarden-1.28.0}/programgarden/database/query_builder.py +0 -0
- {programgarden-1.26.0 → programgarden-1.28.0}/programgarden/database/workflow_position_tracker.py +0 -0
- {programgarden-1.26.0 → programgarden-1.28.0}/programgarden/database/workflow_risk_tracker.py +0 -0
- {programgarden-1.26.0 → programgarden-1.28.0}/programgarden/deep_fixtures.py +0 -0
- {programgarden-1.26.0 → programgarden-1.28.0}/programgarden/node_runner.py +0 -0
- {programgarden-1.26.0 → programgarden-1.28.0}/programgarden/plugin/__init__.py +0 -0
- {programgarden-1.26.0 → programgarden-1.28.0}/programgarden/plugin/sandbox.py +0 -0
- {programgarden-1.26.0 → programgarden-1.28.0}/programgarden/providers/__init__.py +0 -0
- {programgarden-1.26.0 → programgarden-1.28.0}/programgarden/providers/llm_errors.py +0 -0
- {programgarden-1.26.0 → programgarden-1.28.0}/programgarden/providers/llm_provider.py +0 -0
- {programgarden-1.26.0 → programgarden-1.28.0}/programgarden/reconnect_handler.py +0 -0
- {programgarden-1.26.0 → programgarden-1.28.0}/programgarden/resource/__init__.py +0 -0
- {programgarden-1.26.0 → programgarden-1.28.0}/programgarden/resource/context.py +0 -0
- {programgarden-1.26.0 → programgarden-1.28.0}/programgarden/resource/limiter.py +0 -0
- {programgarden-1.26.0 → programgarden-1.28.0}/programgarden/resource/monitor.py +0 -0
- {programgarden-1.26.0 → programgarden-1.28.0}/programgarden/resource/throttle.py +0 -0
- {programgarden-1.26.0 → programgarden-1.28.0}/programgarden/semantic_rules.py +0 -0
- {programgarden-1.26.0 → programgarden-1.28.0}/programgarden/tools/__init__.py +0 -0
- {programgarden-1.26.0 → programgarden-1.28.0}/programgarden/tools/credential_tools.py +0 -0
- {programgarden-1.26.0 → programgarden-1.28.0}/programgarden/tools/definition_tools.py +0 -0
- {programgarden-1.26.0 → programgarden-1.28.0}/programgarden/tools/event_tools.py +0 -0
- {programgarden-1.26.0 → programgarden-1.28.0}/programgarden/tools/job_tools.py +0 -0
- {programgarden-1.26.0 → programgarden-1.28.0}/programgarden/tools/registry_tools.py +0 -0
- {programgarden-1.26.0 → programgarden-1.28.0}/programgarden/tools/sqlite_tools.py +0 -0
- {programgarden-1.26.0 → programgarden-1.28.0}/programgarden/validation_recommender.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: programgarden
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.28.0
|
|
4
4
|
Summary: ProgramGarden - 노드 기반 자동매매 DSL 실행 엔진
|
|
5
5
|
License-Expression: AGPL-3.0-or-later
|
|
6
6
|
Author: 프로그램동산
|
|
@@ -16,7 +16,7 @@ Requires-Dist: croniter (>=6.0.0,<7.0.0)
|
|
|
16
16
|
Requires-Dist: litellm (>=1.40.0)
|
|
17
17
|
Requires-Dist: lxml (>=6.0.2,<7.0.0)
|
|
18
18
|
Requires-Dist: programgarden-community (>=1.13.11,<2.0.0)
|
|
19
|
-
Requires-Dist: programgarden-core (>=1.
|
|
19
|
+
Requires-Dist: programgarden-core (>=1.20.0,<2.0.0)
|
|
20
20
|
Requires-Dist: programgarden-finance (>=1.6.14,<2.0.0)
|
|
21
21
|
Requires-Dist: psutil (>=6.0.0,<7.0.0)
|
|
22
22
|
Requires-Dist: psycopg2-binary (>=2.9.11,<3.0.0)
|
|
@@ -2626,26 +2626,46 @@ class ExecutionContext:
|
|
|
2626
2626
|
logger.warning(f"Failed to sync fills from history: {e}")
|
|
2627
2627
|
return 0
|
|
2628
2628
|
|
|
2629
|
+
# 노드 출력에 실려 외부로 나가면 안 되는 키 (부분일치, 소문자 비교).
|
|
2630
|
+
# BrokerNode 는 `connection.appkey/appsecret` 을 하류 노드에 넘기기 위해 **출력에 싣는다**
|
|
2631
|
+
# (내부 전송 경로라 지울 수 없다). 따라서 외부로 나가는 모든 경계에서 가려야 한다.
|
|
2632
|
+
SENSITIVE_OUTPUT_KEYS = frozenset(
|
|
2633
|
+
{"appkey", "appsecret", "secret", "password", "token", "api_key", "apikey", "private_key"}
|
|
2634
|
+
)
|
|
2635
|
+
|
|
2636
|
+
def _sanitize_value(self, value: Any) -> Any:
|
|
2637
|
+
"""dict/list 를 재귀적으로 훑어 민감 키를 가린다."""
|
|
2638
|
+
if isinstance(value, dict):
|
|
2639
|
+
return self._sanitize_outputs(value)
|
|
2640
|
+
if isinstance(value, (list, tuple)):
|
|
2641
|
+
# 리스트 안의 dict 도 가려야 한다 (예: credentials[] 배열).
|
|
2642
|
+
sanitized_items = [self._sanitize_value(item) for item in value]
|
|
2643
|
+
return type(value)(sanitized_items) if isinstance(value, tuple) else sanitized_items
|
|
2644
|
+
return value
|
|
2645
|
+
|
|
2629
2646
|
def _sanitize_outputs(self, outputs: Optional[Dict[str, Any]]) -> Optional[Dict[str, Any]]:
|
|
2630
2647
|
"""Remove sensitive information from outputs."""
|
|
2631
2648
|
# None은 None으로 반환, 빈 딕셔너리 {}는 그대로 유지
|
|
2632
2649
|
if outputs is None:
|
|
2633
2650
|
return None
|
|
2634
|
-
|
|
2635
|
-
# Filter sensitive keywords
|
|
2636
|
-
sensitive_keys = {"appkey", "appsecret", "secret", "password", "token", "api_key"}
|
|
2651
|
+
|
|
2637
2652
|
sanitized = {}
|
|
2638
|
-
|
|
2639
2653
|
for k, v in outputs.items():
|
|
2640
|
-
if any(sk in k.lower() for sk in
|
|
2654
|
+
if any(sk in str(k).lower() for sk in self.SENSITIVE_OUTPUT_KEYS):
|
|
2641
2655
|
sanitized[k] = "[REDACTED]"
|
|
2642
|
-
elif isinstance(v, dict):
|
|
2643
|
-
sanitized[k] = self._sanitize_outputs(v)
|
|
2644
2656
|
else:
|
|
2645
|
-
sanitized[k] = v
|
|
2646
|
-
|
|
2657
|
+
sanitized[k] = self._sanitize_value(v)
|
|
2658
|
+
|
|
2647
2659
|
return sanitized
|
|
2648
2660
|
|
|
2661
|
+
def get_all_outputs_sanitized(self, node_id: str) -> Dict[str, Any]:
|
|
2662
|
+
"""외부로 내보낼 노드 출력 — 민감 키가 가려진 사본.
|
|
2663
|
+
|
|
2664
|
+
내부 전송(바인딩 해석 · broker connection auto-inject)은 `get_all_outputs()` 의
|
|
2665
|
+
raw 값을 그대로 쓰고, **외부 노출면**(리스너 이벤트 · `get_state()`)만 이걸 쓴다.
|
|
2666
|
+
"""
|
|
2667
|
+
return self._sanitize_outputs(self.get_all_outputs(node_id)) or {}
|
|
2668
|
+
|
|
2649
2669
|
# === Logging ===
|
|
2650
2670
|
|
|
2651
2671
|
def log(
|