paimon 0.2.5__tar.gz → 0.2.7__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. {paimon-0.2.5/paimon.egg-info → paimon-0.2.7}/PKG-INFO +97 -8
  2. {paimon-0.2.5 → paimon-0.2.7}/README.md +94 -6
  3. {paimon-0.2.5 → paimon-0.2.7}/README.zh-CN.md +92 -6
  4. paimon-0.2.7/paimon/_grep_worker.py +16 -0
  5. {paimon-0.2.5 → paimon-0.2.7}/paimon/agent.py +490 -117
  6. {paimon-0.2.5 → paimon-0.2.7}/paimon/app.py +112 -124
  7. {paimon-0.2.5 → paimon-0.2.7}/paimon/app.tcss +16 -5
  8. {paimon-0.2.5 → paimon-0.2.7}/paimon/cli.py +34 -12
  9. {paimon-0.2.5 → paimon-0.2.7}/paimon/commandpane.py +37 -33
  10. {paimon-0.2.5 → paimon-0.2.7}/paimon/compaction.py +5 -16
  11. {paimon-0.2.5 → paimon-0.2.7}/paimon/config.py +3 -7
  12. {paimon-0.2.5 → paimon-0.2.7}/paimon/diff.py +1 -1
  13. {paimon-0.2.5 → paimon-0.2.7}/paimon/headless.py +42 -16
  14. paimon-0.2.7/paimon/herdr.py +145 -0
  15. {paimon-0.2.5 → paimon-0.2.7}/paimon/llm.py +24 -2
  16. {paimon-0.2.5 → paimon-0.2.7}/paimon/lockfile.py +39 -3
  17. {paimon-0.2.5 → paimon-0.2.7}/paimon/pane.py +345 -138
  18. {paimon-0.2.5 → paimon-0.2.7}/paimon/prompt.py +56 -29
  19. {paimon-0.2.5 → paimon-0.2.7}/paimon/session.py +49 -31
  20. {paimon-0.2.5 → paimon-0.2.7}/paimon/skill/SKILL.md +5 -2
  21. {paimon-0.2.5 → paimon-0.2.7}/paimon/tools.py +286 -203
  22. paimon-0.2.7/paimon/turns.py +198 -0
  23. {paimon-0.2.5 → paimon-0.2.7}/paimon/ui.py +128 -10
  24. paimon-0.2.7/paimon/websearch.py +126 -0
  25. {paimon-0.2.5 → paimon-0.2.7/paimon.egg-info}/PKG-INFO +97 -8
  26. {paimon-0.2.5 → paimon-0.2.7}/paimon.egg-info/SOURCES.txt +4 -4
  27. {paimon-0.2.5 → paimon-0.2.7}/paimon.egg-info/requires.txt +2 -1
  28. {paimon-0.2.5 → paimon-0.2.7}/paimon.egg-info/scm_file_list.json +27 -9
  29. paimon-0.2.7/paimon.egg-info/scm_version.json +8 -0
  30. {paimon-0.2.5 → paimon-0.2.7}/pyproject.toml +2 -1
  31. paimon-0.2.5/paimon/agents.py +0 -259
  32. paimon-0.2.5/paimon/aside.py +0 -165
  33. paimon-0.2.5/paimon/jobs.py +0 -454
  34. paimon-0.2.5/paimon/supervisor.py +0 -425
  35. paimon-0.2.5/paimon.egg-info/scm_version.json +0 -8
  36. {paimon-0.2.5 → paimon-0.2.7}/LICENSE +0 -0
  37. {paimon-0.2.5 → paimon-0.2.7}/MANIFEST.in +0 -0
  38. {paimon-0.2.5 → paimon-0.2.7}/paimon/__init__.py +0 -0
  39. {paimon-0.2.5 → paimon-0.2.7}/paimon/__main__.py +0 -0
  40. {paimon-0.2.5 → paimon-0.2.7}/paimon/commands.py +0 -0
  41. {paimon-0.2.5 → paimon-0.2.7}/paimon/errors.py +0 -0
  42. {paimon-0.2.5 → paimon-0.2.7}/paimon/login.py +0 -0
  43. {paimon-0.2.5 → paimon-0.2.7}/paimon/mentions.py +0 -0
  44. {paimon-0.2.5 → paimon-0.2.7}/paimon/model_windows.py +0 -0
  45. {paimon-0.2.5 → paimon-0.2.7}/paimon/retry.py +0 -0
  46. {paimon-0.2.5 → paimon-0.2.7}/paimon/skills.py +0 -0
  47. {paimon-0.2.5 → paimon-0.2.7}/paimon/tabs.py +0 -0
  48. {paimon-0.2.5 → paimon-0.2.7}/paimon/telemetry.py +0 -0
  49. {paimon-0.2.5 → paimon-0.2.7}/paimon.egg-info/dependency_links.txt +0 -0
  50. {paimon-0.2.5 → paimon-0.2.7}/paimon.egg-info/entry_points.txt +0 -0
  51. {paimon-0.2.5 → paimon-0.2.7}/paimon.egg-info/top_level.txt +0 -0
  52. {paimon-0.2.5 → paimon-0.2.7}/setup.cfg +0 -0
