paimon 0.2.7__tar.gz → 0.2.8__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.
- {paimon-0.2.7/paimon.egg-info → paimon-0.2.8}/PKG-INFO +39 -20
- {paimon-0.2.7 → paimon-0.2.8}/README.md +34 -18
- {paimon-0.2.7 → paimon-0.2.8}/README.zh-CN.md +34 -18
- {paimon-0.2.7 → paimon-0.2.8}/paimon/agent.py +193 -66
- paimon-0.2.8/paimon/agentpane.py +136 -0
- paimon-0.2.8/paimon/antigravity.py +422 -0
- {paimon-0.2.7 → paimon-0.2.8}/paimon/app.py +92 -114
- {paimon-0.2.7 → paimon-0.2.8}/paimon/app.tcss +38 -14
- paimon-0.2.8/paimon/chatgpt.py +208 -0
- {paimon-0.2.7 → paimon-0.2.8}/paimon/cli.py +27 -18
- {paimon-0.2.7 → paimon-0.2.8}/paimon/commandpane.py +5 -5
- {paimon-0.2.7 → paimon-0.2.8}/paimon/commands.py +125 -42
- {paimon-0.2.7 → paimon-0.2.8}/paimon/compaction.py +24 -47
- {paimon-0.2.7 → paimon-0.2.8}/paimon/config.py +123 -116
- {paimon-0.2.7 → paimon-0.2.8}/paimon/errors.py +1 -1
- {paimon-0.2.7 → paimon-0.2.8}/paimon/headless.py +6 -4
- paimon-0.2.8/paimon/llm.py +250 -0
- {paimon-0.2.7 → paimon-0.2.8}/paimon/login.py +98 -41
- paimon-0.2.8/paimon/oauth.py +234 -0
- {paimon-0.2.7 → paimon-0.2.8}/paimon/pane.py +56 -340
- paimon-0.2.8/paimon/review.py +170 -0
- {paimon-0.2.7 → paimon-0.2.8}/paimon/skill/SKILL.md +9 -9
- {paimon-0.2.7 → paimon-0.2.8}/paimon/tabs.py +17 -22
- {paimon-0.2.7 → paimon-0.2.8}/paimon/telemetry.py +1 -1
- paimon-0.2.8/paimon/textual_debug.py +230 -0
- {paimon-0.2.7 → paimon-0.2.8}/paimon/tools.py +415 -481
- paimon-0.2.8/paimon/transcript.py +287 -0
- {paimon-0.2.7 → paimon-0.2.8}/paimon/ui.py +241 -26
- {paimon-0.2.7 → paimon-0.2.8/paimon.egg-info}/PKG-INFO +39 -20
- {paimon-0.2.7 → paimon-0.2.8}/paimon.egg-info/SOURCES.txt +7 -1
- paimon-0.2.8/paimon.egg-info/requires.txt +9 -0
- {paimon-0.2.7 → paimon-0.2.8}/paimon.egg-info/scm_file_list.json +12 -2
- paimon-0.2.8/paimon.egg-info/scm_version.json +8 -0
- {paimon-0.2.7 → paimon-0.2.8}/pyproject.toml +4 -1
- paimon-0.2.7/paimon/llm.py +0 -130
- paimon-0.2.7/paimon/model_windows.py +0 -2852
- paimon-0.2.7/paimon.egg-info/requires.txt +0 -6
- paimon-0.2.7/paimon.egg-info/scm_version.json +0 -8
- {paimon-0.2.7 → paimon-0.2.8}/LICENSE +0 -0
- {paimon-0.2.7 → paimon-0.2.8}/MANIFEST.in +0 -0
- {paimon-0.2.7 → paimon-0.2.8}/paimon/__init__.py +0 -0
- {paimon-0.2.7 → paimon-0.2.8}/paimon/__main__.py +0 -0
- {paimon-0.2.7 → paimon-0.2.8}/paimon/_grep_worker.py +0 -0
- {paimon-0.2.7 → paimon-0.2.8}/paimon/diff.py +0 -0
- {paimon-0.2.7 → paimon-0.2.8}/paimon/herdr.py +0 -0
- {paimon-0.2.7 → paimon-0.2.8}/paimon/lockfile.py +0 -0
- {paimon-0.2.7 → paimon-0.2.8}/paimon/mentions.py +0 -0
- {paimon-0.2.7 → paimon-0.2.8}/paimon/prompt.py +0 -0
- {paimon-0.2.7 → paimon-0.2.8}/paimon/retry.py +0 -0
- {paimon-0.2.7 → paimon-0.2.8}/paimon/session.py +0 -0
- {paimon-0.2.7 → paimon-0.2.8}/paimon/skills.py +0 -0
- {paimon-0.2.7 → paimon-0.2.8}/paimon/turns.py +0 -0
- {paimon-0.2.7 → paimon-0.2.8}/paimon/websearch.py +0 -0
- {paimon-0.2.7 → paimon-0.2.8}/paimon.egg-info/dependency_links.txt +0 -0
- {paimon-0.2.7 → paimon-0.2.8}/paimon.egg-info/entry_points.txt +0 -0
- {paimon-0.2.7 → paimon-0.2.8}/paimon.egg-info/top_level.txt +0 -0
- {paimon-0.2.7 → paimon-0.2.8}/setup.cfg +0 -0
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: paimon
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.8
|
|
4
4
|
Summary: A minimal code agent built on pydantic-ai + textual
|
|
5
5
|
Requires-Python: >=3.10
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
7
7
|
License-File: LICENSE
|
|
8
8
|
Requires-Dist: httpx>=0.27
|
|
9
|
-
Requires-Dist:
|
|
9
|
+
Requires-Dist: genai-prices>=0.1.6
|
|
10
|
+
Requires-Dist: pydantic-ai-slim[anthropic,google,openai]>=2.54.0
|
|
10
11
|
Requires-Dist: textual>=8.2.7
|
|
11
12
|
Requires-Dist: textual-serve>=1.1.3
|
|
12
13
|
Requires-Dist: pyyaml>=6
|
|
14
|
+
Requires-Dist: pydantic>=2.10
|
|
15
|
+
Requires-Dist: typing-extensions>=4.12
|
|
13
16
|
Requires-Dist: ddgs>=9
|
|
14
17
|
Dynamic: license-file
|
|
15
18
|
|
|
@@ -39,11 +42,11 @@ Or run it without installing anything:
|
|
|
39
42
|
uvx paimon
|
|
40
43
|
```
|
|
41
44
|
|
|
42
|
-
The first launch asks for a provider,
|
|
45
|
+
The first launch asks for a provider, its API base and key, then a model. Then just type what you want done. Write `@path/to/file` in a prompt to hand a file to the agent.
|
|
43
46
|
|
|
44
|
-
While it runs: `Shift+Tab` switches how much the agent may do on its own (**read**
|
|
47
|
+
While it runs: `Shift+Tab` switches how much the agent may do on its own (**read** only reads, **auto** edits inside the working directory and has a second model call approve everything else, **yolo** checks nothing and is the default), `Esc` interrupts the current turn, `Ctrl+P` opens the command palette, `Ctrl+C` quits. A line starting with `!` runs in a shell instead of being sent, and Paimon sees what it printed. `!!` keeps it to yourself.
|
|
45
48
|
|
|
46
|
-
`Ctrl+T` opens another session in a pane of its own, `Ctrl+W` closes one, `Ctrl+PageUp` and `Ctrl+PageDown` move between them, and `Ctrl+G` jumps to a pane waiting for permission. Paimon can work in parallel: ask for two independent things and it starts a second agent in
|
|
49
|
+
`Ctrl+T` opens another session in a pane of its own, `Ctrl+W` closes one, `Ctrl+PageUp` and `Ctrl+PageDown` move between them, and `Ctrl+G` jumps to a pane waiting for permission. Paimon can work in parallel: ask for two independent things and it starts a second agent in a tab of its own, where you can watch it work and answer what it asks, and whose answer comes back into the conversation when it is done. Closing the tab stops it. It can also leave a command running in a tab, a dev server or a watcher, instead of holding up a turn.
|
|
47
50
|
|
|
48
51
|
## Web search
|
|
49
52
|
|
|
@@ -55,11 +58,11 @@ Paimon loads [Agent Skills](https://agentskills.io) from `~/.config/paimon/skill
|
|
|
55
58
|
|
|
56
59
|
## Using Paimon as a subagent
|
|
57
60
|
|
|
58
|
-
Frontier models are good at planning and reviewing; the steps in between are often mechanical. Point Paimon at a cheaper model and let Claude Code or Codex write the plan and check the result.
|
|
61
|
+
Frontier models are good at planning and reviewing; the steps in between are often mechanical. Point Paimon at a cheaper model and let Claude Code or Codex write the plan and check the result. Log in to that model's provider once, then name the model on each run:
|
|
59
62
|
|
|
60
63
|
```bash
|
|
61
|
-
paimon login
|
|
62
|
-
paimon --
|
|
64
|
+
paimon login zai --api-key-env ZAI_API_KEY
|
|
65
|
+
paimon --model zai:glm-4.7 -p "apply the plan in PLAN.md" --mode auto --output-format result
|
|
63
66
|
```
|
|
64
67
|
|
|
65
68
|
The bundled skill teaches the calling agent this workflow:
|
|
@@ -80,7 +83,7 @@ import asyncio
|
|
|
80
83
|
from paimon.agent import Agent, TextDelta
|
|
81
84
|
|
|
82
85
|
async def main():
|
|
83
|
-
agent = Agent.open(mode="
|
|
86
|
+
agent = Agent.open(mode="auto")
|
|
84
87
|
async for event in agent.run("summarize the tests in this directory"):
|
|
85
88
|
if isinstance(event, TextDelta):
|
|
86
89
|
print(event.text, end="", flush=True)
|
|
@@ -88,7 +91,7 @@ async def main():
|
|
|
88
91
|
asyncio.run(main())
|
|
89
92
|
```
|
|
90
93
|
|
|
91
|
-
`Agent.open()` also takes a working directory, an async `confirm` callback for permission prompts, and a `toolset` to hand the model fewer tools or tools of your own. An agent holds its session until it goes away; to give it back at a definite moment, call `close()` or use the agent as a context manager. It writes the same session files as the CLI, so a run started in code can be resumed later with `paimon -r`.
|
|
94
|
+
`Agent.open()` also takes a working directory, an async `confirm` callback for the permission prompts that are left, and a `toolset` to hand the model fewer tools or tools of your own. An agent holds its session until it goes away; to give it back at a definite moment, call `close()` or use the agent as a context manager. It writes the same session files as the CLI, so a run started in code can be resumed later with `paimon -r`.
|
|
92
95
|
|
|
93
96
|
## Sessions
|
|
94
97
|
|
|
@@ -106,43 +109,55 @@ paimon log a1b2c3 # what a session did, one line per event
|
|
|
106
109
|
|
|
107
110
|
```bash
|
|
108
111
|
paimon --mode read # start in a more cautious permission mode (yolo is the default)
|
|
109
|
-
paimon --strict #
|
|
112
|
+
paimon --strict # hold every command, even read-only ones
|
|
110
113
|
paimon --no-web-search # take the web search tool away for this run
|
|
111
114
|
paimon --web # the same UI in a browser (--port, default 8000)
|
|
112
115
|
paimon -p "what does cli.py do?" # one answer on stdout, no UI
|
|
113
116
|
cat log.txt | paimon -p "summarize this"
|
|
114
117
|
paimon --model zai:glm-4.7 # this model for this run only
|
|
115
|
-
paimon --profile work # a separately configured account
|
|
116
118
|
```
|
|
117
119
|
|
|
118
120
|
`-p` never stops to ask, so with the default `yolo` mode it can already write files and run commands. Add `--output-format result` for a single JSON object with the outcome, which is what a calling program should read. `paimon --help` lists the rest.
|
|
119
121
|
|
|
120
122
|
Inside a [Herdr](https://herdr.dev) pane the UI reports its state and resume command to Herdr on its own, with nothing to install.
|
|
121
123
|
|
|
124
|
+
### Debugging the Textual UI
|
|
125
|
+
|
|
126
|
+
Start with `paimon --textual-debug` (also works with `--web`) when Paimon needs to diagnose its own layout or styling. It is off by default. When enabled, the model receives five tools scoped to the live UI process:
|
|
127
|
+
|
|
128
|
+
- `textual_inspect` queries the DOM by CSS selector and reports geometry, pseudo-classes, focus and computed CSS;
|
|
129
|
+
- `textual_eval` / `textual_exec` run Python in the UI process, including private APIs, persistent variables and top-level `await`;
|
|
130
|
+
- `textual_apply_css` layers on CSS and relayouts immediately;
|
|
131
|
+
- `textual_screenshot` exports the current render to SVG.
|
|
132
|
+
|
|
133
|
+
You can ask it, for example, to “find why `#prompt` is narrower than expected, try a live fix, and take a screenshot.” `textual_exec` deliberately provides unrestricted in-process Python and can change any Textual or Paimon state. Use this development option only with trusted prompts. Live changes last only until exit; after confirming a fix, ask Paimon to edit the source.
|
|
134
|
+
|
|
122
135
|
## Configuration
|
|
123
136
|
|
|
124
|
-
|
|
137
|
+
Model settings are kept in `~/.config/paimon/config.json`, written by the first launch or by `paimon login`. Each provider keeps its own credentials, and `paimon model provider:name` or Switch model in the command palette picks the model to run on. A ChatGPT plan works in place of an API key: `paimon login chatgpt` signs in through the browser. `paimon login antigravity` does the same for an Antigravity plan, which Google does not support outside Antigravity: Paimon signs in as the Antigravity client and calls an internal endpoint, so the account may be limited or closed, and the risk is yours. Sessions live in `~/.local/share/paimon/sessions/`.
|
|
125
138
|
|
|
126
|
-
Read and
|
|
139
|
+
Read and auto modes run a small set of clearly read-only commands (`ls`, `cat`, `git status`, …) on their own; `--strict` turns that off, and on Windows, where cmd.exe runs the commands, none are recognized. Read mode refuses everything else. Auto mode asks a reviewer model, which sees your messages and the agent's tool calls but not its reasoning or any tool output, and answers allow or block. It asks you instead when the reviewer cannot be reached or has blocked three calls in a row, and under `-p` those are refusals. Current models review with their provider's fast tier by default (GPT with Luna, Claude with Haiku, GLM with Flash) and the rest review with themselves; set `"review_model": "provider:name"` in the config to choose. **All of this is a guardrail against agent mistakes, not a security boundary.** For real isolation, run Paimon inside a container or VM.
|
|
127
140
|
|
|
128
141
|
## Architecture
|
|
129
142
|
|
|
130
|
-
`Agent.run` is a UI-agnostic stream of events; the TUI, `--web` and headless mode are three renderers over that one stream. An agent holds the subagents and background commands it starts. A subagent is another `Agent` running as a task in the same process, and its answer is delivered to its parent as a message.
|
|
143
|
+
`Agent.run` is a UI-agnostic stream of events; the TUI, `--web` and headless mode are three renderers over that one stream. An agent holds the subagents and background commands it starts. A subagent is another `Agent` running as a task in the same process, and its answer is delivered to its parent as a message. A UI that wants to show a job hooks `Agent.open_job`, which is how the TUI gives each one a pane.
|
|
131
144
|
|
|
132
145
|
```mermaid
|
|
133
146
|
flowchart TD
|
|
134
147
|
subgraph entry["Entry points"]
|
|
135
148
|
CLI["cli.py"]
|
|
136
|
-
Commands["commands.py<br/>status / login / sessions"]
|
|
149
|
+
Commands["commands.py<br/>status / login / model / sessions"]
|
|
137
150
|
Headless["headless.py<br/>-p, one-shot"]
|
|
138
151
|
App["app.py<br/>Textual TUI / --web"]
|
|
139
152
|
end
|
|
140
153
|
|
|
141
154
|
subgraph tui["TUI widgets"]
|
|
142
155
|
Pane["pane.py<br/>SessionPane"]
|
|
156
|
+
AgentPane["agentpane.py<br/>subagent pane"]
|
|
143
157
|
CommandPane["commandpane.py<br/>background command pane"]
|
|
158
|
+
Transcript["transcript.py<br/>conversation log, event renderer"]
|
|
144
159
|
Tabs["tabs.py<br/>pane strip"]
|
|
145
|
-
Login["login.py<br/>provider /
|
|
160
|
+
Login["login.py<br/>provider / key"]
|
|
146
161
|
UIWidgets["ui.py<br/>prompt input, confirmations"]
|
|
147
162
|
Diff["diff.py<br/>side-by-side diff rendering"]
|
|
148
163
|
end
|
|
@@ -154,14 +169,13 @@ flowchart TD
|
|
|
154
169
|
ToolsMod["tools.py<br/>tool REGISTRY"]
|
|
155
170
|
SessionMod["session.py<br/>JSONL persistence"]
|
|
156
171
|
Compaction["compaction.py"]
|
|
157
|
-
ModelWindows["model_windows.py<br/>context window sizes"]
|
|
158
172
|
Retry["retry.py"]
|
|
159
173
|
Mentions["mentions.py<br/>@path expansion"]
|
|
160
174
|
Jobs["turns.py<br/>turn driver"]
|
|
161
175
|
end
|
|
162
176
|
|
|
163
177
|
subgraph support["Config & skills"]
|
|
164
|
-
Config["config.py<br/>
|
|
178
|
+
Config["config.py<br/>settings, credentials"]
|
|
165
179
|
Skills["skills.py<br/>Agent Skills discovery"]
|
|
166
180
|
end
|
|
167
181
|
|
|
@@ -174,6 +188,7 @@ flowchart TD
|
|
|
174
188
|
Headless --> Mentions
|
|
175
189
|
|
|
176
190
|
App --> Pane
|
|
191
|
+
App --> AgentPane
|
|
177
192
|
App --> CommandPane
|
|
178
193
|
App --> Tabs
|
|
179
194
|
App --> Login
|
|
@@ -182,9 +197,13 @@ flowchart TD
|
|
|
182
197
|
Pane --> Jobs
|
|
183
198
|
Pane --> AgentLoop
|
|
184
199
|
Pane --> Diff
|
|
200
|
+
Pane --> Transcript
|
|
185
201
|
Pane --> UIWidgets
|
|
186
202
|
Pane --> LLM
|
|
203
|
+
AgentPane --> Pane
|
|
204
|
+
AgentPane --> Transcript
|
|
187
205
|
CommandPane --> Pane
|
|
206
|
+
Transcript --> UIWidgets
|
|
188
207
|
UIWidgets --> Diff
|
|
189
208
|
|
|
190
209
|
AgentLoop --> LLM
|
|
@@ -195,10 +214,10 @@ flowchart TD
|
|
|
195
214
|
AgentLoop --> Retry
|
|
196
215
|
AgentLoop --> Mentions
|
|
197
216
|
AgentLoop -. "spawn_agent" .-> AgentLoop
|
|
217
|
+
AgentLoop -. "spawn_agent" .-> AgentPane
|
|
198
218
|
AgentLoop -. "run_background" .-> CommandPane
|
|
199
219
|
|
|
200
220
|
PromptMod --> Skills
|
|
201
|
-
Compaction --> ModelWindows
|
|
202
221
|
|
|
203
222
|
Jobs --> AgentLoop
|
|
204
223
|
|
|
@@ -24,11 +24,11 @@ Or run it without installing anything:
|
|
|
24
24
|
uvx paimon
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
-
The first launch asks for a provider,
|
|
27
|
+
The first launch asks for a provider, its API base and key, then a model. Then just type what you want done. Write `@path/to/file` in a prompt to hand a file to the agent.
|
|
28
28
|
|
|
29
|
-
While it runs: `Shift+Tab` switches how much the agent may do on its own (**read**
|
|
29
|
+
While it runs: `Shift+Tab` switches how much the agent may do on its own (**read** only reads, **auto** edits inside the working directory and has a second model call approve everything else, **yolo** checks nothing and is the default), `Esc` interrupts the current turn, `Ctrl+P` opens the command palette, `Ctrl+C` quits. A line starting with `!` runs in a shell instead of being sent, and Paimon sees what it printed. `!!` keeps it to yourself.
|
|
30
30
|
|
|
31
|
-
`Ctrl+T` opens another session in a pane of its own, `Ctrl+W` closes one, `Ctrl+PageUp` and `Ctrl+PageDown` move between them, and `Ctrl+G` jumps to a pane waiting for permission. Paimon can work in parallel: ask for two independent things and it starts a second agent in
|
|
31
|
+
`Ctrl+T` opens another session in a pane of its own, `Ctrl+W` closes one, `Ctrl+PageUp` and `Ctrl+PageDown` move between them, and `Ctrl+G` jumps to a pane waiting for permission. Paimon can work in parallel: ask for two independent things and it starts a second agent in a tab of its own, where you can watch it work and answer what it asks, and whose answer comes back into the conversation when it is done. Closing the tab stops it. It can also leave a command running in a tab, a dev server or a watcher, instead of holding up a turn.
|
|
32
32
|
|
|
33
33
|
## Web search
|
|
34
34
|
|
|
@@ -40,11 +40,11 @@ Paimon loads [Agent Skills](https://agentskills.io) from `~/.config/paimon/skill
|
|
|
40
40
|
|
|
41
41
|
## Using Paimon as a subagent
|
|
42
42
|
|
|
43
|
-
Frontier models are good at planning and reviewing; the steps in between are often mechanical. Point Paimon at a cheaper model and let Claude Code or Codex write the plan and check the result.
|
|
43
|
+
Frontier models are good at planning and reviewing; the steps in between are often mechanical. Point Paimon at a cheaper model and let Claude Code or Codex write the plan and check the result. Log in to that model's provider once, then name the model on each run:
|
|
44
44
|
|
|
45
45
|
```bash
|
|
46
|
-
paimon login
|
|
47
|
-
paimon --
|
|
46
|
+
paimon login zai --api-key-env ZAI_API_KEY
|
|
47
|
+
paimon --model zai:glm-4.7 -p "apply the plan in PLAN.md" --mode auto --output-format result
|
|
48
48
|
```
|
|
49
49
|
|
|
50
50
|
The bundled skill teaches the calling agent this workflow:
|
|
@@ -65,7 +65,7 @@ import asyncio
|
|
|
65
65
|
from paimon.agent import Agent, TextDelta
|
|
66
66
|
|
|
67
67
|
async def main():
|
|
68
|
-
agent = Agent.open(mode="
|
|
68
|
+
agent = Agent.open(mode="auto")
|
|
69
69
|
async for event in agent.run("summarize the tests in this directory"):
|
|
70
70
|
if isinstance(event, TextDelta):
|
|
71
71
|
print(event.text, end="", flush=True)
|
|
@@ -73,7 +73,7 @@ async def main():
|
|
|
73
73
|
asyncio.run(main())
|
|
74
74
|
```
|
|
75
75
|
|
|
76
|
-
`Agent.open()` also takes a working directory, an async `confirm` callback for permission prompts, and a `toolset` to hand the model fewer tools or tools of your own. An agent holds its session until it goes away; to give it back at a definite moment, call `close()` or use the agent as a context manager. It writes the same session files as the CLI, so a run started in code can be resumed later with `paimon -r`.
|
|
76
|
+
`Agent.open()` also takes a working directory, an async `confirm` callback for the permission prompts that are left, and a `toolset` to hand the model fewer tools or tools of your own. An agent holds its session until it goes away; to give it back at a definite moment, call `close()` or use the agent as a context manager. It writes the same session files as the CLI, so a run started in code can be resumed later with `paimon -r`.
|
|
77
77
|
|
|
78
78
|
## Sessions
|
|
79
79
|
|
|
@@ -91,43 +91,55 @@ paimon log a1b2c3 # what a session did, one line per event
|
|
|
91
91
|
|
|
92
92
|
```bash
|
|
93
93
|
paimon --mode read # start in a more cautious permission mode (yolo is the default)
|
|
94
|
-
paimon --strict #
|
|
94
|
+
paimon --strict # hold every command, even read-only ones
|
|
95
95
|
paimon --no-web-search # take the web search tool away for this run
|
|
96
96
|
paimon --web # the same UI in a browser (--port, default 8000)
|
|
97
97
|
paimon -p "what does cli.py do?" # one answer on stdout, no UI
|
|
98
98
|
cat log.txt | paimon -p "summarize this"
|
|
99
99
|
paimon --model zai:glm-4.7 # this model for this run only
|
|
100
|
-
paimon --profile work # a separately configured account
|
|
101
100
|
```
|
|
102
101
|
|
|
103
102
|
`-p` never stops to ask, so with the default `yolo` mode it can already write files and run commands. Add `--output-format result` for a single JSON object with the outcome, which is what a calling program should read. `paimon --help` lists the rest.
|
|
104
103
|
|
|
105
104
|
Inside a [Herdr](https://herdr.dev) pane the UI reports its state and resume command to Herdr on its own, with nothing to install.
|
|
106
105
|
|
|
106
|
+
### Debugging the Textual UI
|
|
107
|
+
|
|
108
|
+
Start with `paimon --textual-debug` (also works with `--web`) when Paimon needs to diagnose its own layout or styling. It is off by default. When enabled, the model receives five tools scoped to the live UI process:
|
|
109
|
+
|
|
110
|
+
- `textual_inspect` queries the DOM by CSS selector and reports geometry, pseudo-classes, focus and computed CSS;
|
|
111
|
+
- `textual_eval` / `textual_exec` run Python in the UI process, including private APIs, persistent variables and top-level `await`;
|
|
112
|
+
- `textual_apply_css` layers on CSS and relayouts immediately;
|
|
113
|
+
- `textual_screenshot` exports the current render to SVG.
|
|
114
|
+
|
|
115
|
+
You can ask it, for example, to “find why `#prompt` is narrower than expected, try a live fix, and take a screenshot.” `textual_exec` deliberately provides unrestricted in-process Python and can change any Textual or Paimon state. Use this development option only with trusted prompts. Live changes last only until exit; after confirming a fix, ask Paimon to edit the source.
|
|
116
|
+
|
|
107
117
|
## Configuration
|
|
108
118
|
|
|
109
|
-
|
|
119
|
+
Model settings are kept in `~/.config/paimon/config.json`, written by the first launch or by `paimon login`. Each provider keeps its own credentials, and `paimon model provider:name` or Switch model in the command palette picks the model to run on. A ChatGPT plan works in place of an API key: `paimon login chatgpt` signs in through the browser. `paimon login antigravity` does the same for an Antigravity plan, which Google does not support outside Antigravity: Paimon signs in as the Antigravity client and calls an internal endpoint, so the account may be limited or closed, and the risk is yours. Sessions live in `~/.local/share/paimon/sessions/`.
|
|
110
120
|
|
|
111
|
-
Read and
|
|
121
|
+
Read and auto modes run a small set of clearly read-only commands (`ls`, `cat`, `git status`, …) on their own; `--strict` turns that off, and on Windows, where cmd.exe runs the commands, none are recognized. Read mode refuses everything else. Auto mode asks a reviewer model, which sees your messages and the agent's tool calls but not its reasoning or any tool output, and answers allow or block. It asks you instead when the reviewer cannot be reached or has blocked three calls in a row, and under `-p` those are refusals. Current models review with their provider's fast tier by default (GPT with Luna, Claude with Haiku, GLM with Flash) and the rest review with themselves; set `"review_model": "provider:name"` in the config to choose. **All of this is a guardrail against agent mistakes, not a security boundary.** For real isolation, run Paimon inside a container or VM.
|
|
112
122
|
|
|
113
123
|
## Architecture
|
|
114
124
|
|
|
115
|
-
`Agent.run` is a UI-agnostic stream of events; the TUI, `--web` and headless mode are three renderers over that one stream. An agent holds the subagents and background commands it starts. A subagent is another `Agent` running as a task in the same process, and its answer is delivered to its parent as a message.
|
|
125
|
+
`Agent.run` is a UI-agnostic stream of events; the TUI, `--web` and headless mode are three renderers over that one stream. An agent holds the subagents and background commands it starts. A subagent is another `Agent` running as a task in the same process, and its answer is delivered to its parent as a message. A UI that wants to show a job hooks `Agent.open_job`, which is how the TUI gives each one a pane.
|
|
116
126
|
|
|
117
127
|
```mermaid
|
|
118
128
|
flowchart TD
|
|
119
129
|
subgraph entry["Entry points"]
|
|
120
130
|
CLI["cli.py"]
|
|
121
|
-
Commands["commands.py<br/>status / login / sessions"]
|
|
131
|
+
Commands["commands.py<br/>status / login / model / sessions"]
|
|
122
132
|
Headless["headless.py<br/>-p, one-shot"]
|
|
123
133
|
App["app.py<br/>Textual TUI / --web"]
|
|
124
134
|
end
|
|
125
135
|
|
|
126
136
|
subgraph tui["TUI widgets"]
|
|
127
137
|
Pane["pane.py<br/>SessionPane"]
|
|
138
|
+
AgentPane["agentpane.py<br/>subagent pane"]
|
|
128
139
|
CommandPane["commandpane.py<br/>background command pane"]
|
|
140
|
+
Transcript["transcript.py<br/>conversation log, event renderer"]
|
|
129
141
|
Tabs["tabs.py<br/>pane strip"]
|
|
130
|
-
Login["login.py<br/>provider /
|
|
142
|
+
Login["login.py<br/>provider / key"]
|
|
131
143
|
UIWidgets["ui.py<br/>prompt input, confirmations"]
|
|
132
144
|
Diff["diff.py<br/>side-by-side diff rendering"]
|
|
133
145
|
end
|
|
@@ -139,14 +151,13 @@ flowchart TD
|
|
|
139
151
|
ToolsMod["tools.py<br/>tool REGISTRY"]
|
|
140
152
|
SessionMod["session.py<br/>JSONL persistence"]
|
|
141
153
|
Compaction["compaction.py"]
|
|
142
|
-
ModelWindows["model_windows.py<br/>context window sizes"]
|
|
143
154
|
Retry["retry.py"]
|
|
144
155
|
Mentions["mentions.py<br/>@path expansion"]
|
|
145
156
|
Jobs["turns.py<br/>turn driver"]
|
|
146
157
|
end
|
|
147
158
|
|
|
148
159
|
subgraph support["Config & skills"]
|
|
149
|
-
Config["config.py<br/>
|
|
160
|
+
Config["config.py<br/>settings, credentials"]
|
|
150
161
|
Skills["skills.py<br/>Agent Skills discovery"]
|
|
151
162
|
end
|
|
152
163
|
|
|
@@ -159,6 +170,7 @@ flowchart TD
|
|
|
159
170
|
Headless --> Mentions
|
|
160
171
|
|
|
161
172
|
App --> Pane
|
|
173
|
+
App --> AgentPane
|
|
162
174
|
App --> CommandPane
|
|
163
175
|
App --> Tabs
|
|
164
176
|
App --> Login
|
|
@@ -167,9 +179,13 @@ flowchart TD
|
|
|
167
179
|
Pane --> Jobs
|
|
168
180
|
Pane --> AgentLoop
|
|
169
181
|
Pane --> Diff
|
|
182
|
+
Pane --> Transcript
|
|
170
183
|
Pane --> UIWidgets
|
|
171
184
|
Pane --> LLM
|
|
185
|
+
AgentPane --> Pane
|
|
186
|
+
AgentPane --> Transcript
|
|
172
187
|
CommandPane --> Pane
|
|
188
|
+
Transcript --> UIWidgets
|
|
173
189
|
UIWidgets --> Diff
|
|
174
190
|
|
|
175
191
|
AgentLoop --> LLM
|
|
@@ -180,10 +196,10 @@ flowchart TD
|
|
|
180
196
|
AgentLoop --> Retry
|
|
181
197
|
AgentLoop --> Mentions
|
|
182
198
|
AgentLoop -. "spawn_agent" .-> AgentLoop
|
|
199
|
+
AgentLoop -. "spawn_agent" .-> AgentPane
|
|
183
200
|
AgentLoop -. "run_background" .-> CommandPane
|
|
184
201
|
|
|
185
202
|
PromptMod --> Skills
|
|
186
|
-
Compaction --> ModelWindows
|
|
187
203
|
|
|
188
204
|
Jobs --> AgentLoop
|
|
189
205
|
|
|
@@ -24,11 +24,11 @@ paimon
|
|
|
24
24
|
uvx paimon
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
-
首次启动会询问 provider
|
|
27
|
+
首次启动会询问 provider 及其 API base 和 key,然后选择模型。之后输入要完成的任务即可。在提示中写 `@path/to/file` 可以把文件提供给 agent。
|
|
28
28
|
|
|
29
|
-
运行时:`Shift+Tab` 切换 agent 的自主程度(**read**
|
|
29
|
+
运行时:`Shift+Tab` 切换 agent 的自主程度(**read** 只读,**auto** 放行工作目录内的编辑,其余操作交给另一次模型调用审批,**yolo** 不做任何检查,也是默认值),`Esc` 打断当前回合,`Ctrl+P` 打开命令面板,`Ctrl+C` 退出。以 `!` 开头的一行不发给模型,而是直接在 shell 里执行,输出 Paimon 也能看到。`!!` 则不告诉它。
|
|
30
30
|
|
|
31
|
-
`Ctrl+T` 在新 pane 里打开另一个会话,`Ctrl+W` 关闭当前 pane,`Ctrl+PageUp` 和 `Ctrl+PageDown` 在 pane 之间切换,`Ctrl+G` 跳到正在等待授权的 pane。Paimon
|
|
31
|
+
`Ctrl+T` 在新 pane 里打开另一个会话,`Ctrl+W` 关闭当前 pane,`Ctrl+PageUp` 和 `Ctrl+PageDown` 在 pane 之间切换,`Ctrl+G` 跳到正在等待授权的 pane。Paimon 也能并行干活:让它同时做两件互不相干的事,它会在单独的 tab 里起第二个 agent,你可以在那里看它干活、回答它的授权请求,做完后结果会回到当前会话里,关掉 tab 就是停掉它。它也能把一条命令留在 tab 里跑,比如开发服务器或者文件监视,不占着当前回合。
|
|
32
32
|
|
|
33
33
|
## 网页搜索
|
|
34
34
|
|
|
@@ -40,11 +40,11 @@ Paimon 会从 `~/.config/paimon/skills`、`~/.agents/skills` 以及工作目录
|
|
|
40
40
|
|
|
41
41
|
## 当作 subagent 使用
|
|
42
42
|
|
|
43
|
-
前沿模型擅长制定计划和验收结果,中间的执行步骤往往比较机械。让 Paimon 使用成本较低的模型执行,由 Claude Code 或 Codex
|
|
43
|
+
前沿模型擅长制定计划和验收结果,中间的执行步骤往往比较机械。让 Paimon 使用成本较低的模型执行,由 Claude Code 或 Codex 制定计划并检查结果。先登录该模型的 provider,之后每次运行时指定模型:
|
|
44
44
|
|
|
45
45
|
```bash
|
|
46
|
-
paimon login
|
|
47
|
-
paimon --
|
|
46
|
+
paimon login zai --api-key-env ZAI_API_KEY
|
|
47
|
+
paimon --model zai:glm-4.7 -p "apply the plan in PLAN.md" --mode auto --output-format result
|
|
48
48
|
```
|
|
49
49
|
|
|
50
50
|
自带的 skill 会向调用方 agent 说明这套流程:
|
|
@@ -65,7 +65,7 @@ import asyncio
|
|
|
65
65
|
from paimon.agent import Agent, TextDelta
|
|
66
66
|
|
|
67
67
|
async def main():
|
|
68
|
-
agent = Agent.open(mode="
|
|
68
|
+
agent = Agent.open(mode="auto")
|
|
69
69
|
async for event in agent.run("summarize the tests in this directory"):
|
|
70
70
|
if isinstance(event, TextDelta):
|
|
71
71
|
print(event.text, end="", flush=True)
|
|
@@ -73,7 +73,7 @@ async def main():
|
|
|
73
73
|
asyncio.run(main())
|
|
74
74
|
```
|
|
75
75
|
|
|
76
|
-
`Agent.open()`
|
|
76
|
+
`Agent.open()` 还接受工作目录、用于剩余权限确认的异步 `confirm` 回调,以及 `toolset`,可以只给模型一部分工具,或者换成你自己的工具。agent 被回收时会交还会话,想在确定的时刻交还就调 `close()`,或者把它当上下文管理器用。它写的会话文件和 CLI 一样,所以代码里跑出来的会话之后可以用 `paimon -r` 恢复。
|
|
77
77
|
|
|
78
78
|
## 会话
|
|
79
79
|
|
|
@@ -91,41 +91,53 @@ paimon log a1b2c3 # 查看会话做了什么,每个事件一行
|
|
|
91
91
|
|
|
92
92
|
```bash
|
|
93
93
|
paimon --mode read # 以更谨慎的权限模式启动(默认为 yolo)
|
|
94
|
-
paimon --strict #
|
|
94
|
+
paimon --strict # 不再放行只读命令
|
|
95
95
|
paimon --no-web-search # 本次运行不提供网页搜索工具
|
|
96
96
|
paimon --web # 在浏览器中使用同一套 UI(--port,默认 8000)
|
|
97
97
|
paimon -p "what does cli.py do?" # 直接在 stdout 输出回答,不启动 UI
|
|
98
98
|
cat log.txt | paimon -p "summarize this"
|
|
99
99
|
paimon --model zai:glm-4.7 # 仅本次运行使用该模型
|
|
100
|
-
paimon --profile work # 单独配置的另一个账号
|
|
101
100
|
```
|
|
102
101
|
|
|
103
102
|
`-p` 不会停下来询问,配合默认的 `yolo` 模式,它已经可以修改文件和执行命令。加 `--output-format result` 会输出一个包含结果的 JSON 对象,调用方程序读这个就够了。其余选项见 `paimon --help`。
|
|
104
103
|
|
|
104
|
+
### 调试 Textual UI
|
|
105
|
+
|
|
106
|
+
需要让 Paimon 排查自己的布局或样式时,用 `paimon --textual-debug` 启动(也可与 `--web` 一起使用)。默认不启用;开启后模型会多出五个只作用于当前 UI 进程的工具:
|
|
107
|
+
|
|
108
|
+
- `textual_inspect`:按 CSS selector 查看 DOM、geometry、pseudo-classes、焦点和 computed CSS;
|
|
109
|
+
- `textual_eval` / `textual_exec`:在 UI 进程里运行 Python,支持 private API、持久变量和 top-level `await`;
|
|
110
|
+
- `textual_apply_css`:动态叠加 CSS 并立即重新布局;
|
|
111
|
+
- `textual_screenshot`:把当前渲染结果导出成 SVG。
|
|
112
|
+
|
|
113
|
+
例如可以直接让它“检查 `#prompt` 为什么比预期窄,动态试一个修复并截图”。`textual_exec` 有意提供完整的进程内 Python 能力,能修改任意 Textual/Paimon 状态;这个选项只适合开发调试,不应对不受信任的 prompt 开启。动态修改只保留到进程退出,确定修复后仍需让 Paimon编辑源码。
|
|
114
|
+
|
|
105
115
|
## 配置
|
|
106
116
|
|
|
107
|
-
|
|
117
|
+
模型设置保存在 `~/.config/paimon/config.json`,由首次启动或 `paimon login` 写入。每个 provider 各自保存凭据,用 `paimon model provider:name` 或命令面板里的 Switch model 选择要用的模型。也可以用 ChatGPT 订阅代替 API key,`paimon login chatgpt` 会通过浏览器登录。会话存放在 `~/.local/share/paimon/sessions/`。
|
|
108
118
|
|
|
109
|
-
read 和
|
|
119
|
+
read 和 auto 模式会直接执行一小组明确只读的命令(`ls`、`cat`、`git status` 等),`--strict` 可以关掉,Windows 上命令由 cmd.exe 执行,一条也不识别。read 模式拒绝其余所有操作。auto 模式把它们交给审批模型,它能看到你的消息和 agent 的工具调用,看不到 agent 的推理和工具输出,只回答放行或拦截。审批模型不可用或者连续拦截三次时改为询问你,`-p` 下则直接拒绝。当前的模型默认用同一家里快速档的那个来审批(GPT 用 Luna,Claude 用 Haiku,GLM 用 Flash),其余模型自己审自己,在配置里写 `"review_model": "provider:name"` 可以自行指定。**这些都是防止 agent 失误的护栏,不是安全边界。** 需要真正的隔离时,请在容器或虚拟机中运行 Paimon。
|
|
110
120
|
|
|
111
121
|
## 架构
|
|
112
122
|
|
|
113
|
-
`Agent.run` 产出一串与 UI 无关的事件流,TUI、`--web` 和无头模式都是这条事件流的渲染器。agent 自己持有它启动的子 agent 和后台命令。子 agent 是同一进程里作为任务运行的另一个 `Agent`,它的结果会作为一条消息送回父 agent
|
|
123
|
+
`Agent.run` 产出一串与 UI 无关的事件流,TUI、`--web` 和无头模式都是这条事件流的渲染器。agent 自己持有它启动的子 agent 和后台命令。子 agent 是同一进程里作为任务运行的另一个 `Agent`,它的结果会作为一条消息送回父 agent。想把 job 显示出来的 UI 挂上 `Agent.open_job` 即可,TUI 就是这样给每个 job 开 pane 的。
|
|
114
124
|
|
|
115
125
|
```mermaid
|
|
116
126
|
flowchart TD
|
|
117
127
|
subgraph entry["入口"]
|
|
118
128
|
CLI["cli.py"]
|
|
119
|
-
Commands["commands.py<br/>status / login / sessions"]
|
|
129
|
+
Commands["commands.py<br/>status / login / model / sessions"]
|
|
120
130
|
Headless["headless.py<br/>-p,单次运行"]
|
|
121
131
|
App["app.py<br/>Textual TUI / --web"]
|
|
122
132
|
end
|
|
123
133
|
|
|
124
134
|
subgraph tui["TUI 组件"]
|
|
125
135
|
Pane["pane.py<br/>SessionPane"]
|
|
136
|
+
AgentPane["agentpane.py<br/>子 agent pane"]
|
|
126
137
|
CommandPane["commandpane.py<br/>后台命令 pane"]
|
|
138
|
+
Transcript["transcript.py<br/>对话记录与事件渲染"]
|
|
127
139
|
Tabs["tabs.py<br/>pane 标签栏"]
|
|
128
|
-
Login["login.py<br/>provider /
|
|
140
|
+
Login["login.py<br/>provider / key"]
|
|
129
141
|
UIWidgets["ui.py<br/>输入框、确认面板"]
|
|
130
142
|
Diff["diff.py<br/>并排 diff 渲染"]
|
|
131
143
|
end
|
|
@@ -137,14 +149,13 @@ flowchart TD
|
|
|
137
149
|
ToolsMod["tools.py<br/>工具注册表"]
|
|
138
150
|
SessionMod["session.py<br/>JSONL 持久化"]
|
|
139
151
|
Compaction["compaction.py"]
|
|
140
|
-
ModelWindows["model_windows.py<br/>各模型上下文窗口大小"]
|
|
141
152
|
Retry["retry.py"]
|
|
142
153
|
Mentions["mentions.py<br/>@path 展开"]
|
|
143
154
|
Jobs["turns.py<br/>回合驱动"]
|
|
144
155
|
end
|
|
145
156
|
|
|
146
157
|
subgraph support["配置与 skills"]
|
|
147
|
-
Config["config.py<br
|
|
158
|
+
Config["config.py<br/>设置、凭证"]
|
|
148
159
|
Skills["skills.py<br/>Agent Skills 发现"]
|
|
149
160
|
end
|
|
150
161
|
|
|
@@ -157,6 +168,7 @@ flowchart TD
|
|
|
157
168
|
Headless --> Mentions
|
|
158
169
|
|
|
159
170
|
App --> Pane
|
|
171
|
+
App --> AgentPane
|
|
160
172
|
App --> CommandPane
|
|
161
173
|
App --> Tabs
|
|
162
174
|
App --> Login
|
|
@@ -165,9 +177,13 @@ flowchart TD
|
|
|
165
177
|
Pane --> Jobs
|
|
166
178
|
Pane --> AgentLoop
|
|
167
179
|
Pane --> Diff
|
|
180
|
+
Pane --> Transcript
|
|
168
181
|
Pane --> UIWidgets
|
|
169
182
|
Pane --> LLM
|
|
183
|
+
AgentPane --> Pane
|
|
184
|
+
AgentPane --> Transcript
|
|
170
185
|
CommandPane --> Pane
|
|
186
|
+
Transcript --> UIWidgets
|
|
171
187
|
UIWidgets --> Diff
|
|
172
188
|
|
|
173
189
|
AgentLoop --> LLM
|
|
@@ -178,10 +194,10 @@ flowchart TD
|
|
|
178
194
|
AgentLoop --> Retry
|
|
179
195
|
AgentLoop --> Mentions
|
|
180
196
|
AgentLoop -. "spawn_agent" .-> AgentLoop
|
|
197
|
+
AgentLoop -. "spawn_agent" .-> AgentPane
|
|
181
198
|
AgentLoop -. "run_background" .-> CommandPane
|
|
182
199
|
|
|
183
200
|
PromptMod --> Skills
|
|
184
|
-
Compaction --> ModelWindows
|
|
185
201
|
|
|
186
202
|
Jobs --> AgentLoop
|
|
187
203
|
|