strix-agent 0.4.0__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/__init__.py +0 -0
- strix/agents/StrixAgent/__init__.py +4 -0
- strix/agents/StrixAgent/strix_agent.py +89 -0
- strix/agents/StrixAgent/system_prompt.jinja +404 -0
- strix/agents/__init__.py +10 -0
- strix/agents/base_agent.py +518 -0
- strix/agents/state.py +163 -0
- strix/interface/__init__.py +4 -0
- strix/interface/assets/tui_styles.tcss +694 -0
- strix/interface/cli.py +230 -0
- strix/interface/main.py +500 -0
- strix/interface/tool_components/__init__.py +39 -0
- strix/interface/tool_components/agents_graph_renderer.py +123 -0
- strix/interface/tool_components/base_renderer.py +62 -0
- strix/interface/tool_components/browser_renderer.py +120 -0
- strix/interface/tool_components/file_edit_renderer.py +99 -0
- strix/interface/tool_components/finish_renderer.py +31 -0
- strix/interface/tool_components/notes_renderer.py +108 -0
- strix/interface/tool_components/proxy_renderer.py +255 -0
- strix/interface/tool_components/python_renderer.py +34 -0
- strix/interface/tool_components/registry.py +72 -0
- strix/interface/tool_components/reporting_renderer.py +53 -0
- strix/interface/tool_components/scan_info_renderer.py +64 -0
- strix/interface/tool_components/terminal_renderer.py +131 -0
- strix/interface/tool_components/thinking_renderer.py +29 -0
- strix/interface/tool_components/user_message_renderer.py +43 -0
- strix/interface/tool_components/web_search_renderer.py +28 -0
- strix/interface/tui.py +1274 -0
- strix/interface/utils.py +559 -0
- strix/llm/__init__.py +15 -0
- strix/llm/config.py +20 -0
- strix/llm/llm.py +465 -0
- strix/llm/memory_compressor.py +212 -0
- strix/llm/request_queue.py +87 -0
- strix/llm/utils.py +87 -0
- strix/prompts/README.md +64 -0
- strix/prompts/__init__.py +109 -0
- strix/prompts/cloud/.gitkeep +0 -0
- strix/prompts/coordination/root_agent.jinja +41 -0
- strix/prompts/custom/.gitkeep +0 -0
- strix/prompts/frameworks/fastapi.jinja +142 -0
- strix/prompts/frameworks/nextjs.jinja +126 -0
- strix/prompts/protocols/graphql.jinja +215 -0
- strix/prompts/reconnaissance/.gitkeep +0 -0
- strix/prompts/technologies/firebase_firestore.jinja +177 -0
- strix/prompts/technologies/supabase.jinja +189 -0
- strix/prompts/vulnerabilities/authentication_jwt.jinja +147 -0
- strix/prompts/vulnerabilities/broken_function_level_authorization.jinja +146 -0
- strix/prompts/vulnerabilities/business_logic.jinja +171 -0
- strix/prompts/vulnerabilities/csrf.jinja +174 -0
- strix/prompts/vulnerabilities/idor.jinja +195 -0
- strix/prompts/vulnerabilities/information_disclosure.jinja +222 -0
- strix/prompts/vulnerabilities/insecure_file_uploads.jinja +188 -0
- strix/prompts/vulnerabilities/mass_assignment.jinja +141 -0
- strix/prompts/vulnerabilities/open_redirect.jinja +177 -0
- strix/prompts/vulnerabilities/path_traversal_lfi_rfi.jinja +142 -0
- strix/prompts/vulnerabilities/race_conditions.jinja +164 -0
- strix/prompts/vulnerabilities/rce.jinja +154 -0
- strix/prompts/vulnerabilities/sql_injection.jinja +151 -0
- strix/prompts/vulnerabilities/ssrf.jinja +135 -0
- strix/prompts/vulnerabilities/subdomain_takeover.jinja +155 -0
- strix/prompts/vulnerabilities/xss.jinja +169 -0
- strix/prompts/vulnerabilities/xxe.jinja +184 -0
- strix/runtime/__init__.py +19 -0
- strix/runtime/docker_runtime.py +399 -0
- strix/runtime/runtime.py +29 -0
- strix/runtime/tool_server.py +205 -0
- strix/telemetry/__init__.py +4 -0
- strix/telemetry/tracer.py +337 -0
- strix/tools/__init__.py +64 -0
- strix/tools/agents_graph/__init__.py +16 -0
- strix/tools/agents_graph/agents_graph_actions.py +621 -0
- strix/tools/agents_graph/agents_graph_actions_schema.xml +226 -0
- strix/tools/argument_parser.py +121 -0
- strix/tools/browser/__init__.py +4 -0
- strix/tools/browser/browser_actions.py +236 -0
- strix/tools/browser/browser_actions_schema.xml +183 -0
- strix/tools/browser/browser_instance.py +533 -0
- strix/tools/browser/tab_manager.py +342 -0
- strix/tools/executor.py +305 -0
- strix/tools/file_edit/__init__.py +4 -0
- strix/tools/file_edit/file_edit_actions.py +141 -0
- strix/tools/file_edit/file_edit_actions_schema.xml +128 -0
- strix/tools/finish/__init__.py +4 -0
- strix/tools/finish/finish_actions.py +174 -0
- strix/tools/finish/finish_actions_schema.xml +45 -0
- strix/tools/notes/__init__.py +14 -0
- strix/tools/notes/notes_actions.py +191 -0
- strix/tools/notes/notes_actions_schema.xml +150 -0
- strix/tools/proxy/__init__.py +20 -0
- strix/tools/proxy/proxy_actions.py +101 -0
- strix/tools/proxy/proxy_actions_schema.xml +267 -0
- strix/tools/proxy/proxy_manager.py +785 -0
- strix/tools/python/__init__.py +4 -0
- strix/tools/python/python_actions.py +47 -0
- strix/tools/python/python_actions_schema.xml +131 -0
- strix/tools/python/python_instance.py +172 -0
- strix/tools/python/python_manager.py +131 -0
- strix/tools/registry.py +196 -0
- strix/tools/reporting/__init__.py +6 -0
- strix/tools/reporting/reporting_actions.py +63 -0
- strix/tools/reporting/reporting_actions_schema.xml +30 -0
- strix/tools/terminal/__init__.py +4 -0
- strix/tools/terminal/terminal_actions.py +35 -0
- strix/tools/terminal/terminal_actions_schema.xml +146 -0
- strix/tools/terminal/terminal_manager.py +151 -0
- strix/tools/terminal/terminal_session.py +447 -0
- strix/tools/thinking/__init__.py +4 -0
- strix/tools/thinking/thinking_actions.py +18 -0
- strix/tools/thinking/thinking_actions_schema.xml +52 -0
- strix/tools/web_search/__init__.py +4 -0
- strix/tools/web_search/web_search_actions.py +80 -0
- strix/tools/web_search/web_search_actions_schema.xml +83 -0
- strix_agent-0.4.0.dist-info/LICENSE +201 -0
- strix_agent-0.4.0.dist-info/METADATA +282 -0
- strix_agent-0.4.0.dist-info/RECORD +118 -0
- strix_agent-0.4.0.dist-info/WHEEL +4 -0
- strix_agent-0.4.0.dist-info/entry_points.txt +3 -0
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import uuid
|
|
2
|
+
from datetime import UTC, datetime
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
from strix.tools.registry import register_tool
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
_notes_storage: dict[str, dict[str, Any]] = {}
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def _filter_notes(
|
|
12
|
+
category: str | None = None,
|
|
13
|
+
tags: list[str] | None = None,
|
|
14
|
+
priority: str | None = None,
|
|
15
|
+
search_query: str | None = None,
|
|
16
|
+
) -> list[dict[str, Any]]:
|
|
17
|
+
filtered_notes = []
|
|
18
|
+
|
|
19
|
+
for note_id, note in _notes_storage.items():
|
|
20
|
+
if category and note.get("category") != category:
|
|
21
|
+
continue
|
|
22
|
+
|
|
23
|
+
if priority and note.get("priority") != priority:
|
|
24
|
+
continue
|
|
25
|
+
|
|
26
|
+
if tags:
|
|
27
|
+
note_tags = note.get("tags", [])
|
|
28
|
+
if not any(tag in note_tags for tag in tags):
|
|
29
|
+
continue
|
|
30
|
+
|
|
31
|
+
if search_query:
|
|
32
|
+
search_lower = search_query.lower()
|
|
33
|
+
title_match = search_lower in note.get("title", "").lower()
|
|
34
|
+
content_match = search_lower in note.get("content", "").lower()
|
|
35
|
+
if not (title_match or content_match):
|
|
36
|
+
continue
|
|
37
|
+
|
|
38
|
+
note_with_id = note.copy()
|
|
39
|
+
note_with_id["note_id"] = note_id
|
|
40
|
+
filtered_notes.append(note_with_id)
|
|
41
|
+
|
|
42
|
+
filtered_notes.sort(key=lambda x: x.get("created_at", ""), reverse=True)
|
|
43
|
+
return filtered_notes
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@register_tool
|
|
47
|
+
def create_note(
|
|
48
|
+
title: str,
|
|
49
|
+
content: str,
|
|
50
|
+
category: str = "general",
|
|
51
|
+
tags: list[str] | None = None,
|
|
52
|
+
priority: str = "normal",
|
|
53
|
+
) -> dict[str, Any]:
|
|
54
|
+
try:
|
|
55
|
+
if not title or not title.strip():
|
|
56
|
+
return {"success": False, "error": "Title cannot be empty", "note_id": None}
|
|
57
|
+
|
|
58
|
+
if not content or not content.strip():
|
|
59
|
+
return {"success": False, "error": "Content cannot be empty", "note_id": None}
|
|
60
|
+
|
|
61
|
+
valid_categories = ["general", "findings", "methodology", "todo", "questions", "plan"]
|
|
62
|
+
if category not in valid_categories:
|
|
63
|
+
return {
|
|
64
|
+
"success": False,
|
|
65
|
+
"error": f"Invalid category. Must be one of: {', '.join(valid_categories)}",
|
|
66
|
+
"note_id": None,
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
valid_priorities = ["low", "normal", "high", "urgent"]
|
|
70
|
+
if priority not in valid_priorities:
|
|
71
|
+
return {
|
|
72
|
+
"success": False,
|
|
73
|
+
"error": f"Invalid priority. Must be one of: {', '.join(valid_priorities)}",
|
|
74
|
+
"note_id": None,
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
note_id = str(uuid.uuid4())[:5]
|
|
78
|
+
timestamp = datetime.now(UTC).isoformat()
|
|
79
|
+
|
|
80
|
+
note = {
|
|
81
|
+
"title": title.strip(),
|
|
82
|
+
"content": content.strip(),
|
|
83
|
+
"category": category,
|
|
84
|
+
"tags": tags or [],
|
|
85
|
+
"priority": priority,
|
|
86
|
+
"created_at": timestamp,
|
|
87
|
+
"updated_at": timestamp,
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
_notes_storage[note_id] = note
|
|
91
|
+
|
|
92
|
+
except (ValueError, TypeError) as e:
|
|
93
|
+
return {"success": False, "error": f"Failed to create note: {e}", "note_id": None}
|
|
94
|
+
else:
|
|
95
|
+
return {
|
|
96
|
+
"success": True,
|
|
97
|
+
"note_id": note_id,
|
|
98
|
+
"message": f"Note '{title}' created successfully",
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
@register_tool
|
|
103
|
+
def list_notes(
|
|
104
|
+
category: str | None = None,
|
|
105
|
+
tags: list[str] | None = None,
|
|
106
|
+
priority: str | None = None,
|
|
107
|
+
search: str | None = None,
|
|
108
|
+
) -> dict[str, Any]:
|
|
109
|
+
try:
|
|
110
|
+
filtered_notes = _filter_notes(
|
|
111
|
+
category=category, tags=tags, priority=priority, search_query=search
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
return {
|
|
115
|
+
"success": True,
|
|
116
|
+
"notes": filtered_notes,
|
|
117
|
+
"total_count": len(filtered_notes),
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
except (ValueError, TypeError) as e:
|
|
121
|
+
return {
|
|
122
|
+
"success": False,
|
|
123
|
+
"error": f"Failed to list notes: {e}",
|
|
124
|
+
"notes": [],
|
|
125
|
+
"total_count": 0,
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
@register_tool
|
|
130
|
+
def update_note(
|
|
131
|
+
note_id: str,
|
|
132
|
+
title: str | None = None,
|
|
133
|
+
content: str | None = None,
|
|
134
|
+
tags: list[str] | None = None,
|
|
135
|
+
priority: str | None = None,
|
|
136
|
+
) -> dict[str, Any]:
|
|
137
|
+
try:
|
|
138
|
+
if note_id not in _notes_storage:
|
|
139
|
+
return {"success": False, "error": f"Note with ID '{note_id}' not found"}
|
|
140
|
+
|
|
141
|
+
note = _notes_storage[note_id]
|
|
142
|
+
|
|
143
|
+
if title is not None:
|
|
144
|
+
if not title.strip():
|
|
145
|
+
return {"success": False, "error": "Title cannot be empty"}
|
|
146
|
+
note["title"] = title.strip()
|
|
147
|
+
|
|
148
|
+
if content is not None:
|
|
149
|
+
if not content.strip():
|
|
150
|
+
return {"success": False, "error": "Content cannot be empty"}
|
|
151
|
+
note["content"] = content.strip()
|
|
152
|
+
|
|
153
|
+
if tags is not None:
|
|
154
|
+
note["tags"] = tags
|
|
155
|
+
|
|
156
|
+
if priority is not None:
|
|
157
|
+
valid_priorities = ["low", "normal", "high", "urgent"]
|
|
158
|
+
if priority not in valid_priorities:
|
|
159
|
+
return {
|
|
160
|
+
"success": False,
|
|
161
|
+
"error": f"Invalid priority. Must be one of: {', '.join(valid_priorities)}",
|
|
162
|
+
}
|
|
163
|
+
note["priority"] = priority
|
|
164
|
+
|
|
165
|
+
note["updated_at"] = datetime.now(UTC).isoformat()
|
|
166
|
+
|
|
167
|
+
return {
|
|
168
|
+
"success": True,
|
|
169
|
+
"message": f"Note '{note['title']}' updated successfully",
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
except (ValueError, TypeError) as e:
|
|
173
|
+
return {"success": False, "error": f"Failed to update note: {e}"}
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
@register_tool
|
|
177
|
+
def delete_note(note_id: str) -> dict[str, Any]:
|
|
178
|
+
try:
|
|
179
|
+
if note_id not in _notes_storage:
|
|
180
|
+
return {"success": False, "error": f"Note with ID '{note_id}' not found"}
|
|
181
|
+
|
|
182
|
+
note_title = _notes_storage[note_id]["title"]
|
|
183
|
+
del _notes_storage[note_id]
|
|
184
|
+
|
|
185
|
+
except (ValueError, TypeError) as e:
|
|
186
|
+
return {"success": False, "error": f"Failed to delete note: {e}"}
|
|
187
|
+
else:
|
|
188
|
+
return {
|
|
189
|
+
"success": True,
|
|
190
|
+
"message": f"Note '{note_title}' deleted successfully",
|
|
191
|
+
}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
<tools>
|
|
2
|
+
<tool name="create_note">
|
|
3
|
+
<description>Create a personal note for TODOs, side notes, plans, and organizational purposes during
|
|
4
|
+
the scan.</description>
|
|
5
|
+
<details>Use this tool for quick reminders, action items, planning thoughts, and organizational notes
|
|
6
|
+
rather than formal vulnerability reports or detailed findings. This is your personal notepad
|
|
7
|
+
for keeping track of tasks, ideas, and things to remember or follow up on.</details>
|
|
8
|
+
<parameters>
|
|
9
|
+
<parameter name="title" type="string" required="true">
|
|
10
|
+
<description>Title of the note</description>
|
|
11
|
+
</parameter>
|
|
12
|
+
<parameter name="content" type="string" required="true">
|
|
13
|
+
<description>Content of the note</description>
|
|
14
|
+
</parameter>
|
|
15
|
+
<parameter name="category" type="string" required="false">
|
|
16
|
+
<description>Category to organize the note (default: "general", "findings", "methodology", "todo", "questions", "plan")</description>
|
|
17
|
+
</parameter>
|
|
18
|
+
<parameter name="tags" type="string" required="false">
|
|
19
|
+
<description>Tags for categorization</description>
|
|
20
|
+
</parameter>
|
|
21
|
+
<parameter name="priority" type="string" required="false">
|
|
22
|
+
<description>Priority level of the note ("low", "normal", "high", "urgent")</description>
|
|
23
|
+
</parameter>
|
|
24
|
+
</parameters>
|
|
25
|
+
<returns type="Dict[str, Any]">
|
|
26
|
+
<description>Response containing: - note_id: ID of the created note - success: Whether the note was created successfully</description>
|
|
27
|
+
</returns>
|
|
28
|
+
<examples>
|
|
29
|
+
# Create a TODO reminder
|
|
30
|
+
<function=create_note>
|
|
31
|
+
<parameter=title>TODO: Check SSL Certificate Details</parameter>
|
|
32
|
+
<parameter=content>Remember to verify SSL certificate validity and check for weak ciphers
|
|
33
|
+
on the HTTPS service discovered on port 443. Also check for certificate
|
|
34
|
+
transparency logs.</parameter>
|
|
35
|
+
<parameter=category>todo</parameter>
|
|
36
|
+
<parameter=tags>["ssl", "certificate", "followup"]</parameter>
|
|
37
|
+
<parameter=priority>normal</parameter>
|
|
38
|
+
</function>
|
|
39
|
+
|
|
40
|
+
# Planning note
|
|
41
|
+
<function=create_note>
|
|
42
|
+
<parameter=title>Scan Strategy Planning</parameter>
|
|
43
|
+
<parameter=content>Plan for next phase: 1) Complete subdomain enumeration 2) Test discovered
|
|
44
|
+
web apps for OWASP Top 10 3) Check database services for default creds
|
|
45
|
+
4) Review any custom applications for business logic flaws</parameter>
|
|
46
|
+
<parameter=category>plan</parameter>
|
|
47
|
+
<parameter=tags>["planning", "strategy", "next_steps"]</parameter>
|
|
48
|
+
</function>
|
|
49
|
+
|
|
50
|
+
# Side note for later investigation
|
|
51
|
+
<function=create_note>
|
|
52
|
+
<parameter=title>Interesting Directory Found</parameter>
|
|
53
|
+
<parameter=content>Found /backup/ directory that might contain sensitive files. Low priority
|
|
54
|
+
for now but worth checking if time permits. Directory listing seems
|
|
55
|
+
disabled.</parameter>
|
|
56
|
+
<parameter=category>findings</parameter>
|
|
57
|
+
<parameter=tags>["directory", "backup", "low_priority"]</parameter>
|
|
58
|
+
<parameter=priority>low</parameter>
|
|
59
|
+
</function>
|
|
60
|
+
</examples>
|
|
61
|
+
</tool>
|
|
62
|
+
<tool name="delete_note">
|
|
63
|
+
<description>Delete a note.</description>
|
|
64
|
+
<parameters>
|
|
65
|
+
<parameter name="note_id" type="string" required="true">
|
|
66
|
+
<description>ID of the note to delete</description>
|
|
67
|
+
</parameter>
|
|
68
|
+
</parameters>
|
|
69
|
+
<returns type="Dict[str, Any]">
|
|
70
|
+
<description>Response containing: - success: Whether the note was deleted successfully</description>
|
|
71
|
+
</returns>
|
|
72
|
+
<examples>
|
|
73
|
+
<function=delete_note>
|
|
74
|
+
<parameter=note_id>note_123</parameter>
|
|
75
|
+
</function>
|
|
76
|
+
</examples>
|
|
77
|
+
</tool>
|
|
78
|
+
<tool name="list_notes">
|
|
79
|
+
<description>List existing notes with optional filtering and search.</description>
|
|
80
|
+
<parameters>
|
|
81
|
+
<parameter name="category" type="string" required="false">
|
|
82
|
+
<description>Filter by category</description>
|
|
83
|
+
</parameter>
|
|
84
|
+
<parameter name="tags" type="string" required="false">
|
|
85
|
+
<description>Filter by tags (returns notes with any of these tags)</description>
|
|
86
|
+
</parameter>
|
|
87
|
+
<parameter name="priority" type="string" required="false">
|
|
88
|
+
<description>Filter by priority level</description>
|
|
89
|
+
</parameter>
|
|
90
|
+
<parameter name="search" type="string" required="false">
|
|
91
|
+
<description>Search query to find in note titles and content</description>
|
|
92
|
+
</parameter>
|
|
93
|
+
</parameters>
|
|
94
|
+
<returns type="Dict[str, Any]">
|
|
95
|
+
<description>Response containing: - notes: List of matching notes - total_count: Total number of notes found</description>
|
|
96
|
+
</returns>
|
|
97
|
+
<examples>
|
|
98
|
+
# List all findings
|
|
99
|
+
<function=list_notes>
|
|
100
|
+
<parameter=category>findings</parameter>
|
|
101
|
+
</function>
|
|
102
|
+
|
|
103
|
+
# List high priority items
|
|
104
|
+
<function=list_notes>
|
|
105
|
+
<parameter=priority>high</parameter>
|
|
106
|
+
</function>
|
|
107
|
+
|
|
108
|
+
# Search for SQL injection related notes
|
|
109
|
+
<function=list_notes>
|
|
110
|
+
<parameter=search>SQL injection</parameter>
|
|
111
|
+
</function>
|
|
112
|
+
|
|
113
|
+
# Search within a specific category
|
|
114
|
+
<function=list_notes>
|
|
115
|
+
<parameter=search>admin</parameter>
|
|
116
|
+
<parameter=category>findings</parameter>
|
|
117
|
+
</function>
|
|
118
|
+
</examples>
|
|
119
|
+
</tool>
|
|
120
|
+
<tool name="update_note">
|
|
121
|
+
<description>Update an existing note.</description>
|
|
122
|
+
<parameters>
|
|
123
|
+
<parameter name="note_id" type="string" required="true">
|
|
124
|
+
<description>ID of the note to update</description>
|
|
125
|
+
</parameter>
|
|
126
|
+
<parameter name="title" type="string" required="false">
|
|
127
|
+
<description>New title for the note</description>
|
|
128
|
+
</parameter>
|
|
129
|
+
<parameter name="content" type="string" required="false">
|
|
130
|
+
<description>New content for the note</description>
|
|
131
|
+
</parameter>
|
|
132
|
+
<parameter name="tags" type="string" required="false">
|
|
133
|
+
<description>New tags for the note</description>
|
|
134
|
+
</parameter>
|
|
135
|
+
<parameter name="priority" type="string" required="false">
|
|
136
|
+
<description>New priority level</description>
|
|
137
|
+
</parameter>
|
|
138
|
+
</parameters>
|
|
139
|
+
<returns type="Dict[str, Any]">
|
|
140
|
+
<description>Response containing: - success: Whether the note was updated successfully</description>
|
|
141
|
+
</returns>
|
|
142
|
+
<examples>
|
|
143
|
+
<function=update_note>
|
|
144
|
+
<parameter=note_id>note_123</parameter>
|
|
145
|
+
<parameter=content>Updated content with new findings...</parameter>
|
|
146
|
+
<parameter=priority>urgent</parameter>
|
|
147
|
+
</function>
|
|
148
|
+
</examples>
|
|
149
|
+
</tool>
|
|
150
|
+
</tools>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from .proxy_actions import (
|
|
2
|
+
list_requests,
|
|
3
|
+
list_sitemap,
|
|
4
|
+
repeat_request,
|
|
5
|
+
scope_rules,
|
|
6
|
+
send_request,
|
|
7
|
+
view_request,
|
|
8
|
+
view_sitemap_entry,
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
__all__ = [
|
|
13
|
+
"list_requests",
|
|
14
|
+
"list_sitemap",
|
|
15
|
+
"repeat_request",
|
|
16
|
+
"scope_rules",
|
|
17
|
+
"send_request",
|
|
18
|
+
"view_request",
|
|
19
|
+
"view_sitemap_entry",
|
|
20
|
+
]
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
from typing import Any, Literal
|
|
2
|
+
|
|
3
|
+
from strix.tools.registry import register_tool
|
|
4
|
+
|
|
5
|
+
from .proxy_manager import get_proxy_manager
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
RequestPart = Literal["request", "response"]
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@register_tool
|
|
12
|
+
def list_requests(
|
|
13
|
+
httpql_filter: str | None = None,
|
|
14
|
+
start_page: int = 1,
|
|
15
|
+
end_page: int = 1,
|
|
16
|
+
page_size: int = 50,
|
|
17
|
+
sort_by: Literal[
|
|
18
|
+
"timestamp",
|
|
19
|
+
"host",
|
|
20
|
+
"method",
|
|
21
|
+
"path",
|
|
22
|
+
"status_code",
|
|
23
|
+
"response_time",
|
|
24
|
+
"response_size",
|
|
25
|
+
"source",
|
|
26
|
+
] = "timestamp",
|
|
27
|
+
sort_order: Literal["asc", "desc"] = "desc",
|
|
28
|
+
scope_id: str | None = None,
|
|
29
|
+
) -> dict[str, Any]:
|
|
30
|
+
manager = get_proxy_manager()
|
|
31
|
+
return manager.list_requests(
|
|
32
|
+
httpql_filter, start_page, end_page, page_size, sort_by, sort_order, scope_id
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@register_tool
|
|
37
|
+
def view_request(
|
|
38
|
+
request_id: str,
|
|
39
|
+
part: RequestPart = "request",
|
|
40
|
+
search_pattern: str | None = None,
|
|
41
|
+
page: int = 1,
|
|
42
|
+
page_size: int = 50,
|
|
43
|
+
) -> dict[str, Any]:
|
|
44
|
+
manager = get_proxy_manager()
|
|
45
|
+
return manager.view_request(request_id, part, search_pattern, page, page_size)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@register_tool
|
|
49
|
+
def send_request(
|
|
50
|
+
method: str,
|
|
51
|
+
url: str,
|
|
52
|
+
headers: dict[str, str] | None = None,
|
|
53
|
+
body: str = "",
|
|
54
|
+
timeout: int = 30,
|
|
55
|
+
) -> dict[str, Any]:
|
|
56
|
+
if headers is None:
|
|
57
|
+
headers = {}
|
|
58
|
+
manager = get_proxy_manager()
|
|
59
|
+
return manager.send_simple_request(method, url, headers, body, timeout)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
@register_tool
|
|
63
|
+
def repeat_request(
|
|
64
|
+
request_id: str,
|
|
65
|
+
modifications: dict[str, Any] | None = None,
|
|
66
|
+
) -> dict[str, Any]:
|
|
67
|
+
if modifications is None:
|
|
68
|
+
modifications = {}
|
|
69
|
+
manager = get_proxy_manager()
|
|
70
|
+
return manager.repeat_request(request_id, modifications)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
@register_tool
|
|
74
|
+
def scope_rules(
|
|
75
|
+
action: Literal["get", "list", "create", "update", "delete"],
|
|
76
|
+
allowlist: list[str] | None = None,
|
|
77
|
+
denylist: list[str] | None = None,
|
|
78
|
+
scope_id: str | None = None,
|
|
79
|
+
scope_name: str | None = None,
|
|
80
|
+
) -> dict[str, Any]:
|
|
81
|
+
manager = get_proxy_manager()
|
|
82
|
+
return manager.scope_rules(action, allowlist, denylist, scope_id, scope_name)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
@register_tool
|
|
86
|
+
def list_sitemap(
|
|
87
|
+
scope_id: str | None = None,
|
|
88
|
+
parent_id: str | None = None,
|
|
89
|
+
depth: Literal["DIRECT", "ALL"] = "DIRECT",
|
|
90
|
+
page: int = 1,
|
|
91
|
+
) -> dict[str, Any]:
|
|
92
|
+
manager = get_proxy_manager()
|
|
93
|
+
return manager.list_sitemap(scope_id, parent_id, depth, page)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
@register_tool
|
|
97
|
+
def view_sitemap_entry(
|
|
98
|
+
entry_id: str,
|
|
99
|
+
) -> dict[str, Any]:
|
|
100
|
+
manager = get_proxy_manager()
|
|
101
|
+
return manager.view_sitemap_entry(entry_id)
|