nanoPyCodeAgent 0.7.0__tar.gz → 0.8.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.
Files changed (110) hide show
  1. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/.gitignore +3 -0
  2. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/AGENTS.md +27 -1
  3. nanopycodeagent-0.8.0/CONTEXT.md +65 -0
  4. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/PKG-INFO +45 -2
  5. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/README.md +43 -1
  6. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/README.zh-CN.md +39 -1
  7. nanopycodeagent-0.8.0/benchmarks/harbor/README.md +68 -0
  8. nanopycodeagent-0.8.0/benchmarks/harbor/README.zh-CN.md +61 -0
  9. nanopycodeagent-0.8.0/benchmarks/harbor/pyproject.toml +27 -0
  10. nanopycodeagent-0.8.0/benchmarks/harbor/src/harbor_adapter/__init__.py +5 -0
  11. nanopycodeagent-0.8.0/benchmarks/harbor/src/harbor_adapter/adapter.py +208 -0
  12. nanopycodeagent-0.8.0/benchmarks/harbor/tests/fixtures/atif-journal-v1.jsonl +7 -0
  13. nanopycodeagent-0.8.0/benchmarks/harbor/tests/test_adapter.py +264 -0
  14. nanopycodeagent-0.8.0/benchmarks/harbor/tests/test_atif_compatibility.py +15 -0
  15. nanopycodeagent-0.8.0/benchmarks/harbor/uv.lock +2059 -0
  16. nanopycodeagent-0.8.0/docs/changelogs/0.8.x.md +67 -0
  17. nanopycodeagent-0.8.0/docs/dev_docs/README.md +32 -0
  18. nanopycodeagent-0.8.0/docs/dev_docs/en/event-journal-protocol-v1.md +546 -0
  19. nanopycodeagent-0.8.0/docs/dev_docs/zh-CN/event-journal-protocol-v1.md +450 -0
  20. nanopycodeagent-0.8.0/docs/dev_notes/en/0.8.x.md +295 -0
  21. nanopycodeagent-0.8.0/docs/dev_notes/zh-CN/0.8.x.md +295 -0
  22. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/docs/research/README.md +10 -1
  23. nanopycodeagent-0.8.0/docs/research/en/agent_events_to_atif_examples.md +727 -0
  24. nanopycodeagent-0.8.0/docs/research/en/agent_output_and_trajectory.md +755 -0
  25. nanopycodeagent-0.8.0/docs/research/en/benchmark_headless_interface.md +259 -0
  26. nanopycodeagent-0.8.0/docs/research/en/code_agent_benchmark.md +513 -0
  27. nanopycodeagent-0.8.0/docs/research/en/openrouter_cost_accounting.md +335 -0
  28. nanopycodeagent-0.8.0/docs/research/en/openrouter_unified_protocol.md +392 -0
  29. nanopycodeagent-0.8.0/docs/research/zh-CN/agent_events_to_atif_examples.md +727 -0
  30. nanopycodeagent-0.8.0/docs/research/zh-CN/agent_output_and_trajectory.md +755 -0
  31. nanopycodeagent-0.8.0/docs/research/zh-CN/benchmark_headless_interface.md +259 -0
  32. nanopycodeagent-0.8.0/docs/research/zh-CN/code_agent_benchmark.md +513 -0
  33. nanopycodeagent-0.8.0/docs/research/zh-CN/openrouter_cost_accounting.md +335 -0
  34. nanopycodeagent-0.8.0/docs/research/zh-CN/openrouter_unified_protocol.md +392 -0
  35. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/pyproject.toml +1 -0
  36. nanopycodeagent-0.8.0/src/nanopycodeagent/__init__.py +3 -0
  37. nanopycodeagent-0.8.0/src/nanopycodeagent/agent.py +680 -0
  38. nanopycodeagent-0.8.0/src/nanopycodeagent/atif.py +504 -0
  39. nanopycodeagent-0.8.0/src/nanopycodeagent/cli.py +136 -0
  40. nanopycodeagent-0.8.0/src/nanopycodeagent/cost.py +151 -0
  41. nanopycodeagent-0.8.0/src/nanopycodeagent/event_journal.py +751 -0
  42. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/tests/helpers.py +40 -7
  43. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/tests/test_agent.py +6 -5
  44. nanopycodeagent-0.8.0/tests/test_agent_events.py +373 -0
  45. nanopycodeagent-0.8.0/tests/test_atif.py +568 -0
  46. nanopycodeagent-0.8.0/tests/test_cli.py +362 -0
  47. nanopycodeagent-0.8.0/tests/test_cost.py +154 -0
  48. nanopycodeagent-0.8.0/tests/test_event_journal.py +518 -0
  49. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/uv.lock +5 -1
  50. nanopycodeagent-0.7.0/src/nanopycodeagent/__init__.py +0 -5
  51. nanopycodeagent-0.7.0/src/nanopycodeagent/agent.py +0 -194
  52. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/.agents/skills/land-pr/SKILL.md +0 -0
  53. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/.agents/skills/release/SKILL.md +0 -0
  54. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/.agents/skills/release/scripts/verify-release.sh +0 -0
  55. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/.github/workflows/ci.yml +0 -0
  56. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/.github/workflows/release.yml +0 -0
  57. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/.ignore +0 -0
  58. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/.python-version +0 -0
  59. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/.zed/debug.json +0 -0
  60. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/CLAUDE.md +0 -0
  61. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/LICENSE +0 -0
  62. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/docs/RELEASING.md +0 -0
  63. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/docs/changelogs/0.1.x.md +0 -0
  64. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/docs/changelogs/0.2.x.md +0 -0
  65. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/docs/changelogs/0.3.x.md +0 -0
  66. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/docs/changelogs/0.4.x.md +0 -0
  67. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/docs/changelogs/0.5.x.md +0 -0
  68. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/docs/changelogs/0.6.x.md +0 -0
  69. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/docs/changelogs/0.7.x.md +0 -0
  70. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/docs/changelogs/README.md +0 -0
  71. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/docs/dev_notes/README.md +0 -0
  72. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/docs/dev_notes/en/0.1.x.md +0 -0
  73. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/docs/dev_notes/en/0.2.x.md +0 -0
  74. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/docs/dev_notes/en/0.3.x.md +0 -0
  75. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/docs/dev_notes/en/0.4.x.md +0 -0
  76. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/docs/dev_notes/en/0.5.x.md +0 -0
  77. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/docs/dev_notes/en/0.6.x.md +0 -0
  78. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/docs/dev_notes/en/0.7.x.md +0 -0
  79. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/docs/dev_notes/zh-CN/0.1.x.md +0 -0
  80. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/docs/dev_notes/zh-CN/0.2.x.md +0 -0
  81. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/docs/dev_notes/zh-CN/0.3.x.md +0 -0
  82. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/docs/dev_notes/zh-CN/0.4.x.md +0 -0
  83. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/docs/dev_notes/zh-CN/0.5.x.md +0 -0
  84. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/docs/dev_notes/zh-CN/0.6.x.md +0 -0
  85. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/docs/dev_notes/zh-CN/0.7.x.md +0 -0
  86. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/docs/research/en/agent_tools.md +0 -0
  87. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/docs/research/en/edit_tool.md +0 -0
  88. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/docs/research/en/read_tool.md +0 -0
  89. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/docs/research/en/write_tool.md +0 -0
  90. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/docs/research/zh-CN/agent_tools.md +0 -0
  91. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/docs/research/zh-CN/edit_tool.md +0 -0
  92. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/docs/research/zh-CN/read_tool.md +0 -0
  93. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/docs/research/zh-CN/write_tool.md +0 -0
  94. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/docs/superpowers/plans/2026-06-21-release-skills.md +0 -0
  95. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/docs/superpowers/specs/2026-06-21-release-skill-design.md +0 -0
  96. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/docs/superpowers/specs/2026-06-29-config-file-support-design.md +0 -0
  97. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/src/nanopycodeagent/bash_tool.py +0 -0
  98. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/src/nanopycodeagent/edit_tool.py +0 -0
  99. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/src/nanopycodeagent/read_tool.py +0 -0
  100. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/src/nanopycodeagent/settings.py +0 -0
  101. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/src/nanopycodeagent/terminal.py +0 -0
  102. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/src/nanopycodeagent/write_tool.py +0 -0
  103. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/tests/conftest.py +0 -0
  104. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/tests/test_bash_tool.py +0 -0
  105. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/tests/test_edit_tool.py +0 -0
  106. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/tests/test_line_editing.py +0 -0
  107. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/tests/test_read_tool.py +0 -0
  108. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/tests/test_settings.py +0 -0
  109. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/tests/test_terminal.py +0 -0
  110. {nanopycodeagent-0.7.0 → nanopycodeagent-0.8.0}/tests/test_write_tool.py +0 -0
