项目文件夹

文件
Gelei Deng b9869307d0 Legacy multi llm base (#470)
* fix: 🐛 minor typo and build process

* feat: 🎸 [WIP] Pentest mode

* feat: 🎸 code abstraction

* feat: modernize legacy PentestGPT with native multi-LLM support (#469)

Rebuild the classic USENIX-2024 interactive PentestGPT (reasoning / generation /
parsing sessions + Pentesting Task Tree + REPL) as a standalone
`pentestgpt_legacy` package on a native per-provider LLM layer that supports the
latest 2026 models.

- llm/: BaseProvider + OpenAI-compatible / Anthropic / Gemini connectors, a
  web-verified model registry (OpenAI, Anthropic, Gemini, DeepSeek, xAI, Qwen,
  Moonshot, local Ollama), a factory, and an LLMClient bridging async providers
  to the core's synchronous send_new_message/send_message session API.
- CLI `pentestgpt-legacy`: --list-models and --smoke-test (live per-model
  round-trip matrix), plus --reasoning-model / --parsing-model / --base-url.
- Tests: 25 unit tests (mocked, no network). Live smoke test verified 22/22
  models with a configured key respond.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>

* fix(backend): address review on ClaudeCodeBackend subprocess handling

- _build_env: pop ANTHROPIC_API_KEY instead of setting it to "", so an empty
  value can't shadow the CLI's own auth fallback (e.g. subscription login).
- _kill_process: reap the force-killed process with os.waitpid(.., WNOHANG)
  instead of calling the proc.wait() coroutine without awaiting it (removes the
  "coroutine was never awaited" warning).
- query/_drain_stderr: drain subprocess stderr in a background task so its pipe
  buffer can't fill and deadlock the child.

Also reformats backend.py, fixing the failing Lint (ruff format) check.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(docker-test): assert uv instead of Poetry in container health check

The project migrated from Poetry to uv (the Dockerfile installs uv to
/home/pentester/.local/bin, which is on PATH), so test_poetry_installed failed
with exit 127. Replace it with test_uv_installed checking `uv --version`.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 15:25:45 +08:00

126 行
4.3 KiB
Python

#!/usr/bin/env python
"""
url: https://github.com/prompt-toolkit/python-prompt-toolkit/tree/master/examples/prompts/auto-completion
Demonstration of a custom completer class and the possibility of styling
completions independently by passing formatted text objects to the "display"
and "display_meta" arguments of "Completion".
"""
from typing import ClassVar
from prompt_toolkit.completion import Completer, Completion
from prompt_toolkit.formatted_text import HTML
from prompt_toolkit.shortcuts import prompt
class localTaskCompleter(Completer):
tasks: ClassVar[list[str]] = [
"discuss", # discuss with pentestGPT on the local task
"brainstorm", # let pentestGPT brainstorm on the local task
"help", # show the help page (for this local task)
"google", # search on Google
"continue", # quit the local task (for this local task)
]
task_meta: ClassVar[dict[str, HTML]] = {
"discuss": HTML("Discuss with <b>PentestGPT</b> about this local task."),
"brainstorm": HTML(
"Let <b>PentestGPT</b> brainstorm on the local task for all the possible solutions."
),
"help": HTML("Show the help page for this local task."),
"google": HTML("Search on Google."),
"continue": HTML("Quit the local task and continue the previous testing."),
}
task_details = """
Below are the available tasks:
- discuss: Discuss with PentestGPT about this local task.
- brainstorm: Let PentestGPT brainstorm on the local task for all the possible solutions.
- help: Show the help page for this local task.
- google: Search on Google.
- quit: Quit the local task and continue the testing."""
def get_completions(self, document, complete_event):
word = document.get_word_before_cursor()
for task in self.tasks:
if task.startswith(word):
yield Completion(
task,
start_position=-len(word),
display=task,
display_meta=self.task_meta.get(task),
)
class mainTaskCompleter(Completer):
tasks: ClassVar[list[str]] = [
"next",
"more",
"todo",
"discuss",
"google",
"help",
"quit",
]
task_meta: ClassVar[dict[str, HTML]] = {
"next": HTML("Go to the next step."),
"more": HTML("Explain the task with more details."),
"todo": HTML("Ask <b>PentestGPT</b> for todos."),
"discuss": HTML("Discuss with <b>PentestGPT</b>."),
"google": HTML("Search on Google."),
"help": HTML("Show the help page."),
"quit": HTML("End the current session."),
}
task_details = """
Below are the available tasks:
- next: Continue to the next step by inputting the test results.
- more: Explain the previous given task with more details.
- todo: Ask PentestGPT for the task list and what to do next.
- discuss: Discuss with PentestGPT. You can ask for help, discuss the task, or give any feedbacks.
- google: Search your question on Google. The results are automatically parsed by Google.
- help: Show this help page.
- quit: End the current session."""
def get_completions(self, document, complete_event):
word = document.get_word_before_cursor()
for task in self.tasks:
if task.startswith(word):
yield Completion(
task,
start_position=-len(word),
display=task,
display_meta=self.task_meta.get(task),
)
def main_task_entry(text="> "):
"""
Entry point for the task prompt. Auto-complete
"""
task_completer = mainTaskCompleter()
while True:
result = prompt(text, completer=task_completer)
if result not in task_completer.tasks:
print("Invalid task, try again.")
else:
return result
def local_task_entry(text="> "):
"""
Entry point for the task prompt. Auto-complete
"""
task_completer = localTaskCompleter()
while True:
result = prompt(text, completer=task_completer)
if result not in task_completer.tasks:
print("Invalid task, try again.")
else:
return result
if __name__ == "__main__":
main_task_entry()