Skip to content

Features zh

Dev edited this page Sep 7, 2026 · 2 revisions

English · 中文

特性总览

对应 v0.12.0(3a762b1)。按领域梳理 nanopi 实际实现了什么。 安装步骤和完整的 CLI 参数表见 README。

nanopi 是 Pi 的 Rust 精简移植——一个编码 agent,产物是单个静态 musl 二进制,无运行时依赖。


模型接入

两套协议。 原生 Anthropic adapter,以及任意 OpenAI 兼容端点。Provider 抽象在 v0.6 落地。

Vendor 分发。 根据 base URL 和 model id 嗅探,为 anthropic、openai、deepseek、minimax、qwen、xiaomi、zai 各自适配,外加一个通用兜底。显式设置 api_kind 会覆盖嗅探结果——在网关让端点"看起来像别的东西"时需要它。

流式。 手写的 SSE 解析器,没用 reqwest-eventsource,为的是压住依赖树。

重试信封。 对 5xx、429 和瞬时错误做带 jitter 的指数退避,各 provider 统一。

思考级别。 模型支持时可配置 extended thinking 预算。


会话

会话是 JSONL 追加写——选它是因为写到一半崩溃时文件仍然可用,而单个 JSON 文档做不到。

能力 方式
恢复最近会话 --continue
按 id 恢复 --session <id>
调用方指定 id --session-id
从某点分叉 --fork <id>,或 TUI 里 Esc-Esc 选一条历史用户消息
回放整个记录 /resume 把会话重新渲染进 scrollback
导出 /export 默认输出完整 HTML(按扩展名也可 JSONL)
导入 /import 读回 JSONL 会话

压缩。 基于 token 阈值的自动压缩会用 LLM 总结较早的上下文;/compact 手动触发。两条路径都会发出 session_before_compact 和 session_compact 钩子,matcher 匹配的是原因字符串(threshold 或 manual)。

分叉选择器会沿父链向上走,所以早先创建的分支不会被最新的挡住而消失。


内置工具

七个,全部本地:read、write、edit、bash、grep、find、ls。

工具调用默认并行;tool_exec_mode = "sequential" 可切换为串行。

工具注册表会归一化被网关改写过的工具名。


交互

TUI(stdin 是 TTY 时的默认模式)基于 ratatui,采用内联视口,保留终端 scrollback 而不是整屏接管。

  • 多行编辑器 + Emacs 键位;Ctrl+J 换行
  • fish 风格的按词合并撤销
  • Markdown 渲染;Ctrl+O 展开最后一次工具输出
  • 统一工具卡片——命令、输出、耗时在同一块内
  • 三行状态栏,含上下文占比
  • 工具专属的 spinner 文案和实时在途工具条
  • Esc 取消运行中的工具;Esc Esc 打开分叉选择器
  • 输入历史跨会话保留
  • 流式中途转向——生成过程中打字会注入当前这轮,而不是排队等下一轮(v0.11.0)

斜杠命令: /model /settings /keybindings /skills /tools /session /name /compact /fork /new /resume /export /import /copy /reload /hotkeys /quit /exit

已加载的 skills 会以 /skill:<name> 出现在同一个命令面板里,插件注册的命令也一样,并带上插件名。插件命令只在交互模式下可用——nanopi -p 没有面板,但该插件的工具在那边照样能用。

/tools 是清点页:先是模型可调用的工具(标 [builtin] 或 [plugin:<name>]),然后每个插件一行 Plugin grants,最后是 Watching events。它读的是活的 registry,不是启动时的快照,所以 /new、/resume 之后依然准确。

/reload 可热重载 skills、config、settings 和上下文文件,无需重启。但它刻意不重新读取 [[extensions]],并会明确说明这一点。

非交互 -p 模式遵循 Claude Code 语义,--output json 便于脚本化,也支持 prompt 从 stdin 管道传入。


可扩展性

五套彼此独立的机制,按能力从弱到强:

上下文文件。 AGENTS.md / CLAUDE.md 发现,与 Pi 对齐。-C 关闭。

Skills。 实现了 Agent Skills 规范。把 SKILL.md 放进 ~/.nanopi/skills/<name>/,用 /skill:<name> 调用,或让模型通过系统提示里自动追加的 <available_skills> 块自行发现。项目级 skills 需要信任。

Hooks。 在生命周期节点触发的 shell 命令,写在 config.toml 的 [hooks.*] 下,键名是 snake_case(settings.toml 仍然有效,但已是 legacy)。

类别 事件
工具调用 tool_execution_start、tool_execution_end
Prompt before_agent_start、input
轮次 / 消息 turn_start、turn_end、message_end
会话 session_start、session_shutdown
压缩 session_before_compact、session_compact

十一个事件,全部用 PI 的命名。v0.12 把原先借用 Claude Code 的那四个改了名——pre_tool_use → tool_execution_start、post_tool_use → tool_execution_end、user_prompt_submit → input、session_end → session_shutdown——不留别名,也没有过渡期。用旧键名会导致配置加载失败,错误里点名新键。因为最坏的结果是 [[hooks.pre_tool_use]] 被静默忽略:用户以为自己给 bash 装了道闸,其实什么都没有,而且没有任何地方提示。