@@ -218,3 +218,6 @@ __marimo__/
218
218
  .streamlit/secrets.toml
219
219
 
220
220
  references/
221
+
222
+ # Harbor benchmark results
223
+ /jobs/
@@ -37,11 +37,15 @@ The **only** exception is documentation explicitly designated as Chinese:
37
37
  Everything outside that list — including code under `src/`, this file, and all
38
38
  other docs — is English.
39
39
 
40
+ Do not label a document as `hand-written` unless its contents are actually
41
+ authored and maintained by humans. For agent-authored source-of-truth documents,
42
+ use wording such as `Chinese source` instead.
43
+
40
44
  ### Bilingual research notes
41
45
 
42
46
  Research notes are bilingual:
43
47
 
44
- - `docs/research/zh-CN/` contains the hand-written Chinese sources of truth.
48
+ - `docs/research/zh-CN/` contains the Chinese sources of truth.
45
49
  - `docs/research/en/` contains English versions generated from the Chinese
46
50
  sources; regenerate the whole corresponding file instead of hand-editing it.
47
51
 
@@ -52,6 +56,28 @@ the English version is in sync, even when it has already been updated.
52
56
 
53
57
  ## Commits & PRs
54
58
 
59
+ ### Branch and pull request workflow
60
+
61
+ All non-release changes MUST be made on a dedicated branch and merged into
62
+ `main` through a GitHub pull request.
63
+
64
+ - Before modifying repository files, agents MUST verify that the current branch
65
+ is not `main`. If it is `main`, create or switch to a dedicated branch first.
66
+ - Agents MUST NOT commit directly to `main` or push non-release commits to
67
+ `origin/main`.
68
+ - Open a pull request targeting `main`, and use the `land-pr` skill to merge it.
69
+ Do not merge without the skill's mandatory maintainer confirmation.
70
+ - If work was accidentally started on `main`, move the changes to a dedicated
71
+ branch before committing or pushing them.
72
+
73
+ The sole exception is the release workflow in `.agents/skills/release/SKILL.md`.
74
+ Only when the maintainer explicitly requests a release may that skill commit and
75
+ push its release-only changes directly to `main`, and only after its mandatory
76
+ confirmation gate. Documentation, chores, hotfixes, and all other work still
77
+ require a branch and pull request.
78
+
79
+ ### Commit and PR title format
80
+
55
81
  All agents working in this repo MUST follow
