radsimcli 1.2.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- radsim/__init__.py +127 -0
- radsim/__main__.py +6 -0
- radsim/access_control.py +93 -0
- radsim/adversarial.py +511 -0
- radsim/agent.py +2663 -0
- radsim/agent_config.py +372 -0
- radsim/api_client.py +912 -0
- radsim/archaeology.py +595 -0
- radsim/background.py +188 -0
- radsim/browser.py +172 -0
- radsim/cli.py +301 -0
- radsim/code_quality.py +191 -0
- radsim/commands.py +2443 -0
- radsim/complexity.py +436 -0
- radsim/config.py +692 -0
- radsim/diff_display.py +288 -0
- radsim/escape_listener.py +180 -0
- radsim/file_tools.py +432 -0
- radsim/git_tools.py +207 -0
- radsim/health.py +253 -0
- radsim/hooks.py +225 -0
- radsim/jobs.py +549 -0
- radsim/keybindings.py +66 -0
- radsim/learning/__init__.py +119 -0
- radsim/learning/active_learner.py +356 -0
- radsim/learning/analytics.py +351 -0
- radsim/learning/error_analyzer.py +278 -0
- radsim/learning/few_shot_assembler.py +294 -0
- radsim/learning/preference_learner.py +366 -0
- radsim/learning/reflection_engine.py +399 -0
- radsim/learning/self_improver.py +578 -0
- radsim/learning/tool_optimizer.py +383 -0
- radsim/log_config.py +29 -0
- radsim/memory.py +489 -0
- radsim/menu.py +119 -0
- radsim/model_router.py +253 -0
- radsim/modes.py +351 -0
- radsim/onboarding.py +991 -0
- radsim/output.py +1492 -0
- radsim/panning.py +259 -0
- radsim/patch.py +240 -0
- radsim/planner.py +449 -0
- radsim/prompts.py +468 -0
- radsim/rate_limiter.py +351 -0
- radsim/repo_map.py +296 -0
- radsim/response_validator.py +180 -0
- radsim/safety.py +300 -0
- radsim/scheduler.py +308 -0
- radsim/search_tools.py +391 -0
- radsim/shell_tools.py +181 -0
- radsim/skill_registry.py +148 -0
- radsim/skills/README.md +54 -0
- radsim/skills/browser_automation.md +191 -0
- radsim/skills/directory_operations.md +100 -0
- radsim/skills/file_operations.md +150 -0
- radsim/skills/git_operations.md +229 -0
- radsim/skills/production_readiness.md +153 -0
- radsim/skills/search.md +178 -0
- radsim/skills/shell_commands.md +138 -0
- radsim/skills/web_tools.md +135 -0
- radsim/skills.py +350 -0
- radsim/sub_agent.py +590 -0
- radsim/task_logger.py +328 -0
- radsim/telegram.py +661 -0
- radsim/todo.py +126 -0
- radsim/tool_result.py +115 -0
- radsim/tools/__init__.py +435 -0
- radsim/tools/advanced.py +660 -0
- radsim/tools/code_intel.py +209 -0
- radsim/tools/command_policy.py +168 -0
- radsim/tools/constants.py +89 -0
- radsim/tools/definitions.py +1152 -0
- radsim/tools/dependencies.py +328 -0
- radsim/tools/directory_ops.py +95 -0
- radsim/tools/file_ops.py +354 -0
- radsim/tools/git.py +194 -0
- radsim/tools/project.py +208 -0
- radsim/tools/search.py +186 -0
- radsim/tools/shell.py +57 -0
- radsim/tools/testing.py +285 -0
- radsim/tools/validation.py +170 -0
- radsim/tools/web.py +49 -0
- radsim/ui.py +328 -0
- radsim/update_checker.py +144 -0
- radsim/vector_memory.py +649 -0
- radsimcli-1.2.1.dist-info/METADATA +665 -0
- radsimcli-1.2.1.dist-info/RECORD +91 -0
- radsimcli-1.2.1.dist-info/WHEEL +4 -0
- radsimcli-1.2.1.dist-info/entry_points.txt +2 -0
- radsimcli-1.2.1.dist-info/licenses/LICENSE +21 -0
- radsimcli-1.2.1.dist-info/licenses/NOTICE +24 -0
radsim/__init__.py
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# RadSim - AI Coding Agent
|
|
2
|
+
# Copyright (c) 2024-2026 Matthew Bright
|
|
3
|
+
# Licensed under the MIT License. See LICENSE file for details.
|
|
4
|
+
|
|
5
|
+
"""RadSim Agent Framework - Radically Simple Code Generation."""
|
|
6
|
+
|
|
7
|
+
__version__ = "1.2.1"
|
|
8
|
+
__author__ = "Emera Digital Tools"
|
|
9
|
+
|
|
10
|
+
# Core exports
|
|
11
|
+
from .health import (
|
|
12
|
+
HealthChecker,
|
|
13
|
+
HealthStatus,
|
|
14
|
+
SecretExpirationMonitor,
|
|
15
|
+
check_health,
|
|
16
|
+
check_secret_expirations,
|
|
17
|
+
get_expiration_monitor,
|
|
18
|
+
get_health_checker,
|
|
19
|
+
validate_startup,
|
|
20
|
+
)
|
|
21
|
+
from .hooks import (
|
|
22
|
+
HookContext,
|
|
23
|
+
HooksManager,
|
|
24
|
+
HookType,
|
|
25
|
+
get_hooks_manager,
|
|
26
|
+
on_error,
|
|
27
|
+
post_api,
|
|
28
|
+
post_tool,
|
|
29
|
+
pre_api,
|
|
30
|
+
pre_tool,
|
|
31
|
+
)
|
|
32
|
+
from .model_router import (
|
|
33
|
+
ModelRouter,
|
|
34
|
+
TaskComplexity,
|
|
35
|
+
get_router,
|
|
36
|
+
select_model_for_task,
|
|
37
|
+
)
|
|
38
|
+
from .skill_registry import (
|
|
39
|
+
SkillRegistry,
|
|
40
|
+
get_skill_registry,
|
|
41
|
+
load_skill,
|
|
42
|
+
load_skill_for_tool,
|
|
43
|
+
)
|
|
44
|
+
from .sub_agent import (
|
|
45
|
+
SubAgentResult,
|
|
46
|
+
SubAgentTask,
|
|
47
|
+
delegate_task,
|
|
48
|
+
execute_subagent_task,
|
|
49
|
+
list_available_models,
|
|
50
|
+
quick_task,
|
|
51
|
+
resolve_model_name,
|
|
52
|
+
)
|
|
53
|
+
from .task_logger import (
|
|
54
|
+
TaskLogger,
|
|
55
|
+
get_logger,
|
|
56
|
+
log_api,
|
|
57
|
+
log_error,
|
|
58
|
+
log_tool,
|
|
59
|
+
)
|
|
60
|
+
from .tool_result import ToolResult, wrap_tool_call
|
|
61
|
+
from .vector_memory import (
|
|
62
|
+
VectorMemory,
|
|
63
|
+
get_context,
|
|
64
|
+
get_memory_backend,
|
|
65
|
+
is_vector_memory_available,
|
|
66
|
+
recall,
|
|
67
|
+
remember,
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
__all__ = [
|
|
71
|
+
# Version
|
|
72
|
+
"__version__",
|
|
73
|
+
"__author__",
|
|
74
|
+
# Tool Results
|
|
75
|
+
"ToolResult",
|
|
76
|
+
"wrap_tool_call",
|
|
77
|
+
# Skill Registry
|
|
78
|
+
"SkillRegistry",
|
|
79
|
+
"get_skill_registry",
|
|
80
|
+
"load_skill",
|
|
81
|
+
"load_skill_for_tool",
|
|
82
|
+
# Hooks
|
|
83
|
+
"HookType",
|
|
84
|
+
"HookContext",
|
|
85
|
+
"HooksManager",
|
|
86
|
+
"get_hooks_manager",
|
|
87
|
+
"pre_tool",
|
|
88
|
+
"post_tool",
|
|
89
|
+
"pre_api",
|
|
90
|
+
"post_api",
|
|
91
|
+
"on_error",
|
|
92
|
+
# Logging
|
|
93
|
+
"TaskLogger",
|
|
94
|
+
"get_logger",
|
|
95
|
+
"log_tool",
|
|
96
|
+
"log_api",
|
|
97
|
+
"log_error",
|
|
98
|
+
# Model Routing
|
|
99
|
+
"ModelRouter",
|
|
100
|
+
"TaskComplexity",
|
|
101
|
+
"get_router",
|
|
102
|
+
"select_model_for_task",
|
|
103
|
+
# Vector Memory
|
|
104
|
+
"VectorMemory",
|
|
105
|
+
"remember",
|
|
106
|
+
"recall",
|
|
107
|
+
"get_context",
|
|
108
|
+
"is_vector_memory_available",
|
|
109
|
+
"get_memory_backend",
|
|
110
|
+
# Sub-Agent Delegation
|
|
111
|
+
"SubAgentTask",
|
|
112
|
+
"SubAgentResult",
|
|
113
|
+
"delegate_task",
|
|
114
|
+
"quick_task",
|
|
115
|
+
"execute_subagent_task",
|
|
116
|
+
"list_available_models",
|
|
117
|
+
"resolve_model_name",
|
|
118
|
+
# Health Checks
|
|
119
|
+
"HealthChecker",
|
|
120
|
+
"HealthStatus",
|
|
121
|
+
"SecretExpirationMonitor",
|
|
122
|
+
"check_health",
|
|
123
|
+
"check_secret_expirations",
|
|
124
|
+
"get_expiration_monitor",
|
|
125
|
+
"get_health_checker",
|
|
126
|
+
"validate_startup",
|
|
127
|
+
]
|
radsim/__main__.py
ADDED
radsim/access_control.py
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"""Secure Access Control - RadSim Principle: Defense in Depth.
|
|
2
|
+
|
|
3
|
+
Access code security:
|
|
4
|
+
1. Never logged to any file or database
|
|
5
|
+
2. Never printed to console (uses getpass)
|
|
6
|
+
3. Never committed to version control
|
|
7
|
+
4. Loaded from environment variable only
|
|
8
|
+
5. Uses constant-time comparison (prevents timing attacks)
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import hmac
|
|
12
|
+
import os
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _secure_compare(provided: str, stored: str) -> bool:
|
|
16
|
+
"""Compare strings in constant time to prevent timing attacks.
|
|
17
|
+
|
|
18
|
+
RadSim Principle: Security by Default
|
|
19
|
+
Timing attacks can reveal password length/characters by measuring
|
|
20
|
+
comparison time. HMAC compare_digest prevents this.
|
|
21
|
+
"""
|
|
22
|
+
return hmac.compare_digest(provided.encode("utf-8"), stored.encode("utf-8"))
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def get_access_code_from_env() -> str | None:
|
|
26
|
+
"""Load access code from environment (never log this value)."""
|
|
27
|
+
# Check ~/.radsim/.env first, then system env
|
|
28
|
+
from .config import load_env_file
|
|
29
|
+
|
|
30
|
+
env_config = load_env_file()
|
|
31
|
+
|
|
32
|
+
# Look for RADSIM_ACCESS_CODE in .env keys
|
|
33
|
+
if "keys" in env_config and "RADSIM_ACCESS_CODE" in env_config["keys"]:
|
|
34
|
+
return env_config["keys"]["RADSIM_ACCESS_CODE"]
|
|
35
|
+
|
|
36
|
+
# Fall back to system environment
|
|
37
|
+
return os.getenv("RADSIM_ACCESS_CODE")
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def is_access_protected() -> bool:
|
|
41
|
+
"""Check if access code protection is enabled."""
|
|
42
|
+
code = get_access_code_from_env()
|
|
43
|
+
return bool(code and code.strip())
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def verify_access_code(user_input: str) -> bool:
|
|
47
|
+
"""Verify access code without logging.
|
|
48
|
+
|
|
49
|
+
SECURITY: This function never logs the input or stored code.
|
|
50
|
+
Returns True if code matches, False otherwise.
|
|
51
|
+
"""
|
|
52
|
+
stored_code = get_access_code_from_env()
|
|
53
|
+
|
|
54
|
+
if not stored_code:
|
|
55
|
+
return True # No code configured = no protection
|
|
56
|
+
|
|
57
|
+
return _secure_compare(user_input.strip(), stored_code.strip())
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def prompt_for_access() -> bool:
|
|
61
|
+
"""Prompt user for access code in interactive mode.
|
|
62
|
+
|
|
63
|
+
Uses getpass to hide input from terminal.
|
|
64
|
+
Never logs or prints the entered code.
|
|
65
|
+
"""
|
|
66
|
+
if not is_access_protected():
|
|
67
|
+
return True
|
|
68
|
+
|
|
69
|
+
import getpass
|
|
70
|
+
|
|
71
|
+
max_attempts = 3
|
|
72
|
+
for attempt in range(max_attempts):
|
|
73
|
+
try:
|
|
74
|
+
code = getpass.getpass("🔐 Enter access code: ")
|
|
75
|
+
if verify_access_code(code):
|
|
76
|
+
return True
|
|
77
|
+
remaining = max_attempts - attempt - 1
|
|
78
|
+
if remaining > 0:
|
|
79
|
+
print(f" ❌ Invalid code. {remaining} attempts remaining.")
|
|
80
|
+
except (KeyboardInterrupt, EOFError):
|
|
81
|
+
print("\n Access cancelled.")
|
|
82
|
+
return False
|
|
83
|
+
|
|
84
|
+
print(" ❌ Access denied.")
|
|
85
|
+
return False
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def check_access_on_startup() -> bool:
|
|
89
|
+
"""Verify access code on startup if protection is enabled.
|
|
90
|
+
|
|
91
|
+
Call this from CLI before starting the agent.
|
|
92
|
+
"""
|
|
93
|
+
return prompt_for_access()
|