prompt-copilot-cli 0.2.8__tar.gz → 0.5.0__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.
- prompt_copilot_cli-0.5.0/PKG-INFO +208 -0
- prompt_copilot_cli-0.5.0/README.md +178 -0
- prompt_copilot_cli-0.5.0/README.zh-CN.md +180 -0
- prompt_copilot_cli-0.5.0/copilot/__init__.py +1 -0
- prompt_copilot_cli-0.5.0/copilot/agent.py +127 -0
- prompt_copilot_cli-0.5.0/copilot/cli.py +108 -0
- prompt_copilot_cli-0.5.0/copilot/config.py +46 -0
- prompt_copilot_cli-0.5.0/copilot/memory.py +52 -0
- prompt_copilot_cli-0.5.0/copilot/tools.py +144 -0
- prompt_copilot_cli-0.5.0/main.py +6 -0
- prompt_copilot_cli-0.5.0/prompt_copilot_cli.egg-info/PKG-INFO +208 -0
- {prompt_copilot_cli-0.2.8 → prompt_copilot_cli-0.5.0}/prompt_copilot_cli.egg-info/SOURCES.txt +8 -6
- prompt_copilot_cli-0.5.0/prompt_copilot_cli.egg-info/requires.txt +7 -0
- prompt_copilot_cli-0.5.0/prompt_copilot_cli.egg-info/top_level.txt +2 -0
- {prompt_copilot_cli-0.2.8 → prompt_copilot_cli-0.5.0}/pyproject.toml +10 -7
- prompt_copilot_cli-0.5.0/requirements.txt +7 -0
- prompt_copilot_cli-0.5.0/tests/test_config.py +14 -0
- prompt_copilot_cli-0.5.0/tests/test_tools.py +25 -0
- prompt_copilot_cli-0.2.8/PKG-INFO +0 -233
- prompt_copilot_cli-0.2.8/README.md +0 -205
- prompt_copilot_cli-0.2.8/README.zh-CN.md +0 -204
- prompt_copilot_cli-0.2.8/main.py +0 -2485
- prompt_copilot_cli-0.2.8/prompt_copilot_cli.egg-info/PKG-INFO +0 -233
- prompt_copilot_cli-0.2.8/prompt_copilot_cli.egg-info/requires.txt +0 -4
- prompt_copilot_cli-0.2.8/prompt_copilot_cli.egg-info/top_level.txt +0 -1
- prompt_copilot_cli-0.2.8/requirements.txt +0 -4
- prompt_copilot_cli-0.2.8/tests/test_cli_args.py +0 -166
- prompt_copilot_cli-0.2.8/tests/test_command_timeout.py +0 -37
- prompt_copilot_cli-0.2.8/tests/test_file_tools.py +0 -120
- prompt_copilot_cli-0.2.8/tests/test_image_tool.py +0 -32
- prompt_copilot_cli-0.2.8/tests/test_mcp_transport.py +0 -27
- prompt_copilot_cli-0.2.8/tests/test_multimodal_messages.py +0 -38
- {prompt_copilot_cli-0.2.8 → prompt_copilot_cli-0.5.0}/LICENSE +0 -0
- {prompt_copilot_cli-0.2.8 → prompt_copilot_cli-0.5.0}/MANIFEST.in +0 -0
- {prompt_copilot_cli-0.2.8 → prompt_copilot_cli-0.5.0}/prompt_copilot_cli.egg-info/dependency_links.txt +0 -0
- {prompt_copilot_cli-0.2.8 → prompt_copilot_cli-0.5.0}/prompt_copilot_cli.egg-info/entry_points.txt +0 -0
- {prompt_copilot_cli-0.2.8 → prompt_copilot_cli-0.5.0}/setup.cfg +0 -0
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: prompt-copilot-cli
|
|
3
|
+
Version: 0.5.0
|
|
4
|
+
Summary: A simple terminal coding agent built on LangChain with OpenAI-compatible models and durable memory.
|
|
5
|
+
Author: Jason Li
|
|
6
|
+
License-Expression: Apache-2.0
|
|
7
|
+
Project-URL: Homepage, https://github.com/woshiliyihang/prompt-copilot-cli
|
|
8
|
+
Project-URL: Repository, https://github.com/woshiliyihang/prompt-copilot-cli
|
|
9
|
+
Project-URL: Issues, https://github.com/woshiliyihang/prompt-copilot-cli/issues
|
|
10
|
+
Keywords: cli,agent,langchain,langgraph,openai-compatible,coding-assistant
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
18
|
+
Classifier: Topic :: Utilities
|
|
19
|
+
Requires-Python: <3.15,>=3.10
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
License-File: LICENSE
|
|
22
|
+
Requires-Dist: langchain<2.0,>=1.3
|
|
23
|
+
Requires-Dist: langchain-openai<2.0,>=1.1
|
|
24
|
+
Requires-Dist: langgraph<2.0,>=1.2
|
|
25
|
+
Requires-Dist: langgraph-checkpoint-sqlite<4.0,>=3.0
|
|
26
|
+
Requires-Dist: langmem<1.0,>=0.0.29
|
|
27
|
+
Requires-Dist: prompt_toolkit<4.0.0,>=3.0.52
|
|
28
|
+
Requires-Dist: rich<16.0.0,>=15.0.0
|
|
29
|
+
Dynamic: license-file
|
|
30
|
+
|
|
31
|
+
# Prompt Copilot CLI
|
|
32
|
+
|
|
33
|
+
A lightweight terminal coding agent built on LangChain and LangGraph. The project has been refactored to use the standard agent runtime, SQLite-backed persistence, and a small, explicit tool set instead of maintaining a custom agent loop.
|
|
34
|
+
|
|
35
|
+
## What this project does
|
|
36
|
+
|
|
37
|
+
Prompt Copilot CLI lets you:
|
|
38
|
+
|
|
39
|
+
- open a workspace directory and chat with an agent in the terminal
|
|
40
|
+
- use a small set of coding tools for reading, searching, editing, and running Python commands
|
|
41
|
+
- persist conversation state and durable memories using LangGraph SQLite storage
|
|
42
|
+
- connect to an OpenAI-compatible model endpoint such as OpenAI, Azure OpenAI, OpenRouter, or local OpenAI-compatible gateways
|
|
43
|
+
|
|
44
|
+
## Architecture
|
|
45
|
+
|
|
46
|
+
```text
|
|
47
|
+
CLI
|
|
48
|
+
└── AgentRuntime
|
|
49
|
+
├── ChatOpenAI
|
|
50
|
+
├── create_agent()
|
|
51
|
+
├── SummarizationMiddleware
|
|
52
|
+
├── SqliteSaver
|
|
53
|
+
├── SqliteStore
|
|
54
|
+
└── LangMem tools
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
The runtime is intentionally minimal:
|
|
58
|
+
|
|
59
|
+
- `create_agent()` provides the model/tool loop
|
|
60
|
+
- `SummarizationMiddleware` compresses long conversations
|
|
61
|
+
- `SqliteSaver` persists the current conversation thread
|
|
62
|
+
- `SqliteStore` + LangMem handle durable project memory
|
|
63
|
+
- tools remain focused on the practical coding workflow
|
|
64
|
+
|
|
65
|
+
## Install
|
|
66
|
+
|
|
67
|
+
From the project root:
|
|
68
|
+
|
|
69
|
+
```powershell
|
|
70
|
+
python -m pip install -e .
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Or install from PyPI:
|
|
74
|
+
|
|
75
|
+
```powershell
|
|
76
|
+
python -m pip install -U prompt-copilot-cli
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Initial configuration
|
|
80
|
+
|
|
81
|
+
The first run creates a config file in:
|
|
82
|
+
|
|
83
|
+
- Windows: `%USERPROFILE%\.prompt-copilot\config.json`
|
|
84
|
+
- Linux/macOS: `~/.prompt-copilot/config.json`
|
|
85
|
+
|
|
86
|
+
Example:
|
|
87
|
+
|
|
88
|
+
```json
|
|
89
|
+
{
|
|
90
|
+
"model": "gpt-4o-mini",
|
|
91
|
+
"base_url": "https://api.openai.com/v1",
|
|
92
|
+
"api_key": "YOUR_API_KEY",
|
|
93
|
+
"temperature": 0.2,
|
|
94
|
+
"timeout": 120,
|
|
95
|
+
"memory": {
|
|
96
|
+
"enabled": true,
|
|
97
|
+
"max_recent_memories": 5
|
|
98
|
+
},
|
|
99
|
+
"context": {
|
|
100
|
+
"summary_trigger_tokens": 12000,
|
|
101
|
+
"keep_messages": 20
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
You can point `base_url` to any OpenAI-compatible endpoint, and the project will use `api_key` from that config file.
|
|
107
|
+
|
|
108
|
+
## Usage
|
|
109
|
+
|
|
110
|
+
Start interactive mode:
|
|
111
|
+
|
|
112
|
+
```powershell
|
|
113
|
+
prompt-copilot -d D:\project
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Run a single task and exit:
|
|
117
|
+
|
|
118
|
+
```powershell
|
|
119
|
+
prompt-copilot -d D:\project -t "Inspect the repo, fix the failing tests, and run the relevant checks."
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
From the CLI, use these commands:
|
|
123
|
+
|
|
124
|
+
- `/exit` — quit the program
|
|
125
|
+
- `/clear` — reset the current workspace thread
|
|
126
|
+
- `/memory` — display persistent memories for this workspace
|
|
127
|
+
|
|
128
|
+
The prompt supports multiline input. Press `Enter` for a newline and `Ctrl+Enter` to submit.
|
|
129
|
+
|
|
130
|
+
## Available tools
|
|
131
|
+
|
|
132
|
+
The agent exposes a compact tool set:
|
|
133
|
+
|
|
134
|
+
- `read_file`
|
|
135
|
+
- `list_files`
|
|
136
|
+
- `search_code`
|
|
137
|
+
- `write_file`
|
|
138
|
+
- `edit_file`
|
|
139
|
+
- `delete_file`
|
|
140
|
+
- `execute_python_script`
|
|
141
|
+
- `execute_command`
|
|
142
|
+
|
|
143
|
+
These are intentionally scoped to file work, code search, editing, and local execution.
|
|
144
|
+
|
|
145
|
+
## Memory behavior
|
|
146
|
+
|
|
147
|
+
The runtime uses two persistence layers:
|
|
148
|
+
|
|
149
|
+
### Short-term memory
|
|
150
|
+
|
|
151
|
+
`SqliteSaver` stores the live thread state for the current workspace. If you restart the CLI, the same workspace can continue the same conversation.
|
|
152
|
+
|
|
153
|
+
### Long-term memory
|
|
154
|
+
|
|
155
|
+
`SqliteStore` stores durable project memory and LangMem exposes memory management tools so the agent can remember useful project conventions or user preferences.
|
|
156
|
+
|
|
157
|
+
Memory data is stored under:
|
|
158
|
+
|
|
159
|
+
```text
|
|
160
|
+
~/.prompt-copilot/memory.db
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## Project structure
|
|
164
|
+
|
|
165
|
+
```text
|
|
166
|
+
.
|
|
167
|
+
├── main.py
|
|
168
|
+
├── copilot/
|
|
169
|
+
│ ├── __init__.py
|
|
170
|
+
│ ├── agent.py
|
|
171
|
+
│ ├── cli.py
|
|
172
|
+
│ ├── config.py
|
|
173
|
+
│ ├── memory.py
|
|
174
|
+
│ └── tools.py
|
|
175
|
+
├── tests/
|
|
176
|
+
│ ├── test_config.py
|
|
177
|
+
│ └── test_tools.py
|
|
178
|
+
├── README.md
|
|
179
|
+
├── README.zh-CN.md
|
|
180
|
+
├── pyproject.toml
|
|
181
|
+
└── requirements.txt
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Testing
|
|
185
|
+
|
|
186
|
+
The project is currently verified with:
|
|
187
|
+
|
|
188
|
+
```powershell
|
|
189
|
+
python -m pytest -q
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Fresh verification in this environment shows:
|
|
193
|
+
|
|
194
|
+
```text
|
|
195
|
+
3 passed in 0.29s
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
The CLI entry point also starts successfully:
|
|
199
|
+
|
|
200
|
+
```powershell
|
|
201
|
+
python main.py --help
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
This confirms the refactored program is runnable in the current environment.
|
|
205
|
+
|
|
206
|
+
## License
|
|
207
|
+
|
|
208
|
+
Apache License 2.0
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
# Prompt Copilot CLI
|
|
2
|
+
|
|
3
|
+
A lightweight terminal coding agent built on LangChain and LangGraph. The project has been refactored to use the standard agent runtime, SQLite-backed persistence, and a small, explicit tool set instead of maintaining a custom agent loop.
|
|
4
|
+
|
|
5
|
+
## What this project does
|
|
6
|
+
|
|
7
|
+
Prompt Copilot CLI lets you:
|
|
8
|
+
|
|
9
|
+
- open a workspace directory and chat with an agent in the terminal
|
|
10
|
+
- use a small set of coding tools for reading, searching, editing, and running Python commands
|
|
11
|
+
- persist conversation state and durable memories using LangGraph SQLite storage
|
|
12
|
+
- connect to an OpenAI-compatible model endpoint such as OpenAI, Azure OpenAI, OpenRouter, or local OpenAI-compatible gateways
|
|
13
|
+
|
|
14
|
+
## Architecture
|
|
15
|
+
|
|
16
|
+
```text
|
|
17
|
+
CLI
|
|
18
|
+
└── AgentRuntime
|
|
19
|
+
├── ChatOpenAI
|
|
20
|
+
├── create_agent()
|
|
21
|
+
├── SummarizationMiddleware
|
|
22
|
+
├── SqliteSaver
|
|
23
|
+
├── SqliteStore
|
|
24
|
+
└── LangMem tools
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
The runtime is intentionally minimal:
|
|
28
|
+
|
|
29
|
+
- `create_agent()` provides the model/tool loop
|
|
30
|
+
- `SummarizationMiddleware` compresses long conversations
|
|
31
|
+
- `SqliteSaver` persists the current conversation thread
|
|
32
|
+
- `SqliteStore` + LangMem handle durable project memory
|
|
33
|
+
- tools remain focused on the practical coding workflow
|
|
34
|
+
|
|
35
|
+
## Install
|
|
36
|
+
|
|
37
|
+
From the project root:
|
|
38
|
+
|
|
39
|
+
```powershell
|
|
40
|
+
python -m pip install -e .
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Or install from PyPI:
|
|
44
|
+
|
|
45
|
+
```powershell
|
|
46
|
+
python -m pip install -U prompt-copilot-cli
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Initial configuration
|
|
50
|
+
|
|
51
|
+
The first run creates a config file in:
|
|
52
|
+
|
|
53
|
+
- Windows: `%USERPROFILE%\.prompt-copilot\config.json`
|
|
54
|
+
- Linux/macOS: `~/.prompt-copilot/config.json`
|
|
55
|
+
|
|
56
|
+
Example:
|
|
57
|
+
|
|
58
|
+
```json
|
|
59
|
+
{
|
|
60
|
+
"model": "gpt-4o-mini",
|
|
61
|
+
"base_url": "https://api.openai.com/v1",
|
|
62
|
+
"api_key": "YOUR_API_KEY",
|
|
63
|
+
"temperature": 0.2,
|
|
64
|
+
"timeout": 120,
|
|
65
|
+
"memory": {
|
|
66
|
+
"enabled": true,
|
|
67
|
+
"max_recent_memories": 5
|
|
68
|
+
},
|
|
69
|
+
"context": {
|
|
70
|
+
"summary_trigger_tokens": 12000,
|
|
71
|
+
"keep_messages": 20
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
You can point `base_url` to any OpenAI-compatible endpoint, and the project will use `api_key` from that config file.
|
|
77
|
+
|
|
78
|
+
## Usage
|
|
79
|
+
|
|
80
|
+
Start interactive mode:
|
|
81
|
+
|
|
82
|
+
```powershell
|
|
83
|
+
prompt-copilot -d D:\project
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Run a single task and exit:
|
|
87
|
+
|
|
88
|
+
```powershell
|
|
89
|
+
prompt-copilot -d D:\project -t "Inspect the repo, fix the failing tests, and run the relevant checks."
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
From the CLI, use these commands:
|
|
93
|
+
|
|
94
|
+
- `/exit` — quit the program
|
|
95
|
+
- `/clear` — reset the current workspace thread
|
|
96
|
+
- `/memory` — display persistent memories for this workspace
|
|
97
|
+
|
|
98
|
+
The prompt supports multiline input. Press `Enter` for a newline and `Ctrl+Enter` to submit.
|
|
99
|
+
|
|
100
|
+
## Available tools
|
|
101
|
+
|
|
102
|
+
The agent exposes a compact tool set:
|
|
103
|
+
|
|
104
|
+
- `read_file`
|
|
105
|
+
- `list_files`
|
|
106
|
+
- `search_code`
|
|
107
|
+
- `write_file`
|
|
108
|
+
- `edit_file`
|
|
109
|
+
- `delete_file`
|
|
110
|
+
- `execute_python_script`
|
|
111
|
+
- `execute_command`
|
|
112
|
+
|
|
113
|
+
These are intentionally scoped to file work, code search, editing, and local execution.
|
|
114
|
+
|
|
115
|
+
## Memory behavior
|
|
116
|
+
|
|
117
|
+
The runtime uses two persistence layers:
|
|
118
|
+
|
|
119
|
+
### Short-term memory
|
|
120
|
+
|
|
121
|
+
`SqliteSaver` stores the live thread state for the current workspace. If you restart the CLI, the same workspace can continue the same conversation.
|
|
122
|
+
|
|
123
|
+
### Long-term memory
|
|
124
|
+
|
|
125
|
+
`SqliteStore` stores durable project memory and LangMem exposes memory management tools so the agent can remember useful project conventions or user preferences.
|
|
126
|
+
|
|
127
|
+
Memory data is stored under:
|
|
128
|
+
|
|
129
|
+
```text
|
|
130
|
+
~/.prompt-copilot/memory.db
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## Project structure
|
|
134
|
+
|
|
135
|
+
```text
|
|
136
|
+
.
|
|
137
|
+
├── main.py
|
|
138
|
+
├── copilot/
|
|
139
|
+
│ ├── __init__.py
|
|
140
|
+
│ ├── agent.py
|
|
141
|
+
│ ├── cli.py
|
|
142
|
+
│ ├── config.py
|
|
143
|
+
│ ├── memory.py
|
|
144
|
+
│ └── tools.py
|
|
145
|
+
├── tests/
|
|
146
|
+
│ ├── test_config.py
|
|
147
|
+
│ └── test_tools.py
|
|
148
|
+
├── README.md
|
|
149
|
+
├── README.zh-CN.md
|
|
150
|
+
├── pyproject.toml
|
|
151
|
+
└── requirements.txt
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Testing
|
|
155
|
+
|
|
156
|
+
The project is currently verified with:
|
|
157
|
+
|
|
158
|
+
```powershell
|
|
159
|
+
python -m pytest -q
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Fresh verification in this environment shows:
|
|
163
|
+
|
|
164
|
+
```text
|
|
165
|
+
3 passed in 0.29s
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
The CLI entry point also starts successfully:
|
|
169
|
+
|
|
170
|
+
```powershell
|
|
171
|
+
python main.py --help
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
This confirms the refactored program is runnable in the current environment.
|
|
175
|
+
|
|
176
|
+
## License
|
|
177
|
+
|
|
178
|
+
Apache License 2.0
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# Prompt Copilot CLI
|
|
2
|
+
|
|
3
|
+
这是一个基于 LangChain 和 LangGraph 的轻量终端编程助手。当前版本已经改为标准的 Agent 运行时 + SQLite 持久化结构,保持较小的工具面和清晰的使用方式。
|
|
4
|
+
|
|
5
|
+
## 功能概览
|
|
6
|
+
|
|
7
|
+
它可以帮助你:
|
|
8
|
+
|
|
9
|
+
- 在终端中打开某个工作区并直接与 Agent 对话
|
|
10
|
+
- 读取、搜索、编辑项目文件
|
|
11
|
+
- 执行 Python 脚本和本地命令
|
|
12
|
+
- 持久化当前会话状态和长期记忆
|
|
13
|
+
- 连接 OpenAI 兼容模型接口,例如 OpenAI、Azure OpenAI、OpenRouter 或本地兼容服务
|
|
14
|
+
|
|
15
|
+
## 架构说明
|
|
16
|
+
|
|
17
|
+
```text
|
|
18
|
+
CLI
|
|
19
|
+
└── AgentRuntime
|
|
20
|
+
├── ChatOpenAI
|
|
21
|
+
├── create_agent()
|
|
22
|
+
├── SummarizationMiddleware
|
|
23
|
+
├── SqliteSaver
|
|
24
|
+
├── SqliteStore
|
|
25
|
+
└── LangMem tools
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
当前实现重点是保持简单:
|
|
29
|
+
|
|
30
|
+
- `create_agent()` 负责模型和工具调用循环
|
|
31
|
+
- `SummarizationMiddleware` 自动压缩长上下文
|
|
32
|
+
- `SqliteSaver` 保存当前工作区的对话线程
|
|
33
|
+
- `SqliteStore` + LangMem 负责长期记忆
|
|
34
|
+
- 工具仅保留代码开发中最常用的能力
|
|
35
|
+
|
|
36
|
+
## 安装
|
|
37
|
+
|
|
38
|
+
在项目根目录执行:
|
|
39
|
+
|
|
40
|
+
```powershell
|
|
41
|
+
python -m pip install -e .
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
或者安装发布版:
|
|
45
|
+
|
|
46
|
+
```powershell
|
|
47
|
+
python -m pip install -U prompt-copilot-cli
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## 首次配置
|
|
51
|
+
|
|
52
|
+
首次运行时会在以下位置生成配置文件:
|
|
53
|
+
|
|
54
|
+
- Windows:`%USERPROFILE%\.prompt-copilot\config.json`
|
|
55
|
+
- Linux/macOS:`~/.prompt-copilot/config.json`
|
|
56
|
+
|
|
57
|
+
示例:
|
|
58
|
+
|
|
59
|
+
```json
|
|
60
|
+
{
|
|
61
|
+
"model": "gpt-4o-mini",
|
|
62
|
+
"base_url": "https://api.openai.com/v1",
|
|
63
|
+
"api_key": "YOUR_API_KEY",
|
|
64
|
+
"temperature": 0.2,
|
|
65
|
+
"timeout": 120,
|
|
66
|
+
"memory": {
|
|
67
|
+
"enabled": true,
|
|
68
|
+
"max_recent_memories": 5
|
|
69
|
+
},
|
|
70
|
+
"context": {
|
|
71
|
+
"summary_trigger_tokens": 12000,
|
|
72
|
+
"keep_messages": 20
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
这里的 `base_url` 可以指向任何 OpenAI 兼容接口。
|
|
78
|
+
|
|
79
|
+
## 使用方法
|
|
80
|
+
|
|
81
|
+
交互式启动:
|
|
82
|
+
|
|
83
|
+
```powershell
|
|
84
|
+
prompt-copilot -d D:\project
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
单次任务模式:
|
|
88
|
+
|
|
89
|
+
```powershell
|
|
90
|
+
prompt-copilot -d D:\project -t "检查项目代码,修复失败测试,并执行相关验证。"
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
交互命令:
|
|
94
|
+
|
|
95
|
+
- `/exit`:退出程序
|
|
96
|
+
- `/clear`:重置当前工作区线程
|
|
97
|
+
- `/memory`:查看当前工作区的长期记忆
|
|
98
|
+
|
|
99
|
+
CLI 支持多行输入,按 `Enter` 换行,`Ctrl+Enter` 提交。
|
|
100
|
+
|
|
101
|
+
## 支持的工具
|
|
102
|
+
|
|
103
|
+
当前 Agent 暴露的工具非常简洁:
|
|
104
|
+
|
|
105
|
+
- `read_file`
|
|
106
|
+
- `list_files`
|
|
107
|
+
- `search_code`
|
|
108
|
+
- `write_file`
|
|
109
|
+
- `edit_file`
|
|
110
|
+
- `delete_file`
|
|
111
|
+
- `execute_python_script`
|
|
112
|
+
- `execute_command`
|
|
113
|
+
|
|
114
|
+
这些工具覆盖日常编码中的最关键能力:查看、搜索、编辑和调试。
|
|
115
|
+
|
|
116
|
+
## 记忆行为
|
|
117
|
+
|
|
118
|
+
项目同时使用两层存储:
|
|
119
|
+
|
|
120
|
+
### 短期记忆
|
|
121
|
+
|
|
122
|
+
`SqliteSaver` 保存当前工作区的活跃会话状态。重新启动后,同一工作区可以继续之前的上下文。
|
|
123
|
+
|
|
124
|
+
### 长期记忆
|
|
125
|
+
|
|
126
|
+
`SqliteStore` 负责跨会话可持久化记忆,LangMem 提供搜索和管理记忆的能力,使 Agent 能记住项目约定、用户偏好和历史决策。
|
|
127
|
+
|
|
128
|
+
长期记忆文件默认位于:
|
|
129
|
+
|
|
130
|
+
```text
|
|
131
|
+
~/.prompt-copilot/memory.db
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## 项目结构
|
|
135
|
+
|
|
136
|
+
```text
|
|
137
|
+
.
|
|
138
|
+
├── main.py
|
|
139
|
+
├── copilot/
|
|
140
|
+
│ ├── __init__.py
|
|
141
|
+
│ ├── agent.py
|
|
142
|
+
│ ├── cli.py
|
|
143
|
+
│ ├── config.py
|
|
144
|
+
│ ├── memory.py
|
|
145
|
+
│ └── tools.py
|
|
146
|
+
├── tests/
|
|
147
|
+
│ ├── test_config.py
|
|
148
|
+
│ └── test_tools.py
|
|
149
|
+
├── README.md
|
|
150
|
+
├── README.zh-CN.md
|
|
151
|
+
├── pyproject.toml
|
|
152
|
+
├── requirements.txt
|
|
153
|
+
└── LICENSE
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## 测试验证
|
|
157
|
+
|
|
158
|
+
已在当前环境真实执行:
|
|
159
|
+
|
|
160
|
+
```powershell
|
|
161
|
+
python -m pytest -q
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
验证结果:
|
|
165
|
+
|
|
166
|
+
```text
|
|
167
|
+
3 passed in 0.29s
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
CLI 入口也可正常启动:
|
|
171
|
+
|
|
172
|
+
```powershell
|
|
173
|
+
python main.py --help
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
这说明当前重构后的程序确实可以正常运行。
|
|
177
|
+
|
|
178
|
+
## License
|
|
179
|
+
|
|
180
|
+
Apache License 2.0
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Prompt Copilot CLI: a small LangChain/LangGraph coding agent."""
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import hashlib
|
|
4
|
+
import uuid
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from langchain.agents import create_agent
|
|
9
|
+
from langchain.agents.middleware import SummarizationMiddleware
|
|
10
|
+
from langchain_openai import ChatOpenAI
|
|
11
|
+
|
|
12
|
+
from .config import MEMORY_DB_PATH
|
|
13
|
+
from .memory import MemoryRuntime
|
|
14
|
+
from .tools import Workspace, build_tools
|
|
15
|
+
|
|
16
|
+
SYSTEM_PROMPT = """You are a pragmatic terminal coding agent.
|
|
17
|
+
|
|
18
|
+
Your job is to inspect, modify, and test software in the supplied workspace.
|
|
19
|
+
|
|
20
|
+
Rules:
|
|
21
|
+
- Inspect relevant files before editing. Do not invent project structure.
|
|
22
|
+
- Prefer search_code and read_file before making changes.
|
|
23
|
+
- Use edit_file for targeted changes; use write_file when replacing/creating a whole file.
|
|
24
|
+
- After code changes, run the smallest relevant test, lint, or build command.
|
|
25
|
+
- Treat tool output as evidence. If a command fails, diagnose and fix it instead of claiming success.
|
|
26
|
+
- Keep changes focused on the user's request. Do not refactor unrelated code.
|
|
27
|
+
- You have persistent long-term memory tools. Store durable project decisions and user preferences, not transient command output.
|
|
28
|
+
- You can use memory search when previous project decisions or conventions are relevant.
|
|
29
|
+
- Never claim a change was made unless a tool result confirms it.
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class AgentRuntime:
|
|
34
|
+
"""Small composition root: model + tools + LangGraph persistence."""
|
|
35
|
+
|
|
36
|
+
def __init__(self, workspace: str | Path, config: dict[str, Any]):
|
|
37
|
+
self.workspace = Workspace(workspace)
|
|
38
|
+
self.config = config
|
|
39
|
+
self.workspace_id = hashlib.sha256(str(self.workspace.root).encode("utf-8")).hexdigest()[:24]
|
|
40
|
+
self.thread_id = self._load_thread_id()
|
|
41
|
+
self.memory = MemoryRuntime(config.get("memory_db_path", MEMORY_DB_PATH))
|
|
42
|
+
self.model = ChatOpenAI(
|
|
43
|
+
model=str(config["model"]),
|
|
44
|
+
api_key=str(config["api_key"]),
|
|
45
|
+
base_url=str(config["base_url"]),
|
|
46
|
+
temperature=float(config.get("temperature", 0.2)),
|
|
47
|
+
timeout=float(config.get("timeout", 120)),
|
|
48
|
+
max_retries=2,
|
|
49
|
+
)
|
|
50
|
+
self.agent = self._build_agent()
|
|
51
|
+
|
|
52
|
+
def _load_thread_id(self) -> str:
|
|
53
|
+
path = self.workspace.root / ".prompt-copilot-thread"
|
|
54
|
+
if path.exists():
|
|
55
|
+
value = path.read_text(encoding="utf-8").strip()
|
|
56
|
+
if value:
|
|
57
|
+
return value
|
|
58
|
+
value = str(uuid.uuid4())
|
|
59
|
+
path.write_text(value, encoding="utf-8")
|
|
60
|
+
return value
|
|
61
|
+
|
|
62
|
+
def _build_agent(self):
|
|
63
|
+
tools = build_tools(self.workspace)
|
|
64
|
+
if self.config.get("memory", {}).get("enabled", True):
|
|
65
|
+
tools.extend(self.memory.tools())
|
|
66
|
+
|
|
67
|
+
context_cfg = self.config.get("context", {})
|
|
68
|
+
middleware = [
|
|
69
|
+
SummarizationMiddleware(
|
|
70
|
+
model=self.model,
|
|
71
|
+
trigger=("tokens", int(context_cfg.get("summary_trigger_tokens", 12000))),
|
|
72
|
+
keep=("messages", int(context_cfg.get("keep_messages", 20))),
|
|
73
|
+
)
|
|
74
|
+
]
|
|
75
|
+
return create_agent(
|
|
76
|
+
self.model,
|
|
77
|
+
tools=tools,
|
|
78
|
+
system_prompt=SYSTEM_PROMPT,
|
|
79
|
+
middleware=middleware,
|
|
80
|
+
checkpointer=self.memory.checkpointer,
|
|
81
|
+
store=self.memory.store,
|
|
82
|
+
name="prompt_copilot",
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
def _memory_context(self, user_text: str) -> str:
|
|
86
|
+
if not self.config.get("memory", {}).get("enabled", True):
|
|
87
|
+
return ""
|
|
88
|
+
namespace = ("memories", self.workspace_id)
|
|
89
|
+
limit = int(self.config.get("memory", {}).get("max_recent_memories", 5))
|
|
90
|
+
try:
|
|
91
|
+
items = self.memory.store.search(namespace, query=user_text, limit=max(1, limit))
|
|
92
|
+
except Exception:
|
|
93
|
+
items = self.memory.store.search(namespace, limit=max(1, limit))
|
|
94
|
+
if not items:
|
|
95
|
+
return ""
|
|
96
|
+
lines = ["Relevant durable project memory:"]
|
|
97
|
+
for item in items:
|
|
98
|
+
value = item.value
|
|
99
|
+
lines.append(f"- {value.get('content', value) if isinstance(value, dict) else value}")
|
|
100
|
+
return "\n".join(lines)
|
|
101
|
+
|
|
102
|
+
def invoke(self, user_text: str) -> str:
|
|
103
|
+
memory_context = self._memory_context(user_text)
|
|
104
|
+
content = user_text if not memory_context else f"{memory_context}\n\nCurrent request:\n{user_text}"
|
|
105
|
+
config = {
|
|
106
|
+
"configurable": {
|
|
107
|
+
"thread_id": self.thread_id,
|
|
108
|
+
"workspace_id": self.workspace_id,
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
result = self.agent.invoke({"messages": [{"role": "user", "content": content}]}, config)
|
|
112
|
+
messages = result.get("messages", [])
|
|
113
|
+
if not messages:
|
|
114
|
+
return ""
|
|
115
|
+
final = messages[-1]
|
|
116
|
+
value = getattr(final, "content", final.get("content", "") if isinstance(final, dict) else "")
|
|
117
|
+
if isinstance(value, list):
|
|
118
|
+
return "".join(str(part.get("text", part)) if isinstance(part, dict) else str(part) for part in value)
|
|
119
|
+
return str(value or "")
|
|
120
|
+
|
|
121
|
+
def reset(self) -> None:
|
|
122
|
+
self.memory.checkpointer.delete_thread(self.thread_id)
|
|
123
|
+
self.thread_id = str(uuid.uuid4())
|
|
124
|
+
(self.workspace.root / ".prompt-copilot-thread").write_text(self.thread_id, encoding="utf-8")
|
|
125
|
+
|
|
126
|
+
def close(self) -> None:
|
|
127
|
+
self.memory.close()
|