tool_execution_start 可以拦截调用或改写参数;tool_execution_end 可以改写结果内容;before_agent_start 和 input 可以中止本轮或改写 prompt。其余是 advisory——它们的 block 会被打印出来然后丢弃。细节见 生命周期 hooks。

WASM 插件(v0.11.0,v0.12.0 大幅拓宽)。跑在 wasmtime 里的沙箱组件,能力逐项 opt-in。v0.12 起插件还可以观察全部十一个生命周期事件,payload 和 shell hook 拿到的完全一致,但只能观察:handle-event 的返回值被丢弃。一句话:插件只看,hooks 才能拒。见 Plugin-Development-zh、Plugin-Capabilities-zh 和 插件事件订阅。

自定义系统提示。 --system-prompt 替换内置的身份/准则块,--append-system-prompt 追加。两者都接受字面文本或文件路径。不带 flag 时,nanopi 会发现 .nanopi/SYSTEM.md 和 .nanopi/APPEND_SYSTEM.md(先项目后全局)。


信任与安全

项目信任。 项目级资源——skills、SYSTEM.md、项目配置——都受信任决策管控,因为 clone 下来的仓库属于不可信输入。-a 为本次运行授信,-N 拒绝,持久化的决策覆盖后续运行。全局的同类文件不需要这道门:那是你自己的机器。

插件能力。 WASM 插件默认什么都拿不到。v0.12 把宿主导入从三个扩到了 九个,其中六个各有一道门:

导入 门
host-log、host-notify 无——输出不等于访问。用速率限制而非授权来兜(notify 每插件每轮 10 行)
host-fs-read allow_fs,且 canonicalize 之后的路径必须仍在工作目录内
host-http-get allow_network 加 url_allowlist;空白名单拒绝一切
host-store-get / host-store-set allow_store——插件给的是 key,文件位置由宿主决定,插件永远不指定路径
host-set-context allow_context——这段文字会被模型当成指令读,所以每次变更都会在 scrollback 里公告
host-call-tool allow_tools,按工具名逐个授权;[] 拒绝一切,而且你的 hooks 照样在这些调用上触发
host-send-user-message allow_send_message——唯一会花钱的能力,因此它单独出现就会告警

生命周期观察是第七道门 events,单独一页:插件事件订阅。几种危险组合会在启动时告警——events + allow_network、allow_store + allow_network、allow_context + allow_network、allow_tools 里含 bash,以及只要出现 allow_send_message。细节见 Plugin-Capabilities-zh。

--no-hooks 是紧急开关,一次性禁用所有钩子。

这是相对上游 Pi 的刻意分歧:Pi 的 extension 不带沙箱、在主进程内运行、拥有完整 Node 全局,也没有任何 URL 白名单。


配置

两层——全局 ~/.nanopi/config.toml 和项目 <cwd>/.nanopi/config.toml——不同字段有三种不同的合并行为。见 Configuration-zh;"拼接 vs 覆盖"这个区别最容易踩坑。

Settings 和键位单独放在 settings.toml,可通过 /settings 和 /keybindings 选择器编辑,用 toml_edit 往返读写以保留注释。

首次运行向导(nanopi init,或在找不到凭据时自动触发):provider 选择列表、写入前先探测校验、API key 以 0600 权限写入 ~/.nanopi/api_key。


版本演进

版本 内容
v0.12.0 统一事件词汇——四个 hook 键改用 PI 命名,旧键直接报错;插件可订阅生命周期事件(world extension-events,只观察,由 events 授权);六个新宿主导入(host-store-*、host-notify、host-set-context、host-call-tool、host-send-user-message)及各自的门;/tools 新增 Plugin grants 和 Watching events 两段
v0.11.0 WASM 扩展,带门控的 host-fs-read / host-http-get,以及插件注册的斜杠命令;Pi 生命周期钩子;流式中途转向;可配置的工具执行模式
v0.10.0 自定义系统提示;显式 api_kind 覆盖 vendor 嗅探;-p 模式下工具失败可读化;UPX 压缩发布(1.6 MB)
v0.9.x 首次运行向导;/settings + /keybindings;8 vendor 分发;重试信封
v0.9.0 Skills(与 Pi 对齐);--skill / --no-skills;user_prompt_submit 钩子
v0.8.x 完整 ratatui TUI;/fork;--continue / --session;JSONL 会话
v0.6 Provider 抽象;Anthropic adapter;自动压缩;grep/find/ls;统一配置
v0.5 工具(read/write/edit/bash);-p 模式;JSON 输出;钩子
v0.1 单文件 OpenAI 流式 demo

README 的版本表停在 v0.11.0;而在 v0.12.0 分支上,VERSION 和 Cargo.toml 仍写着 0.11.0——版本号是随 release tag 才 bump 的。判断"手上这个构建是什么"以 VERSION 和 Cargo.toml 为准,判断"代码树里已经有什么"以本表为准。


值得知道的设计取舍

  • musl + LTO + panic=abort + strip 换来小体积静态二进制;用 rustls 避开 OpenSSL 依赖
  • 手写 SSE 解析器,压住依赖树
  • JSONL 而非 JSON,追加写的会话文件能在写到一半崩溃时幸存
  • WASM 插件而非进程内扩展——这正是能力门得以存在的前提

Clone this wiki locally