pawnlogic 1.1__tar.gz

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 (76) hide show
  1. pawnlogic-1.1/LICENSE +21 -0
  2. pawnlogic-1.1/PKG-INFO +149 -0
  3. pawnlogic-1.1/README.md +115 -0
  4. pawnlogic-1.1/config/__init__.py +47 -0
  5. pawnlogic-1.1/config/paths.py +17 -0
  6. pawnlogic-1.1/config/phases.py +40 -0
  7. pawnlogic-1.1/config/providers.py +271 -0
  8. pawnlogic-1.1/config/sandbox.py +36 -0
  9. pawnlogic-1.1/config/security.py +65 -0
  10. pawnlogic-1.1/config/tiers.py +50 -0
  11. pawnlogic-1.1/core/api_client.py +842 -0
  12. pawnlogic-1.1/core/gsa.py +937 -0
  13. pawnlogic-1.1/core/logger.py +169 -0
  14. pawnlogic-1.1/core/mcp_client_manager.py +422 -0
  15. pawnlogic-1.1/core/memory.py +1056 -0
  16. pawnlogic-1.1/core/naming.py +216 -0
  17. pawnlogic-1.1/core/persistence.py +405 -0
  18. pawnlogic-1.1/core/provider_tui.py +1000 -0
  19. pawnlogic-1.1/core/session.py +2666 -0
  20. pawnlogic-1.1/core/skill_manager.py +385 -0
  21. pawnlogic-1.1/core/state.py +35 -0
  22. pawnlogic-1.1/core/workspace_cleanup.py +479 -0
  23. pawnlogic-1.1/main.py +3180 -0
  24. pawnlogic-1.1/pawnlogic.egg-info/PKG-INFO +149 -0
  25. pawnlogic-1.1/pawnlogic.egg-info/SOURCES.txt +74 -0
  26. pawnlogic-1.1/pawnlogic.egg-info/dependency_links.txt +1 -0
  27. pawnlogic-1.1/pawnlogic.egg-info/entry_points.txt +2 -0
  28. pawnlogic-1.1/pawnlogic.egg-info/requires.txt +10 -0
  29. pawnlogic-1.1/pawnlogic.egg-info/top_level.txt +6 -0
  30. pawnlogic-1.1/pyproject.toml +74 -0
  31. pawnlogic-1.1/setup.cfg +4 -0
  32. pawnlogic-1.1/skills/README.md +86 -0
  33. pawnlogic-1.1/skills/ctf_app_system/manifest.json +42 -0
  34. pawnlogic-1.1/skills/ctf_app_system/skill.md +2226 -0
  35. pawnlogic-1.1/skills/ctf_automation/manifest.json +42 -0
  36. pawnlogic-1.1/skills/ctf_automation/skill.md +167 -0
  37. pawnlogic-1.1/skills/ctf_crypto/manifest.json +42 -0
  38. pawnlogic-1.1/skills/ctf_crypto/skill.md +4519 -0
  39. pawnlogic-1.1/skills/ctf_forensics/manifest.json +42 -0
  40. pawnlogic-1.1/skills/ctf_forensics/skill.md +4604 -0
  41. pawnlogic-1.1/skills/ctf_malware/manifest.json +42 -0
  42. pawnlogic-1.1/skills/ctf_malware/skill.md +906 -0
  43. pawnlogic-1.1/skills/ctf_misc/manifest.json +42 -0
  44. pawnlogic-1.1/skills/ctf_misc/skill.md +3449 -0
  45. pawnlogic-1.1/skills/ctf_osint/manifest.json +42 -0
  46. pawnlogic-1.1/skills/ctf_osint/skill.md +1089 -0
  47. pawnlogic-1.1/skills/ctf_pwn/manifest.json +42 -0
  48. pawnlogic-1.1/skills/ctf_pwn/skill.md +6649 -0
  49. pawnlogic-1.1/skills/ctf_reverse/manifest.json +42 -0
  50. pawnlogic-1.1/skills/ctf_reverse/skill.md +6512 -0
  51. pawnlogic-1.1/skills/ctf_web/manifest.json +42 -0
  52. pawnlogic-1.1/skills/ctf_web/skill.md +5001 -0
  53. pawnlogic-1.1/skills/demo_stack_overflow/guide.md +85 -0
  54. pawnlogic-1.1/skills/demo_stack_overflow/manifest.json +17 -0
  55. pawnlogic-1.1/skills/heap_exploit/manifest.json +8 -0
  56. pawnlogic-1.1/skills/heap_exploit/skill.md +27 -0
  57. pawnlogic-1.1/skills/solve_challenge/manifest.json +42 -0
  58. pawnlogic-1.1/skills/solve_challenge/skill.md +152 -0
  59. pawnlogic-1.1/tests/test_api_empty_response.py +247 -0
  60. pawnlogic-1.1/tests/test_config.py +86 -0
  61. pawnlogic-1.1/tests/test_naming.py +147 -0
  62. pawnlogic-1.1/tests/test_providers.py +174 -0
  63. pawnlogic-1.1/tests/test_security.py +115 -0
  64. pawnlogic-1.1/tests/test_session_utils.py +420 -0
  65. pawnlogic-1.1/tools/browser_ops.py +507 -0
  66. pawnlogic-1.1/tools/delegate_tool.py +331 -0
  67. pawnlogic-1.1/tools/docker_sandbox.py +829 -0
  68. pawnlogic-1.1/tools/file_ops.py +871 -0
  69. pawnlogic-1.1/tools/lsp_lite.py +330 -0
  70. pawnlogic-1.1/tools/merge_ctf_skills.py +137 -0
  71. pawnlogic-1.1/tools/pwn_chain.py +809 -0
  72. pawnlogic-1.1/tools/recon_ops.py +258 -0
  73. pawnlogic-1.1/tools/sandbox.py +388 -0
  74. pawnlogic-1.1/tools/vision.py +184 -0
  75. pawnlogic-1.1/tools/web_ops.py +403 -0
  76. pawnlogic-1.1/utils/ansi.py +118 -0
