mini-agent-cli 0.2.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.
@@ -0,0 +1,161 @@
1
+ Metadata-Version: 2.3
2
+ Name: mini-agent-cli
3
+ Version: 0.2.0
4
+ Summary: 终端里的编码 Agent:配置驱动,支持 OpenAI Chat / Responses 与 Anthropic 协议、MCP、Agent Skills
5
+ Keywords: agent,llm,mcp,cli,coding-agent,skills
6
+ Author: zhaomo08
7
+ Classifier: Environment :: Console
8
+ Classifier: Operating System :: MacOS
9
+ Classifier: Operating System :: POSIX :: Linux
10
+ Classifier: Programming Language :: Python :: 3.13
11
+ Classifier: Topic :: Software Development
12
+ Requires-Dist: mcp>=2.1.1
13
+ Requires-Python: >=3.13
14
+ Project-URL: Repository, https://github.com/zhaomo08/mini-agent
15
+ Description-Content-Type: text/markdown
16
+
17
+ # mini-agent
18
+
19
+ 终端里的编码 Agent,面向会写配置的开发者。模型、MCP、权限都写在一个 `mini-agent.json` 里,
20
+ skill 用和 Claude Code / Codex / opencode 相同的 `SKILL.md` 格式。唯一的依赖是 `mcp`。
21
+
22
+ ```
23
+ Agent = LLM + 工具 + 循环
24
+ ```
25
+
26
+ ## 安装
27
+
28
+ 三种方式任选,装完都是 `mini-agent` 命令。需要先有 [uv](https://docs.astral.sh/uv/)(`curl -LsSf https://astral.sh/uv/install.sh | sh` 或 `brew install uv`),它会自动准备 Python 3.13:
29
+
30
+ ```bash
31
+ uv tool install mini-agent-cli # PyPI(包名带 -cli,命令是 mini-agent)
32
+ npm i -g @zhaomo08/mini-agent # npm(启动器,内部用 uvx 跑同版本的 PyPI 包)
33
+ uvx --from mini-agent-cli mini-agent # 不安装,直接跑
34
+ ```
35
+
36
+ 首次运行会把包里的 `mini-agent.example.json` 复制到 `~/.config/mini-agent/mini-agent.json`,改这份就行。
37
+
38
+ 开发时用 `uv tool install -e .`,改代码即时生效。
39
+
40
+ ## 使用
41
+
42
+ ```bash
43
+ mini-agent # 交互模式,在哪个目录启动就在哪干活
44
+ mini-agent -p "这个仓库是干什么的" > out.md # 问一句就退出;stdout 只有答案,思考和工具进度走 stderr
45
+ mini-agent -m bailian-anthropic/qwen3.8-flash
46
+ mini-agent --yes # ask 类操作全部放行(deny 仍然禁止)
47
+ ```
48
+
49
+ | 命令 | 作用 |
50
+ |---|---|
51
+ | `/model [provider/model]` | 查看或切换模型。对话保留,可以跨厂商、跨协议 |
52
+ | `/reload` | 重新读配置、skills、MCP,对话保留 |
53
+ | `/img [路径]` | 挂一张图,不带路径从剪贴板取;也可以直接把图片文件拖进来 |
54
+ | `/clear` `/tools` `/help` | |
55
+ | Ctrl+C | 回答中:打断这一轮(包括审批提示);输入时:清空当前行 |
56
+ | Ctrl+D / `exit` | 退出 |
57
+
58
+ 输出是流式的,思考过程以灰色显示。
59
+
60
+ ## 配置:mini-agent.json
61
+
62
+ 完整带注释的示例见 [mini_agent/mini-agent.example.json](mini_agent/mini-agent.example.json)。
63
+
64
+ | 位置 | 作用 |
65
+ |---|---|
66
+ | `~/.config/mini-agent/mini-agent.json` | 全局(`$MINI_AGENT_CONFIG` 可改) |
67
+ | 项目里的 `mini-agent.json` | 从 git 根目录到当前目录逐层深度合并,越近优先级越高 |
68
+
69
+ ```jsonc
70
+ {
71
+ "model": "deepseek/deepseek-flash",
72
+ "provider": {
73
+ "deepseek": { "api": "openai-chat", "baseURL": "https://api.deepseek.com", "apiKey": "{env:DEEPSEEK_API_KEY}" }
74
+ },
75
+ "mcp": {
76
+ "memory": { "type": "local", "command": ["npx", "-y", "@modelcontextprotocol/server-memory"] },
77
+ "amap": { "type": "remote", "url": "https://mcp.amap.com/mcp?key={env:AMAP_MAPS_API_KEY}" }
78
+ },
79
+ "permission": { "bash": "ask", "edit": "ask", "external": "ask", "mcp": "ask" }
80
+ }
81
+ ```
82
+
83
+ **协议**(`api` 字段),baseURL 的写法和各家 SDK 一致:
84
+
85
+ | api | 请求 | baseURL 示例 |
86
+ |---|---|---|
87
+ | `openai-chat` | `POST {baseURL}/chat/completions` | `https://api.deepseek.com` |
88
+ | `openai-responses` | `POST {baseURL}/responses` | `https://api.openai.com/v1` |
89
+ | `anthropic` | `POST {baseURL}/v1/messages` | `https://api.anthropic.com` |
90
+
91
+ `options` 原样并进请求体(`enable_thinking`、`max_tokens`、`temperature`…),
92
+ `models.<id>.options` 只对某个模型生效。密钥写 `{env:变量名}`;配置文件支持整行 `//` 注释。
93
+
94
+ **让模型改配置**:直接说「加一个 xxx MCP」。内置的 `mini-agent-config` skill 会引导模型
95
+ 用 edit 改文件、校验 JSON,然后你输入 `/reload` 就生效。
96
+
97
+ ## 工具
98
+
99
+ | 工具 | 说明 | 权限类别 |
100
+ |---|---|---|
101
+ | `bash` | 执行命令;awk / sed / jq 都走它 | `bash` |
102
+ | `read` | 带行号,默认 2000 行,`offset` 分段 | 工作目录外归 `external` |
103
+ | `write` / `edit` | 整体写入 / 精确字符串替换,确认时显示 diff | `edit` |
104
+ | `grep` | 有 ripgrep 就用 ripgrep,没有就用 grep -rn | 工作目录外归 `external` |
105
+ | `glob` | 按通配符找文件,最近修改的在前 | 工作目录外归 `external` |
106
+ | `skill` | 按需读取 skill 正文 | — |
107
+ | MCP 工具 | 名字以 create / delete / send / run … 开头的 | `mcp` |
108
+
109
+ 权限:`ask` 先问,`allow` 直接放行,`deny` 禁止。非交互模式(管道或 `-p`)下没加 `--yes` 时,ask 一律按拒绝处理。
110
+
111
+ ## Skills
112
+
113
+ 一个目录加一个 `SKILL.md`(frontmatter 写 `name`、`description`),脚本和参考资料放在同一目录,
114
+ 正文里让模型用 bash / read 去调用。启动时只把描述放进 system prompt,正文由模型按需读取。
115
+
116
+ 查找顺序,同名的先找到先用:
117
+
118
+ 1. 项目:从当前目录往上到 git 根目录,每层的 `.agents/skills`、`.claude/skills`、`.opencode/skills`
119
+ 2. 全局:`~/.config/mini-agent/skills`、`~/.agents/skills`、`~/.claude/skills`、`~/.config/opencode/skills`
120
+ 3. 内置:`mini_agent/skills/`
121
+
122
+ ## 中途换模型
123
+
124
+ 参考 pi-ai 的 cross-provider handoff 设计。历史用中立格式保存,每条 assistant 消息都记着它是由哪个协议、哪个模型产生的:
125
+
126
+ - **同一个模型产生的**:原样回放协议原文,thinking 签名、加密 reasoning 都不会丢
127
+ - **其他模型产生的**:只用中立字段重建。thinking 转成 `<thinking>` 文本,签名丢弃,
128
+ 工具调用 id 规范成 `[A-Za-z0-9_-]{1,64}`(Anthropic 的要求)
129
+ - **中断后留下的"有调用没结果"的工具调用**:补一条占位结果,保证每家接口都接受这段历史
130
+
131
+ ## 上下文预算
132
+
133
+ - 工具结果超过 3 万字符就截断
134
+ - 只有最新一条消息保留图片
135
+ - 历史超过 40 万字符,就从最旧的一轮开始整轮丢弃
136
+
137
+ ## 代码
138
+
139
+ ```
140
+ mini_agent/
141
+ __main__.py 命令行 / REPL agent.py 装配、权限、循环、上下文预算
142
+ config.py 配置加载与合并 llm.py 三种协议,标准库 urllib
143
+ tools.py 内置工具 mcp.py MCP 连接
144
+ skills.py skill 发现与加载 images.py 剪贴板 / 文件 → 多模态
145
+ test_agent.py 不调模型的自检:uv run python test_agent.py
146
+ ```
147
+
148
+ 排查用:`uv run python -m mini_agent.mcp`、`uv run python -m mini_agent.skills`。
149
+
150
+ 早期的教学版(step1–3、extras/)在 git 历史里:`git show c619ecb`。
151
+
152
+ ## 发布
153
+
154
+ 版本号要在三个地方保持一致:`pyproject.toml`、`npm/package.json` 和 git tag。推送 tag 后,由
155
+ `.github/workflows/release.yml` 依次完成:检查版本号 → 自检 → 验证 wheel 能装 → 发布 PyPI → 发布 npm。
156
+ 两边都用 Trusted Publishing(OIDC),仓库里不存任何 token。
157
+
158
+ ```bash
159
+ # 改好两处 version 之后
160
+ git tag v0.2.1 && git push origin v0.2.1
161
+ ```
@@ -0,0 +1,145 @@
1
+ # mini-agent
2
+
3
+ 终端里的编码 Agent,面向会写配置的开发者。模型、MCP、权限都写在一个 `mini-agent.json` 里,
4
+ skill 用和 Claude Code / Codex / opencode 相同的 `SKILL.md` 格式。唯一的依赖是 `mcp`。
5
+
6
+ ```
7
+ Agent = LLM + 工具 + 循环
8
+ ```
9
+
10
+ ## 安装
11
+
12
+ 三种方式任选,装完都是 `mini-agent` 命令。需要先有 [uv](https://docs.astral.sh/uv/)(`curl -LsSf https://astral.sh/uv/install.sh | sh` 或 `brew install uv`),它会自动准备 Python 3.13:
13
+
14
+ ```bash
15
+ uv tool install mini-agent-cli # PyPI(包名带 -cli,命令是 mini-agent)
16
+ npm i -g @zhaomo08/mini-agent # npm(启动器,内部用 uvx 跑同版本的 PyPI 包)
17
+ uvx --from mini-agent-cli mini-agent # 不安装,直接跑
18
+ ```
19
+
20
+ 首次运行会把包里的 `mini-agent.example.json` 复制到 `~/.config/mini-agent/mini-agent.json`,改这份就行。
21
+
22
+ 开发时用 `uv tool install -e .`,改代码即时生效。
23
+
24
+ ## 使用
25
+
26
+ ```bash
27
+ mini-agent # 交互模式,在哪个目录启动就在哪干活
28
+ mini-agent -p "这个仓库是干什么的" > out.md # 问一句就退出;stdout 只有答案,思考和工具进度走 stderr
29
+ mini-agent -m bailian-anthropic/qwen3.8-flash
30
+ mini-agent --yes # ask 类操作全部放行(deny 仍然禁止)
31
+ ```
32
+
33
+ | 命令 | 作用 |
34
+ |---|---|
35
+ | `/model [provider/model]` | 查看或切换模型。对话保留,可以跨厂商、跨协议 |
36
+ | `/reload` | 重新读配置、skills、MCP,对话保留 |
37
+ | `/img [路径]` | 挂一张图,不带路径从剪贴板取;也可以直接把图片文件拖进来 |
38
+ | `/clear` `/tools` `/help` | |
39
+ | Ctrl+C | 回答中:打断这一轮(包括审批提示);输入时:清空当前行 |
40
+ | Ctrl+D / `exit` | 退出 |
41
+
42
+ 输出是流式的,思考过程以灰色显示。
43
+
44
+ ## 配置:mini-agent.json
45
+
46
+ 完整带注释的示例见 [mini_agent/mini-agent.example.json](mini_agent/mini-agent.example.json)。
47
+
48
+ | 位置 | 作用 |
49
+ |---|---|
50
+ | `~/.config/mini-agent/mini-agent.json` | 全局(`$MINI_AGENT_CONFIG` 可改) |
51
+ | 项目里的 `mini-agent.json` | 从 git 根目录到当前目录逐层深度合并,越近优先级越高 |
52
+
53
+ ```jsonc
54
+ {
55
+ "model": "deepseek/deepseek-flash",
56
+ "provider": {
57
+ "deepseek": { "api": "openai-chat", "baseURL": "https://api.deepseek.com", "apiKey": "{env:DEEPSEEK_API_KEY}" }
58
+ },
59
+ "mcp": {
60
+ "memory": { "type": "local", "command": ["npx", "-y", "@modelcontextprotocol/server-memory"] },
61
+ "amap": { "type": "remote", "url": "https://mcp.amap.com/mcp?key={env:AMAP_MAPS_API_KEY}" }
62
+ },
63
+ "permission": { "bash": "ask", "edit": "ask", "external": "ask", "mcp": "ask" }
64
+ }
65
+ ```
66
+
67
+ **协议**(`api` 字段),baseURL 的写法和各家 SDK 一致:
68
+
69
+ | api | 请求 | baseURL 示例 |
70
+ |---|---|---|
71
+ | `openai-chat` | `POST {baseURL}/chat/completions` | `https://api.deepseek.com` |
72
+ | `openai-responses` | `POST {baseURL}/responses` | `https://api.openai.com/v1` |
73
+ | `anthropic` | `POST {baseURL}/v1/messages` | `https://api.anthropic.com` |
74
+
75
+ `options` 原样并进请求体(`enable_thinking`、`max_tokens`、`temperature`…),
76
+ `models.<id>.options` 只对某个模型生效。密钥写 `{env:变量名}`;配置文件支持整行 `//` 注释。
77
+
78
+ **让模型改配置**:直接说「加一个 xxx MCP」。内置的 `mini-agent-config` skill 会引导模型
79
+ 用 edit 改文件、校验 JSON,然后你输入 `/reload` 就生效。
80
+
81
+ ## 工具
82
+
83
+ | 工具 | 说明 | 权限类别 |
84
+ |---|---|---|
85
+ | `bash` | 执行命令;awk / sed / jq 都走它 | `bash` |
86
+ | `read` | 带行号,默认 2000 行,`offset` 分段 | 工作目录外归 `external` |
87
+ | `write` / `edit` | 整体写入 / 精确字符串替换,确认时显示 diff | `edit` |
88
+ | `grep` | 有 ripgrep 就用 ripgrep,没有就用 grep -rn | 工作目录外归 `external` |
89
+ | `glob` | 按通配符找文件,最近修改的在前 | 工作目录外归 `external` |
90
+ | `skill` | 按需读取 skill 正文 | — |
91
+ | MCP 工具 | 名字以 create / delete / send / run … 开头的 | `mcp` |
92
+
93
+ 权限:`ask` 先问,`allow` 直接放行,`deny` 禁止。非交互模式(管道或 `-p`)下没加 `--yes` 时,ask 一律按拒绝处理。
94
+
95
+ ## Skills
96
+
97
+ 一个目录加一个 `SKILL.md`(frontmatter 写 `name`、`description`),脚本和参考资料放在同一目录,
98
+ 正文里让模型用 bash / read 去调用。启动时只把描述放进 system prompt,正文由模型按需读取。
99
+
100
+ 查找顺序,同名的先找到先用:
101
+
102
+ 1. 项目:从当前目录往上到 git 根目录,每层的 `.agents/skills`、`.claude/skills`、`.opencode/skills`
103
+ 2. 全局:`~/.config/mini-agent/skills`、`~/.agents/skills`、`~/.claude/skills`、`~/.config/opencode/skills`
104
+ 3. 内置:`mini_agent/skills/`
105
+
106
+ ## 中途换模型
107
+
108
+ 参考 pi-ai 的 cross-provider handoff 设计。历史用中立格式保存,每条 assistant 消息都记着它是由哪个协议、哪个模型产生的:
109
+
110
+ - **同一个模型产生的**:原样回放协议原文,thinking 签名、加密 reasoning 都不会丢
111
+ - **其他模型产生的**:只用中立字段重建。thinking 转成 `<thinking>` 文本,签名丢弃,
112
+ 工具调用 id 规范成 `[A-Za-z0-9_-]{1,64}`(Anthropic 的要求)
113
+ - **中断后留下的"有调用没结果"的工具调用**:补一条占位结果,保证每家接口都接受这段历史
114
+
115
+ ## 上下文预算
116
+
117
+ - 工具结果超过 3 万字符就截断
118
+ - 只有最新一条消息保留图片
119
+ - 历史超过 40 万字符,就从最旧的一轮开始整轮丢弃
120
+
121
+ ## 代码
122
+
123
+ ```
124
+ mini_agent/
125
+ __main__.py 命令行 / REPL agent.py 装配、权限、循环、上下文预算
126
+ config.py 配置加载与合并 llm.py 三种协议,标准库 urllib
127
+ tools.py 内置工具 mcp.py MCP 连接
128
+ skills.py skill 发现与加载 images.py 剪贴板 / 文件 → 多模态
129
+ test_agent.py 不调模型的自检:uv run python test_agent.py
130
+ ```
131
+
132
+ 排查用:`uv run python -m mini_agent.mcp`、`uv run python -m mini_agent.skills`。
133
+
134
+ 早期的教学版(step1–3、extras/)在 git 历史里:`git show c619ecb`。
135
+
136
+ ## 发布
137
+
138
+ 版本号要在三个地方保持一致:`pyproject.toml`、`npm/package.json` 和 git tag。推送 tag 后,由
139
+ `.github/workflows/release.yml` 依次完成:检查版本号 → 自检 → 验证 wheel 能装 → 发布 PyPI → 发布 npm。
140
+ 两边都用 Trusted Publishing(OIDC),仓库里不存任何 token。
141
+
142
+ ```bash
143
+ # 改好两处 version 之后
144
+ git tag v0.2.1 && git push origin v0.2.1
145
+ ```
@@ -0,0 +1,11 @@
1
+ """mini-agent:终端里的编码 Agent。
2
+
3
+ config.py 读 mini-agent.json(全局 + 项目,深度合并)
4
+ llm.py 三种协议:openai-chat / openai-responses / anthropic
5
+ tools.py 内置工具:bash read write edit grep glob
6
+ mcp.py mcp 段 -> 连 MCP server
7
+ skills.py Agent Skills(SKILL.md)发现与加载
8
+ images.py 剪贴板 / 文件里的图 -> 多模态 content
9
+ agent.py 装配、权限、循环、上下文预算
10
+ __main__.py 命令行入口
11
+ """
@@ -0,0 +1,172 @@
1
+ """命令行入口。
2
+
3
+ mini-agent 交互模式
4
+ mini-agent -p "帮我看下这个仓库" 问一句就退出,适合脚本 / 管道
5
+ mini-agent -m bailian/qwen3.8-plus 换模型(<provider>/<model>,provider 来自配置)
6
+ mini-agent --yes ask 类操作全部放行(deny 仍然禁止)
7
+ """
8
+
9
+ import argparse
10
+ import asyncio
11
+ import readline # noqa: F401 让 input() 支持方向键和历史
12
+ import signal
13
+ import sys
14
+ from contextlib import AsyncExitStack
15
+ from importlib.metadata import version
16
+
17
+ from .agent import Agent
18
+ from .config import load
19
+ from .images import grab_clipboard, looks_like_image
20
+ from .llm import make_llm
21
+
22
+ HELP = """/img [路径] 挂一张图(不带路径从剪贴板取;也可以直接把图片文件拖进来)
23
+ /model [p/m] 看或切换模型(对话保留,可以跨厂商、跨协议)
24
+ /reload 重新读配置、skills、MCP(对话保留)
25
+ Ctrl+C 回答中:打断这一轮;输入时:清空当前行
26
+ Ctrl+D 退出
27
+ /clear 清空对话
28
+ /tools 看工具清单
29
+ exit 退出"""
30
+
31
+
32
+ def switch_model(agent, ref):
33
+ try:
34
+ llm = make_llm(agent.config, ref)
35
+ except SystemExit as error:
36
+ print(f" {error}")
37
+ return
38
+ # 历史是中立格式:别家模型的回复会被重建成新协议能接受的样子(见 llm.py 开头)
39
+ agent.llm = llm
40
+ print(f" 已切换到 {llm.ref}({llm.api})")
41
+
42
+
43
+ class Turn:
44
+ """Ctrl+C 的去向:回答进行中就取消这一轮,否则按默认行为抛 KeyboardInterrupt。"""
45
+ task = agent = None
46
+
47
+ @classmethod
48
+ def on_sigint(cls, signum, frame):
49
+ if cls.task and not cls.task.done() and not (cls.agent and cls.agent.prompting):
50
+ cls.task.get_loop().call_soon_threadsafe(cls.task.cancel)
51
+ return
52
+ raise KeyboardInterrupt
53
+
54
+ @classmethod
55
+ async def run(cls, coroutine):
56
+ cls.task = asyncio.ensure_future(coroutine)
57
+ try:
58
+ return await cls.task
59
+ finally:
60
+ cls.task = None
61
+
62
+
63
+ async def repl(agent):
64
+ """返回 "reload" 表示要重新装配,其余情况就是退出。"""
65
+ pending = []
66
+ while True:
67
+ # 输入在主线程里同步读:Ctrl+C 直接打断 input(),不会有卡在 stdin 上的后台线程
68
+ try:
69
+ line = input(f"\n❯ {f'[{len(pending)}图] ' if pending else ''}").strip()
70
+ except KeyboardInterrupt:
71
+ continue
72
+ except EOFError:
73
+ print()
74
+ return None
75
+ if not line:
76
+ continue
77
+ command, _, argument = line.partition(" ")
78
+ argument = argument.strip()
79
+ if line in ("exit", "quit", "/exit"):
80
+ return None
81
+ if command == "/help":
82
+ print(HELP)
83
+ continue
84
+ if command == "/reload":
85
+ return "reload"
86
+ if command == "/clear":
87
+ agent.reset()
88
+ pending = []
89
+ print(" 已清空。")
90
+ continue
91
+ if command == "/tools":
92
+ print(agent.report())
93
+ continue
94
+ if command == "/model":
95
+ if argument:
96
+ switch_model(agent, argument)
97
+ else:
98
+ print(f" 当前 {agent.llm.ref};provider:{'、'.join(agent.config.get('provider', {}))}")
99
+ continue
100
+
101
+ # 绝对路径也是 / 开头,先认图片路径再认命令
102
+ image = looks_like_image(line)
103
+ if not image and command == "/img":
104
+ image = looks_like_image(argument) if argument else grab_clipboard()
105
+ if not image:
106
+ print(" 没取到图片。")
107
+ continue
108
+ if image:
109
+ pending.append(image)
110
+ print(f" 已挂上 {image.name},接着把问题打出来。")
111
+ continue
112
+
113
+ try:
114
+ await Turn.run(agent.ask(line, pending))
115
+ except asyncio.CancelledError:
116
+ print(" 已中断。", file=sys.stderr)
117
+ except Exception as error:
118
+ print(f"\n 请求失败:{type(error).__name__}: {error}", file=sys.stderr)
119
+ finally:
120
+ pending = []
121
+
122
+
123
+ async def run(args):
124
+ signal.signal(signal.SIGINT, Turn.on_sigint)
125
+ config, sources = load()
126
+ agent = Turn.agent = Agent(config, make_llm(config, args.model), auto_yes=args.yes)
127
+ failure = None
128
+ while True:
129
+ async with AsyncExitStack() as stack:
130
+ await agent.build(stack)
131
+ if args.prompt:
132
+ try:
133
+ await Turn.run(agent.ask(args.prompt)) # 正文已经流式打到 stdout
134
+ except asyncio.CancelledError:
135
+ failure = "已中断"
136
+ except Exception as error:
137
+ # 不能在这里 raise:MCP 的 TaskGroup 会把它包成一大坨异常组
138
+ failure = f"请求失败:{type(error).__name__}: {error}"
139
+ break
140
+ print("配置 " + "、".join(map(str, sources)))
141
+ print(agent.report())
142
+ print("\n/help 看命令,exit 退出。")
143
+ action = await repl(agent)
144
+ if action != "reload":
145
+ break
146
+ try:
147
+ config, sources = load()
148
+ except SystemExit as error:
149
+ print(f" {error}\n 沿用旧配置。")
150
+ continue
151
+ agent.config, agent.permission = config, config.get("permission") or {}
152
+ # 当前模型在新配置里还在就沿用,否则回到配置里的默认模型
153
+ name = agent.llm.ref.partition("/")[0]
154
+ switch_model(agent, agent.llm.ref if name in config.get("provider", {}) else None)
155
+ if failure:
156
+ raise SystemExit(failure)
157
+
158
+
159
+ def main():
160
+ parser = argparse.ArgumentParser(prog="mini-agent", description="终端里的编码 Agent")
161
+ parser.add_argument("-p", "--prompt", help="问一句就退出")
162
+ parser.add_argument("-m", "--model", help="<provider>/<model>,默认用配置里的 model")
163
+ parser.add_argument("-y", "--yes", action="store_true", help="ask 类操作全部放行")
164
+ parser.add_argument("-V", "--version", action="version", version=f"mini-agent {version('mini-agent-cli')}")
165
+ try:
166
+ asyncio.run(run(parser.parse_args()))
167
+ except KeyboardInterrupt:
168
+ pass
169
+
170
+
171
+ if __name__ == "__main__":
172
+ main()