strix-agent 0.1.9__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.
- strix/agents/StrixAgent/strix_agent.py +18 -6
- strix/agents/StrixAgent/system_prompt.jinja +26 -7
- strix/agents/base_agent.py +3 -0
- strix/cli/app.py +3 -1
- strix/cli/main.py +88 -1
- strix/cli/tool_components/terminal_renderer.py +92 -60
- strix/runtime/docker_runtime.py +204 -160
- strix/runtime/runtime.py +3 -2
- strix/runtime/tool_server.py +136 -28
- strix/tools/agents_graph/agents_graph_actions.py +4 -4
- strix/tools/agents_graph/agents_graph_actions_schema.xml +17 -1
- strix/tools/argument_parser.py +2 -1
- strix/tools/executor.py +3 -0
- strix/tools/terminal/__init__.py +2 -2
- strix/tools/terminal/terminal_actions.py +22 -40
- strix/tools/terminal/terminal_actions_schema.xml +113 -88
- strix/tools/terminal/terminal_manager.py +83 -123
- strix/tools/terminal/terminal_session.py +447 -0
- {strix_agent-0.1.9.dist-info → strix_agent-0.1.10.dist-info}/METADATA +4 -2
- {strix_agent-0.1.9.dist-info → strix_agent-0.1.10.dist-info}/RECORD +23 -23
- strix/tools/terminal/terminal_instance.py +0 -231
- {strix_agent-0.1.9.dist-info → strix_agent-0.1.10.dist-info}/LICENSE +0 -0
- {strix_agent-0.1.9.dist-info → strix_agent-0.1.10.dist-info}/WHEEL +0 -0
- {strix_agent-0.1.9.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.
|
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:
|
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)
|
@@ -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=
|
4
|
-
strix/agents/StrixAgent/system_prompt.jinja,sha256=
|
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=
|
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=
|
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=
|
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,7 +21,7 @@ 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=
|
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
|
@@ -45,20 +45,20 @@ strix/prompts/vulnerabilities/ssrf.jinja,sha256=MfRs3MtvgAEauaOrCHpKIoRnS0YCZKyC
|
|
45
45
|
strix/prompts/vulnerabilities/xss.jinja,sha256=rVD25fOYxeVgd6k-7eePkzADxCi2XopPSSNPd4J9NWg,6202
|
46
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
|
49
|
-
strix/runtime/runtime.py,sha256=
|
50
|
-
strix/runtime/tool_server.py,sha256=
|
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=
|
54
|
-
strix/tools/agents_graph/agents_graph_actions_schema.xml,sha256=
|
55
|
-
strix/tools/argument_parser.py,sha256=
|
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=
|
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=
|
85
|
-
strix/tools/terminal/terminal_actions.py,sha256=
|
86
|
-
strix/tools/terminal/terminal_actions_schema.xml,sha256=
|
87
|
-
strix/tools/terminal/
|
88
|
-
strix/tools/terminal/
|
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.
|
96
|
-
strix_agent-0.1.
|
97
|
-
strix_agent-0.1.
|
98
|
-
strix_agent-0.1.
|
99
|
-
strix_agent-0.1.
|
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,,
|