plyngent 0.1.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.
- plyngent-0.1.0/LICENSE +21 -0
- plyngent-0.1.0/PKG-INFO +268 -0
- plyngent-0.1.0/README.md +248 -0
- plyngent-0.1.0/pyproject.toml +182 -0
- plyngent-0.1.0/src/plyngent/__init__.py +6 -0
- plyngent-0.1.0/src/plyngent/__main__.py +4 -0
- plyngent-0.1.0/src/plyngent/agent/__init__.py +28 -0
- plyngent-0.1.0/src/plyngent/agent/budget.py +200 -0
- plyngent-0.1.0/src/plyngent/agent/chat.py +337 -0
- plyngent-0.1.0/src/plyngent/agent/client.py +35 -0
- plyngent-0.1.0/src/plyngent/agent/compact.py +180 -0
- plyngent-0.1.0/src/plyngent/agent/events.py +66 -0
- plyngent-0.1.0/src/plyngent/agent/loop.py +299 -0
- plyngent-0.1.0/src/plyngent/agent/responses_bridge.py +312 -0
- plyngent-0.1.0/src/plyngent/agent/responses_client.py +126 -0
- plyngent-0.1.0/src/plyngent/agent/tools.py +243 -0
- plyngent-0.1.0/src/plyngent/agent/usage.py +154 -0
- plyngent-0.1.0/src/plyngent/cli/__init__.py +1 -0
- plyngent-0.1.0/src/plyngent/cli/__main__.py +4 -0
- plyngent-0.1.0/src/plyngent/cli/app.py +488 -0
- plyngent-0.1.0/src/plyngent/cli/display.py +215 -0
- plyngent-0.1.0/src/plyngent/cli/editor.py +175 -0
- plyngent-0.1.0/src/plyngent/cli/exit_codes.py +8 -0
- plyngent-0.1.0/src/plyngent/cli/export.py +122 -0
- plyngent-0.1.0/src/plyngent/cli/input_text.py +125 -0
- plyngent-0.1.0/src/plyngent/cli/interrupt.py +73 -0
- plyngent-0.1.0/src/plyngent/cli/limits.py +168 -0
- plyngent-0.1.0/src/plyngent/cli/models_source.py +62 -0
- plyngent-0.1.0/src/plyngent/cli/provider_recovery.py +113 -0
- plyngent-0.1.0/src/plyngent/cli/readline_setup.py +102 -0
- plyngent-0.1.0/src/plyngent/cli/repl.py +59 -0
- plyngent-0.1.0/src/plyngent/cli/retry.py +215 -0
- plyngent-0.1.0/src/plyngent/cli/selection.py +101 -0
- plyngent-0.1.0/src/plyngent/cli/slash.py +876 -0
- plyngent-0.1.0/src/plyngent/cli/state.py +448 -0
- plyngent-0.1.0/src/plyngent/config/__init__.py +47 -0
- plyngent-0.1.0/src/plyngent/config/models.py +110 -0
- plyngent-0.1.0/src/plyngent/config/path.py +19 -0
- plyngent-0.1.0/src/plyngent/config/store.py +273 -0
- plyngent-0.1.0/src/plyngent/lmproto/__init__.py +0 -0
- plyngent-0.1.0/src/plyngent/lmproto/deepseek/__init__.py +8 -0
- plyngent-0.1.0/src/plyngent/lmproto/deepseek/openai_compat/client.py +56 -0
- plyngent-0.1.0/src/plyngent/lmproto/deepseek/openai_compat/model.py +57 -0
- plyngent-0.1.0/src/plyngent/lmproto/openai/__init__.py +12 -0
- plyngent-0.1.0/src/plyngent/lmproto/openai/client.py +131 -0
- plyngent-0.1.0/src/plyngent/lmproto/openai/model.py +325 -0
- plyngent-0.1.0/src/plyngent/lmproto/openai_compatible/__init__.py +43 -0
- plyngent-0.1.0/src/plyngent/lmproto/openai_compatible/client.py +249 -0
- plyngent-0.1.0/src/plyngent/lmproto/openai_compatible/config.py +7 -0
- plyngent-0.1.0/src/plyngent/lmproto/openai_compatible/model.py +276 -0
- plyngent-0.1.0/src/plyngent/memory/__init__.py +9 -0
- plyngent-0.1.0/src/plyngent/memory/database/__init__.py +10 -0
- plyngent-0.1.0/src/plyngent/memory/database/engine.py +35 -0
- plyngent-0.1.0/src/plyngent/memory/database/schema.py +57 -0
- plyngent-0.1.0/src/plyngent/memory/database/store.py +310 -0
- plyngent-0.1.0/src/plyngent/prompting.py +403 -0
- plyngent-0.1.0/src/plyngent/runtime/__init__.py +3 -0
- plyngent-0.1.0/src/plyngent/runtime/client_factory.py +83 -0
- plyngent-0.1.0/src/plyngent/tools/__init__.py +44 -0
- plyngent-0.1.0/src/plyngent/tools/chat/__init__.py +5 -0
- plyngent-0.1.0/src/plyngent/tools/chat/ask.py +18 -0
- plyngent-0.1.0/src/plyngent/tools/chat/choose.py +78 -0
- plyngent-0.1.0/src/plyngent/tools/chat/form.py +74 -0
- plyngent-0.1.0/src/plyngent/tools/danger.py +46 -0
- plyngent-0.1.0/src/plyngent/tools/file/__init__.py +25 -0
- plyngent-0.1.0/src/plyngent/tools/file/edit_lineno.py +97 -0
- plyngent-0.1.0/src/plyngent/tools/file/edit_replace.py +20 -0
- plyngent-0.1.0/src/plyngent/tools/file/fs_ops.py +152 -0
- plyngent-0.1.0/src/plyngent/tools/file/glob_paths.py +99 -0
- plyngent-0.1.0/src/plyngent/tools/file/grep_files.py +171 -0
- plyngent-0.1.0/src/plyngent/tools/file/listdir.py +17 -0
- plyngent-0.1.0/src/plyngent/tools/file/read.py +24 -0
- plyngent-0.1.0/src/plyngent/tools/file/tree.py +149 -0
- plyngent-0.1.0/src/plyngent/tools/file/write.py +13 -0
- plyngent-0.1.0/src/plyngent/tools/process/__init__.py +7 -0
- plyngent-0.1.0/src/plyngent/tools/process/close_pty.py +17 -0
- plyngent-0.1.0/src/plyngent/tools/process/open_pty.py +32 -0
- plyngent-0.1.0/src/plyngent/tools/process/pty_backend.py +287 -0
- plyngent-0.1.0/src/plyngent/tools/process/pty_session.py +415 -0
- plyngent-0.1.0/src/plyngent/tools/process/read_pty.py +45 -0
- plyngent-0.1.0/src/plyngent/tools/process/run_command.py +172 -0
- plyngent-0.1.0/src/plyngent/tools/process/write_pty.py +27 -0
- plyngent-0.1.0/src/plyngent/tools/vcs/__init__.py +11 -0
- plyngent-0.1.0/src/plyngent/tools/vcs/backend.py +29 -0
- plyngent-0.1.0/src/plyngent/tools/vcs/detect.py +50 -0
- plyngent-0.1.0/src/plyngent/tools/vcs/git_backend.py +120 -0
- plyngent-0.1.0/src/plyngent/tools/vcs/tools.py +83 -0
- plyngent-0.1.0/src/plyngent/tools/workspace.py +114 -0
- plyngent-0.1.0/src/plyngent/typedef.py +7 -0
- plyngent-0.1.0/src/plyngent/utils/__init__.py +1 -0
- plyngent-0.1.0/src/plyngent/utils/components.py +48 -0
- plyngent-0.1.0/tests/__init__.py +0 -0
- plyngent-0.1.0/tests/test_agent/test_budget.py +22 -0
- plyngent-0.1.0/tests/test_agent/test_compact.py +262 -0
- plyngent-0.1.0/tests/test_agent/test_compact_summarize.py +150 -0
- plyngent-0.1.0/tests/test_agent/test_confirm.py +59 -0
- plyngent-0.1.0/tests/test_agent/test_loop.py +827 -0
- plyngent-0.1.0/tests/test_agent/test_parallel_tools.py +158 -0
- plyngent-0.1.0/tests/test_agent/test_responses_bridge.py +174 -0
- plyngent-0.1.0/tests/test_agent/test_stream_merge.py +49 -0
- plyngent-0.1.0/tests/test_agent/test_tools.py +90 -0
- plyngent-0.1.0/tests/test_agent/test_usage.py +109 -0
- plyngent-0.1.0/tests/test_cli/test_app.py +33 -0
- plyngent-0.1.0/tests/test_cli/test_compact_cmd.py +133 -0
- plyngent-0.1.0/tests/test_cli/test_display.py +107 -0
- plyngent-0.1.0/tests/test_cli/test_editor.py +161 -0
- plyngent-0.1.0/tests/test_cli/test_export.py +49 -0
- plyngent-0.1.0/tests/test_cli/test_input_text.py +61 -0
- plyngent-0.1.0/tests/test_cli/test_interrupt.py +50 -0
- plyngent-0.1.0/tests/test_cli/test_limits.py +32 -0
- plyngent-0.1.0/tests/test_cli/test_models_source.py +52 -0
- plyngent-0.1.0/tests/test_cli/test_oneshot.py +159 -0
- plyngent-0.1.0/tests/test_cli/test_provider_recovery.py +75 -0
- plyngent-0.1.0/tests/test_cli/test_readline_setup.py +183 -0
- plyngent-0.1.0/tests/test_cli/test_repl_commands.py +392 -0
- plyngent-0.1.0/tests/test_cli/test_retry.py +213 -0
- plyngent-0.1.0/tests/test_cli/test_selection.py +88 -0
- plyngent-0.1.0/tests/test_cli/test_workspace_resume.py +183 -0
- plyngent-0.1.0/tests/test_config/.gitignore +1 -0
- plyngent-0.1.0/tests/test_config/plyngent-bad.toml +15 -0
- plyngent-0.1.0/tests/test_config/plyngent-empty.toml +0 -0
- plyngent-0.1.0/tests/test_config/plyngent-invalid.toml +3 -0
- plyngent-0.1.0/tests/test_config/plyngent-valid.toml +32 -0
- plyngent-0.1.0/tests/test_config/test_agent_section.py +43 -0
- plyngent-0.1.0/tests/test_config/test_config.py +198 -0
- plyngent-0.1.0/tests/test_lmproto/test_models.py +58 -0
- plyngent-0.1.0/tests/test_lmproto/test_responses.py +155 -0
- plyngent-0.1.0/tests/test_lmproto/test_sse_parse.py +116 -0
- plyngent-0.1.0/tests/test_memory/test_store.py +205 -0
- plyngent-0.1.0/tests/test_prompting.py +144 -0
- plyngent-0.1.0/tests/test_runtime/test_client_factory.py +80 -0
- plyngent-0.1.0/tests/test_tools/__init__.py +0 -0
- plyngent-0.1.0/tests/test_tools/conftest.py +19 -0
- plyngent-0.1.0/tests/test_tools/helpers.py +20 -0
- plyngent-0.1.0/tests/test_tools/test_chat_tools.py +66 -0
- plyngent-0.1.0/tests/test_tools/test_danger.py +28 -0
- plyngent-0.1.0/tests/test_tools/test_edit_lineno.py +37 -0
- plyngent-0.1.0/tests/test_tools/test_file.py +40 -0
- plyngent-0.1.0/tests/test_tools/test_fs_ops.py +99 -0
- plyngent-0.1.0/tests/test_tools/test_glob_paths.py +42 -0
- plyngent-0.1.0/tests/test_tools/test_grep_files.py +47 -0
- plyngent-0.1.0/tests/test_tools/test_process.py +295 -0
- plyngent-0.1.0/tests/test_tools/test_tree.py +85 -0
- plyngent-0.1.0/tests/test_tools/test_vcs.py +110 -0
- plyngent-0.1.0/tests/test_tools/test_workspace.py +55 -0
plyngent-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 NCBM
|
|
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.
|
plyngent-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: plyngent
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: LLM chat and agent toolkit
|
|
5
|
+
Author-Email: HivertMoZara <worldmozara@163.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Requires-Python: <4,>=3.14
|
|
8
|
+
Requires-Dist: msgspec>=0.21.1
|
|
9
|
+
Requires-Dist: niquests>=3.20
|
|
10
|
+
Requires-Dist: typing-extensions>=4.15.0
|
|
11
|
+
Requires-Dist: platformdirs>=4.10.0
|
|
12
|
+
Requires-Dist: tomlkit>=0.15.0
|
|
13
|
+
Requires-Dist: sqlalchemy>=2.0.51
|
|
14
|
+
Requires-Dist: aiosqlite>=0.22.1
|
|
15
|
+
Requires-Dist: click>=8.4.2
|
|
16
|
+
Requires-Dist: awaitlet>=0.0.1
|
|
17
|
+
Requires-Dist: pywinpty>=2.0.0; sys_platform == "win32"
|
|
18
|
+
Requires-Dist: rich>=13
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
|
|
21
|
+
# plyngent
|
|
22
|
+
|
|
23
|
+
Single-user LLM chat and agent toolkit for the terminal.
|
|
24
|
+
|
|
25
|
+
Python **3.14+**. OpenAI-compatible APIs (including DeepSeek OpenAI-compat), OpenAI Responses with optional hosted tools, SQLite session memory, workspace-scoped file/process/VCS tools, and a readline REPL with slash commands.
|
|
26
|
+
|
|
27
|
+
Requires **Python 3.14+** on your `PATH` (or via [uv](https://docs.astral.sh/uv/) / [pipx](https://pipx.pypa.io/)).
|
|
28
|
+
|
|
29
|
+
## Install
|
|
30
|
+
|
|
31
|
+
### Quick try (`uvx`)
|
|
32
|
+
|
|
33
|
+
No permanent install — runs the published package in a temporary environment:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
uvx plyngent --help
|
|
37
|
+
uvx plyngent chat
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### User tool install
|
|
41
|
+
|
|
42
|
+
Keep `plyngent` on your PATH as a managed tool:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
# uv (recommended)
|
|
46
|
+
uv tool install plyngent
|
|
47
|
+
plyngent --help
|
|
48
|
+
|
|
49
|
+
# pipx
|
|
50
|
+
pipx install plyngent
|
|
51
|
+
plyngent --help
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Upgrade later:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
uv tool upgrade plyngent
|
|
58
|
+
# or: pipx upgrade plyngent
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### pip (venv or user)
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
python3.14 -m venv .venv
|
|
65
|
+
source .venv/bin/activate # Windows: .venv\Scripts\activate
|
|
66
|
+
pip install -U pip
|
|
67
|
+
pip install plyngent
|
|
68
|
+
plyngent --help
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Or user install (if you accept that layout):
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
pip install --user plyngent
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### From a git clone (development)
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
pdm install # first time
|
|
81
|
+
pdm sync # after pull
|
|
82
|
+
pdm run plyngent --help
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Dev checks:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
pdm run basedpyright .
|
|
89
|
+
pdm run ruff check .
|
|
90
|
+
pdm run ruff format .
|
|
91
|
+
pdm run pytest
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Basic usage
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
# 1) Create / open config
|
|
98
|
+
plyngent config path
|
|
99
|
+
plyngent config edit # needs $EDITOR
|
|
100
|
+
|
|
101
|
+
# Minimal provider (OpenAI platform — Responses API; preset defaults to openai):
|
|
102
|
+
# [providers.oai]
|
|
103
|
+
# access_key_or_token = "sk-..."
|
|
104
|
+
# # models default: gpt-5.4, gpt-5.4-mini, gpt-5.4-nano
|
|
105
|
+
# # provider_tools default: web_search (use provider_tools = [] to disable)
|
|
106
|
+
|
|
107
|
+
# 2) Chat
|
|
108
|
+
plyngent chat
|
|
109
|
+
plyngent chat --provider oai --model gpt-5.4-mini
|
|
110
|
+
plyngent chat -p "Summarize this repo" --provider oai --model gpt-5.4-mini --no-stream
|
|
111
|
+
|
|
112
|
+
# 3) List providers from config
|
|
113
|
+
plyngent providers
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
In the REPL: type normally, use `/help` for slash commands, `"""` … `"""` for multiline, `/markdown` for Rich rendering, `/quit` to leave.
|
|
117
|
+
|
|
118
|
+
## Configure
|
|
119
|
+
|
|
120
|
+
Default config path (platformdirs):
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
plyngent config path
|
|
124
|
+
plyngent config edit # opens $EDITOR (e.g. codium --wait)
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Copy the example and fill in a real token:
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
cp doc/plyngent.example.toml "$(plyngent config path)"
|
|
131
|
+
# then edit providers
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Minimal shape:
|
|
135
|
+
|
|
136
|
+
```toml
|
|
137
|
+
[providers.local]
|
|
138
|
+
preset = "openai-compatible"
|
|
139
|
+
url = "https://api.openai.com/v1"
|
|
140
|
+
access_key_or_token = "sk-..."
|
|
141
|
+
|
|
142
|
+
[providers.local.models]
|
|
143
|
+
"gpt-4o-mini" = { text = true }
|
|
144
|
+
|
|
145
|
+
[agent]
|
|
146
|
+
system_prompt = "You are a careful coding assistant."
|
|
147
|
+
confirm_destructive = true
|
|
148
|
+
max_context_tokens = 200000
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Supported provider presets today: `openai` (default if `preset` is omitted; default models `gpt-5.4` / `gpt-5.4-mini` / `gpt-5.4-nano` when `models` is omitted), `openai-compatible`, `deepseek` (OpenAI convention; default models `deepseek-v4-flash` and `deepseek-v4-pro` if `models` is omitted). Anthropic presets are modeled in config but not wired in the runtime client yet.
|
|
152
|
+
|
|
153
|
+
If `[database]` is omitted (or SQLite `url` is empty/`":memory:"`), chat uses a durable file under the user data dir (e.g. `~/.local/share/plyngent/chat.db` on Linux).
|
|
154
|
+
|
|
155
|
+
## Chat
|
|
156
|
+
|
|
157
|
+
### Interactive REPL
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
plyngent chat
|
|
161
|
+
plyngent chat --provider local --model gpt-4o-mini
|
|
162
|
+
plyngent chat --workspace /path/to/project --new
|
|
163
|
+
plyngent chat --session 3
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
| Flag | Meaning |
|
|
167
|
+
|------|---------|
|
|
168
|
+
| `--provider` / `--model` | Select from config (required when multiple and non-interactive) |
|
|
169
|
+
| `--workspace` | Tool root (default: cwd); sessions bind to this path |
|
|
170
|
+
| `--new` / `--session ID` | Fresh session vs resume by id |
|
|
171
|
+
| `--tools` / `--no-tools` | Default tools on |
|
|
172
|
+
| `--max-rounds` | Tool-loop rounds per turn (default 32) |
|
|
173
|
+
| `--stream` / `--no-stream` | Streaming deltas (default on) |
|
|
174
|
+
| `--quiet` | Less status on stderr |
|
|
175
|
+
| `--yes` | Allow destructive tools without confirm (also for one-shot) |
|
|
176
|
+
| `--log-level` | On the root CLI: `DEBUG`, `INFO`, `WARNING`, … |
|
|
177
|
+
|
|
178
|
+
Sessions resume the **most recently updated** session for the current workspace unless you pass `--new` or `--session`. Each session remembers the last **provider** and **model** (restored on resume so you are not re-prompted).
|
|
179
|
+
|
|
180
|
+
### One-shot (scripts / CI)
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
plyngent chat -p "Summarize README.md" --provider local --model gpt-4o-mini --no-stream
|
|
184
|
+
echo "hello" | plyngent chat --provider local --model gpt-4o-mini
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Exit codes (one-shot):
|
|
188
|
+
|
|
189
|
+
| Code | Meaning |
|
|
190
|
+
|------|---------|
|
|
191
|
+
| 0 | Success |
|
|
192
|
+
| 1 | Config / usage error |
|
|
193
|
+
| 2 | Cancelled |
|
|
194
|
+
| 3 | Turn failed (API / incomplete) |
|
|
195
|
+
|
|
196
|
+
### Input ergonomics
|
|
197
|
+
|
|
198
|
+
- **Multiline**: start a message with `"""`, end a later line with `"""`.
|
|
199
|
+
- **`/edit`**: compose a turn in `$EDITOR` (empty buffer cancels).
|
|
200
|
+
- **Tab**: completes slash commands and some arguments (provider, model, on/off, export, `/help` targets).
|
|
201
|
+
|
|
202
|
+
### Slash commands
|
|
203
|
+
|
|
204
|
+
Type `/help` in the REPL for the live list. Common ones:
|
|
205
|
+
|
|
206
|
+
| Command | Purpose |
|
|
207
|
+
|---------|---------|
|
|
208
|
+
| `/status` | Provider, session, context/usage estimates |
|
|
209
|
+
| `/history [n]` | Recent messages |
|
|
210
|
+
| `/sessions` | Sessions for this workspace |
|
|
211
|
+
| `/new` `/resume` `/rename` `/delete` | Session lifecycle (`/delete` confirms) |
|
|
212
|
+
| `/export [md\|json] [path]` | Transcript from DB (no secrets) |
|
|
213
|
+
| `/compact` | Soft-compact + model summary into a **new** session |
|
|
214
|
+
| `/stream` `/verbose` `/markdown` `/tools` `/rounds` | Toggles and limits |
|
|
215
|
+
|
|
216
|
+
| `/retry` | Re-run incomplete last user turn (after error/cancel) |
|
|
217
|
+
| `/provider` `/model` | Switch without restarting |
|
|
218
|
+
| `/models` | List config + remote `GET /models` (`--refresh` bypasses cache) |
|
|
219
|
+
| `/config` | Edit `plyngent.toml` in `$EDITOR` and reload |
|
|
220
|
+
| `/quit` | Leave the REPL |
|
|
221
|
+
|
|
222
|
+
User messages are saved immediately. On API error or Ctrl+C, partial assistant/tool output is discarded but the user message stays so `/retry` works after resume. Interactive auto-retry uses 10s / 20s / 30s delays.
|
|
223
|
+
|
|
224
|
+
## Workspace model
|
|
225
|
+
|
|
226
|
+
- **Workspace** = root for file/process/VCS tools (default cwd).
|
|
227
|
+
- **Session** = SQLite chat bound to a workspace path.
|
|
228
|
+
- Resuming a session from another directory prompts: keep session workspace, rebind to current, or abort.
|
|
229
|
+
|
|
230
|
+
## Tools (when enabled)
|
|
231
|
+
|
|
232
|
+
Default registry: file ops, `run_command` / PTY (POSIX openpty; Windows ConPTY via pywinpty), read-only VCS (git), and human prompts (`ask_user` / `choose_user` / `form_user`).
|
|
233
|
+
|
|
234
|
+
Safety defaults:
|
|
235
|
+
|
|
236
|
+
- Paths stay under the workspace; optional `path_denylist` substrings.
|
|
237
|
+
- Command basename denylist (e.g. dangerous shells/utilities).
|
|
238
|
+
- Destructive tools (delete/move/overwrite) can require confirm (`confirm_destructive`; default deny in non-TTY).
|
|
239
|
+
- PTY sessions: caps, idle TTL, output budget; master FD is non-inheritable; sessions closed on chat exit.
|
|
240
|
+
|
|
241
|
+
## Usage / context (CLI)
|
|
242
|
+
|
|
243
|
+
- **Context size** prefers API `prompt_tokens` from the last model call; otherwise a char-based estimate (~4 chars/token).
|
|
244
|
+
- **Turn/session usage** sum billed completion usage across tool rounds (history is re-sent each round).
|
|
245
|
+
- Soft compact can calibrate from reported `prompt_tokens`. See `/status`.
|
|
246
|
+
|
|
247
|
+
## Other commands
|
|
248
|
+
|
|
249
|
+
```bash
|
|
250
|
+
plyngent providers # list configured providers
|
|
251
|
+
plyngent config path|edit
|
|
252
|
+
plyngent --log-level INFO chat ...
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
## Architecture (short)
|
|
256
|
+
|
|
257
|
+
See [doc/architecture.md](doc/architecture.md) and [CLAUDE.md](CLAUDE.md) for developers.
|
|
258
|
+
|
|
259
|
+
- **`lmproto/`** — OpenAI-compatible (+ DeepSeek) msgspec models and async SSE clients
|
|
260
|
+
- **`agent/`** — tool loop, streaming, usage, compact
|
|
261
|
+
- **`memory/`** — async SQLAlchemy sessions/messages
|
|
262
|
+
- **`tools/`** — workspace tools
|
|
263
|
+
- **`cli/`** — Click entry + slash registry (`awaitlet` bridges sync Click to async work)
|
|
264
|
+
- Multi-tenant / web (`router/`, real `web/`) are **not** in scope for the single-user CLI (Phase H).
|
|
265
|
+
|
|
266
|
+
## License
|
|
267
|
+
|
|
268
|
+
MIT
|
plyngent-0.1.0/README.md
ADDED
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
# plyngent
|
|
2
|
+
|
|
3
|
+
Single-user LLM chat and agent toolkit for the terminal.
|
|
4
|
+
|
|
5
|
+
Python **3.14+**. OpenAI-compatible APIs (including DeepSeek OpenAI-compat), OpenAI Responses with optional hosted tools, SQLite session memory, workspace-scoped file/process/VCS tools, and a readline REPL with slash commands.
|
|
6
|
+
|
|
7
|
+
Requires **Python 3.14+** on your `PATH` (or via [uv](https://docs.astral.sh/uv/) / [pipx](https://pipx.pypa.io/)).
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
### Quick try (`uvx`)
|
|
12
|
+
|
|
13
|
+
No permanent install — runs the published package in a temporary environment:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
uvx plyngent --help
|
|
17
|
+
uvx plyngent chat
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### User tool install
|
|
21
|
+
|
|
22
|
+
Keep `plyngent` on your PATH as a managed tool:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
# uv (recommended)
|
|
26
|
+
uv tool install plyngent
|
|
27
|
+
plyngent --help
|
|
28
|
+
|
|
29
|
+
# pipx
|
|
30
|
+
pipx install plyngent
|
|
31
|
+
plyngent --help
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Upgrade later:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
uv tool upgrade plyngent
|
|
38
|
+
# or: pipx upgrade plyngent
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### pip (venv or user)
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
python3.14 -m venv .venv
|
|
45
|
+
source .venv/bin/activate # Windows: .venv\Scripts\activate
|
|
46
|
+
pip install -U pip
|
|
47
|
+
pip install plyngent
|
|
48
|
+
plyngent --help
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Or user install (if you accept that layout):
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
pip install --user plyngent
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### From a git clone (development)
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
pdm install # first time
|
|
61
|
+
pdm sync # after pull
|
|
62
|
+
pdm run plyngent --help
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Dev checks:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
pdm run basedpyright .
|
|
69
|
+
pdm run ruff check .
|
|
70
|
+
pdm run ruff format .
|
|
71
|
+
pdm run pytest
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Basic usage
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
# 1) Create / open config
|
|
78
|
+
plyngent config path
|
|
79
|
+
plyngent config edit # needs $EDITOR
|
|
80
|
+
|
|
81
|
+
# Minimal provider (OpenAI platform — Responses API; preset defaults to openai):
|
|
82
|
+
# [providers.oai]
|
|
83
|
+
# access_key_or_token = "sk-..."
|
|
84
|
+
# # models default: gpt-5.4, gpt-5.4-mini, gpt-5.4-nano
|
|
85
|
+
# # provider_tools default: web_search (use provider_tools = [] to disable)
|
|
86
|
+
|
|
87
|
+
# 2) Chat
|
|
88
|
+
plyngent chat
|
|
89
|
+
plyngent chat --provider oai --model gpt-5.4-mini
|
|
90
|
+
plyngent chat -p "Summarize this repo" --provider oai --model gpt-5.4-mini --no-stream
|
|
91
|
+
|
|
92
|
+
# 3) List providers from config
|
|
93
|
+
plyngent providers
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
In the REPL: type normally, use `/help` for slash commands, `"""` … `"""` for multiline, `/markdown` for Rich rendering, `/quit` to leave.
|
|
97
|
+
|
|
98
|
+
## Configure
|
|
99
|
+
|
|
100
|
+
Default config path (platformdirs):
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
plyngent config path
|
|
104
|
+
plyngent config edit # opens $EDITOR (e.g. codium --wait)
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Copy the example and fill in a real token:
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
cp doc/plyngent.example.toml "$(plyngent config path)"
|
|
111
|
+
# then edit providers
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Minimal shape:
|
|
115
|
+
|
|
116
|
+
```toml
|
|
117
|
+
[providers.local]
|
|
118
|
+
preset = "openai-compatible"
|
|
119
|
+
url = "https://api.openai.com/v1"
|
|
120
|
+
access_key_or_token = "sk-..."
|
|
121
|
+
|
|
122
|
+
[providers.local.models]
|
|
123
|
+
"gpt-4o-mini" = { text = true }
|
|
124
|
+
|
|
125
|
+
[agent]
|
|
126
|
+
system_prompt = "You are a careful coding assistant."
|
|
127
|
+
confirm_destructive = true
|
|
128
|
+
max_context_tokens = 200000
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Supported provider presets today: `openai` (default if `preset` is omitted; default models `gpt-5.4` / `gpt-5.4-mini` / `gpt-5.4-nano` when `models` is omitted), `openai-compatible`, `deepseek` (OpenAI convention; default models `deepseek-v4-flash` and `deepseek-v4-pro` if `models` is omitted). Anthropic presets are modeled in config but not wired in the runtime client yet.
|
|
132
|
+
|
|
133
|
+
If `[database]` is omitted (or SQLite `url` is empty/`":memory:"`), chat uses a durable file under the user data dir (e.g. `~/.local/share/plyngent/chat.db` on Linux).
|
|
134
|
+
|
|
135
|
+
## Chat
|
|
136
|
+
|
|
137
|
+
### Interactive REPL
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
plyngent chat
|
|
141
|
+
plyngent chat --provider local --model gpt-4o-mini
|
|
142
|
+
plyngent chat --workspace /path/to/project --new
|
|
143
|
+
plyngent chat --session 3
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
| Flag | Meaning |
|
|
147
|
+
|------|---------|
|
|
148
|
+
| `--provider` / `--model` | Select from config (required when multiple and non-interactive) |
|
|
149
|
+
| `--workspace` | Tool root (default: cwd); sessions bind to this path |
|
|
150
|
+
| `--new` / `--session ID` | Fresh session vs resume by id |
|
|
151
|
+
| `--tools` / `--no-tools` | Default tools on |
|
|
152
|
+
| `--max-rounds` | Tool-loop rounds per turn (default 32) |
|
|
153
|
+
| `--stream` / `--no-stream` | Streaming deltas (default on) |
|
|
154
|
+
| `--quiet` | Less status on stderr |
|
|
155
|
+
| `--yes` | Allow destructive tools without confirm (also for one-shot) |
|
|
156
|
+
| `--log-level` | On the root CLI: `DEBUG`, `INFO`, `WARNING`, … |
|
|
157
|
+
|
|
158
|
+
Sessions resume the **most recently updated** session for the current workspace unless you pass `--new` or `--session`. Each session remembers the last **provider** and **model** (restored on resume so you are not re-prompted).
|
|
159
|
+
|
|
160
|
+
### One-shot (scripts / CI)
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
plyngent chat -p "Summarize README.md" --provider local --model gpt-4o-mini --no-stream
|
|
164
|
+
echo "hello" | plyngent chat --provider local --model gpt-4o-mini
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Exit codes (one-shot):
|
|
168
|
+
|
|
169
|
+
| Code | Meaning |
|
|
170
|
+
|------|---------|
|
|
171
|
+
| 0 | Success |
|
|
172
|
+
| 1 | Config / usage error |
|
|
173
|
+
| 2 | Cancelled |
|
|
174
|
+
| 3 | Turn failed (API / incomplete) |
|
|
175
|
+
|
|
176
|
+
### Input ergonomics
|
|
177
|
+
|
|
178
|
+
- **Multiline**: start a message with `"""`, end a later line with `"""`.
|
|
179
|
+
- **`/edit`**: compose a turn in `$EDITOR` (empty buffer cancels).
|
|
180
|
+
- **Tab**: completes slash commands and some arguments (provider, model, on/off, export, `/help` targets).
|
|
181
|
+
|
|
182
|
+
### Slash commands
|
|
183
|
+
|
|
184
|
+
Type `/help` in the REPL for the live list. Common ones:
|
|
185
|
+
|
|
186
|
+
| Command | Purpose |
|
|
187
|
+
|---------|---------|
|
|
188
|
+
| `/status` | Provider, session, context/usage estimates |
|
|
189
|
+
| `/history [n]` | Recent messages |
|
|
190
|
+
| `/sessions` | Sessions for this workspace |
|
|
191
|
+
| `/new` `/resume` `/rename` `/delete` | Session lifecycle (`/delete` confirms) |
|
|
192
|
+
| `/export [md\|json] [path]` | Transcript from DB (no secrets) |
|
|
193
|
+
| `/compact` | Soft-compact + model summary into a **new** session |
|
|
194
|
+
| `/stream` `/verbose` `/markdown` `/tools` `/rounds` | Toggles and limits |
|
|
195
|
+
|
|
196
|
+
| `/retry` | Re-run incomplete last user turn (after error/cancel) |
|
|
197
|
+
| `/provider` `/model` | Switch without restarting |
|
|
198
|
+
| `/models` | List config + remote `GET /models` (`--refresh` bypasses cache) |
|
|
199
|
+
| `/config` | Edit `plyngent.toml` in `$EDITOR` and reload |
|
|
200
|
+
| `/quit` | Leave the REPL |
|
|
201
|
+
|
|
202
|
+
User messages are saved immediately. On API error or Ctrl+C, partial assistant/tool output is discarded but the user message stays so `/retry` works after resume. Interactive auto-retry uses 10s / 20s / 30s delays.
|
|
203
|
+
|
|
204
|
+
## Workspace model
|
|
205
|
+
|
|
206
|
+
- **Workspace** = root for file/process/VCS tools (default cwd).
|
|
207
|
+
- **Session** = SQLite chat bound to a workspace path.
|
|
208
|
+
- Resuming a session from another directory prompts: keep session workspace, rebind to current, or abort.
|
|
209
|
+
|
|
210
|
+
## Tools (when enabled)
|
|
211
|
+
|
|
212
|
+
Default registry: file ops, `run_command` / PTY (POSIX openpty; Windows ConPTY via pywinpty), read-only VCS (git), and human prompts (`ask_user` / `choose_user` / `form_user`).
|
|
213
|
+
|
|
214
|
+
Safety defaults:
|
|
215
|
+
|
|
216
|
+
- Paths stay under the workspace; optional `path_denylist` substrings.
|
|
217
|
+
- Command basename denylist (e.g. dangerous shells/utilities).
|
|
218
|
+
- Destructive tools (delete/move/overwrite) can require confirm (`confirm_destructive`; default deny in non-TTY).
|
|
219
|
+
- PTY sessions: caps, idle TTL, output budget; master FD is non-inheritable; sessions closed on chat exit.
|
|
220
|
+
|
|
221
|
+
## Usage / context (CLI)
|
|
222
|
+
|
|
223
|
+
- **Context size** prefers API `prompt_tokens` from the last model call; otherwise a char-based estimate (~4 chars/token).
|
|
224
|
+
- **Turn/session usage** sum billed completion usage across tool rounds (history is re-sent each round).
|
|
225
|
+
- Soft compact can calibrate from reported `prompt_tokens`. See `/status`.
|
|
226
|
+
|
|
227
|
+
## Other commands
|
|
228
|
+
|
|
229
|
+
```bash
|
|
230
|
+
plyngent providers # list configured providers
|
|
231
|
+
plyngent config path|edit
|
|
232
|
+
plyngent --log-level INFO chat ...
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
## Architecture (short)
|
|
236
|
+
|
|
237
|
+
See [doc/architecture.md](doc/architecture.md) and [CLAUDE.md](CLAUDE.md) for developers.
|
|
238
|
+
|
|
239
|
+
- **`lmproto/`** — OpenAI-compatible (+ DeepSeek) msgspec models and async SSE clients
|
|
240
|
+
- **`agent/`** — tool loop, streaming, usage, compact
|
|
241
|
+
- **`memory/`** — async SQLAlchemy sessions/messages
|
|
242
|
+
- **`tools/`** — workspace tools
|
|
243
|
+
- **`cli/`** — Click entry + slash registry (`awaitlet` bridges sync Click to async work)
|
|
244
|
+
- Multi-tenant / web (`router/`, real `web/`) are **not** in scope for the single-user CLI (Phase H).
|
|
245
|
+
|
|
246
|
+
## License
|
|
247
|
+
|
|
248
|
+
MIT
|