@@ -1,15 +1,16 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: paimon
3
- Version: 0.2.5
3
+ Version: 0.2.7
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: pydantic-ai-slim[anthropic,openai]>=2.31.0
9
+ Requires-Dist: pydantic-ai-slim[anthropic,openai]>=2.38.0
10
10
  Requires-Dist: textual>=8.2.7
11
11
  Requires-Dist: textual-serve>=1.1.3
12
12
  Requires-Dist: pyyaml>=6
13
+ Requires-Dist: ddgs>=9
13
14
  Dynamic: license-file
14
15
 
15
16
  # Paimon
@@ -40,9 +41,13 @@ uvx paimon
40
41
 
41
42
  The first launch asks for a provider, model, API base and key. Then just type what you want done. Write `@path/to/file` in a prompt to hand a file to the agent.
42
43
 
43
- While it runs: `Shift+Tab` switches how much the agent may do on its own (**read** asks before writing files or running commands, **edit** lets edits inside the working directory through, **yolo** never asks and is the default), `Esc` interrupts the current turn, `Ctrl+P` opens the command palette, `Ctrl+C` quits.
44
+ While it runs: `Shift+Tab` switches how much the agent may do on its own (**read** asks before writing files or running commands, **edit** lets edits inside the working directory through, **yolo** never asks 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.
44
45
 
45
- `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 open panes itself: ask for two independent things and it starts a second agent in its own tab. It can also leave a command running in a tab of its own, a dev server or a watcher, instead of holding up a turn.
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 the background, whose answer comes back into the conversation when it is done. It can also leave a command running in a tab of its own, a dev server or a watcher, instead of holding up a turn.
47
+
48
+ ## Web search
49
+
50
+ Paimon can search the web without an API key. It asks in no permission mode, because a search changes nothing on your machine. Searches go through [ddgs](https://github.com/deedy5/ddgs), a metasearch library, so a query may be sent to any of several public search engines. `--no-web-search` takes the tool away for a run.
46
51
 
47
52
  ## Skills
48
53
 
@@ -102,6 +107,7 @@ paimon log a1b2c3 # what a session did, one line per event
102
107
  ```bash
103
108
  paimon --mode read # start in a more cautious permission mode (yolo is the default)
104
109
  paimon --strict # ask before every command, even read-only ones
110
+ paimon --no-web-search # take the web search tool away for this run
105
111
  paimon --web # the same UI in a browser (--port, default 8000)
106
112
  paimon -p "what does cli.py do?" # one answer on stdout, no UI
107
113
  cat log.txt | paimon -p "summarize this"
@@ -111,12 +117,95 @@ paimon --profile work # a separately configured account
111
117
 
112
118
  `-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.
113
119
 
114
- ## Configuration
120
+ Inside a [Herdr](https://herdr.dev) pane the UI reports its state and resume command to Herdr on its own, with nothing to install.
115
121
 
116
- Each profile keeps its model settings in `~/.config/paimon/<name>/config.json`, written by the first launch or by `paimon login`. Sessions live in `~/.local/share/paimon/sessions/`. File changes render nicer if [delta](https://github.com/dandavison/delta) is installed.
122
+ ## Configuration
117
123
 
118
- Read and edit modes run a small set of clearly read-only commands (`ls`, `cat`, `git status`, …) without asking; `--strict` turns that off. **This is a guardrail against agent mistakes, not a security boundary.** For real isolation, run Paimon inside a container or VM.
124
+ Each profile keeps its model settings in `~/.config/paimon/<name>/config.json`, written by the first launch or by `paimon login`. Sessions live in `~/.local/share/paimon/sessions/`.
125
+
126
+ Read and edit modes run a small set of clearly read-only commands (`ls`, `cat`, `git status`, …) without asking; `--strict` turns that off. On Windows, where cmd.exe runs the commands, every command asks. **This is a guardrail against agent mistakes, not a security boundary.** For real isolation, run Paimon inside a container or VM.
127
+
128
+ ## Architecture
129
+
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.
131
+
132
+ ```mermaid
133
+ flowchart TD
134
+ subgraph entry["Entry points"]
135
+ CLI["cli.py"]
136
+ Commands["commands.py<br/>status / login / sessions"]
137
+ Headless["headless.py<br/>-p, one-shot"]
138
+ App["app.py<br/>Textual TUI / --web"]
139
+ end
140
+
141
+ subgraph tui["TUI widgets"]
142
+ Pane["pane.py<br/>SessionPane"]
143
+ CommandPane["commandpane.py<br/>background command pane"]
144
+ Tabs["tabs.py<br/>pane strip"]
145
+ Login["login.py<br/>provider / model / key"]
146
+ UIWidgets["ui.py<br/>prompt input, confirmations"]
147
+ Diff["diff.py<br/>side-by-side diff rendering"]
148
+ end
149
+
150
+ subgraph core["Agent loop"]
151
+ AgentLoop["agent.py<br/>Agent.run()"]
152
+ LLM["llm.py<br/>build_model()"]
153
+ PromptMod["prompt.py<br/>system prompt"]
154
+ ToolsMod["tools.py<br/>tool REGISTRY"]
155
+ SessionMod["session.py<br/>JSONL persistence"]
156
+ Compaction["compaction.py"]
157
+ ModelWindows["model_windows.py<br/>context window sizes"]
158
+ Retry["retry.py"]
159
+ Mentions["mentions.py<br/>@path expansion"]
160
+ Jobs["turns.py<br/>turn driver"]
161
+ end
162
+
163
+ subgraph support["Config & skills"]
164
+ Config["config.py<br/>profiles, credentials"]
165
+ Skills["skills.py<br/>Agent Skills discovery"]
166
+ end
167
+
168
+ CLI --> Commands
169
+ CLI --> Headless
170
+ CLI --> App
171
+ CLI --> Config
172
+
173
+ Headless --> AgentLoop
174
+ Headless --> Mentions
175
+
176
+ App --> Pane
177
+ App --> CommandPane
178
+ App --> Tabs
179
+ App --> Login
180
+ App --> Config
181
+
182
+ Pane --> Jobs
183
+ Pane --> AgentLoop
184
+ Pane --> Diff
185
+ Pane --> UIWidgets
186
+ Pane --> LLM
187
+ CommandPane --> Pane
188
+ UIWidgets --> Diff
189
+
190
+ AgentLoop --> LLM
191
+ AgentLoop --> PromptMod
192
+ AgentLoop --> ToolsMod
193
+ AgentLoop --> SessionMod
194
+ AgentLoop --> Compaction
195
+ AgentLoop --> Retry
196
+ AgentLoop --> Mentions
197
+ AgentLoop -. "spawn_agent" .-> AgentLoop
198
+ AgentLoop -. "run_background" .-> CommandPane
199
+
200
+ PromptMod --> Skills
201
+ Compaction --> ModelWindows
202
+
203
+ Jobs --> AgentLoop
204
+
205
+ Skills --> Config
206
+ Config --> LLM
207
+ ```
119
208
 
120
209
  ## Telemetry
121
210
 
122
- Each launch sends one anonymous event to Google Analytics: a random install id, the launch mode, the version, the OS name and the configured provider and model name. Nothing from your sessions, prompts, files or credentials is included. Set `PAIMON_NO_TELEMETRY=1` or `DO_NOT_TRACK=1` to turn it off.
211
+ Each launch sends one anonymous event to Google Analytics: a random install id, the launch mode, the version, the OS name, the language from `LC_ALL`/`LANG`, whether this is the first launch, and the configured provider and model name. Nothing from your sessions, prompts, files or credentials is included. Set `PAIMON_NO_TELEMETRY=1` or `DO_NOT_TRACK=1` to turn it off.
@@ -26,9 +26,13 @@ uvx paimon
26
26
 
27
27
  The first launch asks for a provider, model, API base and key. 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** asks before writing files or running commands, **edit** lets edits inside the working directory through, **yolo** never asks and is the default), `Esc` interrupts the current turn, `Ctrl+P` opens the command palette, `Ctrl+C` quits.
29
+ While it runs: `Shift+Tab` switches how much the agent may do on its own (**read** asks before writing files or running commands, **edit** lets edits inside the working directory through, **yolo** never asks 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 open panes itself: ask for two independent things and it starts a second agent in its own tab. It can also leave a command running in a tab of its own, a dev server or a watcher, instead of holding up a turn.
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 the background, whose answer comes back into the conversation when it is done. It can also leave a command running in a tab of its own, a dev server or a watcher, instead of holding up a turn.
32
+
33
+ ## Web search
34
+
35
+ Paimon can search the web without an API key. It asks in no permission mode, because a search changes nothing on your machine. Searches go through [ddgs](https://github.com/deedy5/ddgs), a metasearch library, so a query may be sent to any of several public search engines. `--no-web-search` takes the tool away for a run.
32
36
 
33
37
  ## Skills
34
38
 
@@ -88,6 +92,7 @@ paimon log a1b2c3 # what a session did, one line per event
88
92
  ```bash
89
93
  paimon --mode read # start in a more cautious permission mode (yolo is the default)
90
94
  paimon --strict # ask before every command, even read-only ones
95
+ paimon --no-web-search # take the web search tool away for this run
91
96
  paimon --web # the same UI in a browser (--port, default 8000)
92
97
  paimon -p "what does cli.py do?" # one answer on stdout, no UI
93
98
  cat log.txt | paimon -p "summarize this"
@@ -97,12 +102,95 @@ paimon --profile work # a separately configured account
97
102
 
98
103
  `-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.
99
104
 
100
- ## Configuration
105
+ Inside a [Herdr](https://herdr.dev) pane the UI reports its state and resume command to Herdr on its own, with nothing to install.
101
106
 
102
- Each profile keeps its model settings in `~/.config/paimon/<name>/config.json`, written by the first launch or by `paimon login`. Sessions live in `~/.local/share/paimon/sessions/`. File changes render nicer if [delta](https://github.com/dandavison/delta) is installed.
107
+ ## Configuration
103
108
 
104
- Read and edit modes run a small set of clearly read-only commands (`ls`, `cat`, `git status`, …) without asking; `--strict` turns that off. **This is a guardrail against agent mistakes, not a security boundary.** For real isolation, run Paimon inside a container or VM.
109
+ Each profile keeps its model settings in `~/.config/paimon/<name>/config.json`, written by the first launch or by `paimon login`. Sessions live in `~/.local/share/paimon/sessions/`.
110
+
111
+ Read and edit modes run a small set of clearly read-only commands (`ls`, `cat`, `git status`, …) without asking; `--strict` turns that off. On Windows, where cmd.exe runs the commands, every command asks. **This is a guardrail against agent mistakes, not a security boundary.** For real isolation, run Paimon inside a container or VM.
112
+
113
+ ## Architecture
114
+
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.
116
+
117
+ ```mermaid
118
+ flowchart TD
119
+ subgraph entry["Entry points"]
120
+ CLI["cli.py"]
121
+ Commands["commands.py<br/>status / login / sessions"]
122
+ Headless["headless.py<br/>-p, one-shot"]
123
+ App["app.py<br/>Textual TUI / --web"]
124
+ end
125
+
126
+ subgraph tui["TUI widgets"]
127
+ Pane["pane.py<br/>SessionPane"]
128
+ CommandPane["commandpane.py<br/>background command pane"]
129
+ Tabs["tabs.py<br/>pane strip"]
130
+ Login["login.py<br/>provider / model / key"]
131
+ UIWidgets["ui.py<br/>prompt input, confirmations"]
132
+ Diff["diff.py<br/>side-by-side diff rendering"]
133
+ end
134
+
135
+ subgraph core["Agent loop"]
136
+ AgentLoop["agent.py<br/>Agent.run()"]
137
+ LLM["llm.py<br/>build_model()"]
138
+ PromptMod["prompt.py<br/>system prompt"]
139
+ ToolsMod["tools.py<br/>tool REGISTRY"]
140
+ SessionMod["session.py<br/>JSONL persistence"]
141
+ Compaction["compaction.py"]
142
+ ModelWindows["model_windows.py<br/>context window sizes"]
143
+ Retry["retry.py"]
144
+ Mentions["mentions.py<br/>@path expansion"]
145
+ Jobs["turns.py<br/>turn driver"]
146
+ end
147
+
148
+ subgraph support["Config & skills"]
149
+ Config["config.py<br/>profiles, credentials"]
150
+ Skills["skills.py<br/>Agent Skills discovery"]
151
+ end
152
+
153
+ CLI --> Commands
154
+ CLI --> Headless
155
+ CLI --> App
156
+ CLI --> Config
157
+
158
+ Headless --> AgentLoop
159
+ Headless --> Mentions
160
+
161
+ App --> Pane
162
+ App --> CommandPane
163
+ App --> Tabs
164
+ App --> Login
165
+ App --> Config
166
+
167
+ Pane --> Jobs
168
+ Pane --> AgentLoop
169
+ Pane --> Diff
170
+ Pane --> UIWidgets
171
+ Pane --> LLM
172
+ CommandPane --> Pane
173
+ UIWidgets --> Diff
174
+
175
+ AgentLoop --> LLM
176
+ AgentLoop --> PromptMod
177
+ AgentLoop --> ToolsMod
178
+ AgentLoop --> SessionMod
179
+ AgentLoop --> Compaction
180
+ AgentLoop --> Retry
181
+ AgentLoop --> Mentions
182
+ AgentLoop -. "spawn_agent" .-> AgentLoop
183
+ AgentLoop -. "run_background" .-> CommandPane
184
+
185
+ PromptMod --> Skills
186
+ Compaction --> ModelWindows
187
+
188
+ Jobs --> AgentLoop
189
+
190
+ Skills --> Config
191
+ Config --> LLM
192
+ ```
105
193
 
106
194
  ## Telemetry
107
195
 
108
- Each launch sends one anonymous event to Google Analytics: a random install id, the launch mode, the version, the OS name and the configured provider and model name. Nothing from your sessions, prompts, files or credentials is included. Set `PAIMON_NO_TELEMETRY=1` or `DO_NOT_TRACK=1` to turn it off.
196
+ Each launch sends one anonymous event to Google Analytics: a random install id, the launch mode, the version, the OS name, the language from `LC_ALL`/`LANG`, whether this is the first launch, and the configured provider and model name. Nothing from your sessions, prompts, files or credentials is included. Set `PAIMON_NO_TELEMETRY=1` or `DO_NOT_TRACK=1` to turn it off.
@@ -26,9 +26,13 @@ uvx paimon
26
26
 
27
27
  首次启动会询问 provider、模型、API base 和 key。之后输入要完成的任务即可。在提示中写 `@path/to/file` 可以把文件提供给 agent。
28
28
 
29
- 运行时:`Shift+Tab` 切换 agent 的自主程度(**read** 写文件或执行命令前先询问,**edit** 放行工作目录内的编辑,**yolo** 从不询问,也是默认值),`Esc` 打断当前回合,`Ctrl+P` 打开命令面板,`Ctrl+C` 退出。
29
+ 运行时:`Shift+Tab` 切换 agent 的自主程度(**read** 写文件或执行命令前先询问,**edit** 放行工作目录内的编辑,**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 自己也能开 pane:让它同时做两件互不相干的事,它会在新 tab 里起第二个 agent。它也能把一条命令留在单独的 tab 里跑,比如开发服务器或者文件监视,不占着当前回合。
31
+ `Ctrl+T` 在新 pane 里打开另一个会话,`Ctrl+W` 关闭当前 pane,`Ctrl+PageUp` 和 `Ctrl+PageDown` 在 pane 之间切换,`Ctrl+G` 跳到正在等待授权的 pane。Paimon 也能并行干活:让它同时做两件互不相干的事,它会在后台起第二个 agent,做完后结果会回到当前会话里。它也能把一条命令留在单独的 tab 里跑,比如开发服务器或者文件监视,不占着当前回合。
32
+
33
+ ## 网页搜索
34
+
35
+ Paimon 可以搜索网页,不需要 API key。任何权限模式下都不会询问,因为搜索不会改动本机的任何东西。搜索通过元搜索库 [ddgs](https://github.com/deedy5/ddgs) 进行,所以一条 query 可能被发往多个公共搜索引擎中的任意一个。`--no-web-search` 可以在本次运行中去掉这个工具。
32
36
 
33
37
  ## Skills
34
38
 
@@ -88,6 +92,7 @@ paimon log a1b2c3 # 查看会话做了什么,每个事件一行
88
92
  ```bash
89
93
  paimon --mode read # 以更谨慎的权限模式启动(默认为 yolo)
90
94
  paimon --strict # 每条命令都先询问,包括只读命令
95
+ paimon --no-web-search # 本次运行不提供网页搜索工具
91
96
  paimon --web # 在浏览器中使用同一套 UI(--port,默认 8000)
92
97
  paimon -p "what does cli.py do?" # 直接在 stdout 输出回答,不启动 UI
93
98
  cat log.txt | paimon -p "summarize this"
@@ -99,10 +104,91 @@ paimon --profile work # 单独配置的另一个账号
99
104
 
100
105
  ## 配置
101
106
 
102
- 每个 profile 的模型设置保存在 `~/.config/paimon/<name>/config.json`,由首次启动或 `paimon login` 写入。会话存放在 `~/.local/share/paimon/sessions/`。安装 [delta](https://github.com/dandavison/delta) 后文件改动的展示效果更好。
103
-
104
- read 和 edit 模式会不经询问执行一小组明确只读的命令(`ls`、`cat`、`git status` 等),`--strict` 可以关掉。**这是防止 agent 失误的护栏,不是安全边界。** 需要真正的隔离时,请在容器或虚拟机中运行 Paimon。
107
+ 每个 profile 的模型设置保存在 `~/.config/paimon/<name>/config.json`,由首次启动或 `paimon login` 写入。会话存放在 `~/.local/share/paimon/sessions/`。
108
+
109
+ read 和 edit 模式会不经询问执行一小组明确只读的命令(`ls`、`cat`、`git status` 等),`--strict` 可以关掉。Windows 上命令由 cmd.exe 执行,每条命令都会询问。**这是防止 agent 失误的护栏,不是安全边界。** 需要真正的隔离时,请在容器或虚拟机中运行 Paimon。
110
+
111
+ ## 架构
112
+
113
+ `Agent.run` 产出一串与 UI 无关的事件流,TUI、`--web` 和无头模式都是这条事件流的渲染器。agent 自己持有它启动的子 agent 和后台命令。子 agent 是同一进程里作为任务运行的另一个 `Agent`,它的结果会作为一条消息送回父 agent。
114
+
115
+ ```mermaid
116
+ flowchart TD
117
+ subgraph entry["入口"]
118
+ CLI["cli.py"]
119
+ Commands["commands.py<br/>status / login / sessions"]
120
+ Headless["headless.py<br/>-p,单次运行"]
121
+ App["app.py<br/>Textual TUI / --web"]
122
+ end
123
+
124
+ subgraph tui["TUI 组件"]
125
+ Pane["pane.py<br/>SessionPane"]
126
+ CommandPane["commandpane.py<br/>后台命令 pane"]
127
+ Tabs["tabs.py<br/>pane 标签栏"]
128
+ Login["login.py<br/>provider / 模型 / key"]
129
+ UIWidgets["ui.py<br/>输入框、确认面板"]
130
+ Diff["diff.py<br/>并排 diff 渲染"]
131
+ end
132
+
133
+ subgraph core["Agent 主循环"]
134
+ AgentLoop["agent.py<br/>Agent.run()"]
135
+ LLM["llm.py<br/>build_model()"]
136
+ PromptMod["prompt.py<br/>system prompt"]
137
+ ToolsMod["tools.py<br/>工具注册表"]
138
+ SessionMod["session.py<br/>JSONL 持久化"]
139
+ Compaction["compaction.py"]
140
+ ModelWindows["model_windows.py<br/>各模型上下文窗口大小"]
141
+ Retry["retry.py"]
142
+ Mentions["mentions.py<br/>@path 展开"]
143
+ Jobs["turns.py<br/>回合驱动"]
144
+ end
145
+
146
+ subgraph support["配置与 skills"]
147
+ Config["config.py<br/>profile、凭证"]
148
+ Skills["skills.py<br/>Agent Skills 发现"]
149
+ end
150
+
151
+ CLI --> Commands
152
+ CLI --> Headless
153
+ CLI --> App
154
+ CLI --> Config
155
+
156
+ Headless --> AgentLoop
157
+ Headless --> Mentions
158
+
159
+ App --> Pane
160
+ App --> CommandPane
161
+ App --> Tabs
162
+ App --> Login
163
+ App --> Config
164
+
165
+ Pane --> Jobs
166
+ Pane --> AgentLoop
167
+ Pane --> Diff
168
+ Pane --> UIWidgets
169
+ Pane --> LLM
170
+ CommandPane --> Pane
171
+ UIWidgets --> Diff
172
+
173
+ AgentLoop --> LLM
174
+ AgentLoop --> PromptMod
175
+ AgentLoop --> ToolsMod
176
+ AgentLoop --> SessionMod
177
+ AgentLoop --> Compaction
178
+ AgentLoop --> Retry
179
+ AgentLoop --> Mentions
180
+ AgentLoop -. "spawn_agent" .-> AgentLoop
181
+ AgentLoop -. "run_background" .-> CommandPane
182
+
183
+ PromptMod --> Skills
184
+ Compaction --> ModelWindows
185
+
186
+ Jobs --> AgentLoop
187
+
188
+ Skills --> Config
189
+ Config --> LLM
190
+ ```
105
191
 
106
192
  ## 遥测
107
193
 
108
- 每次启动会向 Google Analytics 发送一条匿名事件:随机生成的安装 id、启动方式、版本号、操作系统名称,以及配置的 provider 和模型名。会话、提示词、文件和密钥一概不上报。设置 `PAIMON_NO_TELEMETRY=1` 或 `DO_NOT_TRACK=1` 可以关闭。
194
+ 每次启动会向 Google Analytics 发送一条匿名事件:随机生成的安装 id、启动方式、版本号、操作系统名称、取自 `LC_ALL`/`LANG` 的语言、是否首次启动,以及配置的 provider 和模型名。会话、提示词、文件和密钥一概不上报。设置 `PAIMON_NO_TELEMETRY=1` 或 `DO_NOT_TRACK=1` 可以关闭。
@@ -0,0 +1,16 @@
1
+ """Disposable process for bounded, cancellable code searches."""
2
+
3
+ import json
4
+ import sys
5
+ from pathlib import Path
6
+
7
+ from .tools import _grep
8
+
9
+
10
+ def main() -> None:
11
+ args, cwd, sandboxed = json.load(sys.stdin)
12
+ sys.stdout.write(json.dumps(_grep(args, Path(cwd), sandboxed=sandboxed)))
13
+
14
+
15
+ if __name__ == "__main__":
16
+ main()