strix-agent 0.1.8__py3-none-any.whl → 0.1.10__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 (35) hide show
  1. strix/agents/StrixAgent/strix_agent.py +18 -6
  2. strix/agents/StrixAgent/system_prompt.jinja +29 -203
  3. strix/agents/base_agent.py +3 -0
  4. strix/cli/app.py +3 -1
  5. strix/cli/main.py +95 -8
  6. strix/cli/tool_components/terminal_renderer.py +92 -60
  7. strix/llm/config.py +1 -1
  8. strix/llm/llm.py +66 -2
  9. strix/llm/memory_compressor.py +1 -1
  10. strix/prompts/__init__.py +9 -13
  11. strix/prompts/vulnerabilities/authentication_jwt.jinja +7 -7
  12. strix/prompts/vulnerabilities/csrf.jinja +1 -1
  13. strix/prompts/vulnerabilities/idor.jinja +3 -3
  14. strix/prompts/vulnerabilities/rce.jinja +1 -1
  15. strix/prompts/vulnerabilities/sql_injection.jinja +3 -3
  16. strix/prompts/vulnerabilities/xss.jinja +3 -3
  17. strix/prompts/vulnerabilities/xxe.jinja +1 -1
  18. strix/runtime/docker_runtime.py +204 -160
  19. strix/runtime/runtime.py +3 -2
  20. strix/runtime/tool_server.py +136 -28
  21. strix/tools/agents_graph/agents_graph_actions.py +4 -10
  22. strix/tools/agents_graph/agents_graph_actions_schema.xml +18 -12
  23. strix/tools/argument_parser.py +2 -1
  24. strix/tools/executor.py +3 -0
  25. strix/tools/terminal/__init__.py +2 -2
  26. strix/tools/terminal/terminal_actions.py +22 -40
  27. strix/tools/terminal/terminal_actions_schema.xml +113 -84
  28. strix/tools/terminal/terminal_manager.py +83 -123
  29. strix/tools/terminal/terminal_session.py +447 -0
  30. {strix_agent-0.1.8.dist-info → strix_agent-0.1.10.dist-info}/METADATA +6 -4
  31. {strix_agent-0.1.8.dist-info → strix_agent-0.1.10.dist-info}/RECORD +34 -34
  32. strix/tools/terminal/terminal_instance.py +0 -231
  33. {strix_agent-0.1.8.dist-info → strix_agent-0.1.10.dist-info}/LICENSE +0 -0
  34. {strix_agent-0.1.8.dist-info → strix_agent-0.1.10.dist-info}/WHEEL +0 -0
  35. {strix_agent-0.1.8.dist-info → strix_agent-0.1.10.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,447 @@
1
+ import logging
2
+ import re
3
+ import time
4
+ import uuid
5
+ from enum import Enum
6
+ from pathlib import Path
7
+ from typing import Any
8
+
9
+ import libtmux
10
+
11
+
12
+ logger = logging.getLogger(__name__)
13
+
14
+
15
+ class BashCommandStatus(Enum):
16
+ CONTINUE = "continue"
17
+ COMPLETED = "completed"
18
+ NO_CHANGE_TIMEOUT = "no_change_timeout"
19
+ HARD_TIMEOUT = "hard_timeout"
20
+
21
+
22
+ def _remove_command_prefix(command_output: str, command: str) -> str:
23
+ return command_output.lstrip().removeprefix(command.lstrip()).lstrip()
24
+
25
+
26
+ class TerminalSession:
27
+ POLL_INTERVAL = 0.5
28
+ HISTORY_LIMIT = 10_000
29
+ PS1_END = "]$ "
30
+
31
+ def __init__(self, session_id: str, work_dir: str = "/workspace") -> None:
32
+ self.session_id = session_id
33
+ self.work_dir = str(Path(work_dir).resolve())
34
+ self._closed = False
35
+ self._cwd = self.work_dir
36
+
37
+ self.server: libtmux.Server | None = None
38
+ self.session: libtmux.Session | None = None
39
+ self.window: libtmux.Window | None = None
40
+ self.pane: libtmux.Pane | None = None
41
+
42
+ self.prev_status: BashCommandStatus | None = None
43
+ self.prev_output: str = ""
44
+ self._initialized = False
45
+
46
+ self.initialize()
47
+
48
+ @property
49
+ def PS1(self) -> str: # noqa: N802
50
+ return r"[STRIX_$?]$ "
51
+
52
+ @property
53
+ def PS1_PATTERN(self) -> str: # noqa: N802
54
+ return r"\[STRIX_(\d+)\]"
55
+
56
+ def initialize(self) -> None:
57
+ self.server = libtmux.Server()
58
+
59
+ session_name = f"strix-{self.session_id}-{uuid.uuid4()}"
60
+ self.session = self.server.new_session(
61
+ session_name=session_name,
62
+ start_directory=self.work_dir,
63
+ kill_session=True,
64
+ x=120,
65
+ y=30,
66
+ )
67
+
68
+ self.session.set_option("history-limit", str(self.HISTORY_LIMIT))
69
+ self.session.history_limit = self.HISTORY_LIMIT
70
+
71
+ _initial_window = self.session.active_window
72
+ self.window = self.session.new_window(
73
+ window_name="bash",
74
+ window_shell="/bin/bash",
75
+ start_directory=self.work_dir,
76
+ )
77
+ self.pane = self.window.active_pane
78
+ _initial_window.kill()
79
+
80
+ self.pane.send_keys(f'export PROMPT_COMMAND=\'export PS1="{self.PS1}"\'; export PS2=""')
81
+ time.sleep(0.1)
82
+ self._clear_screen()
83
+
84
+ self.prev_status = None
85
+ self.prev_output = ""
86
+ self._closed = False
87
+
88
+ self._cwd = str(Path(self.work_dir).resolve())
89
+ self._initialized = True
90
+
91
+ assert self.server is not None
92
+ assert self.session is not None
93
+ assert self.window is not None
94
+ assert self.pane is not None
95
+
96
+ def _get_pane_content(self) -> str:
97
+ if not self.pane:
98
+ raise RuntimeError("Terminal session not properly initialized")
99
+ return "\n".join(
100
+ line.rstrip() for line in self.pane.cmd("capture-pane", "-J", "-pS", "-").stdout
101
+ )
102
+
103
+ def _clear_screen(self) -> None:
104
+ if not self.pane:
105
+ raise RuntimeError("Terminal session not properly initialized")
106
+ self.pane.send_keys("C-l", enter=False)
107
+ time.sleep(0.1)
108
+ self.pane.cmd("clear-history")
109
+
110
+ def _is_control_key(self, command: str) -> bool:
111
+ return (
112
+ (command.startswith("C-") and len(command) >= 3)
113
+ or (command.startswith("^") and len(command) >= 2)
114
+ or (command.startswith("S-") and len(command) >= 3)
115
+ or (command.startswith("M-") and len(command) >= 3)
116
+ )
117
+
118
+ def _is_function_key(self, command: str) -> bool:
119
+ if not command.startswith("F") or len(command) > 3:
120
+ return False
121
+ try:
122
+ num_part = command[1:]
123
+ return num_part.isdigit() and 1 <= int(num_part) <= 12
124
+ except (ValueError, IndexError):
125
+ return False
126
+
127
+ def _is_navigation_or_special_key(self, command: str) -> bool:
128
+ navigation_keys = {"Up", "Down", "Left", "Right", "Home", "End"}
129
+ special_keys = {"BSpace", "BTab", "DC", "Enter", "Escape", "IC", "Space", "Tab"}
130
+ page_keys = {"NPage", "PageDown", "PgDn", "PPage", "PageUp", "PgUp"}
131
+
132
+ return command in navigation_keys or command in special_keys or command in page_keys
133
+
134
+ def _is_complex_modifier_key(self, command: str) -> bool:
135
+ return "-" in command and any(
136
+ command.startswith(prefix)
137
+ for prefix in ["C-S-", "C-M-", "S-M-", "M-S-", "M-C-", "S-C-"]
138
+ )
139
+
140
+ def _is_special_key(self, command: str) -> bool:
141
+ _command = command.strip()
142
+
143
+ if not _command:
144
+ return False
145
+
146
+ return (
147
+ self._is_control_key(_command)
148
+ or self._is_function_key(_command)
149
+ or self._is_navigation_or_special_key(_command)
150
+ or self._is_complex_modifier_key(_command)
151
+ )
152
+
153
+ def _matches_ps1_metadata(self, content: str) -> list[re.Match[str]]:
154
+ return list(re.finditer(self.PS1_PATTERN + r"\]\$ ", content))
155
+
156
+ def _get_command_output(
157
+ self,
158
+ command: str,
159
+ raw_command_output: str,
160
+ continue_prefix: str = "",
161
+ ) -> str:
162
+ if self.prev_output:
163
+ command_output = raw_command_output.removeprefix(self.prev_output)
164
+ if continue_prefix:
165
+ command_output = continue_prefix + command_output
166
+ else:
167
+ command_output = raw_command_output
168
+ self.prev_output = raw_command_output
169
+ command_output = _remove_command_prefix(command_output, command)
170
+ return command_output.rstrip()
171
+
172
+ def _combine_outputs_between_matches(
173
+ self,
174
+ pane_content: str,
175
+ ps1_matches: list[re.Match[str]],
176
+ get_content_before_last_match: bool = False,
177
+ ) -> str:
178
+ if len(ps1_matches) == 1:
179
+ if get_content_before_last_match:
180
+ return pane_content[: ps1_matches[0].start()]
181
+ return pane_content[ps1_matches[0].end() + 1 :]
182
+ if len(ps1_matches) == 0:
183
+ return pane_content
184
+
185
+ combined_output = ""
186
+ for i in range(len(ps1_matches) - 1):
187
+ output_segment = pane_content[ps1_matches[i].end() + 1 : ps1_matches[i + 1].start()]
188
+ combined_output += output_segment + "\n"
189
+ combined_output += pane_content[ps1_matches[-1].end() + 1 :]
190
+ return combined_output
191
+
192
+ def _extract_exit_code_from_matches(self, ps1_matches: list[re.Match[str]]) -> int | None:
193
+ if not ps1_matches:
194
+ return None
195
+
196
+ last_match = ps1_matches[-1]
197
+ try:
198
+ return int(last_match.group(1))
199
+ except (ValueError, IndexError):
200
+ return None
201
+
202
+ def _handle_empty_command(
203
+ self,
204
+ cur_pane_output: str,
205
+ ps1_matches: list[re.Match[str]],
206
+ is_command_running: bool,
207
+ timeout: float,
208
+ ) -> dict[str, Any]:
209
+ if not is_command_running:
210
+ raw_command_output = self._combine_outputs_between_matches(cur_pane_output, ps1_matches)
211
+ command_output = self._get_command_output("", raw_command_output)
212
+ return {
213
+ "content": command_output,
214
+ "status": "completed",
215
+ "exit_code": 0,
216
+ "working_dir": self._cwd,
217
+ }
218
+
219
+ start_time = time.time()
220
+ last_pane_output = cur_pane_output
221
+
222
+ while True:
223
+ cur_pane_output = self._get_pane_content()
224
+ ps1_matches = self._matches_ps1_metadata(cur_pane_output)
225
+
226
+ if cur_pane_output.rstrip().endswith(self.PS1_END.rstrip()) or len(ps1_matches) > 0:
227
+ exit_code = self._extract_exit_code_from_matches(ps1_matches)
228
+ raw_command_output = self._combine_outputs_between_matches(
229
+ cur_pane_output, ps1_matches
230
+ )
231
+ command_output = self._get_command_output("", raw_command_output)
232
+ self.prev_status = BashCommandStatus.COMPLETED
233
+ self.prev_output = ""
234
+ self._ready_for_next_command()
235
+ return {
236
+ "content": command_output,
237
+ "status": "completed",
238
+ "exit_code": exit_code or 0,
239
+ "working_dir": self._cwd,
240
+ }
241
+
242
+ elapsed_time = time.time() - start_time
243
+ if elapsed_time >= timeout:
244
+ raw_command_output = self._combine_outputs_between_matches(
245
+ cur_pane_output, ps1_matches
246
+ )
247
+ command_output = self._get_command_output("", raw_command_output)
248
+ return {
249
+ "content": command_output
250
+ + f"\n[Command still running after {timeout}s - showing output so far]",
251
+ "status": "running",
252
+ "exit_code": None,
253
+ "working_dir": self._cwd,
254
+ }
255
+
256
+ if cur_pane_output != last_pane_output:
257
+ last_pane_output = cur_pane_output
258
+
259
+ time.sleep(self.POLL_INTERVAL)
260
+
261
+ def _handle_input_command(
262
+ self, command: str, no_enter: bool, is_command_running: bool
263
+ ) -> dict[str, Any]:
264
+ if not is_command_running:
265
+ return {
266
+ "content": "No command is currently running. Cannot send input.",
267
+ "status": "error",
268
+ "exit_code": None,
269
+ "working_dir": self._cwd,
270
+ }
271
+
272
+ if not self.pane:
273
+ raise RuntimeError("Terminal session not properly initialized")
274
+
275
+ is_special_key = self._is_special_key(command)
276
+ should_add_enter = not is_special_key and not no_enter
277
+ self.pane.send_keys(command, enter=should_add_enter)
278
+
279
+ time.sleep(2)
280
+ cur_pane_output = self._get_pane_content()
281
+ ps1_matches = self._matches_ps1_metadata(cur_pane_output)
282
+ raw_command_output = self._combine_outputs_between_matches(cur_pane_output, ps1_matches)
283
+ command_output = self._get_command_output(command, raw_command_output)
284
+
285
+ is_still_running = not (
286
+ cur_pane_output.rstrip().endswith(self.PS1_END.rstrip()) or len(ps1_matches) > 0
287
+ )
288
+
289
+ if is_still_running:
290
+ return {
291
+ "content": command_output,
292
+ "status": "running",
293
+ "exit_code": None,
294
+ "working_dir": self._cwd,
295
+ }
296
+
297
+ exit_code = self._extract_exit_code_from_matches(ps1_matches)
298
+ self.prev_status = BashCommandStatus.COMPLETED
299
+ self.prev_output = ""
300
+ self._ready_for_next_command()
301
+ return {
302
+ "content": command_output,
303
+ "status": "completed",
304
+ "exit_code": exit_code or 0,
305
+ "working_dir": self._cwd,
306
+ }
307
+
308
+ def _execute_new_command(self, command: str, no_enter: bool, timeout: float) -> dict[str, Any]:
309
+ if not self.pane:
310
+ raise RuntimeError("Terminal session not properly initialized")
311
+
312
+ initial_pane_output = self._get_pane_content()
313
+ initial_ps1_matches = self._matches_ps1_metadata(initial_pane_output)
314
+ initial_ps1_count = len(initial_ps1_matches)
315
+
316
+ start_time = time.time()
317
+ last_pane_output = initial_pane_output
318
+
319
+ is_special_key = self._is_special_key(command)
320
+ should_add_enter = not is_special_key and not no_enter
321
+ self.pane.send_keys(command, enter=should_add_enter)
322
+
323
+ while True:
324
+ cur_pane_output = self._get_pane_content()
325
+ ps1_matches = self._matches_ps1_metadata(cur_pane_output)
326
+ current_ps1_count = len(ps1_matches)
327
+
328
+ if cur_pane_output != last_pane_output:
329
+ last_pane_output = cur_pane_output
330
+
331
+ if current_ps1_count > initial_ps1_count or cur_pane_output.rstrip().endswith(
332
+ self.PS1_END.rstrip()
333
+ ):
334
+ exit_code = self._extract_exit_code_from_matches(ps1_matches)
335
+
336
+ get_content_before_last_match = bool(len(ps1_matches) == 1)
337
+ raw_command_output = self._combine_outputs_between_matches(
338
+ cur_pane_output,
339
+ ps1_matches,
340
+ get_content_before_last_match=get_content_before_last_match,
341
+ )
342
+
343
+ command_output = self._get_command_output(command, raw_command_output)
344
+ self.prev_status = BashCommandStatus.COMPLETED
345
+ self.prev_output = ""
346
+ self._ready_for_next_command()
347
+
348
+ return {
349
+ "content": command_output,
350
+ "status": "completed",
351
+ "exit_code": exit_code or 0,
352
+ "working_dir": self._cwd,
353
+ }
354
+
355
+ elapsed_time = time.time() - start_time
356
+ if elapsed_time >= timeout:
357
+ raw_command_output = self._combine_outputs_between_matches(
358
+ cur_pane_output, ps1_matches
359
+ )
360
+ command_output = self._get_command_output(
361
+ command,
362
+ raw_command_output,
363
+ continue_prefix="[Below is the output of the previous command.]\n",
364
+ )
365
+ self.prev_status = BashCommandStatus.CONTINUE
366
+
367
+ timeout_msg = (
368
+ f"\n[Command still running after {timeout}s - showing output so far. "
369
+ "Use C-c to interrupt if needed.]"
370
+ )
371
+ return {
372
+ "content": command_output + timeout_msg,
373
+ "status": "running",
374
+ "exit_code": None,
375
+ "working_dir": self._cwd,
376
+ }
377
+
378
+ time.sleep(self.POLL_INTERVAL)
379
+
380
+ def execute(
381
+ self, command: str, is_input: bool = False, timeout: float = 10.0, no_enter: bool = False
382
+ ) -> dict[str, Any]:
383
+ if not self._initialized:
384
+ raise RuntimeError("Bash session is not initialized")
385
+
386
+ cur_pane_output = self._get_pane_content()
387
+ ps1_matches = self._matches_ps1_metadata(cur_pane_output)
388
+ is_command_running = not (
389
+ cur_pane_output.rstrip().endswith(self.PS1_END.rstrip()) or len(ps1_matches) > 0
390
+ )
391
+
392
+ if command.strip() == "":
393
+ return self._handle_empty_command(
394
+ cur_pane_output, ps1_matches, is_command_running, timeout
395
+ )
396
+
397
+ is_special_key = self._is_special_key(command)
398
+
399
+ if is_input:
400
+ return self._handle_input_command(command, no_enter, is_command_running)
401
+
402
+ if is_special_key and is_command_running:
403
+ return self._handle_input_command(command, no_enter, is_command_running)
404
+
405
+ if is_command_running:
406
+ return {
407
+ "content": (
408
+ "A command is already running. Use is_input=true to send input to it, "
409
+ "or interrupt it first (e.g., with C-c)."
410
+ ),
411
+ "status": "error",
412
+ "exit_code": None,
413
+ "working_dir": self._cwd,
414
+ }
415
+
416
+ return self._execute_new_command(command, no_enter, timeout)
417
+
418
+ def _ready_for_next_command(self) -> None:
419
+ self._clear_screen()
420
+
421
+ def is_running(self) -> bool:
422
+ if self._closed or not self.session:
423
+ return False
424
+ try:
425
+ return self.session.id in [s.id for s in self.server.sessions] if self.server else False
426
+ except (AttributeError, OSError) as e:
427
+ logger.debug("Error checking if session is running: %s", e)
428
+ return False
429
+
430
+ def get_working_dir(self) -> str:
431
+ return self._cwd
432
+
433
+ def close(self) -> None:
434
+ if self._closed:
435
+ return
436
+
437
+ if self.session:
438
+ try:
439
+ self.session.kill()
440
+ except (AttributeError, OSError) as e:
441
+ logger.debug("Error closing terminal session: %s", e)
442
+
443
+ self._closed = True
444
+ self.server = None
445
+ self.session = None
446
+ self.window = None
447
+ self.pane = None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: strix-agent
3
- Version: 0.1.8
3
+ Version: 0.1.10
4
4
  Summary: Open-source AI Hackers for your apps
5
5
  License: Apache-2.0
6
6
  Keywords: cybersecurity,security,vulnerability,scanner,pentest,agent,ai,cli
@@ -22,8 +22,10 @@ Requires-Dist: docker (>=7.1.0,<8.0.0)
22
22
  Requires-Dist: fastapi
23
23
  Requires-Dist: gql[requests] (>=3.5.3,<4.0.0)
24
24
  Requires-Dist: ipython (>=9.3.0,<10.0.0)
25
- Requires-Dist: litellm[proxy] (>=1.75.5.post1,<2.0.0)
25
+ Requires-Dist: libtmux (>=0.46.2,<0.47.0)
26
+ Requires-Dist: litellm[proxy] (>=1.75.8,<1.76.0)
26
27
  Requires-Dist: numpydoc (>=1.8.0,<2.0.0)
28
+ Requires-Dist: openai (>=1.99.5,<1.100.0)
27
29
  Requires-Dist: openhands-aci (>=0.3.0,<0.4.0)
28
30
  Requires-Dist: playwright (>=1.48.0,<2.0.0)
29
31
  Requires-Dist: pydantic[email] (>=2.11.3,<3.0.0)
@@ -68,7 +70,7 @@ Strix are autonomous AI agents that act just like real hackers - they run your c
68
70
  pipx install strix-agent
69
71
 
70
72
  # Configure AI provider
71
- export STRIX_LLM="anthropic/claude-opus-4-1-20250805"
73
+ export STRIX_LLM="openai/gpt-5"
72
74
  export LLM_API_KEY="your-api-key"
73
75
 
74
76
  # Run security assessment
@@ -131,7 +133,7 @@ strix --target api.your-app.com --instruction "Prioritize authentication and aut
131
133
 
132
134
  ```bash
133
135
  # Required
134
- export STRIX_LLM="anthropic/claude-opus-4-1-20250805"
136
+ export STRIX_LLM="openai/gpt-5"
135
137
  export LLM_API_KEY="your-api-key"
136
138
 
137
139
  # Recommended
@@ -1,14 +1,14 @@
1
1
  strix/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  strix/agents/StrixAgent/__init__.py,sha256=VORJn9aPTJyNn2-QAv6DbTxO1P9wBQoSZlAw-YuTJhQ,63
3
- strix/agents/StrixAgent/strix_agent.py,sha256=CZNhwr1jao6Y64_PS5or83KZJrM2RoZjfj7IgBy0ph0,2117
4
- strix/agents/StrixAgent/system_prompt.jinja,sha256=zQaz6k7HjY2ZbKw5fcO1HaYnqr1nwkry5IDtuYmhJ8w,25652
3
+ strix/agents/StrixAgent/strix_agent.py,sha256=T0B2rcPe_YUE6Fv-B9Hl9C-xHTuvDL5whGEArqFRXVk,2676
4
+ strix/agents/StrixAgent/system_prompt.jinja,sha256=NDOnqVDC1Eayixmv2PZEO-OM0_Ok0fWLZ5fhS2XOHzI,15412
5
5
  strix/agents/__init__.py,sha256=F64zhlv4XZIvYJSL9eSSuKUsIVGPLG3ycpQBhZwvE6A,168
6
- strix/agents/base_agent.py,sha256=SnpVGft0SFKcUBYzsKyC0WCxYBS9232msw6yQJhK2tk,14329
6
+ strix/agents/base_agent.py,sha256=YMluoaFLbUnYDm0pOrDJ3zckZOSzvpzXhBDOGGU_YVg,14452
7
7
  strix/agents/state.py,sha256=ORN2VyLOcQrppiuGcelD0C-1-uhxc6TS4AEqdbK7LZg,4858
8
8
  strix/cli/__init__.py,sha256=ww23sFOQhICEIrIo0MtwWv2qHW5qUprvPj8QVjv3SM0,44
9
- strix/cli/app.py,sha256=5p-jnS628Ax_HzH7juUuuf605ItSCDzKzzJtuvrhwk0,39114
9
+ strix/cli/app.py,sha256=x05-SyJrZrodGbw-vS5f0oNMJrXzM2ESRKlQu83d3O8,39284
10
10
  strix/cli/assets/cli.tcss,sha256=y7N_l8sJhDeflwqjmGz_Zm6xhVzpKUPJ6zcci-3qesE,11914
11
- strix/cli/main.py,sha256=WITQC-_NWXQMGpgJIRK6JrHdHr-mFkIysd9cEjhTQ64,18854
11
+ strix/cli/main.py,sha256=3T2ncIPXMvtPP_GRiai5zWuO4PXz89Xphet365LLcy4,21650
12
12
  strix/cli/tool_components/__init__.py,sha256=Dz5ci3VMzvhlPOwQ2x9Nd11cmFzx1OP7sdlpZPMTT4k,935
13
13
  strix/cli/tool_components/agents_graph_renderer.py,sha256=e470Fj47WI9DDrOKLM-8YqpToXPohwnzHQuA4Kp7qGs,4380
14
14
  strix/cli/tool_components/base_renderer.py,sha256=e-xD2I3N8EDN-94tfMKAvVt0NGYC-5m2USNRGFMrEQc,1867
@@ -21,44 +21,44 @@ strix/cli/tool_components/python_renderer.py,sha256=uddPvUVpeCU3ihHfn3zpM-IaWC88
21
21
  strix/cli/tool_components/registry.py,sha256=faTEi5upl3Z9okx-PCHqHSsN9DBGnTh3IaWvBFm6LOg,2338
22
22
  strix/cli/tool_components/reporting_renderer.py,sha256=C_q7a548mu9U9IYD0YiDeN3ShTDEiGdCmKnyzFCUWGE,1719
23
23
  strix/cli/tool_components/scan_info_renderer.py,sha256=9gcwJIzp9R9pOn8DtYv8WtRF1QL-sWXihGiA3JMbZmw,1981
24
- strix/cli/tool_components/terminal_renderer.py,sha256=fvicmKAZXU6_pefoewQe0y7CuKXjxLnLeVpElL32AEc,3036
24
+ strix/cli/tool_components/terminal_renderer.py,sha256=09gP26djA9i3uz1Lwbc09gYn9EQQGoFBNqMM86607nw,3330
25
25
  strix/cli/tool_components/thinking_renderer.py,sha256=s8Y1V8lvDYv9sottCZPOWQmKLyvDP1wpHO22x7XMc_U,927
26
26
  strix/cli/tool_components/user_message_renderer.py,sha256=6gHJ1hG-pwcTsxLM7JuYZuaDu8cZ2MeOuUDF3LGy-4I,1432
27
27
  strix/cli/tool_components/web_search_renderer.py,sha256=JnJa22ACIcRksfxxdenesUo8Th9cHSxo-fej9YcuYHs,911
28
28
  strix/cli/tracer.py,sha256=Dhr-0GCrRWxQ7mij0wosqC5hH-4_79_3p11ZqYF1iw0,11058
29
29
  strix/llm/__init__.py,sha256=tzsJlDGGQE_Hw917dyzBWtwXsajZsIS-qdlPuS6EmSY,139
30
- strix/llm/config.py,sha256=UkHAhbaUV0WcE-TC6WnT0ZSf0qGlseFV_OPx4bUv-tY,625
31
- strix/llm/llm.py,sha256=fJLmx0tLaUUVIqf1hdcrqHeZ2_-CUcFM8RXH1G9XqTs,11034
32
- strix/llm/memory_compressor.py,sha256=HBG2V2YEkM_fP7D-_rQ6QFE42ZojdlYoDOivzKhpopU,6878
30
+ strix/llm/config.py,sha256=iBv1tuUOUDcP2gVQWhjtN8wtO5lWOipsER7Rnc3p6k4,603
31
+ strix/llm/llm.py,sha256=wtzAh7THjPoZGOH12Fe-5IDZn_9qwwS7M9-4EfXFfWc,12719
32
+ strix/llm/memory_compressor.py,sha256=U2eD90SmVOxjZJTiNwVmf4G6g3lnhfwqIPtwhLztoag,6856
33
33
  strix/llm/request_queue.py,sha256=hBjj8c_6_D30-j1FCz-fm2eHJA7XGE7rk52j_8QR_4s,2090
34
34
  strix/llm/utils.py,sha256=M84mVstjWY3-fwc2KyVAcfpF3IMHWnbkjRpGUUQ1TcM,2474
35
- strix/prompts/__init__.py,sha256=JGzGxp0J86mpmCcWurtikKh_xcd8PvVfjtFDOOh0NaQ,3621
35
+ strix/prompts/__init__.py,sha256=ocFjc9d-QolphPKr2cMVMHS52piJSSubBJdrwEFEBTI,3490
36
36
  strix/prompts/coordination/root_agent.jinja,sha256=Z34uffB-lIt6Oei307dtD7oyXSmX2DSApeoRcA3LcnM,1902
37
- strix/prompts/vulnerabilities/authentication_jwt.jinja,sha256=o0mfundZ3OfTGHOJRuGb8W17XuoZDcUoegIKrmmMxqU,3827
37
+ strix/prompts/vulnerabilities/authentication_jwt.jinja,sha256=FA2z8zdugITAc6QphrocA5O8bqyTl9TN_iTJxrtyNkQ,3974
38
38
  strix/prompts/vulnerabilities/business_logic.jinja,sha256=pazAYPIduxcnTyn0rDJj7nQ2Gmr9Ww6EqtY1b-oKC_k,4036
39
- strix/prompts/vulnerabilities/csrf.jinja,sha256=u5gxyUT44enHyG3fqBo4X-4Sd4STSDapGZyOBH6iZ3k,4430
40
- strix/prompts/vulnerabilities/idor.jinja,sha256=1q_0BNqRyA6SjRCFmPAnWMqVpDy9qaAcVDJp-xnq8VM,4345
39
+ strix/prompts/vulnerabilities/csrf.jinja,sha256=CiwzG5UFT8SEt9jlEfSU4gJvonrVSDlaiZ1ff9eYE_0,4451
40
+ strix/prompts/vulnerabilities/idor.jinja,sha256=tpk74gFvrkO2pcPeBB5BpZ2-ZusbU4X-XxFFd5SYvbM,4408
41
41
  strix/prompts/vulnerabilities/race_conditions.jinja,sha256=31aKYDqL50v5SP2keS2Gj7cTBuF3WhKIs2DKsZNezSI,4869
42
- strix/prompts/vulnerabilities/rce.jinja,sha256=PUUnIJqH5IXQm9qLV6rqIAarP_8NQo6QVhYh_55ZCOA,5792
43
- strix/prompts/vulnerabilities/sql_injection.jinja,sha256=oFTaN5ZFQ5dJSDoTbLMRkTxEw6Q4pbvPtLUo7K3bSYM,5637
42
+ strix/prompts/vulnerabilities/rce.jinja,sha256=VPkQR4vHNDph_u_wWfQKyercq9jMpn8xTWr1k-ybPck,5813
43
+ strix/prompts/vulnerabilities/sql_injection.jinja,sha256=xdcasdmd80zX7qpd9bu3Hn1BKD4qp1NEcq5yP-OgLTc,5700
44
44
  strix/prompts/vulnerabilities/ssrf.jinja,sha256=MfRs3MtvgAEauaOrCHpKIoRnS0YCZKyCDaIb_xm5EWA,4440
45
- strix/prompts/vulnerabilities/xss.jinja,sha256=ozaEuV1X4QPRLYiUAfpQplzbovQU6QmtVF115-8_xrk,6139
46
- strix/prompts/vulnerabilities/xxe.jinja,sha256=E8QUtIMQoEft7FRQzz7a2SgvrpqNecRVYvhaIWOco0w,7081
45
+ strix/prompts/vulnerabilities/xss.jinja,sha256=rVD25fOYxeVgd6k-7eePkzADxCi2XopPSSNPd4J9NWg,6202
46
+ strix/prompts/vulnerabilities/xxe.jinja,sha256=hZ_SlrQQPsDWN2UF4VhIhpXIDAK66su055uEpgAdt5Y,7102
47
47
  strix/runtime/__init__.py,sha256=v2oQ1JnfZXOTU8N3NOEI_MbxNp8BfNj8hTgvjCsNGvY,445
48
- strix/runtime/docker_runtime.py,sha256=-GNUWcqiWyxaXHI5YzlD-ZsfKW6NU23aeKERbqacvpg,10279
49
- strix/runtime/runtime.py,sha256=cHn_LnK7yLZLncVdIflz97oqNvvvhc8cWG4zsqgaF70,670
50
- strix/runtime/tool_server.py,sha256=7Swr4dgl6gEvDGzhSXsZk9__NEtmrwqg6Gnx-Ai8I5E,3466
48
+ strix/runtime/docker_runtime.py,sha256=n0RqsTuWqYSlSIyowtXbTkZ32_69vAPRhqP-Nq5JHyA,12695
49
+ strix/runtime/runtime.py,sha256=yUVLl9BTQChQgaba2jJCrEmHeJFDE9N0sF9M_XjqEbg,692
50
+ strix/runtime/tool_server.py,sha256=pKI_cL1aSEFC8b6Dqaz9bRfh0LvcCKwb6ZCN-v6OYls,6618
51
51
  strix/tools/__init__.py,sha256=_uTsOImNlJ-q5FFuQBTIYpIAgTETNI7Pm2hkaLE-Z5Y,1743
52
52
  strix/tools/agents_graph/__init__.py,sha256=FLJ2kGxXICY2pRKrC0sgIc3w3KhZo7VID7hbwYcgBfM,278
53
- strix/tools/agents_graph/agents_graph_actions.py,sha256=T0c68IQPL_SLLdUVGziZoKUZSnZeTIF599E1k-N0NfQ,20346
54
- strix/tools/agents_graph/agents_graph_actions_schema.xml,sha256=nMUg_AiIjoBqhkQTO7rxWyhut0nPTWzDGHq3Sa5s6ag,12477
55
- strix/tools/argument_parser.py,sha256=FpRFuXHrrMcLOthPkeKd2qmXk5IwFU_EMV1mL8RvPls,3835
53
+ strix/tools/agents_graph/agents_graph_actions.py,sha256=7D4MWAumYolgYpg2fbzYQkFL69Pkk6RtPZkt2gb3hyM,20374
54
+ strix/tools/agents_graph/agents_graph_actions_schema.xml,sha256=KbDu8Ds2RWyy6b4iF0WY83T7wL9lU9mJ16midNiT_uI,12645
55
+ strix/tools/argument_parser.py,sha256=FA9LY0UBtMqDRJ9yHHUzQCbGmpTQvo4xTtLiNRYG2FU,3861
56
56
  strix/tools/browser/__init__.py,sha256=7azA1td3CfwCVqMYIIzT0vGM0-JUNq3sZBYB0QnwFDk,75
57
57
  strix/tools/browser/browser_actions.py,sha256=ZmHdPoow9R-rkSjopYsY1-56fL7Tm-WDCaIPvs1_hys,7037
58
58
  strix/tools/browser/browser_actions_schema.xml,sha256=zZQD8sZWsNnxxnlY3QYDrfKHFu0x6i1vtfSOlIGyiho,9573
59
59
  strix/tools/browser/browser_instance.py,sha256=vgb-dJP20SLaBOhFExn-uwfjdISBrHJpG7ewfiKQkYU,18605
60
60
  strix/tools/browser/tab_manager.py,sha256=SMkDFOgEr3ADK2rP5Ko2uK-A24-8p0VsbjoxEj5eU-Y,13011
61
- strix/tools/executor.py,sha256=9a83t9nA2ktjRjMYEnqK9enwueItbpQhfiu4O_MyLyg,10112
61
+ strix/tools/executor.py,sha256=waqMpX7IsRtVK9RAiUu-j1VnZNRU6STV8SEGw4ZZX4o,10202
62
62
  strix/tools/file_edit/__init__.py,sha256=8f6VlEoGP627hGtcdLkr63vdrTmdb8uyPIqB0qVgZd8,141
63
63
  strix/tools/file_edit/file_edit_actions.py,sha256=Aq-LwzmmfUJrBZWy5TeP9Pxz9TlmeqOSqemD4jBkt2s,3951
64
64
  strix/tools/file_edit/file_edit_actions_schema.xml,sha256=tt0_QgSjOtTEy8ordsXUcEiVTePiybgn4aisZJ_qnbc,5477
@@ -81,19 +81,19 @@ strix/tools/registry.py,sha256=zG8T-bsJQRBqn4S1IKIAZ2Yzu1pp8I9RaPrCg2axCjU,6025
81
81
  strix/tools/reporting/__init__.py,sha256=_cYxb3OP0vZtCwO_ExLBjhAn1ECaG-SH1Z4wfGDyT1Y,110
82
82
  strix/tools/reporting/reporting_actions.py,sha256=RIp3u3pmlRXx_uCr2Kc8R7yYiSe3pzPtVSUHw3cNM4s,2186
83
83
  strix/tools/reporting/reporting_actions_schema.xml,sha256=y_g0iuyBuCh79fvA0ri8fOPlXY7uUd-P-mdzXLUyIJg,1629
84
- strix/tools/terminal/__init__.py,sha256=yF9qWbC9tYXYbkQsX5p8NNKwxlpmlGrF8UU4r6y0qwI,78
85
- strix/tools/terminal/terminal_actions.py,sha256=CMy3SzbMfIwDWVurOcRh28VBSoOexrUirF3kjCiHtq4,1706
86
- strix/tools/terminal/terminal_actions_schema.xml,sha256=aBUt3hOcfudnmeX5_rQVqqqE6MGiLuuVWa-GklVzkmk,7280
87
- strix/tools/terminal/terminal_instance.py,sha256=rnLtP54eswcpw-gjKzHPrrqytf2iHahpSH0Bc6Z6Xlo,7280
88
- strix/tools/terminal/terminal_manager.py,sha256=xV4MPnaFn9yJQ8bZgptupYjBuSO_NlFUXXqqxb6gfVI,6601
84
+ strix/tools/terminal/__init__.py,sha256=xvflcrbLQ31o_K3cWFsIhTm7gxY5JF0nVnhOIadwFV0,80
85
+ strix/tools/terminal/terminal_actions.py,sha256=9BGsK7Io7PyW8YGpJfXHeJTP3AVqBAgaKZl-1YziF8Y,888
86
+ strix/tools/terminal/terminal_actions_schema.xml,sha256=X-dbr9Bybdx58qvA71GCHPCpdfj__85DpsUCf_t_1qk,6971
87
+ strix/tools/terminal/terminal_manager.py,sha256=cTWosczkMoSRSjQ-xPR56D5cIYcylA3NAZb4FSi32Ko,4838
88
+ strix/tools/terminal/terminal_session.py,sha256=peHQrYCty-KHYECbT8jOww06ayGUK_rAcnTlYIfQe00,16008
89
89
  strix/tools/thinking/__init__.py,sha256=-v4fG4fyFkqsTSWspDtCT6IRlyRM8zeUwEM-kscaxDE,58
90
90
  strix/tools/thinking/thinking_actions.py,sha256=Ll96ZjlnOS5zSRSCmGzi7hcgyURBlCdq4xcstEhdRao,564
91
91
  strix/tools/thinking/thinking_actions_schema.xml,sha256=otD4dOhQx4uyudLnjA_HIP6EmUS5NvKG4l3CVFrg8go,2756
92
92
  strix/tools/web_search/__init__.py,sha256=m5PCHXqeNVraLRLNIbh54Z2N4Y_75d-ftqwyq3dbCd0,70
93
93
  strix/tools/web_search/web_search_actions.py,sha256=LRS3AjGO4JLIyu_B6-ogfWOsnENwqrrCa8Rz0vxuuGQ,3107
94
94
  strix/tools/web_search/web_search_actions_schema.xml,sha256=Ihc3Gv4LaPI_MzBbwZOt3y4pwg9xmtl8KfPNvFihEP4,4805
95
- strix_agent-0.1.8.dist-info/LICENSE,sha256=fblpcTQlHjFL2NOSV_4XDJiz4q2bLtZ-l6yvlhPnueM,11345
96
- strix_agent-0.1.8.dist-info/METADATA,sha256=7JmVDFBTSKSlQdRozliZQ45urg1B7TF9A6eiK-8NV2A,6571
97
- strix_agent-0.1.8.dist-info/WHEEL,sha256=RaoafKOydTQ7I_I3JTrPCg6kUmTgtm4BornzOqyEfJ8,88
98
- strix_agent-0.1.8.dist-info/entry_points.txt,sha256=sswIgnkzSVSzQ3Rd046g7mhIPQaj_7RYlXgU_bQelF0,45
99
- strix_agent-0.1.8.dist-info/RECORD,,
95
+ strix_agent-0.1.10.dist-info/LICENSE,sha256=fblpcTQlHjFL2NOSV_4XDJiz4q2bLtZ-l6yvlhPnueM,11345
96
+ strix_agent-0.1.10.dist-info/METADATA,sha256=OIeEKEsIIN1KSrXmr4WvHgMDeQbcZ5xggLXVZxBaDok,6607
97
+ strix_agent-0.1.10.dist-info/WHEEL,sha256=RaoafKOydTQ7I_I3JTrPCg6kUmTgtm4BornzOqyEfJ8,88
98
+ strix_agent-0.1.10.dist-info/entry_points.txt,sha256=sswIgnkzSVSzQ3Rd046g7mhIPQaj_7RYlXgU_bQelF0,45
99
+ strix_agent-0.1.10.dist-info/RECORD,,