56
82
  [Conventional Commits 1.0.0](https://www.conventionalcommits.org/en/v1.0.0/)
57
83
  for **commit messages** and **PR titles** (squash-merge often uses the PR
@@ -0,0 +1,65 @@
1
+ # Code Agent Runtime
2
+
3
+ This glossary defines the runtime artifacts produced and maintained by a code agent so that public output, diagnostics, evaluation data, and resumable state remain distinct.
4
+
5
+ ## Language
6
+
7
+ **Agent Run**:
8
+ A bounded execution that starts with an instruction and ends when the agent stops autonomous work.
9
+ _Avoid_: Session, turn
10
+
11
+ **Run Output**:
12
+ The public result or event protocol that one agent run emits to its caller.
13
+ _Avoid_: Trace, transcript
14
+
15
+ **Run Result Object**:
16
+ A single public object that summarizes how one Agent Run ended, including its final result and optional usage metadata.
17
+ _Avoid_: Trajectory, session export
18
+
19
+ **Public Event Stream**:
20
+ A caller-facing Run Output that exposes a stable, selected sequence of Agent Run events as they occur.
21
+ _Avoid_: Internal event bus, execution trace
22
+
23
+ **Source Record**:
24
+ An agent-specific record observed at a CLI, SDK, or protocol boundary and consumed by an adapter; it may already be a projection of the agent's internal state.
25
+ _Avoid_: Native event, journal entry
26
+
27
+ **Native Event**:
28
+ An agent-independent runtime fact accepted by the core directly or normalized from a Source Record.
29
+ _Avoid_: Source record, public event record, trajectory step
30
+
31
+ **Journal Entry**:
32
+ A Native Event together with the identity, ordering, and recording metadata required for durable history.
33
+ _Avoid_: Persistence envelope, trajectory step
34
+
35
+ **Event Journal**:
36
+ A durable append-only sequence of Journal Entries for an Agent Run from which derived artifacts can be rebuilt.
37
+ _Avoid_: Trajectory, session, public event stream
38
+
39
+ **Partial Content**:
40
+ An unfinished representation of a message, reasoning block, or tool input that is exposed before the logical content is complete.
41
+ _Avoid_: Final message, completed event
42
+
43
+ **Content Delta**:
44
+ The incremental fragment or change relative to content already emitted for the same logical item.
45
+ _Avoid_: Partial snapshot, final message
46
+
47
+ **Terminal Event**:
48
+ The final Public Event Stream record that explicitly states how an Agent Run ended.
49
+ _Avoid_: EOF, last message
50
+
51
+ **Execution Trace**:
52
+ A diagnostic record of runtime activity retained to explain failures, timing, and internal behavior.
53
+ _Avoid_: Run output, trajectory
54
+
55
+ **Trajectory**:
56
+ A task-scoped record of observations, actions, results, and outcome prepared for evaluation or offline analysis.
57
+ _Avoid_: Execution trace, session, transcript
58
+
59
+ **ATIF Trajectory**:
60
+ A Trajectory represented by the Agent Trajectory Interchange Format and exposed as the runtime's public trajectory contract.
61
+ _Avoid_: Event journal, native trajectory
62
+
63
+ **Session**:
64
+ Durable agent state that can span multiple runs and supports continuing or branching prior work.
65
+ _Avoid_: Agent run, trajectory, transcript
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: nanoPyCodeAgent
3
- Version: 0.7.0
3
+ Version: 0.8.0
4
4
  Summary: A nano code agent built from scratch in pure Python.
5
5
  Project-URL: Homepage, https://github.com/minixalpha/nanoPyCodeAgent
6
6
  Project-URL: Repository, https://github.com/minixalpha/nanoPyCodeAgent
@@ -14,6 +14,7 @@ Classifier: Programming Language :: Python :: 3
14
14
  Classifier: Programming Language :: Python :: 3.13
15
15
  Requires-Python: >=3.13
16
16
  Requires-Dist: anthropic>=0.112.0
17
+ Requires-Dist: httpx>=0.25.0
17
18
  Description-Content-Type: text/markdown
18
19
 
19
20
  # nanoPyCodeAgent
@@ -49,6 +50,46 @@ uv tool install nanoPyCodeAgent # or: pipx install nanoPyCodeAgent
49
50
  nanoPyCodeAgent
50
51
  ```
51
52
 
53
+ #### Run one task and exit
54
+
55
+ Give it a task and it works through it on its own, with no prompt and nothing
56
+ to confirm — the shape a script or a benchmark harness needs:
57
+
58
+ ```bash
59
+ nanoPyCodeAgent -p "add a --version flag and run the tests"
60
+ nanoPyCodeAgent --prompt-file task.md
61
+ printf "%s" "$TASK" | nanoPyCodeAgent
62
+ ```
63
+
64
+ The task is carried out in the current directory. `--max-turns N` caps how
65
+ many model replies one run may spend (50 by default).
66
+
67
+ Add `--trajectory PATH` to save that headless Agent Run as one complete
68
+ [ATIF-v1.7](https://www.harborframework.com/docs/agents/trajectory-format)
69
+ JSON document without changing stdout:
70
+
71
+ ```bash
72
+ nanoPyCodeAgent -p "read README.md and summarize it" \
73
+ --trajectory ./trajectory.json
74
+ ```
75
+
76
+ The option creates the requested file with owner-only permissions (`0600`)
77
+ after the run reaches a terminal state. It refuses to overwrite an existing
78
+ path. Trajectories may contain the task, model replies, tool arguments, and
79
+ tool results, so treat them as sensitive data.
80
+
81
+ A run like this exits `0` whenever the agent actually ran — including when it
82
+ gave up or ran out of turns with the task unfinished, which is for whatever
83
+ checks the result to judge. A non-zero exit means the run could not happen at
84
+ all: `1` for missing credentials or an API that kept refusing, `2` for a
85
+ misused command line.
86
+
87
+ Every Agent Run also writes a replayable internal Event Journal under
88
+ `~/.nanoPyCodeAgent/journals/`. These JSONL files can contain prompts, model
89
+ replies, repository content, and tool results, so treat them as sensitive;
90
+ the directory is user-only (`0700`) and each file is `0600`. Journals are not
91
+ public run output or trajectories, and they are not rotated automatically yet.
92
+
52
93
  #### Run a branch or tagged version
53
94
 
54
95
  Run an unreleased branch or a specific release tag straight from GitHub:
@@ -75,6 +116,7 @@ put the values under an `env` object. Empty or whitespace-only values are ignore
75
116
  {
76
117
  "env": {
77
118
  "ANTHROPIC_API_KEY": "",
119
+ "ANTHROPIC_AUTH_TOKEN": "",
78
120
  "ANTHROPIC_BASE_URL": "",
79
121
  "ANTHROPIC_MODEL": ""
80
122
  }
@@ -83,7 +125,8 @@ put the values under an `env` object. Empty or whitespace-only values are ignore
83
125
 
84
126
  | Variable | Required | Default | Description |
85
127
  | --- | --- | --- | --- |
86
- | `ANTHROPIC_API_KEY` | Yes | — | Your Anthropic API key, or the key for a third-party / proxy service. |
128
+ | `ANTHROPIC_API_KEY` | One credential required | — | Your Anthropic API key, or an API key accepted by a third-party service. |
129
+ | `ANTHROPIC_AUTH_TOKEN` | One credential required | — | A bearer token used instead of `ANTHROPIC_API_KEY`; OpenRouter recommends this mode for its Anthropic-compatible endpoint. |
87
130
  | `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. |
88
131
  | `ANTHROPIC_MODEL` | No | `claude-sonnet-4-6` | Override the model. An empty or whitespace-only value falls back to the default. |
89
132
 
@@ -31,6 +31,46 @@ uv tool install nanoPyCodeAgent # or: pipx install nanoPyCodeAgent
31
31
  nanoPyCodeAgent
32
32
  ```
33
33
 
34
+ #### Run one task and exit
35
+
36
+ Give it a task and it works through it on its own, with no prompt and nothing
37
+ to confirm — the shape a script or a benchmark harness needs:
38
+
39
+ ```bash
40
+ nanoPyCodeAgent -p "add a --version flag and run the tests"
41
+ nanoPyCodeAgent --prompt-file task.md
42
+ printf "%s" "$TASK" | nanoPyCodeAgent
43
+ ```
44
+
45
+ The task is carried out in the current directory. `--max-turns N` caps how
46
+ many model replies one run may spend (50 by default).
47
+
48
+ Add `--trajectory PATH` to save that headless Agent Run as one complete
49
+ [ATIF-v1.7](https://www.harborframework.com/docs/agents/trajectory-format)
50
+ JSON document without changing stdout:
51
+
52
+ ```bash
53
+ nanoPyCodeAgent -p "read README.md and summarize it" \
54
+ --trajectory ./trajectory.json
55
+ ```
56
+
57
+ The option creates the requested file with owner-only permissions (`0600`)
58
+ after the run reaches a terminal state. It refuses to overwrite an existing
59
+ path. Trajectories may contain the task, model replies, tool arguments, and
60
+ tool results, so treat them as sensitive data.
61
+
62
+ A run like this exits `0` whenever the agent actually ran — including when it
63
+ gave up or ran out of turns with the task unfinished, which is for whatever
64
+ checks the result to judge. A non-zero exit means the run could not happen at
65
+ all: `1` for missing credentials or an API that kept refusing, `2` for a
66
+ misused command line.
67
+
68
+ Every Agent Run also writes a replayable internal Event Journal under
69
+ `~/.nanoPyCodeAgent/journals/`. These JSONL files can contain prompts, model
70
+ replies, repository content, and tool results, so treat them as sensitive;
71
+ the directory is user-only (`0700`) and each file is `0600`. Journals are not
72
+ public run output or trajectories, and they are not rotated automatically yet.
73
+
34
74
  #### Run a branch or tagged version
35
75
 
36
76
  Run an unreleased branch or a specific release tag straight from GitHub:
@@ -57,6 +97,7 @@ put the values under an `env` object. Empty or whitespace-only values are ignore
57
97
  {
58
98
  "env": {
59
99
  "ANTHROPIC_API_KEY": "",
100
+ "ANTHROPIC_AUTH_TOKEN": "",
60
101
  "ANTHROPIC_BASE_URL": "",
61
102
  "ANTHROPIC_MODEL": ""
62
103
  }
@@ -65,7 +106,8 @@ put the values under an `env` object. Empty or whitespace-only values are ignore
65
106
 
66
107
  | Variable | Required | Default | Description |
67
108
  | --- | --- | --- | --- |
68
- | `ANTHROPIC_API_KEY` | Yes | — | Your Anthropic API key, or the key for a third-party / proxy service. |
109
+ | `ANTHROPIC_API_KEY` | One credential required | — | Your Anthropic API key, or an API key accepted by a third-party service. |
110
+ | `ANTHROPIC_AUTH_TOKEN` | One credential required | — | A bearer token used instead of `ANTHROPIC_API_KEY`; OpenRouter recommends this mode for its Anthropic-compatible endpoint. |
69
111
  | `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. |
70
112
  | `ANTHROPIC_MODEL` | No | `claude-sonnet-4-6` | Override the model. An empty or whitespace-only value falls back to the default. |
71
113
 
@@ -31,6 +31,42 @@ uv tool install nanoPyCodeAgent # 或: pipx install nanoPyCodeAgent
31
31
  nanoPyCodeAgent
32
32
  ```
33
33
 
34
+ #### 一次性任务(非交互)
35
+
36
+ 给它一个任务,它会自己做完退出——不给提示符,也不会停下来等确认,这正是脚本或
37
+ benchmark harness 需要的形态:
38
+
39
+ ```bash
40
+ nanoPyCodeAgent -p "add a --version flag and run the tests"
41
+ nanoPyCodeAgent --prompt-file task.md
42
+ printf "%s" "$TASK" | nanoPyCodeAgent
43
+ ```
44
+
45
+ 任务在当前目录下执行。`--max-turns N` 限制一次运行最多花费多少轮模型回复(默认
46
+ 50 轮)。
47
+
48
+ 增加 `--trajectory PATH` 可以把这次 headless Agent Run 保存为一份完整的
49
+ [ATIF-v1.7](https://www.harborframework.com/docs/agents/trajectory-format) JSON
50
+ 文档,同时不改变 stdout:
51
+
52
+ ```bash
53
+ nanoPyCodeAgent -p "read README.md and summarize it" \
54
+ --trajectory ./trajectory.json
55
+ ```
56
+
57
+ run 到达终态后,该选项才会以仅当前用户可读写的权限(`0600`)创建目标文件;如果
58
+ 目标已存在则拒绝覆盖。trajectory 可能包含任务、模型回复、工具参数和工具结果,
59
+ 应按敏感数据处理。
60
+
61
+ 只要 agent 真的跑起来了,退出码就是 `0`——包括它放弃了、或者轮数用尽而任务没做
62
+ 完,那该由检查结果的一方去判定。非零退出码表示这次运行根本没能进行:`1` 是缺少
63
+ 凭据或 API 持续失败,`2` 是命令行用错了。
64
+
65
+ 每次 Agent Run 还会在 `~/.nanoPyCodeAgent/journals/` 下写入可重放的内部 Event
66
+ Journal。这些 JSONL 文件可能包含提示词、模型回复、仓库内容和工具结果,应按敏感
67
+ 数据处理;目录只允许当前用户访问(`0700`),每个文件的权限为 `0600`。Journal 既
68
+ 不是公开 run output,也不是 trajectory,目前还不会自动轮转。
69
+
34
70
  #### 运行某个分支或标签版本
35
71
 
36
72
  直接从 GitHub 运行未发布的分支,或某个具体的发布标签:
@@ -56,6 +92,7 @@ uvx --from "git+https://github.com/minixalpha/nanoPyCodeAgent@v0.1.0" nanoPyCode
56
92
  {
57
93
  "env": {
58
94
  "ANTHROPIC_API_KEY": "",
95
+ "ANTHROPIC_AUTH_TOKEN": "",
59
96
  "ANTHROPIC_BASE_URL": "",
60
97
  "ANTHROPIC_MODEL": ""
61
98
  }
@@ -64,7 +101,8 @@ uvx --from "git+https://github.com/minixalpha/nanoPyCodeAgent@v0.1.0" nanoPyCode
64
101
 
65
102
  | 变量 | 是否必填 | 默认值 | 说明 |
66
103
  | --- | --- | --- | --- |
67
- | `ANTHROPIC_API_KEY` | | 无 | 你的 Anthropic API key,或第三方/代理服务的 key。 |
104
+ | `ANTHROPIC_API_KEY` | 两种凭据任选其一 | 无 | 你的 Anthropic API key,或第三方服务接受的 API key。 |
105
+ | `ANTHROPIC_AUTH_TOKEN` | 两种凭据任选其一 | 无 | 代替 `ANTHROPIC_API_KEY` 使用的 bearer token;OpenRouter 的 Anthropic-compatible endpoint 推荐这种方式。 |
68
106
  | `ANTHROPIC_BASE_URL` | 否 | `https://api.anthropic.com` | 将 SDK 指向非官方/代理 endpoint。使用官方 API 时保持不设置;留空值会导致请求失败。 |
69
107
  | `ANTHROPIC_MODEL` | 否 | `claude-sonnet-4-6` | 覆盖默认模型。空值或纯空白会回退到默认值。 |
70
108
 
@@ -0,0 +1,68 @@
1
+ # Harbor adapter
2
+
3
+ [English](README.md) | [简体中文](README.zh-CN.md)
4
+
5
+ This isolated workspace contains the nanoPyCodeAgent adapter for Terminal-Bench
6
+ and other benchmarks run by Harbor. It is development infrastructure, not part
7
+ of the end-user `nanoPyCodeAgent` package. Harbor is pinned to 0.21.0 in this
8
+ workspace's lockfile.
9
+
10
+ ## Run a benchmark
11
+
12
+ Set the connection credentials used by the CLI. For a third-party or proxy
13
+ endpoint, configure the API key and base URL; select the model with Harbor's
14
+ `--model` option shown below:
15
+
16
+ ```bash
17
+ export ANTHROPIC_API_KEY="..."
18
+ export ANTHROPIC_BASE_URL="https://gateway.example"
19
+ ```
20
+
21
+ From the repository root, run Harbor through this workspace and pin the agent
22
+ installed in the task container:
23
+
24
+ ```bash
25
+ uv run --project benchmarks/harbor harbor run \
26
+ --task terminal-bench/openssl-selfsigned-cert \
27
+ --agent harbor_adapter:NanoPyCodeAgent \
28
+ --agent-kwarg git_ref=<commit-sha> \
29
+ --model anthropic/claude-sonnet-4-6 \
30
+ --env docker \
31
+ --n-concurrent 1 \
32
+ --n-attempts 1
33
+ ```
34
+
35
+ Use `--agent-kwarg version=<released-version>` instead of `git_ref` to install a
36
+ published PyPI release. The two pins are mutually exclusive. If neither is
37
+ provided, the adapter installs the latest published release. For reproducible
38
+ benchmark results, always provide one of them. Prefer a full 40-character commit
39
+ SHA for `git_ref`; Harbor may parse an unquoted abbreviated SHA such as `83e6271`
40
+ as a number. To use an abbreviated revision, preserve its string type with
41
+ `--agent-kwarg 'git_ref="83e6271"'`.
42
+
43
+ The adapter sends the instruction through stdin, runs the agent in the task
44
+ container's current directory, and saves combined stdout/stderr to
45
+ `/logs/agent/nanopycodeagent.txt`. It uses the CLI's 50-turn default; override
46
+ that with `--agent-kwarg max_turns=20`.
47
+
48
+ The adapter also asks the agent to write an ATIF-v1.7 trajectory directly to
49
+ `/logs/agent/trajectory.json`. Harbor collects that file as the trial's native
50
+ ATIF output and backfills prompt, completion, cache-token, and cost totals into
51
+ the agent result. Missing, invalid, or partial trajectories remain explicitly
52
+ diagnosed; unknown usage or cost is not reported as zero.
53
+
54
+ By default, the adapter strips the first provider prefix from `--model` and
55
+ passes the result to nanoPyCodeAgent as `ANTHROPIC_MODEL`. Set
56
+ `ANTHROPIC_MODEL` only when a custom endpoint requires an actual model name that
57
+ differs from Harbor's `provider/model` identity; this explicit override takes
58
+ precedence. Harbor-native provider credentials and configured base URLs are
59
+ also normalized to the `ANTHROPIC_*` variables expected by nanoPyCodeAgent's
60
+ SDK.
61
+
62
+ ## Test the adapter
63
+
64
+ ```bash
65
+ uv run --project benchmarks/harbor pytest \
66
+ -c benchmarks/harbor/pyproject.toml \
67
+ benchmarks/harbor/tests
68
+ ```
@@ -0,0 +1,61 @@
1
+ # Harbor adapter
2
+
3
+ [English](README.md) | [简体中文](README.zh-CN.md)
4
+
5
+ 这个独立 workspace 包含 nanoPyCodeAgent 面向 Terminal-Bench 及其他 Harbor
6
+ 评测任务的 adapter。它属于开发基础设施,不是面向普通用户的
7
+ `nanoPyCodeAgent` 软件包的一部分。该 workspace 的 lockfile 将 Harbor 固定在
8
+ 0.21.0。
9
+
10
+ ## 运行 benchmark
11
+
12
+ 设置 CLI 使用的连接凭据。使用第三方或代理 endpoint 时,配置 API key 和 base
13
+ URL;模型由下方 Harbor 命令中的 `--model` 选择:
14
+
15
+ ```bash
16
+ export ANTHROPIC_API_KEY="..."
17
+ export ANTHROPIC_BASE_URL="https://gateway.example"
18
+ ```
19
+
20
+ 从仓库根目录通过这个 workspace 运行 Harbor,并固定安装到 task 容器中的 agent:
21
+
22
+ ```bash
23
+ uv run --project benchmarks/harbor harbor run \
24
+ --task terminal-bench/openssl-selfsigned-cert \
25
+ --agent harbor_adapter:NanoPyCodeAgent \
26
+ --agent-kwarg git_ref=<commit-sha> \
27
+ --model anthropic/claude-sonnet-4-6 \
28
+ --env docker \
29
+ --n-concurrent 1 \
30
+ --n-attempts 1
31
+ ```
32
+
33
+ 如需安装已经发布到 PyPI 的版本,请使用
34
+ `--agent-kwarg version=<released-version>` 代替 `git_ref`。这两个版本参数互斥;
35
+ 如果都未提供,adapter 会安装最新发布版本。为了让 benchmark 结果可复现,请始终
36
+ 提供其中一个参数。`git_ref` 最好使用完整的 40 位 commit SHA;Harbor 可能把
37
+ `83e6271` 这样的无引号短 SHA 解析成数字。如果需要使用短 revision,请通过
38
+ `--agent-kwarg 'git_ref="83e6271"'` 保留其字符串类型。
39
+
40
+ adapter 通过 stdin 发送任务指令,在 task 容器的当前目录中运行 agent,并把合并后
41
+ 的 stdout/stderr 保存到 `/logs/agent/nanopycodeagent.txt`。它默认沿用 CLI 的 50
42
+ 轮限制;可以通过 `--agent-kwarg max_turns=20` 覆盖此设置。
43
+
44
+ adapter 还会要求 agent 将 ATIF-v1.7 trajectory 直接写入
45
+ `/logs/agent/trajectory.json`。Harbor 会把该文件作为 trial 的原生 ATIF 输出采集,
46
+ 并将 prompt、completion、cache token 和 cost 汇总回填到 agent result。trajectory
47
+ 缺失、无效或指标不完整时会保留明确诊断;未知 usage 或 cost 不会被记成零。
48
+
49
+ 默认情况下,adapter 会移除 `--model` 中的第一个 provider 前缀,并将结果作为
50
+ `ANTHROPIC_MODEL` 传给 nanoPyCodeAgent。只有自定义 endpoint 要求的实际模型名与
51
+ Harbor 的 `provider/model` 身份不同时,才显式设置 `ANTHROPIC_MODEL`;该覆盖值优先。
52
+ Harbor 原生的 provider 凭证和已经配置的 base URL 也会转换为 nanoPyCodeAgent SDK
53
+ 所需的 `ANTHROPIC_*` 变量。
54
+
55
+ ## 测试 adapter
56
+
57
+ ```bash
58
+ uv run --project benchmarks/harbor pytest \
59
+ -c benchmarks/harbor/pyproject.toml \
60
+ benchmarks/harbor/tests
61
+ ```
@@ -0,0 +1,27 @@
1
+ [project]
2
+ name = "nanopycodeagent-harbor-adapter"
3
+ version = "0.1.0"
4
+ description = "Repository-local Harbor adapter for nanoPyCodeAgent benchmarks."
5
+ requires-python = ">=3.13"
6
+ dependencies = [
7
+ "harbor==0.21.0",
8
+ ]
9
+
10
+ [build-system]
11
+ requires = ["hatchling"]
12
+ build-backend = "hatchling.build"
13
+
14
+ [tool.hatch.build.targets.wheel]
15
+ packages = ["src/harbor_adapter"]
16
+
17
+ [dependency-groups]
18
+ dev = [
19
+ "nanopycodeagent",
20
+ "pytest>=9.1.1",
21
+ ]
22
+
23
+ [tool.uv.sources]
24
+ nanopycodeagent = { path = "../..", editable = true }
25
+
26
+ [tool.pytest.ini_options]
27
+ testpaths = ["tests"]
@@ -0,0 +1,5 @@
1
+ """Public import for the repository-local nanoPyCodeAgent Harbor adapter."""
2
+
3
+ from .adapter import NanoPyCodeAgent
4
+
5
+ __all__ = ["NanoPyCodeAgent"]