pawnlogic-1.1/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 PawnLogic Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
pawnlogic-1.1/PKG-INFO ADDED
@@ -0,0 +1,149 @@
1
+ Metadata-Version: 2.4
2
+ Name: pawnlogic
3
+ Version: 1.1
4
+ Summary: A fully autonomous terminal AI agent — multi-model routing, persistent memory, real tool execution
5
+ Author-email: john0123412 <junjohn05@gmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/john0123412/PawnLogic
8
+ Project-URL: Repository, https://github.com/john0123412/PawnLogic
9
+ Project-URL: Issues, https://github.com/john0123412/PawnLogic/issues
10
+ Project-URL: Changelog, https://github.com/john0123412/PawnLogic/blob/main/CHANGELOG.md
11
+ Keywords: ai-agent,llm,ctf,cli,autonomous,multi-model,security,pwn
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Operating System :: POSIX :: Linux
17
+ Classifier: Environment :: Console
18
+ Classifier: Topic :: Security
19
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
20
+ Classifier: Intended Audience :: Developers
21
+ Requires-Python: >=3.10
22
+ Description-Content-Type: text/markdown
23
+ License-File: LICENSE
24
+ Requires-Dist: python-dotenv>=1.0
25
+ Requires-Dist: rich>=13.0
26
+ Requires-Dist: prompt_toolkit>=3.0
27
+ Requires-Dist: loguru>=0.7
28
+ Requires-Dist: anthropic>=0.40
29
+ Requires-Dist: httpx>=0.27
30
+ Provides-Extra: dev
31
+ Requires-Dist: pytest>=8.0; extra == "dev"
32
+ Requires-Dist: ruff>=0.4; extra == "dev"
33
+ Dynamic: license-file
34
+
35
+ # 🤖 PawnLogic
36
+
37
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
38
+ [![Version](https://img.shields.io/badge/version-1.1-blue.svg)](config/paths.py)
39
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/)
40
+ [![Platform](https://img.shields.io/badge/Platform-Linux%20%7C%20WSL2-lightgrey.svg)]()
41
+
42
+ > **A fully autonomous terminal AI agent** — multi-model routing, persistent memory, real tool execution, and session management. Built for developers and security researchers.
43
+
44
+ ## ⚡ Quick Start
45
+
46
+ ```bash
47
+ git clone https://github.com/john0123412/PawnLogic.git && cd PawnLogic
48
+ python3 -m venv venv && source venv/bin/activate
49
+ pip install -r requirements.txt
50
+ python main.py # first run launches the API configuration wizard
51
+ ```
52
+
53
+ Global `pawn` command:
54
+ ```bash
55
+ chmod +x pawn.sh && ln -sf "$(pwd)/pawn.sh" ~/.local/bin/pawn
56
+ ```
57
+
58
+ ## Key Capabilities
59
+
60
+ | Capability | Description |
61
+ |-----------|-------------|
62
+ | 🔀 **Dynamic Provider System** | Built-in DeepSeek / OpenAI / Anthropic + add any OpenAI-compatible API via `/provider` |
63
+ | 🧠 **Persistent Memory** | SQLite session history, RAG knowledge base, cross-session full-text search |
64
+ | 🛠️ **Real Tool Execution** | Shell, code sandbox (8 languages), web fetch, file ops, Docker containers |
65
+ | 👁️ **Vision** | Feed screenshots to `gpt-4o` or `claude-sonnet` for analysis |
66
+ | 📋 **Spec-Driven Planning** | Agent outputs `<plan>` XML before every action — no blind execution |
67
+ | 💬 **Session Management** | Tag, search, link, and export conversations with `/chat` commands |
68
+ | 🔐 **CTF / Pwn Toolchain** | GDB automation, ROP chain building, libc leak resolution, Docker isolation |
69
+
70
+ ## Supported Models
71
+
72
+ | Provider | Aliases | Best For |
73
+ |----------|---------|----------|
74
+ | DeepSeek | `ds-v4-flash` `ds-v4-pro` | Fast default, flagship reasoning |
75
+ | OpenAI | `gpt-4o` `gpt-4.1` `o3` | Vision, code, complex reasoning |
76
+ | Anthropic | `claude-sonnet` `claude-haiku` | Balanced, fast low-cost |
77
+
78
+ Custom providers added via `/provider fetch` appear automatically in `/model` and Tab completion.
79
+
80
+ ## Provider Management
81
+
82
+ ```bash
83
+ /provider # open interactive TUI panel
84
+ /provider add <name> <base_url> <ENV_KEY> [anthropic]
85
+ /provider fetch <name> # auto-discover models with interactive multi-select
86
+ /provider list # show all providers and key status
87
+ /provider test <model> # test connectivity
88
+ ```
89
+
90
+ All keys are stored in `~/.pawnlogic/.env`. Provider configs (no keys) go to `~/.pawnlogic/custom_providers.json`.
91
+
92
+ ## Quick Command Reference
93
+
94
+ ```bash
95
+ /model [alias] # switch model
96
+ /mode # toggle USER / DEV output mode
97
+ /chat find <keyword> # full-text search across all sessions
98
+ /think <prompt> # single deep-reasoning turn
99
+ /compact # summarize + clear context
100
+ /undo [n] # roll back last n turns
101
+ /deep # switch to deep mode (32k tokens, 50 iter)
102
+ /init_project # initialize GSD engineering pipeline
103
+ /pwnenv # check CTF toolchain integrity
104
+ /keys # show API key status for all providers
105
+ ```
106
+
107
+ ## MCP Tool Integration
108
+
109
+ ```bash
110
+ cp mcp_configs.example.json ~/.pawnlogic/mcp_configs.json
111
+ # edit mcp_configs.json, add TAVILY_API_KEY= etc. to ~/.pawnlogic/.env
112
+ python main.py # MCP servers load automatically
113
+ ```
114
+
115
+ Supported MCP servers: **Tavily** (search), **Playwright** (browser automation), **Filesystem** (file bridge).
116
+
117
+ ## Data Layout
118
+
119
+ All runtime data and API keys are stored in `~/.pawnlogic/` — **never in the project directory**.
120
+
121
+ ```
122
+ ~/.pawnlogic/
123
+ ├── .env # ALL API keys (LLM providers + MCP tools)
124
+ ├── custom_providers.json # user-added provider configs (no keys)
125
+ ├── mcp_configs.json # MCP server declarations
126
+ ├── pawn.db # sessions, messages, knowledge base
127
+ ├── global_skills.md # GSA skill archive
128
+ ├── workspace/ # per-session working directories
129
+ └── logs/ # audit logs
130
+ ```
131
+
132
+ The project directory contains no secrets and is safe to commit or share.
133
+
134
+ ## Documentation
135
+
136
+ | Document | Description |
137
+ |----------|-------------|
138
+ | **README.md** | This page |
139
+ | **README_CN.md** | 中文版 |
140
+ | **GUIDE_EN.md** | Full reference — commands, architecture, FAQ |
141
+ | **GUIDE_CN.md** | 完整参考手册 — 命令、架构、常见问题 |
142
+ | **CHANGELOG.md** | Version history and release notes |
143
+ | **CONTRIBUTING.md** | How to contribute, add providers, run tests |
144
+ | **SECURITY.md** | Vulnerability reporting policy |
145
+
146
+ ## Support
147
+
148
+ - **GitHub**: [github.com/john0123412/PawnLogic](https://github.com/john0123412/PawnLogic)
149
+ - **Issues**: GitHub Issues for bugs and feature requests
@@ -0,0 +1,115 @@
1
+ # 🤖 PawnLogic
2
+
3
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
4
+ [![Version](https://img.shields.io/badge/version-1.1-blue.svg)](config/paths.py)
5
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/)
6
+ [![Platform](https://img.shields.io/badge/Platform-Linux%20%7C%20WSL2-lightgrey.svg)]()
7
+
8
+ > **A fully autonomous terminal AI agent** — multi-model routing, persistent memory, real tool execution, and session management. Built for developers and security researchers.
9
+
10
+ ## ⚡ Quick Start
11
+
12
+ ```bash
13
+ git clone https://github.com/john0123412/PawnLogic.git && cd PawnLogic
14
+ python3 -m venv venv && source venv/bin/activate
15
+ pip install -r requirements.txt
16
+ python main.py # first run launches the API configuration wizard
17
+ ```
18
+
19
+ Global `pawn` command:
20
+ ```bash
21
+ chmod +x pawn.sh && ln -sf "$(pwd)/pawn.sh" ~/.local/bin/pawn
22
+ ```
23
+
24
+ ## Key Capabilities
25
+
26
+ | Capability | Description |
27
+ |-----------|-------------|
28
+ | 🔀 **Dynamic Provider System** | Built-in DeepSeek / OpenAI / Anthropic + add any OpenAI-compatible API via `/provider` |
29
+ | 🧠 **Persistent Memory** | SQLite session history, RAG knowledge base, cross-session full-text search |
30
+ | 🛠️ **Real Tool Execution** | Shell, code sandbox (8 languages), web fetch, file ops, Docker containers |
31
+ | 👁️ **Vision** | Feed screenshots to `gpt-4o` or `claude-sonnet` for analysis |
32
+ | 📋 **Spec-Driven Planning** | Agent outputs `<plan>` XML before every action — no blind execution |
33
+ | 💬 **Session Management** | Tag, search, link, and export conversations with `/chat` commands |
34
+ | 🔐 **CTF / Pwn Toolchain** | GDB automation, ROP chain building, libc leak resolution, Docker isolation |
35
+
36
+ ## Supported Models
37
+
38
+ | Provider | Aliases | Best For |
39
+ |----------|---------|----------|
40
+ | DeepSeek | `ds-v4-flash` `ds-v4-pro` | Fast default, flagship reasoning |
41
+ | OpenAI | `gpt-4o` `gpt-4.1` `o3` | Vision, code, complex reasoning |
42
+ | Anthropic | `claude-sonnet` `claude-haiku` | Balanced, fast low-cost |
43
+
44
+ Custom providers added via `/provider fetch` appear automatically in `/model` and Tab completion.
45
+
46
+ ## Provider Management
47
+
48
+ ```bash
49
+ /provider # open interactive TUI panel
50
+ /provider add <name> <base_url> <ENV_KEY> [anthropic]
51
+ /provider fetch <name> # auto-discover models with interactive multi-select
52
+ /provider list # show all providers and key status
53
+ /provider test <model> # test connectivity
54
+ ```
55
+
56
+ All keys are stored in `~/.pawnlogic/.env`. Provider configs (no keys) go to `~/.pawnlogic/custom_providers.json`.
57
+
58
+ ## Quick Command Reference
59
+
60
+ ```bash
61
+ /model [alias] # switch model
62
+ /mode # toggle USER / DEV output mode
63
+ /chat find <keyword> # full-text search across all sessions
64
+ /think <prompt> # single deep-reasoning turn
65
+ /compact # summarize + clear context
66
+ /undo [n] # roll back last n turns
67
+ /deep # switch to deep mode (32k tokens, 50 iter)
68
+ /init_project # initialize GSD engineering pipeline
69
+ /pwnenv # check CTF toolchain integrity
70
+ /keys # show API key status for all providers
71
+ ```
72
+
73
+ ## MCP Tool Integration
74
+
75
+ ```bash
76
+ cp mcp_configs.example.json ~/.pawnlogic/mcp_configs.json
77
+ # edit mcp_configs.json, add TAVILY_API_KEY= etc. to ~/.pawnlogic/.env
78
+ python main.py # MCP servers load automatically
79
+ ```
80
+
81
+ Supported MCP servers: **Tavily** (search), **Playwright** (browser automation), **Filesystem** (file bridge).
82
+
83
+ ## Data Layout
84
+
85
+ All runtime data and API keys are stored in `~/.pawnlogic/` — **never in the project directory**.
86
+
87
+ ```
88
+ ~/.pawnlogic/
89
+ ├── .env # ALL API keys (LLM providers + MCP tools)
90
+ ├── custom_providers.json # user-added provider configs (no keys)
91
+ ├── mcp_configs.json # MCP server declarations
92
+ ├── pawn.db # sessions, messages, knowledge base
93
+ ├── global_skills.md # GSA skill archive
94
+ ├── workspace/ # per-session working directories
95
+ └── logs/ # audit logs
96
+ ```
97
+
98
+ The project directory contains no secrets and is safe to commit or share.
99
+
100
+ ## Documentation
101
+
102
+ | Document | Description |
103
+ |----------|-------------|
104
+ | **README.md** | This page |
105
+ | **README_CN.md** | 中文版 |
106
+ | **GUIDE_EN.md** | Full reference — commands, architecture, FAQ |
107
+ | **GUIDE_CN.md** | 完整参考手册 — 命令、架构、常见问题 |
108
+ | **CHANGELOG.md** | Version history and release notes |
109
+ | **CONTRIBUTING.md** | How to contribute, add providers, run tests |
110
+ | **SECURITY.md** | Vulnerability reporting policy |
111
+
112
+ ## Support
113
+
114
+ - **GitHub**: [github.com/john0123412/PawnLogic](https://github.com/john0123412/PawnLogic)
115
+ - **Issues**: GitHub Issues for bugs and feature requests
@@ -0,0 +1,47 @@
1
+ """
2
+ config/__init__.py — 向后兼容入口
3
+
4
+ 外部代码 `from config import X` 或 `import config; config.X` 无需任何修改。
5
+ """
6
+ from .providers import (
7
+ PROVIDERS, MODELS, DEFAULT_MODEL, VISION_PRIORITY,
8
+ NAMING_MODEL_CHAIN, CUSTOM_PROVIDERS_PATH,
9
+ get_api_config, get_api_format, get_provider_config,
10
+ validate_api_key, list_configured_models,
11
+ get_best_vision_model, list_vision_models,
12
+ load_custom_providers, save_custom_provider, remove_custom_provider,
13
+ is_fast_model, find_fast_peer,
14
+ )
15
+ from .tiers import TIER_LOW, TIER_MID, TIER_DEEP, TIER_MAX
16
+ from .security import (
17
+ READ_BLACKLIST, WRITE_BLACKLIST, DANGEROUS_PATTERNS,
18
+ smart_truncate, user_friendly_error,
19
+ )
20
+ from .sandbox import SANDBOX_LANGS, DOCKER_IMAGES, BROWSER_CONFIG, USER_AGENTS
21
+ from .phases import AGENT_PHASES
22
+ from .paths import (
23
+ VERSION, SESSIONS_DIR, DB_PATH, GLOBAL_SKILLS_PATH,
24
+ SKILLS_DIR, LOG_DIR, WORKSPACE_DIR, WORKSPACE_ROOT,
25
+ )
26
+
27
+ # ── 向后兼容:DYNAMIC_CONFIG / NORMAL_CONFIG ──────────────
28
+ # 这两个可变 dict 由 main.py 在运行时修改(/mid /deep /low 等命令)。
29
+ # 保留在此处以兼容所有 `from config import DYNAMIC_CONFIG` 的调用。
30
+ DYNAMIC_CONFIG: dict = dict(TIER_MID)
31
+ NORMAL_CONFIG: dict = dict(TIER_MID)
32
+
33
+ # ── 向后兼容:WEB_STRATEGY ────────────────────────────────
34
+ WEB_STRATEGY = {
35
+ "jina_base": "https://r.jina.ai/",
36
+ "use_pandoc": True,
37
+ "timeout": 20,
38
+ "max_html_read": 600_000,
39
+ }
40
+
41
+ # ── 向后兼容:USER_MODE / QUIET_MODE ─────────────────────
42
+ # 这两个标志现在由 core.state 管理。
43
+ # 保留模块级变量以兼容 `import config; config.QUIET_MODE = True` 的写法。
44
+ # 注意:直接赋值此处的变量不会影响 core.state.state,
45
+ # 推荐新代码使用 `from core.state import state`。
46
+ USER_MODE: bool = False
47
+ QUIET_MODE: bool = False
@@ -0,0 +1,17 @@
1
+ """config/paths.py — 路径与版本常量
2
+
3
+ 版本号唯一定义处。全局通过 `from config import VERSION` 读取。
4
+ 升级时只需修改此处。
5
+ """
6
+ from pathlib import Path
7
+
8
+ # ── 唯一版本号定义 ──────────────────────────────────────
9
+ VERSION = "1.1"
10
+
11
+ SESSIONS_DIR = Path.home() / ".pawnlogic" / "sessions"
12
+ DB_PATH = Path.home() / ".pawnlogic" / "pawn.db"
13
+ GLOBAL_SKILLS_PATH = Path.home() / ".pawnlogic" / "global_skills.md"
14
+ SKILLS_DIR = Path(__file__).resolve().parent.parent / "skills"
15
+ LOG_DIR = Path.home() / ".pawnlogic" / "logs"
16
+ WORKSPACE_DIR = str(Path.home() / ".pawnlogic" / "workspace")
17
+ WORKSPACE_ROOT = str(Path.home() / ".pawnlogic")
@@ -0,0 +1,40 @@
1
+ """config/phases.py — MoE 动态工具裁剪专家路由表"""
2
+
3
+ AGENT_PHASES: dict[str, list[str]] = {
4
+ "RECON": [
5
+ "pwn_env", "list_dir", "find_files", "read_file", "inspect_binary",
6
+ "pwn_timed_debug",
7
+ "search_skills",
8
+ "check_service",
9
+ ],
10
+ "VULN_DEV": [
11
+ "pwn_cyclic", "pwn_disasm", "pwn_rop", "pwn_libc", "pwn_one_gadget", "run_shell",
12
+ "pwn_timed_debug",
13
+ ],
14
+ "EXPLOIT": [
15
+ "write_file", "patch_file", "run_code", "pwn_debug", "pwn_timed_debug",
16
+ "run_interactive", "run_shell",
17
+ "run_code_docker", "pwn_container",
18
+ "tool_install_package",
19
+ "docker_prune_resources",
20
+ ],
21
+ "GENERAL": [
22
+ "read_file", "write_file", "patch_file", "run_shell", "web_search", "fetch_url",
23
+ "pwn_timed_debug",
24
+ "run_code_docker", "pwn_container",
25
+ "tool_install_package",
26
+ "docker_prune_resources",
27
+ "bump_skill",
28
+ "search_skills",
29
+ "check_service",
30
+ ],
31
+ "WEB_PEN": [
32
+ "web_fetch", "web_click", "web_screenshot", "web_select", "web_type", "web_navigate",
33
+ "web_search", "fetch_url",
34
+ "read_file", "write_file",
35
+ "run_shell",
36
+ "bump_skill",
37
+ "search_skills",
38
+ "check_service",
39
+ ],
40
+ }
@@ -0,0 +1,271 @@
1
+ """
2
+ config/providers.py — API Provider 与模型注册表
3
+
4
+ 所有 API Key 通过环境变量注入,代码中无任何硬编码凭证。
5
+ """
6
+ import os
7
+ import json
8
+ from pathlib import Path
9
+
10
+ PROVIDERS: dict[str, dict] = {
11
+ "deepseek": {
12
+ "base_url": "https://api.deepseek.com/v1/chat/completions",
13
+ "api_key_env": "DEEPSEEK_API_KEY",
14
+ "label": "DeepSeek",
15
+ "api_format": "openai",
16
+ },
17
+ "openai": {
18
+ "base_url": "https://api.openai.com/v1/chat/completions",
19
+ "api_key_env": "OPENAI_API_KEY",
20
+ "label": "OpenAI",
21
+ "api_format": "openai",
22
+ },
23
+ "anthropic": {
24
+ "base_url": "https://api.anthropic.com/v1/messages",
25
+ "api_key_env": "ANTHROPIC_API_KEY",
26
+ "label": "Anthropic (Claude)",
27
+ "api_format": "anthropic",
28
+ },
29
+ }
30
+
31
+ MODELS: dict[str, dict] = {
32
+ "ds-v4-flash": {
33
+ "id": "deepseek-v4-flash",
34
+ "provider": "deepseek",
35
+ "desc": "DeepSeek V4 Flash — 默认主力,快速低成本",
36
+ "color": "\033[32m",
37
+ "vision": False,
38
+ "reasoning": True, # 返回 reasoning_content,必须回传
39
+ },
40
+ "ds-v4-pro": {
41
+ "id": "deepseek-v4-pro",
42
+ "provider": "deepseek",
43
+ "desc": "DeepSeek V4 Pro — 旗舰推理",
44
+ "color": "\033[92m",
45
+ "vision": False,
46
+ "reasoning": True,
47
+ },
48
+ "gpt-4o": {
49
+ "id": "gpt-4o",
50
+ "provider": "openai",
51
+ "desc": "OpenAI GPT-4o — 视觉+多模态",
52
+ "color": "\033[97m",
53
+ "vision": True,
54
+ "reasoning": False,
55
+ },
56
+ "gpt-4.1": {
57
+ "id": "gpt-4.1",
58
+ "provider": "openai",
59
+ "desc": "OpenAI GPT-4.1 — 代码与指令跟随",
60
+ "color": "\033[37m",
61
+ "vision": False,
62
+ "reasoning": False,
63
+ },
64
+ "o3": {
65
+ "id": "o3",
66
+ "provider": "openai",
67
+ "desc": "OpenAI o3 — 复杂推理",
68
+ "color": "\033[96m",
69
+ "vision": False,
70
+ "reasoning": False, # OpenAI o系列推理内部化,不暴露 reasoning_content 字段
71
+ },
72
+ "claude-sonnet": {
73
+ "id": "claude-sonnet-4-6",
74
+ "provider": "anthropic",
75
+ "desc": "Claude Sonnet 4.6 — 均衡主力",
76
+ "color": "\033[95m",
77
+ "vision": True,
78
+ "reasoning": False, # Anthropic 格式走独立路径,不经过 sanitizer
79
+ },
80
+ "claude-haiku": {
81
+ "id": "claude-haiku-4-5-20251001",
82
+ "provider": "anthropic",
83
+ "desc": "Claude Haiku 4.5 — 快速低成本",
84
+ "color": "\033[35m",
85
+ "vision": True,
86
+ "reasoning": False,
87
+ },
88
+ }
89
+
90
+ DEFAULT_MODEL = "ds-v4-flash"
91
+
92
+ NAMING_MODEL_CHAIN: list = [
93
+ "claude-haiku",
94
+ "ds-v4-flash",
95
+ "gpt-4.1",
96
+ ]
97
+
98
+ VISION_PRIORITY = ["gpt-4o", "claude-sonnet"]
99
+
100
+ CUSTOM_PROVIDERS_PATH = Path.home() / ".pawnlogic" / "custom_providers.json"
101
+
102
+
103
+ def _normalize_url(raw: str, api_format: str = "openai") -> str:
104
+ """Ensure base_url ends with the correct chat endpoint path."""
105
+ raw = raw.rstrip("/")
106
+ if raw.endswith("/chat/completions") or raw.endswith("/messages"):
107
+ return raw
108
+ suffix = "/messages" if api_format == "anthropic" else "/chat/completions"
109
+ if raw.endswith("/v1"):
110
+ return raw + suffix
111
+ return raw + "/v1" + suffix
112
+
113
+
114
+ _FAST_KEYWORDS = {"flash", "haiku", "mini", "turbo", "lite"}
115
+
116
+
117
+ def is_fast_model(model_alias: str) -> bool:
118
+ """Return True if the model id contains a fast-tier keyword."""
119
+ mid = MODELS.get(model_alias, {}).get("id", model_alias).lower()
120
+ return any(k in mid for k in _FAST_KEYWORDS)
121
+
122
+
123
+ def find_fast_peer(model_alias: str) -> str | None:
124
+ """
125
+ Given a pro-tier model alias, return the alias of a fast-tier model
126
+ from the same provider that has a valid API key.
127
+ Returns None if no fast peer is found.
128
+ """
129
+ m = MODELS.get(model_alias)
130
+ if not m:
131
+ return None
132
+ provider = m.get("provider", "")
133
+ for alias, cfg in MODELS.items():
134
+ if cfg.get("provider") != provider:
135
+ continue
136
+ if not is_fast_model(alias):
137
+ continue
138
+ ok, _ = validate_api_key(alias)
139
+ if ok:
140
+ return alias
141
+ return None
142
+
143
+
144
+ def get_api_config(model_alias: str) -> tuple[str, str]:
145
+ """返回 (base_url, api_key)。Key 从环境变量读取,永不硬编码。"""
146
+ m = MODELS.get(model_alias, MODELS[DEFAULT_MODEL])
147
+ prov = PROVIDERS.get(m["provider"], list(PROVIDERS.values())[0])
148
+ key = os.getenv(prov["api_key_env"], "")
149
+ fmt = prov.get("api_format", "openai")
150
+ return _normalize_url(prov["base_url"], fmt), key
151
+
152
+
153
+ def get_api_format(model_alias: str) -> str:
154
+ """返回 'openai' 或 'anthropic'。"""
155
+ m = MODELS.get(model_alias, MODELS[DEFAULT_MODEL])
156
+ prov = PROVIDERS.get(m["provider"], {})
157
+ return prov.get("api_format", "openai")
158
+
159
+
160
+ def get_provider_config(model_alias: str) -> dict:
161
+ """返回完整 provider 配置字典。"""
162
+ m = MODELS.get(model_alias, MODELS[DEFAULT_MODEL])
163
+ prov = PROVIDERS.get(m["provider"], list(PROVIDERS.values())[0])
164
+ key = os.getenv(prov["api_key_env"], "")
165
+ fmt = prov.get("api_format", "openai")
166
+ return {
167
+ "base_url": _normalize_url(prov["base_url"], fmt),
168
+ "api_key": key,
169
+ "api_format": fmt,
170
+ "label": prov.get("label", ""),
171
+ }
172
+
173
+
174
+ def validate_api_key(model_alias: str) -> tuple[bool, str]:
175
+ """检查指定模型的 Key 是否已正确配置。返回 (ok, missing_env_var)。"""
176
+ _, key = get_api_config(model_alias)
177
+ if not key:
178
+ m = MODELS.get(model_alias, MODELS[DEFAULT_MODEL])
179
+ prov = PROVIDERS.get(m["provider"], {})
180
+ return False, prov.get("api_key_env", "")
181
+ return True, ""
182
+
183
+
184
+ def list_configured_models() -> list[str]:
185
+ """返回所有已配置 Key 的模型别名列表。"""
186
+ return [alias for alias in MODELS if validate_api_key(alias)[0]]
187
+
188
+
189
+ def get_best_vision_model() -> tuple[str | None, str | None, str | None]:
190
+ """按优先级找到第一个已配置 Key 的视觉模型。"""
191
+ for alias in VISION_PRIORITY:
192
+ m = MODELS.get(alias)
193
+ if not m or not m.get("vision"):
194
+ continue
195
+ url, key = get_api_config(alias)
196
+ if key:
197
+ return alias, url, key
198
+ return None, None, None
199
+
200
+
201
+ def list_vision_models() -> list[str]:
202
+ """返回所有标记了 vision=True 的模型别名。"""
203
+ return [alias for alias, m in MODELS.items() if m.get("vision")]
204
+
205
+
206
+ def load_custom_providers() -> None:
207
+ """从 custom_providers.json 加载用户自定义 provider,合并进 PROVIDERS/MODELS。"""
208
+ # Reload .env so keys added after startup (e.g. via wizard) are available
209
+ try:
210
+ from dotenv import load_dotenv
211
+ _env = Path.home() / ".pawnlogic" / ".env"
212
+ if _env.exists():
213
+ load_dotenv(_env, override=True)
214
+ except ImportError:
215
+ pass
216
+ if not CUSTOM_PROVIDERS_PATH.exists():
217
+ return
218
+ try:
219
+ data = json.loads(CUSTOM_PROVIDERS_PATH.read_text(encoding="utf-8"))
220
+ except Exception:
221
+ return
222
+ for name, prov in data.get("providers", {}).items():
223
+ if name not in PROVIDERS:
224
+ prov.setdefault("api_format", "openai")
225
+ PROVIDERS[name] = prov
226
+ for alias, model in data.get("models", {}).items():
227
+ if alias not in MODELS:
228
+ model.setdefault("color", "\033[37m")
229
+ model.setdefault("vision", False)
230
+ MODELS[alias] = model
231
+
232
+
233
+ def save_custom_provider(name: str, prov_cfg: dict, models_cfg: dict) -> None:
234
+ """将自定义 provider 持久化到 custom_providers.json(不含 Key)。"""
235
+ CUSTOM_PROVIDERS_PATH.parent.mkdir(parents=True, exist_ok=True)
236
+ data: dict = {"providers": {}, "models": {}}
237
+ if CUSTOM_PROVIDERS_PATH.exists():
238
+ try:
239
+ data = json.loads(CUSTOM_PROVIDERS_PATH.read_text(encoding="utf-8"))
240
+ except Exception:
241
+ pass
242
+ data["providers"][name] = prov_cfg
243
+ data["models"].update(models_cfg)
244
+ CUSTOM_PROVIDERS_PATH.write_text(
245
+ json.dumps(data, ensure_ascii=False, indent=2), encoding="utf-8"
246
+ )
247
+
248
+
249
+ def remove_custom_provider(name: str) -> bool:
250
+ """从 JSON 文件删除自定义 provider。返回是否成功。"""
251
+ if not CUSTOM_PROVIDERS_PATH.exists():
252
+ return False
253
+ try:
254
+ data = json.loads(CUSTOM_PROVIDERS_PATH.read_text(encoding="utf-8"))
255
+ except Exception:
256
+ return False
257
+ if name not in data.get("providers", {}):
258
+ return False
259
+ del data["providers"][name]
260
+ to_remove = [a for a, m in data.get("models", {}).items()
261
+ if m.get("provider") == name]
262
+ for a in to_remove:
263
+ del data["models"][a]
264
+ CUSTOM_PROVIDERS_PATH.write_text(
265
+ json.dumps(data, ensure_ascii=False, indent=2), encoding="utf-8"
266
+ )
267
+ return True
268
+
269
+
270
+ # 模块加载时自动读取自定义 provider
271
+ load_custom_providers()