diff --git a/README.md b/README.md index 472b719..3d95d17 100644 --- a/README.md +++ b/README.md @@ -38,38 +38,12 @@ to confirm — the shape a script or a benchmark harness needs: ```bash nanoPyCodeAgent -p "add a --version flag and run the tests" -nanoPyCodeAgent --prompt-file task.md -printf "%s" "$TASK" | nanoPyCodeAgent ``` -The task is carried out in the current directory. `--max-turns N` caps how -many model replies one run may spend (50 by default). - -Add `--trajectory PATH` to save that headless Agent Run as one complete -[ATIF-v1.7](https://www.harborframework.com/docs/agents/trajectory-format) -JSON document without changing stdout: - -```bash -nanoPyCodeAgent -p "read README.md and summarize it" \ - --trajectory ./trajectory.json -``` - -The option creates the requested file with owner-only permissions (`0600`) -after the run reaches a terminal state. It refuses to overwrite an existing -path. Trajectories may contain the task, model replies, tool arguments, and -tool results, so treat them as sensitive data. - -A run like this exits `0` whenever the agent actually ran — including when it -gave up or ran out of turns with the task unfinished, which is for whatever -checks the result to judge. A non-zero exit means the run could not happen at -all: `1` for missing credentials or an API that kept refusing, `2` for a -misused command line. - -Every Agent Run also writes a replayable internal Event Journal under -`~/.nanoPyCodeAgent/journals/`. These JSONL files can contain prompts, model -replies, repository content, and tool results, so treat them as sensitive; -the directory is user-only (`0700`) and each file is `0600`. Journals are not -public run output or trajectories, and they are not rotated automatically yet. +The task runs in the current directory and the command exits when the run +ends. See the [complete CLI reference](docs/user_docs/en/cli_reference.md) for +all task input methods, options, exit statuses, trajectory output, and Event +Journal behavior. #### Run a branch or tagged version @@ -85,31 +59,11 @@ uvx --from "git+https://github.com/minixalpha/nanoPyCodeAgent@v0.1.0" nanoPyCode ### Configuration -Credentials and the model come from two sources: **environment variables** and -an optional user-level config file at `~/.nanoPyCodeAgent/settings.json`. -Environment variables take precedence — the config file only fills in keys you -have not set in the environment. - -The config file mirrors [Claude Code's settings](https://code.claude.com/docs/en/settings): -put the values under an `env` object. Empty or whitespace-only values are ignored. - -```json -{ - "env": { - "ANTHROPIC_API_KEY": "", - "ANTHROPIC_AUTH_TOKEN": "", - "ANTHROPIC_BASE_URL": "", - "ANTHROPIC_MODEL": "" - } -} -``` - -| Variable | Required | Default | Description | -| --- | --- | --- | --- | -| `ANTHROPIC_API_KEY` | One credential required | — | Your Anthropic API key, or an API key accepted by a third-party service. | -| `ANTHROPIC_AUTH_TOKEN` | One credential required | — | A bearer token used instead of `ANTHROPIC_API_KEY`; OpenRouter recommends this mode for its Anthropic-compatible endpoint. | -| `ANTHROPIC_BASE_URL` | No | `https://api.anthropic.com` | Point the SDK at a non-official / proxy endpoint. Leave it unset to use the official API — an empty value breaks requests. | -| `ANTHROPIC_MODEL` | No | `claude-sonnet-4-6` | Override the model. An empty or whitespace-only value falls back to the default. | +Set `ANTHROPIC_API_KEY` or `ANTHROPIC_AUTH_TOKEN` before running the agent. +You can also configure the endpoint and model through environment variables or +`~/.nanoPyCodeAgent/settings.json`. See the [configuration reference](docs/user_docs/en/configuration.md) +for supported variables, defaults, file format, precedence, and empty-value +handling. ### How to Update diff --git a/README.zh-CN.md b/README.zh-CN.md index a0e590a..51c6521 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -38,34 +38,10 @@ benchmark harness 需要的形态: ```bash nanoPyCodeAgent -p "add a --version flag and run the tests" -nanoPyCodeAgent --prompt-file task.md -printf "%s" "$TASK" | nanoPyCodeAgent ``` -任务在当前目录下执行。`--max-turns N` 限制一次运行最多花费多少轮模型回复(默认 -50 轮)。 - -增加 `--trajectory PATH` 可以把这次 headless Agent Run 保存为一份完整的 -[ATIF-v1.7](https://www.harborframework.com/docs/agents/trajectory-format) JSON -文档,同时不改变 stdout: - -```bash -nanoPyCodeAgent -p "read README.md and summarize it" \ - --trajectory ./trajectory.json -``` - -run 到达终态后,该选项才会以仅当前用户可读写的权限(`0600`)创建目标文件;如果 -目标已存在则拒绝覆盖。trajectory 可能包含任务、模型回复、工具参数和工具结果, -应按敏感数据处理。 - -只要 agent 真的跑起来了,退出码就是 `0`——包括它放弃了、或者轮数用尽而任务没做 -完,那该由检查结果的一方去判定。非零退出码表示这次运行根本没能进行:`1` 是缺少 -凭据或 API 持续失败,`2` 是命令行用错了。 - -每次 Agent Run 还会在 `~/.nanoPyCodeAgent/journals/` 下写入可重放的内部 Event -Journal。这些 JSONL 文件可能包含提示词、模型回复、仓库内容和工具结果,应按敏感 -数据处理;目录只允许当前用户访问(`0700`),每个文件的权限为 `0600`。Journal 既 -不是公开 run output,也不是 trajectory,目前还不会自动轮转。 +任务在当前目录下执行,run 结束后命令随即退出。全部任务输入方式、选项、退出状态、 +trajectory 输出和 Event Journal 行为请参阅[完整 CLI 参考](docs/user_docs/zh-CN/cli_reference.md)。 #### 运行某个分支或标签版本 @@ -81,30 +57,9 @@ uvx --from "git+https://github.com/minixalpha/nanoPyCodeAgent@v0.1.0" nanoPyCode ### 配置 -凭据与模型有两种配置来源:**环境变量**,以及可选的用户级配置文件 -`~/.nanoPyCodeAgent/settings.json`。环境变量优先级更高——配置文件只用于填补你 -未在环境变量中设置的键。 - -配置文件写法与 [Claude Code settings](https://code.claude.com/docs/en/settings) -一致:把值放在 `env` 对象下。空值或纯空白会被忽略。 - -```json -{ - "env": { - "ANTHROPIC_API_KEY": "", - "ANTHROPIC_AUTH_TOKEN": "", - "ANTHROPIC_BASE_URL": "", - "ANTHROPIC_MODEL": "" - } -} -``` - -| 变量 | 是否必填 | 默认值 | 说明 | -| --- | --- | --- | --- | -| `ANTHROPIC_API_KEY` | 两种凭据任选其一 | 无 | 你的 Anthropic API key,或第三方服务接受的 API key。 | -| `ANTHROPIC_AUTH_TOKEN` | 两种凭据任选其一 | 无 | 代替 `ANTHROPIC_API_KEY` 使用的 bearer token;OpenRouter 的 Anthropic-compatible endpoint 推荐这种方式。 | -| `ANTHROPIC_BASE_URL` | 否 | `https://api.anthropic.com` | 将 SDK 指向非官方/代理 endpoint。使用官方 API 时保持不设置;留空值会导致请求失败。 | -| `ANTHROPIC_MODEL` | 否 | `claude-sonnet-4-6` | 覆盖默认模型。空值或纯空白会回退到默认值。 | +运行前请设置 `ANTHROPIC_API_KEY` 或 `ANTHROPIC_AUTH_TOKEN`。你也可以通过 +环境变量或 `~/.nanoPyCodeAgent/settings.json` 配置 endpoint 与模型。支持的变量、 +默认值、文件格式、优先级和空值处理请参阅[配置参考](docs/user_docs/zh-CN/configuration.md)。 ### 如何更新 diff --git a/docs/changelogs/0.8.x.md b/docs/changelogs/0.8.x.md index 0fb5457..1448744 100644 --- a/docs/changelogs/0.8.x.md +++ b/docs/changelogs/0.8.x.md @@ -4,6 +4,12 @@ All notable changes in the **0.8.x** release series are documented here. ## [Unreleased] +### Changed +- Moved detailed CLI and configuration guidance out of the bilingual READMEs + into dedicated English and Chinese user references, keeping the READMEs + concise while documenting task input, options, exit statuses, trajectories, + Event Journals, supported settings, defaults, precedence, and empty values. + ## [0.8.0] - 2026-09-04 ### Added diff --git a/docs/user_docs/README.md b/docs/user_docs/README.md new file mode 100644 index 0000000..71ce390 --- /dev/null +++ b/docs/user_docs/README.md @@ -0,0 +1,10 @@ +# User Documentation + +User-facing reference documentation for nanoPyCodeAgent is available in +English and Simplified Chinese: + +- CLI reference: [English](en/cli_reference.md) | [简体中文](zh-CN/cli_reference.md) +- Configuration: [English](en/configuration.md) | [简体中文](zh-CN/configuration.md) + +For installation and a concise getting-started guide, return to the main +[English README](../../README.md) or [Chinese README](../../README.zh-CN.md). diff --git a/docs/user_docs/en/cli_reference.md b/docs/user_docs/en/cli_reference.md new file mode 100644 index 0000000..57ed671 --- /dev/null +++ b/docs/user_docs/en/cli_reference.md @@ -0,0 +1,154 @@ +# CLI Reference + +[English](cli_reference.md) | [简体中文](../zh-CN/cli_reference.md) | +[User documentation](../README.md) + +`nanoPyCodeAgent` uses one command for an interactive session or a single +headless task. Which mode starts depends on whether the command receives a +task. + +## Synopsis + +```text +nanoPyCodeAgent [-h] [-p TEXT | --prompt-file PATH] [--max-turns N] + [--trajectory PATH] [--version] +``` + +## Modes and task input + +### Interactive mode + +The command starts an interactive session when no task option is present and +stdin is a terminal: + +```bash +nanoPyCodeAgent +``` + +Enter `/exit`, press Ctrl-D, or press Ctrl-C at the `You>` prompt to end the +session normally. `--max-turns` does not limit interactive exchanges. +`--trajectory` is not available in interactive mode. + +### Headless mode + +Any of these input methods starts one headless run: + +| Input method | Example | Behavior | +| --- | --- | --- | +| `-p TEXT`, `--prompt TEXT` | `nanoPyCodeAgent -p "run the tests"` | Uses the argument as the task. | +| `--prompt-file PATH` | `nanoPyCodeAgent --prompt-file task.md` | Reads the entire file as UTF-8. `~` is expanded in the path. | +| Non-terminal stdin | `printf "%s" "$TASK" \| nanoPyCodeAgent` | Reads stdin to EOF as the task when neither task option is present. | + +`-p`/`--prompt` and `--prompt-file` are mutually exclusive. An explicit task +option takes priority over stdin. Leading and trailing whitespace is removed +from every task; an empty or whitespace-only task is a usage error. Therefore, +running the command with empty redirected stdin, such as from `/dev/null`, does +not start an interactive session. + +The headless system prompt tells the agent to work autonomously, avoid asking +for confirmation, verify its work, and finish with a short summary. + +## Current working directory + +nanoPyCodeAgent has no working-directory option. The process's current working +directory is the workspace for the run, including file-tool operations and +shell commands. Start the command from the directory you want the agent to +work in: + +```bash +cd /path/to/project +nanoPyCodeAgent -p "fix the failing tests" +``` + +Relative prompt-file and trajectory paths are also resolved from the current +working directory. + +## Options + +| Option | Default | Contract | +| --- | --- | --- | +| `-h`, `--help` | — | Print help and exit successfully. | +| `-p TEXT`, `--prompt TEXT` | — | Run `TEXT` as one headless task. | +| `--prompt-file PATH` | — | Read one headless task from a UTF-8 file. The file must be readable and contain a non-empty task. | +| `--max-turns N` | `50` | Allow at most `N` model replies in a headless run. `N` must be an integer of at least `1`. | +| `--trajectory PATH` | disabled | Write the headless run as one ATIF-v1.7 JSON document. See [Trajectory output](#trajectory-output). | +| `--version` | — | Print `nanoPyCodeAgent VERSION` and exit successfully. | + +`--max-turns` counts model replies, including replies that contain only tool +calls. If reply `N` still requests tools, those tools are not run because no +reply remains to consume their results. Reaching the limit prints a diagnostic +to stderr but is still a normal headless exit. + +## Output channels + +During a headless run, stdout carries the streamed model text plus echoed tool +calls and tool results. The startup banner, turn-limit diagnostic, and API +errors go to stderr. This separation lets callers capture the run output while +retaining operational diagnostics. + +`--trajectory` does not change stdout. There is currently no JSON or JSONL +stdout mode. + +## Exit statuses + +| Status | Meaning | +| --- | --- | +| `0` | Help or version output completed; an interactive session ended normally; or a headless run started and returned control, even if the model gave up, left work incomplete, or exhausted `--max-turns`. | +| `1` | A runtime or infrastructure failure prevented a normal run, including missing API credentials or an Anthropic/HTTP API failure. | +| `2` | Command-line usage was invalid, including conflicting or empty task input, an invalid turn limit, an unreadable prompt file, or an invalid trajectory destination. | + +Exit status `0` does not certify that a headless task succeeded. A script or +benchmark must inspect the resulting workspace or run its own verifier. +Unexpected failures not handled by the CLI may also terminate the process with +a non-zero status and a traceback. + +## Trajectory output + +Use `--trajectory PATH` with a headless task to write one complete +[ATIF-v1.7](https://www.harborframework.com/docs/agents/trajectory-format) +JSON document: + +```bash +nanoPyCodeAgent -p "read README.md and summarize it" \ + --trajectory ./trajectory.json +``` + +The trajectory is a separate artifact; it does not replace or redirect +stdout. Its task, model replies, tool arguments, tool results, timing, usage, +cost information when available, and terminal state describe a single Agent +Run. A caught API failure after the run has started produces a partial +trajectory with a failed terminal state. + +The path contract is: + +- `--trajectory` requires a headless task and cannot be used in interactive + mode. +- `PATH` must name a file; `-` is rejected because stdout is reserved for run + output. +- `~` is expanded, and relative paths use the current working directory. +- The parent directory must already exist. +- The destination must not already exist, including as a symbolic link. The + command never overwrites it. +- The file is published after the run reaches a terminal state and is created + with owner-only permissions (`0600`). A failure before the Agent Run starts, + such as missing credentials or invalid CLI input, creates no trajectory. + +Trajectories can contain secrets and repository content. Store and share them +as sensitive data. + +## Internal Event Journals + +Each Agent Run automatically creates a replayable internal JSONL Event Journal +under `~/.nanoPyCodeAgent/journals/`. The directory is forced to owner-only +access (`0700`), and each journal file is `0600`. A headless task that starts +has one Agent Run; in an interactive session, each submitted user message +starts a new Agent Run and therefore a new journal. + +The journal is the internal source from which an optional ATIF trajectory is +projected. It is not public run output, not an ATIF trajectory, and has no CLI +flag to redirect or disable it. Journal files are not rotated automatically. +They can contain prompts, model replies, tool arguments, tool results, and +repository content, so treat them as sensitive data. + +See the [configuration reference](configuration.md) for credentials, model +selection, and endpoint settings. diff --git a/docs/user_docs/en/configuration.md b/docs/user_docs/en/configuration.md new file mode 100644 index 0000000..df6f3c4 --- /dev/null +++ b/docs/user_docs/en/configuration.md @@ -0,0 +1,171 @@ +# Configuration Reference + +[English](configuration.md) | [简体中文](../zh-CN/configuration.md) | +[User documentation](../README.md) + +nanoPyCodeAgent reads credentials, the API endpoint, and the model from the +process environment. An optional user-level settings file can fill in values +that are absent from that environment. + +## Configuration sources and precedence + +From highest to lowest priority: + +1. Environment variables already present in the nanoPyCodeAgent process. +2. The `env` object in `~/.nanoPyCodeAgent/settings.json`. +3. Built-in defaults for settings that have one. + +The settings file only fills an environment key that is completely unset. It +never replaces a key that is already present. nanoPyCodeAgent does not load a +project `.env` file, has no project-level settings file, and has no CLI flags +for credentials, endpoint, or model selection. + +The settings file is loaded before the Anthropic client is created and before +the model is selected, so the same precedence applies in interactive and +headless modes. + +## Supported settings + +| Variable | Required | Default | Description | +| --- | --- | --- | --- | +| `ANTHROPIC_API_KEY` | One credential is required | none | Anthropic API key, or an API key accepted by a compatible third-party service. | +| `ANTHROPIC_AUTH_TOKEN` | One credential is required | none | Bearer token used for services that authenticate with `Authorization: Bearer`, such as OpenRouter's Anthropic-compatible endpoint. | +| `ANTHROPIC_BASE_URL` | No | `https://api.anthropic.com` | Base URL used by the Anthropic SDK. Set it for a compatible proxy or third-party endpoint; leave it unset for the official API. | +| `ANTHROPIC_MODEL` | No | `claude-sonnet-4-6` | Model passed to every Messages API call. | + +At least one of `ANTHROPIC_API_KEY` or `ANTHROPIC_AUTH_TOKEN` must provide a +usable credential. If neither is available, the command reports the missing +credentials on stderr and exits with status `1` before starting an Agent Run. + +The settings-file loader accepts any key whose name begins with `ANTHROPIC_`. +The four variables above are the nanoPyCodeAgent configuration contract; +additional variables are interpreted, if at all, by the installed Anthropic +Python SDK and can change with that dependency. + +## Environment variables + +Set variables in the shell that starts the agent. For the official Anthropic +API, the minimum configuration is: + +```bash +export ANTHROPIC_API_KEY="your-api-key" +nanoPyCodeAgent +``` + +For an Anthropic-compatible service, configure the credential form required by +that service, its base URL, and a model it exposes. For example: + +```bash +export ANTHROPIC_AUTH_TOKEN="your-token" +export ANTHROPIC_BASE_URL="https://example.com/anthropic" +export ANTHROPIC_MODEL="provider/model-name" +nanoPyCodeAgent -p "run the test suite" +``` + +Environment variables are inherited in the normal operating-system way. The +agent does not persist them. + +## Settings file + +The optional settings file has the fixed user-level path: + +```text +~/.nanoPyCodeAgent/settings.json +``` + +It must be UTF-8 JSON with a top-level object. Configuration values belong in +an `env` object, which must also be an object when present. The shape mirrors +the `env` field in [Claude Code settings](https://code.claude.com/docs/en/settings): + +```json +{ + "env": { + "ANTHROPIC_API_KEY": "", + "ANTHROPIC_AUTH_TOKEN": "", + "ANTHROPIC_BASE_URL": "", + "ANTHROPIC_MODEL": "" + } +} +``` + +The empty strings are placeholders. Replace the values you use and leave the +rest empty or remove their keys. For example: + +```json +{ + "env": { + "ANTHROPIC_AUTH_TOKEN": "your-token", + "ANTHROPIC_BASE_URL": "https://example.com/anthropic", + "ANTHROPIC_MODEL": "provider/model-name" + } +} +``` + +Settings-file rules: + +- A missing file is normal and is ignored silently. +- A missing `env` field supplies no values. Only entries under `env` are read; + other top-level fields are ignored. +- Only keys beginning with `ANTHROPIC_` are eligible; other environment keys + are ignored. +- A value must be a string. Non-string values are ignored. +- Leading and trailing whitespace is removed from a settings-file value. + Empty and whitespace-only values are ignored. +- An unreadable file, invalid UTF-8 or JSON, a non-object top level, or a + non-object `env` value is a configuration error and stops startup with an + exception. + +The loader does not enforce file permissions. Because this file can contain +credentials, restrict access to your user account; for example: + +```bash +chmod 600 ~/.nanoPyCodeAgent/settings.json +``` + +## Empty values and precedence + +"Unset" and "set to an empty string" are different for environment variables. +The settings loader uses key presence to decide precedence: + +| Environment state | Settings-file value | Result | +| --- | --- | --- | +| Key is unset | Non-empty string | The trimmed settings-file value is loaded. | +| Key is unset | Empty, whitespace-only, or non-string value | The entry is ignored; a built-in default may apply. | +| Key is present and non-empty | Any value | The environment value wins. | +| Key is present but empty or whitespace-only | Any value | The environment key still blocks the settings-file value. | + +For `ANTHROPIC_MODEL`, an empty or whitespace-only final environment value +falls back to `claude-sonnet-4-6`. Empty credential or base-URL environment +values do not receive that fallback and can cause authentication or request +failures. Unset an empty environment variable if you want the settings file to +supply it: + +```bash +unset ANTHROPIC_API_KEY ANTHROPIC_AUTH_TOKEN ANTHROPIC_BASE_URL ANTHROPIC_MODEL +``` + +## Precedence example + +Given this file: + +```json +{ + "env": { + "ANTHROPIC_BASE_URL": "https://settings.example/v1", + "ANTHROPIC_MODEL": "settings-model" + } +} +``` + +and this environment: + +```bash +export ANTHROPIC_MODEL="environment-model" +``` + +the run uses `environment-model` and +`https://settings.example/v1`: the environment keeps the model while the file +fills the otherwise-unset base URL. + +See the [CLI reference](cli_reference.md) for command modes, options, output, +and exit statuses. diff --git a/docs/user_docs/zh-CN/cli_reference.md b/docs/user_docs/zh-CN/cli_reference.md new file mode 100644 index 0000000..dbdd455 --- /dev/null +++ b/docs/user_docs/zh-CN/cli_reference.md @@ -0,0 +1,131 @@ +# CLI 参考 + +[English](../en/cli_reference.md) | [简体中文](cli_reference.md) | +[用户文档](../README.md) + +`nanoPyCodeAgent` 用同一个命令提供交互会话与单次 headless 任务。命令是否收到任务 +决定了启动哪一种模式。 + +## 命令格式 + +```text +nanoPyCodeAgent [-h] [-p TEXT | --prompt-file PATH] [--max-turns N] + [--trajectory PATH] [--version] +``` + +## 模式与任务输入 + +### 交互模式 + +没有提供任务选项、并且 stdin 是终端时,命令会启动交互会话: + +```bash +nanoPyCodeAgent +``` + +输入 `/exit`,或在 `You>` 提示符下按 Ctrl-D 或 Ctrl-C,都可以正常结束会话。 +`--max-turns` 不限制交互会话中的 exchange。交互模式不能使用 `--trajectory`。 + +### Headless 模式 + +以下任一种输入方式都会启动一次 headless run: + +| 输入方式 | 示例 | 行为 | +| --- | --- | --- | +| `-p TEXT`、`--prompt TEXT` | `nanoPyCodeAgent -p "run the tests"` | 把命令行参数用作任务。 | +| `--prompt-file PATH` | `nanoPyCodeAgent --prompt-file task.md` | 以 UTF-8 读取整个文件;路径中的 `~` 会被展开。 | +| 非终端 stdin | `printf "%s" "$TASK" \| nanoPyCodeAgent` | 没有任务选项时,从 stdin 一直读取到 EOF,并将其用作任务。 | + +`-p`/`--prompt` 与 `--prompt-file` 互斥。显式任务选项的优先级高于 stdin。每种方式 +读到的任务都会去除首尾空白;空任务或纯空白任务属于用法错误。因此,如果 stdin +被重定向但内容为空(例如来自 `/dev/null`),运行命令不会进入交互会话。 + +Headless system prompt 要求 agent 自主工作、不请求确认、验证自己的工作,并用一段 +简短总结结束 run。 + +## 当前工作目录 + +nanoPyCodeAgent 没有用于指定工作目录的选项。进程的当前工作目录就是本次 run 的 +workspace,文件工具操作和 shell 命令都在其中执行。请先进入希望 agent 工作的目录: + +```bash +cd /path/to/project +nanoPyCodeAgent -p "fix the failing tests" +``` + +相对形式的 prompt-file 与 trajectory 路径同样以当前工作目录为基准解析。 + +## 选项 + +| 选项 | 默认值 | 契约 | +| --- | --- | --- | +| `-h`、`--help` | 无 | 打印帮助并成功退出。 | +| `-p TEXT`、`--prompt TEXT` | 无 | 把 `TEXT` 作为一次 headless 任务运行。 | +| `--prompt-file PATH` | 无 | 从 UTF-8 文件读取一次 headless 任务;文件必须可读并包含非空任务。 | +| `--max-turns N` | `50` | 一次 headless run 最多允许 `N` 轮模型回复;`N` 必须是大于或等于 `1` 的整数。 | +| `--trajectory PATH` | 禁用 | 把 headless run 写成一份 ATIF-v1.7 JSON 文档;参见[Trajectory 输出](#trajectory-输出)。 | +| `--version` | 无 | 打印 `nanoPyCodeAgent VERSION` 并成功退出。 | + +`--max-turns` 统计模型回复,只含 tool call 的回复也计入。如果第 `N` 个回复仍然请求 +工具,这些工具不会执行,因为已经没有下一轮回复可以使用工具结果。达到上限时,命令 +会在 stderr 打印诊断,但仍属于一次正常的 headless 退出。 + +## 输出通道 + +Headless run 期间,stdout 包含流式模型文本以及回显的工具调用和工具结果。启动 banner、 +轮数上限诊断和 API 错误写入 stderr。调用方因此可以捕获 run output,同时保留运行 +诊断。 + +`--trajectory` 不会改变 stdout。目前没有 JSON 或 JSONL stdout 模式。 + +## 退出状态 + +| 状态 | 含义 | +| --- | --- | +| `0` | help 或 version 输出完成;交互会话正常结束;或者 headless run 已经启动并交回控制权,即使模型放弃、工作未完成或用尽了 `--max-turns`。 | +| `1` | runtime 或基础设施故障阻止了正常运行,包括缺少 API 凭据或 Anthropic/HTTP API 失败。 | +| `2` | 命令行用法无效,包括任务输入冲突或为空、轮数上限无效、prompt file 无法读取,或者 trajectory 目标无效。 | + +退出状态 `0` 不证明 headless 任务成功。脚本或 benchmark 必须检查产生的 workspace, +或者运行自己的 verifier。CLI 未处理的意外故障也可能让进程以非零状态和 traceback +结束。 + +## Trajectory 输出 + +在 headless 任务中使用 `--trajectory PATH`,可以写出一份完整的 +[ATIF-v1.7](https://www.harborframework.com/docs/agents/trajectory-format) JSON +文档: + +```bash +nanoPyCodeAgent -p "read README.md and summarize it" \ + --trajectory ./trajectory.json +``` + +Trajectory 是独立 artifact,不会替代或重定向 stdout。它描述单次 Agent Run 的任务、 +模型回复、工具参数、工具结果、时间、用量、可获得的成本信息和终态。如果 run 启动后 +发生被捕获的 API 失败,仍会产生带失败终态的 partial trajectory。 + +路径契约如下: + +- `--trajectory` 需要 headless 任务,不能在交互模式中使用。 +- `PATH` 必须指向文件;stdout 保留给 run output,因此 `-` 会被拒绝。 +- 路径中的 `~` 会被展开,相对路径以当前工作目录为基准。 +- 父目录必须已经存在。 +- 目标不能已经存在(符号链接也算存在);命令永远不会覆盖它。 +- run 到达终态后,文件才会以仅 owner 可读写的权限(`0600`)发布。在 Agent Run + 启动前发生的失败(例如缺少凭据或 CLI 输入无效)不会产生 trajectory。 + +Trajectory 可能包含 secret 和 repository 内容。请按敏感数据存储和分享。 + +## 内部 Event Journal + +每次 Agent Run 都会自动在 `~/.nanoPyCodeAgent/journals/` 下创建可重放的内部 JSONL +Event Journal。目录权限会被强制设为仅 owner 可访问(`0700`),每个 journal 文件为 +`0600`。一次真正启动的 headless 任务包含一个 Agent Run;在交互会话中,每次提交 +用户消息都会启动新的 Agent Run,因而也会产生新的 journal。 + +Journal 是可选 ATIF trajectory 的内部投影来源。它不是公开 run output,不是 ATIF +trajectory,也没有 CLI 选项可以重定向或禁用。Journal 文件目前不会自动轮转。它们 +可能包含 prompt、模型回复、工具参数、工具结果和 repository 内容,应按敏感数据处理。 + +凭据、模型选择和 endpoint 设置请参阅[配置参考](configuration.md)。 diff --git a/docs/user_docs/zh-CN/configuration.md b/docs/user_docs/zh-CN/configuration.md new file mode 100644 index 0000000..1fb0a7f --- /dev/null +++ b/docs/user_docs/zh-CN/configuration.md @@ -0,0 +1,154 @@ +# 配置参考 + +[English](../en/configuration.md) | [简体中文](configuration.md) | +[用户文档](../README.md) + +nanoPyCodeAgent 从进程环境中读取凭据、API endpoint 和模型。可选的用户级 settings +文件可以填补环境中缺失的值。 + +## 配置来源与优先级 + +优先级从高到低为: + +1. nanoPyCodeAgent 进程中已经存在的环境变量。 +2. `~/.nanoPyCodeAgent/settings.json` 的 `env` 对象。 +3. 有内置默认值的设置使用其默认值。 + +Settings 文件只会填补环境中完全没有设置的键,绝不会替换已经存在的键。 +nanoPyCodeAgent 不加载项目 `.env` 文件,没有项目级 settings 文件,也没有用于设置 +凭据、endpoint 或模型的 CLI 选项。 + +Settings 文件在 Anthropic client 创建和模型选择之前加载,所以交互模式与 headless +模式遵循同一套优先级。 + +## 支持的设置 + +| 变量 | 是否必需 | 默认值 | 说明 | +| --- | --- | --- | --- | +| `ANTHROPIC_API_KEY` | 两种凭据至少提供一种 | 无 | Anthropic API key,或兼容的第三方服务接受的 API key。 | +| `ANTHROPIC_AUTH_TOKEN` | 两种凭据至少提供一种 | 无 | 需要以 `Authorization: Bearer` 认证的服务所使用的 bearer token,例如 OpenRouter 的 Anthropic-compatible endpoint。 | +| `ANTHROPIC_BASE_URL` | 否 | `https://api.anthropic.com` | Anthropic SDK 使用的 base URL。兼容的 proxy 或第三方 endpoint 需要设置此项;使用官方 API 时保持未设置。 | +| `ANTHROPIC_MODEL` | 否 | `claude-sonnet-4-6` | 每次 Messages API 调用所使用的模型。 | + +`ANTHROPIC_API_KEY` 与 `ANTHROPIC_AUTH_TOKEN` 中至少要有一个提供可用凭据。两者都 +不可用时,命令会在 stderr 报告缺少凭据,并在 Agent Run 启动前以状态 `1` 退出。 + +Settings 文件 loader 接受名称以 `ANTHROPIC_` 开头的任何键。上面的四个变量是 +nanoPyCodeAgent 的配置契约;其他变量是否生效由安装的 Anthropic Python SDK 决定, +并可能随着该依赖变化。 + +## 环境变量 + +请在启动 agent 的 shell 中设置变量。使用官方 Anthropic API 时,最小配置如下: + +```bash +export ANTHROPIC_API_KEY="your-api-key" +nanoPyCodeAgent +``` + +使用 Anthropic-compatible 服务时,请设置该服务要求的凭据形式、base URL 和它提供的 +模型。例如: + +```bash +export ANTHROPIC_AUTH_TOKEN="your-token" +export ANTHROPIC_BASE_URL="https://example.com/anthropic" +export ANTHROPIC_MODEL="provider/model-name" +nanoPyCodeAgent -p "run the test suite" +``` + +环境变量按照操作系统的一般规则继承。Agent 不会持久化这些变量。 + +## Settings 文件 + +可选 settings 文件使用固定的用户级路径: + +```text +~/.nanoPyCodeAgent/settings.json +``` + +它必须是顶层为对象的 UTF-8 JSON。配置值放在 `env` 对象中;如果提供 `env`,它也 +必须是对象。其结构与 [Claude Code settings](https://code.claude.com/docs/en/settings) +的 `env` 字段一致: + +```json +{ + "env": { + "ANTHROPIC_API_KEY": "", + "ANTHROPIC_AUTH_TOKEN": "", + "ANTHROPIC_BASE_URL": "", + "ANTHROPIC_MODEL": "" + } +} +``` + +这些空字符串是占位符。请替换需要使用的值,其余项可以留空或删除。例如: + +```json +{ + "env": { + "ANTHROPIC_AUTH_TOKEN": "your-token", + "ANTHROPIC_BASE_URL": "https://example.com/anthropic", + "ANTHROPIC_MODEL": "provider/model-name" + } +} +``` + +Settings 文件遵循以下规则: + +- 文件不存在是正常情况,会被静默忽略。 +- 缺少 `env` 字段时不会提供任何值。只读取 `env` 下的条目,其他顶层字段会被忽略。 +- 只有以 `ANTHROPIC_` 开头的键符合条件,其他环境变量键会被忽略。 +- 值必须是字符串,非字符串值会被忽略。 +- Settings 文件中的值会去除首尾空白;空值与纯空白值会被忽略。 +- 文件不可读、不是有效 UTF-8 或 JSON、顶层不是对象,或者 `env` 不是对象,都属于 + 配置错误,会让启动过程因异常而停止。 + +Loader 不会强制文件权限。这个文件可能包含凭据,请将访问限制在当前用户,例如: + +```bash +chmod 600 ~/.nanoPyCodeAgent/settings.json +``` + +## 空值与优先级 + +对于环境变量,“未设置”和“设置为空字符串”并不相同。Settings loader 根据键是否存在 +来决定优先级: + +| 环境状态 | Settings 文件中的值 | 结果 | +| --- | --- | --- | +| 键未设置 | 非空字符串 | 加载去除首尾空白后的 settings 文件值。 | +| 键未设置 | 空值、纯空白值或非字符串值 | 忽略该条目;如有内置默认值,可以继续使用默认值。 | +| 键存在且非空 | 任意值 | 环境变量胜出。 | +| 键存在但为空或纯空白 | 任意值 | 这个环境变量键仍会阻止 settings 文件值回填。 | + +`ANTHROPIC_MODEL` 的最终环境值为空或纯空白时,会回退到 +`claude-sonnet-4-6`。为空的 credential 或 base-URL 环境变量没有这种回退,可能导致 +认证或请求失败。如果希望由 settings 文件提供值,请先 unset 空环境变量: + +```bash +unset ANTHROPIC_API_KEY ANTHROPIC_AUTH_TOKEN ANTHROPIC_BASE_URL ANTHROPIC_MODEL +``` + +## 优先级示例 + +假设文件内容如下: + +```json +{ + "env": { + "ANTHROPIC_BASE_URL": "https://settings.example/v1", + "ANTHROPIC_MODEL": "settings-model" + } +} +``` + +同时环境中设置了: + +```bash +export ANTHROPIC_MODEL="environment-model" +``` + +本次 run 会使用 `environment-model` 和 `https://settings.example/v1`:环境变量保留 +model,settings 文件填补原本未设置的 base URL。 + +命令模式、选项、输出和退出状态请参阅 [CLI 参考](cli_reference.md)。