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.
Files changed (117) hide show
  1. strix/agents/StrixAgent/strix_agent.py +3 -3
  2. strix/agents/StrixAgent/system_prompt.jinja +30 -26
  3. strix/agents/base_agent.py +159 -75
  4. strix/agents/state.py +5 -2
  5. strix/config/__init__.py +12 -0
  6. strix/config/config.py +172 -0
  7. strix/interface/assets/tui_styles.tcss +195 -230
  8. strix/interface/cli.py +16 -41
  9. strix/interface/main.py +151 -74
  10. strix/interface/streaming_parser.py +119 -0
  11. strix/interface/tool_components/__init__.py +4 -0
  12. strix/interface/tool_components/agent_message_renderer.py +190 -0
  13. strix/interface/tool_components/agents_graph_renderer.py +54 -38
  14. strix/interface/tool_components/base_renderer.py +68 -36
  15. strix/interface/tool_components/browser_renderer.py +106 -91
  16. strix/interface/tool_components/file_edit_renderer.py +117 -36
  17. strix/interface/tool_components/finish_renderer.py +43 -10
  18. strix/interface/tool_components/notes_renderer.py +63 -38
  19. strix/interface/tool_components/proxy_renderer.py +133 -92
  20. strix/interface/tool_components/python_renderer.py +121 -8
  21. strix/interface/tool_components/registry.py +19 -12
  22. strix/interface/tool_components/reporting_renderer.py +196 -28
  23. strix/interface/tool_components/scan_info_renderer.py +22 -19
  24. strix/interface/tool_components/terminal_renderer.py +270 -90
  25. strix/interface/tool_components/thinking_renderer.py +8 -6
  26. strix/interface/tool_components/todo_renderer.py +225 -0
  27. strix/interface/tool_components/user_message_renderer.py +26 -19
  28. strix/interface/tool_components/web_search_renderer.py +7 -6
  29. strix/interface/tui.py +907 -262
  30. strix/interface/utils.py +236 -4
  31. strix/llm/__init__.py +6 -2
  32. strix/llm/config.py +8 -5
  33. strix/llm/dedupe.py +217 -0
  34. strix/llm/llm.py +209 -356
  35. strix/llm/memory_compressor.py +6 -5
  36. strix/llm/utils.py +17 -8
  37. strix/runtime/__init__.py +12 -3
  38. strix/runtime/docker_runtime.py +121 -202
  39. strix/runtime/tool_server.py +55 -95
  40. strix/skills/README.md +64 -0
  41. strix/skills/__init__.py +110 -0
  42. strix/{prompts → skills}/frameworks/nextjs.jinja +26 -0
  43. strix/skills/scan_modes/deep.jinja +145 -0
  44. strix/skills/scan_modes/quick.jinja +63 -0
  45. strix/skills/scan_modes/standard.jinja +91 -0
  46. strix/telemetry/README.md +38 -0
  47. strix/telemetry/__init__.py +7 -1
  48. strix/telemetry/posthog.py +137 -0
  49. strix/telemetry/tracer.py +194 -54
  50. strix/tools/__init__.py +11 -4
  51. strix/tools/agents_graph/agents_graph_actions.py +20 -21
  52. strix/tools/agents_graph/agents_graph_actions_schema.xml +8 -8
  53. strix/tools/browser/browser_actions.py +10 -6
  54. strix/tools/browser/browser_actions_schema.xml +6 -1
  55. strix/tools/browser/browser_instance.py +96 -48
  56. strix/tools/browser/tab_manager.py +121 -102
  57. strix/tools/context.py +12 -0
  58. strix/tools/executor.py +63 -4
  59. strix/tools/file_edit/file_edit_actions.py +6 -3
  60. strix/tools/file_edit/file_edit_actions_schema.xml +45 -3
  61. strix/tools/finish/finish_actions.py +80 -105
  62. strix/tools/finish/finish_actions_schema.xml +121 -14
  63. strix/tools/notes/notes_actions.py +6 -33
  64. strix/tools/notes/notes_actions_schema.xml +50 -46
  65. strix/tools/proxy/proxy_actions.py +14 -2
  66. strix/tools/proxy/proxy_actions_schema.xml +0 -1
  67. strix/tools/proxy/proxy_manager.py +28 -16
  68. strix/tools/python/python_actions.py +2 -2
  69. strix/tools/python/python_actions_schema.xml +9 -1
  70. strix/tools/python/python_instance.py +39 -37
  71. strix/tools/python/python_manager.py +43 -31
  72. strix/tools/registry.py +73 -12
  73. strix/tools/reporting/reporting_actions.py +218 -31
  74. strix/tools/reporting/reporting_actions_schema.xml +256 -8
  75. strix/tools/terminal/terminal_actions.py +2 -2
  76. strix/tools/terminal/terminal_actions_schema.xml +6 -0
  77. strix/tools/terminal/terminal_manager.py +41 -30
  78. strix/tools/thinking/thinking_actions_schema.xml +27 -25
  79. strix/tools/todo/__init__.py +18 -0
  80. strix/tools/todo/todo_actions.py +568 -0
  81. strix/tools/todo/todo_actions_schema.xml +225 -0
  82. strix/utils/__init__.py +0 -0
  83. strix/utils/resource_paths.py +13 -0
  84. {strix_agent-0.4.0.dist-info → strix_agent-0.6.2.dist-info}/METADATA +90 -65
  85. strix_agent-0.6.2.dist-info/RECORD +134 -0
  86. {strix_agent-0.4.0.dist-info → strix_agent-0.6.2.dist-info}/WHEEL +1 -1
  87. strix/llm/request_queue.py +0 -87
  88. strix/prompts/README.md +0 -64
  89. strix/prompts/__init__.py +0 -109
  90. strix_agent-0.4.0.dist-info/RECORD +0 -118
  91. /strix/{prompts → skills}/cloud/.gitkeep +0 -0
  92. /strix/{prompts → skills}/coordination/root_agent.jinja +0 -0
  93. /strix/{prompts → skills}/custom/.gitkeep +0 -0
  94. /strix/{prompts → skills}/frameworks/fastapi.jinja +0 -0
  95. /strix/{prompts → skills}/protocols/graphql.jinja +0 -0
  96. /strix/{prompts → skills}/reconnaissance/.gitkeep +0 -0
  97. /strix/{prompts → skills}/technologies/firebase_firestore.jinja +0 -0
  98. /strix/{prompts → skills}/technologies/supabase.jinja +0 -0
  99. /strix/{prompts → skills}/vulnerabilities/authentication_jwt.jinja +0 -0
  100. /strix/{prompts → skills}/vulnerabilities/broken_function_level_authorization.jinja +0 -0
  101. /strix/{prompts → skills}/vulnerabilities/business_logic.jinja +0 -0
  102. /strix/{prompts → skills}/vulnerabilities/csrf.jinja +0 -0
  103. /strix/{prompts → skills}/vulnerabilities/idor.jinja +0 -0
  104. /strix/{prompts → skills}/vulnerabilities/information_disclosure.jinja +0 -0
  105. /strix/{prompts → skills}/vulnerabilities/insecure_file_uploads.jinja +0 -0
  106. /strix/{prompts → skills}/vulnerabilities/mass_assignment.jinja +0 -0
  107. /strix/{prompts → skills}/vulnerabilities/open_redirect.jinja +0 -0
  108. /strix/{prompts → skills}/vulnerabilities/path_traversal_lfi_rfi.jinja +0 -0
  109. /strix/{prompts → skills}/vulnerabilities/race_conditions.jinja +0 -0
  110. /strix/{prompts → skills}/vulnerabilities/rce.jinja +0 -0
  111. /strix/{prompts → skills}/vulnerabilities/sql_injection.jinja +0 -0
  112. /strix/{prompts → skills}/vulnerabilities/ssrf.jinja +0 -0
  113. /strix/{prompts → skills}/vulnerabilities/subdomain_takeover.jinja +0 -0
  114. /strix/{prompts → skills}/vulnerabilities/xss.jinja +0 -0
  115. /strix/{prompts → skills}/vulnerabilities/xxe.jinja +0 -0
  116. {strix_agent-0.4.0.dist-info → strix_agent-0.6.2.dist-info}/entry_points.txt +0 -0
  117. {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()