strix-agent 0.4.0__py3-none-any.whl → 0.6.2__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.
- strix/agents/StrixAgent/strix_agent.py +3 -3
- strix/agents/StrixAgent/system_prompt.jinja +30 -26
- strix/agents/base_agent.py +159 -75
- strix/agents/state.py +5 -2
- strix/config/__init__.py +12 -0
- strix/config/config.py +172 -0
- strix/interface/assets/tui_styles.tcss +195 -230
- strix/interface/cli.py +16 -41
- strix/interface/main.py +151 -74
- strix/interface/streaming_parser.py +119 -0
- strix/interface/tool_components/__init__.py +4 -0
- strix/interface/tool_components/agent_message_renderer.py +190 -0
- strix/interface/tool_components/agents_graph_renderer.py +54 -38
- strix/interface/tool_components/base_renderer.py +68 -36
- strix/interface/tool_components/browser_renderer.py +106 -91
- strix/interface/tool_components/file_edit_renderer.py +117 -36
- strix/interface/tool_components/finish_renderer.py +43 -10
- strix/interface/tool_components/notes_renderer.py +63 -38
- strix/interface/tool_components/proxy_renderer.py +133 -92
- strix/interface/tool_components/python_renderer.py +121 -8
- strix/interface/tool_components/registry.py +19 -12
- strix/interface/tool_components/reporting_renderer.py +196 -28
- strix/interface/tool_components/scan_info_renderer.py +22 -19
- strix/interface/tool_components/terminal_renderer.py +270 -90
- strix/interface/tool_components/thinking_renderer.py +8 -6
- strix/interface/tool_components/todo_renderer.py +225 -0
- strix/interface/tool_components/user_message_renderer.py +26 -19
- strix/interface/tool_components/web_search_renderer.py +7 -6
- strix/interface/tui.py +907 -262
- strix/interface/utils.py +236 -4
- strix/llm/__init__.py +6 -2
- strix/llm/config.py +8 -5
- strix/llm/dedupe.py +217 -0
- strix/llm/llm.py +209 -356
- strix/llm/memory_compressor.py +6 -5
- strix/llm/utils.py +17 -8
- strix/runtime/__init__.py +12 -3
- strix/runtime/docker_runtime.py +121 -202
- strix/runtime/tool_server.py +55 -95
- strix/skills/README.md +64 -0
- strix/skills/__init__.py +110 -0
- strix/{prompts → skills}/frameworks/nextjs.jinja +26 -0
- strix/skills/scan_modes/deep.jinja +145 -0
- strix/skills/scan_modes/quick.jinja +63 -0
- strix/skills/scan_modes/standard.jinja +91 -0
- strix/telemetry/README.md +38 -0
- strix/telemetry/__init__.py +7 -1
- strix/telemetry/posthog.py +137 -0
- strix/telemetry/tracer.py +194 -54
- strix/tools/__init__.py +11 -4
- strix/tools/agents_graph/agents_graph_actions.py +20 -21
- strix/tools/agents_graph/agents_graph_actions_schema.xml +8 -8
- strix/tools/browser/browser_actions.py +10 -6
- strix/tools/browser/browser_actions_schema.xml +6 -1
- strix/tools/browser/browser_instance.py +96 -48
- strix/tools/browser/tab_manager.py +121 -102
- strix/tools/context.py +12 -0
- strix/tools/executor.py +63 -4
- strix/tools/file_edit/file_edit_actions.py +6 -3
- strix/tools/file_edit/file_edit_actions_schema.xml +45 -3
- strix/tools/finish/finish_actions.py +80 -105
- strix/tools/finish/finish_actions_schema.xml +121 -14
- strix/tools/notes/notes_actions.py +6 -33
- strix/tools/notes/notes_actions_schema.xml +50 -46
- strix/tools/proxy/proxy_actions.py +14 -2
- strix/tools/proxy/proxy_actions_schema.xml +0 -1
- strix/tools/proxy/proxy_manager.py +28 -16
- strix/tools/python/python_actions.py +2 -2
- strix/tools/python/python_actions_schema.xml +9 -1
- strix/tools/python/python_instance.py +39 -37
- strix/tools/python/python_manager.py +43 -31
- strix/tools/registry.py +73 -12
- strix/tools/reporting/reporting_actions.py +218 -31
- strix/tools/reporting/reporting_actions_schema.xml +256 -8
- strix/tools/terminal/terminal_actions.py +2 -2
- strix/tools/terminal/terminal_actions_schema.xml +6 -0
- strix/tools/terminal/terminal_manager.py +41 -30
- strix/tools/thinking/thinking_actions_schema.xml +27 -25
- strix/tools/todo/__init__.py +18 -0
- strix/tools/todo/todo_actions.py +568 -0
- strix/tools/todo/todo_actions_schema.xml +225 -0
- strix/utils/__init__.py +0 -0
- strix/utils/resource_paths.py +13 -0
- {strix_agent-0.4.0.dist-info → strix_agent-0.6.2.dist-info}/METADATA +90 -65
- strix_agent-0.6.2.dist-info/RECORD +134 -0
- {strix_agent-0.4.0.dist-info → strix_agent-0.6.2.dist-info}/WHEEL +1 -1
- strix/llm/request_queue.py +0 -87
- strix/prompts/README.md +0 -64
- strix/prompts/__init__.py +0 -109
- strix_agent-0.4.0.dist-info/RECORD +0 -118
- /strix/{prompts → skills}/cloud/.gitkeep +0 -0
- /strix/{prompts → skills}/coordination/root_agent.jinja +0 -0
- /strix/{prompts → skills}/custom/.gitkeep +0 -0
- /strix/{prompts → skills}/frameworks/fastapi.jinja +0 -0
- /strix/{prompts → skills}/protocols/graphql.jinja +0 -0
- /strix/{prompts → skills}/reconnaissance/.gitkeep +0 -0
- /strix/{prompts → skills}/technologies/firebase_firestore.jinja +0 -0
- /strix/{prompts → skills}/technologies/supabase.jinja +0 -0
- /strix/{prompts → skills}/vulnerabilities/authentication_jwt.jinja +0 -0
- /strix/{prompts → skills}/vulnerabilities/broken_function_level_authorization.jinja +0 -0
- /strix/{prompts → skills}/vulnerabilities/business_logic.jinja +0 -0
- /strix/{prompts → skills}/vulnerabilities/csrf.jinja +0 -0
- /strix/{prompts → skills}/vulnerabilities/idor.jinja +0 -0
- /strix/{prompts → skills}/vulnerabilities/information_disclosure.jinja +0 -0
- /strix/{prompts → skills}/vulnerabilities/insecure_file_uploads.jinja +0 -0
- /strix/{prompts → skills}/vulnerabilities/mass_assignment.jinja +0 -0
- /strix/{prompts → skills}/vulnerabilities/open_redirect.jinja +0 -0
- /strix/{prompts → skills}/vulnerabilities/path_traversal_lfi_rfi.jinja +0 -0
- /strix/{prompts → skills}/vulnerabilities/race_conditions.jinja +0 -0
- /strix/{prompts → skills}/vulnerabilities/rce.jinja +0 -0
- /strix/{prompts → skills}/vulnerabilities/sql_injection.jinja +0 -0
- /strix/{prompts → skills}/vulnerabilities/ssrf.jinja +0 -0
- /strix/{prompts → skills}/vulnerabilities/subdomain_takeover.jinja +0 -0
- /strix/{prompts → skills}/vulnerabilities/xss.jinja +0 -0
- /strix/{prompts → skills}/vulnerabilities/xxe.jinja +0 -0
- {strix_agent-0.4.0.dist-info → strix_agent-0.6.2.dist-info}/entry_points.txt +0 -0
- {strix_agent-0.4.0.dist-info → strix_agent-0.6.2.dist-info/licenses}/LICENSE +0 -0
strix/config/config.py
ADDED
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import contextlib
|
|
2
|
+
import json
|
|
3
|
+
import os
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Config:
|
|
9
|
+
"""Configuration Manager for Strix."""
|
|
10
|
+
|
|
11
|
+
# LLM Configuration
|
|
12
|
+
strix_llm = None
|
|
13
|
+
llm_api_key = None
|
|
14
|
+
llm_api_base = None
|
|
15
|
+
openai_api_base = None
|
|
16
|
+
litellm_base_url = None
|
|
17
|
+
ollama_api_base = None
|
|
18
|
+
strix_reasoning_effort = "high"
|
|
19
|
+
strix_llm_max_retries = "5"
|
|
20
|
+
strix_memory_compressor_timeout = "30"
|
|
21
|
+
llm_timeout = "300"
|
|
22
|
+
_LLM_CANONICAL_NAMES = (
|
|
23
|
+
"strix_llm",
|
|
24
|
+
"llm_api_key",
|
|
25
|
+
"llm_api_base",
|
|
26
|
+
"openai_api_base",
|
|
27
|
+
"litellm_base_url",
|
|
28
|
+
"ollama_api_base",
|
|
29
|
+
"strix_reasoning_effort",
|
|
30
|
+
"strix_llm_max_retries",
|
|
31
|
+
"strix_memory_compressor_timeout",
|
|
32
|
+
"llm_timeout",
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
# Tool & Feature Configuration
|
|
36
|
+
perplexity_api_key = None
|
|
37
|
+
strix_disable_browser = "false"
|
|
38
|
+
|
|
39
|
+
# Runtime Configuration
|
|
40
|
+
strix_image = "ghcr.io/usestrix/strix-sandbox:0.1.11"
|
|
41
|
+
strix_runtime_backend = "docker"
|
|
42
|
+
strix_sandbox_execution_timeout = "120"
|
|
43
|
+
strix_sandbox_connect_timeout = "10"
|
|
44
|
+
|
|
45
|
+
# Telemetry
|
|
46
|
+
strix_telemetry = "1"
|
|
47
|
+
|
|
48
|
+
@classmethod
|
|
49
|
+
def _tracked_names(cls) -> list[str]:
|
|
50
|
+
return [
|
|
51
|
+
k
|
|
52
|
+
for k, v in vars(cls).items()
|
|
53
|
+
if not k.startswith("_") and k[0].islower() and (v is None or isinstance(v, str))
|
|
54
|
+
]
|
|
55
|
+
|
|
56
|
+
@classmethod
|
|
57
|
+
def tracked_vars(cls) -> list[str]:
|
|
58
|
+
return [name.upper() for name in cls._tracked_names()]
|
|
59
|
+
|
|
60
|
+
@classmethod
|
|
61
|
+
def _llm_env_vars(cls) -> set[str]:
|
|
62
|
+
return {name.upper() for name in cls._LLM_CANONICAL_NAMES}
|
|
63
|
+
|
|
64
|
+
@classmethod
|
|
65
|
+
def _llm_env_changed(cls, saved_env: dict[str, Any]) -> bool:
|
|
66
|
+
for var_name in cls._llm_env_vars():
|
|
67
|
+
current = os.getenv(var_name)
|
|
68
|
+
if current is None:
|
|
69
|
+
continue
|
|
70
|
+
if saved_env.get(var_name) != current:
|
|
71
|
+
return True
|
|
72
|
+
return False
|
|
73
|
+
|
|
74
|
+
@classmethod
|
|
75
|
+
def get(cls, name: str) -> str | None:
|
|
76
|
+
env_name = name.upper()
|
|
77
|
+
default = getattr(cls, name, None)
|
|
78
|
+
return os.getenv(env_name, default)
|
|
79
|
+
|
|
80
|
+
@classmethod
|
|
81
|
+
def config_dir(cls) -> Path:
|
|
82
|
+
return Path.home() / ".strix"
|
|
83
|
+
|
|
84
|
+
@classmethod
|
|
85
|
+
def config_file(cls) -> Path:
|
|
86
|
+
return cls.config_dir() / "cli-config.json"
|
|
87
|
+
|
|
88
|
+
@classmethod
|
|
89
|
+
def load(cls) -> dict[str, Any]:
|
|
90
|
+
path = cls.config_file()
|
|
91
|
+
if not path.exists():
|
|
92
|
+
return {}
|
|
93
|
+
try:
|
|
94
|
+
with path.open("r", encoding="utf-8") as f:
|
|
95
|
+
data: dict[str, Any] = json.load(f)
|
|
96
|
+
return data
|
|
97
|
+
except (json.JSONDecodeError, OSError):
|
|
98
|
+
return {}
|
|
99
|
+
|
|
100
|
+
@classmethod
|
|
101
|
+
def save(cls, config: dict[str, Any]) -> bool:
|
|
102
|
+
try:
|
|
103
|
+
cls.config_dir().mkdir(parents=True, exist_ok=True)
|
|
104
|
+
config_path = cls.config_file()
|
|
105
|
+
with config_path.open("w", encoding="utf-8") as f:
|
|
106
|
+
json.dump(config, f, indent=2)
|
|
107
|
+
except OSError:
|
|
108
|
+
return False
|
|
109
|
+
with contextlib.suppress(OSError):
|
|
110
|
+
config_path.chmod(0o600) # may fail on Windows
|
|
111
|
+
return True
|
|
112
|
+
|
|
113
|
+
@classmethod
|
|
114
|
+
def apply_saved(cls) -> dict[str, str]:
|
|
115
|
+
saved = cls.load()
|
|
116
|
+
env_vars = saved.get("env", {})
|
|
117
|
+
if not isinstance(env_vars, dict):
|
|
118
|
+
env_vars = {}
|
|
119
|
+
cleared_vars = {
|
|
120
|
+
var_name
|
|
121
|
+
for var_name in cls.tracked_vars()
|
|
122
|
+
if var_name in os.environ and os.environ.get(var_name) == ""
|
|
123
|
+
}
|
|
124
|
+
if cleared_vars:
|
|
125
|
+
for var_name in cleared_vars:
|
|
126
|
+
env_vars.pop(var_name, None)
|
|
127
|
+
cls.save({"env": env_vars})
|
|
128
|
+
if cls._llm_env_changed(env_vars):
|
|
129
|
+
for var_name in cls._llm_env_vars():
|
|
130
|
+
env_vars.pop(var_name, None)
|
|
131
|
+
cls.save({"env": env_vars})
|
|
132
|
+
applied = {}
|
|
133
|
+
|
|
134
|
+
for var_name, var_value in env_vars.items():
|
|
135
|
+
if var_name in cls.tracked_vars() and var_name not in os.environ:
|
|
136
|
+
os.environ[var_name] = var_value
|
|
137
|
+
applied[var_name] = var_value
|
|
138
|
+
|
|
139
|
+
return applied
|
|
140
|
+
|
|
141
|
+
@classmethod
|
|
142
|
+
def capture_current(cls) -> dict[str, Any]:
|
|
143
|
+
env_vars = {}
|
|
144
|
+
for var_name in cls.tracked_vars():
|
|
145
|
+
value = os.getenv(var_name)
|
|
146
|
+
if value:
|
|
147
|
+
env_vars[var_name] = value
|
|
148
|
+
return {"env": env_vars}
|
|
149
|
+
|
|
150
|
+
@classmethod
|
|
151
|
+
def save_current(cls) -> bool:
|
|
152
|
+
existing = cls.load().get("env", {})
|
|
153
|
+
merged = dict(existing)
|
|
154
|
+
|
|
155
|
+
for var_name in cls.tracked_vars():
|
|
156
|
+
value = os.getenv(var_name)
|
|
157
|
+
if value is None:
|
|
158
|
+
pass
|
|
159
|
+
elif value == "":
|
|
160
|
+
merged.pop(var_name, None)
|
|
161
|
+
else:
|
|
162
|
+
merged[var_name] = value
|
|
163
|
+
|
|
164
|
+
return cls.save({"env": merged})
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def apply_saved_config() -> dict[str, str]:
|
|
168
|
+
return Config.apply_saved()
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def save_current_config() -> bool:
|
|
172
|
+
return Config.save_current()
|