ness-agent 0.2.2__tar.gz → 0.2.4__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.
- {ness_agent-0.2.2 → ness_agent-0.2.4}/.gitignore +5 -1
- {ness_agent-0.2.2 → ness_agent-0.2.4}/CHANGELOG.md +42 -4
- {ness_agent-0.2.2 → ness_agent-0.2.4}/CONTRIBUTING.md +2 -1
- {ness_agent-0.2.2 → ness_agent-0.2.4}/PKG-INFO +11 -6
- {ness_agent-0.2.2 → ness_agent-0.2.4}/README.md +10 -5
- ness_agent-0.2.4/assets/ness-agent-img_page_1.jpg +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/docs/architecture.md +23 -2
- {ness_agent-0.2.2 → ness_agent-0.2.4}/docs/cli.md +7 -7
- {ness_agent-0.2.2 → ness_agent-0.2.4}/docs/configuration.md +14 -11
- {ness_agent-0.2.2 → ness_agent-0.2.4}/docs/sdk-api.md +30 -5
- {ness_agent-0.2.2 → ness_agent-0.2.4}/docs/sdk.md +42 -0
- ness_agent-0.2.4/evals/README.md +68 -0
- ness_agent-0.2.4/evals/TB_BENCH.md +67 -0
- ness_agent-0.2.4/evals/codex/codex_chat_model.py +367 -0
- ness_agent-0.2.4/evals/codex/ness_harbor_agent.py +533 -0
- ness_agent-0.2.4/evals/codex/ness_session.py +133 -0
- ness_agent-0.2.4/evals/configs/tb-errored-3-codex.yaml +18 -0
- ness_agent-0.2.4/evals/configs/tb-multimedia-5-codex.yaml +20 -0
- ness_agent-0.2.4/evals/configs/tb-single-task-codex.yaml +16 -0
- ness_agent-0.2.4/evals/configs/tb-single-task.yaml +16 -0
- ness_agent-0.2.4/evals/configs/tb-targeted-3-codex.yaml +18 -0
- ness_agent-0.2.4/evals/configs/tb-text-only-20-codex.yaml +35 -0
- ness_agent-0.2.4/evals/configs/tb-text-only-20.yaml +35 -0
- ness_agent-0.2.4/evals/ness_harbor_agent.py +416 -0
- ness_agent-0.2.4/evals/ness_session.py +129 -0
- ness_agent-0.2.4/evals/scripts/tb_bench.py +201 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/pyproject.toml +13 -1
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/agent.py +45 -3
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/context/budget.py +26 -3
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/graph/helpers.py +132 -1
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/graph/nodes.py +98 -32
- ness_agent-0.2.4/src/ness_agent/instructions/compaction.py +18 -0
- ness_agent-0.2.4/src/ness_agent/media.py +74 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/permissions.py +72 -28
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/session.py +32 -3
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/session_context.py +1 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/tools/__init__.py +40 -12
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/tools/fs.py +77 -10
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/tracing/cost.py +83 -14
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/tracing/messages.py +3 -1
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/types.py +2 -1
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/chat_model.py +2 -2
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/coding_session.py +99 -43
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/config.py +27 -19
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/config_store.py +3 -1
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/events.py +11 -8
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/headless.py +1 -0
- ness_agent-0.2.4/src/ness_cli/instructions/compaction.md +18 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/provider/codex/adapter.py +12 -5
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/provider/codex/auth.py +2 -2
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/provider/codex/chat_model.py +38 -10
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/provider/codex/transport.py +136 -2
- ness_agent-0.2.4/src/ness_cli/provider/opencode/__init__.py +1 -0
- ness_agent-0.2.4/src/ness_cli/provider/opencode/adapter.py +281 -0
- ness_agent-0.2.4/src/ness_cli/provider/opencode/catalog.py +101 -0
- ness_agent-0.2.4/src/ness_cli/provider/opencode/chat_model.py +24 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/provider/openrouter/chat_model.py +53 -14
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/provider/registry.py +2 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/tui/app.py +2 -3
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/tui/chrome.py +6 -4
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/tui/commands.py +15 -11
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/tui/config_flow.py +3 -4
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/tui/config_registry.py +21 -9
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/tui/images.py +4 -28
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/tui/main.py +1 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/tui/pickers.py +3 -4
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/tui/transcript.py +5 -2
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/tui/turn_renderer.py +7 -1
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/sdk_example_usage.md +9 -6
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_anthropic_messages.py +69 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_cli/conftest.py +19 -1
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_cli/test_chrome.py +5 -5
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_cli/test_codex_provider.py +167 -2
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_cli/test_coding_session.py +34 -1
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_cli/test_commands.py +9 -7
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_cli/test_config_flow.py +10 -2
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_cli/test_config_store.py +13 -0
- ness_agent-0.2.4/tests/test_cli/test_opencode_provider.py +216 -0
- ness_agent-0.2.4/tests/test_codex_harbor_agent.py +118 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_fs.py +76 -2
- ness_agent-0.2.4/tests/test_media.py +87 -0
- ness_agent-0.2.4/tests/test_media_tool_flow.py +214 -0
- ness_agent-0.2.4/tests/test_opencode_live.py +30 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_sdk_regressions.py +434 -3
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/tracing/test_cost.py +18 -2
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/tracing/test_integration.py +4 -1
- {ness_agent-0.2.2 → ness_agent-0.2.4}/uv.lock +1301 -10
- ness_agent-0.2.2/.agents/skills/brandkit/SKILL.md +0 -798
- ness_agent-0.2.2/.agents/skills/design-taste-frontend/SKILL.md +0 -1206
- ness_agent-0.2.2/.agents/skills/gpt-taste/SKILL.md +0 -74
- ness_agent-0.2.2/.agents/skills/high-end-visual-design/SKILL.md +0 -98
- ness_agent-0.2.2/.agents/skills/image-to-code/SKILL.md +0 -1228
- ness_agent-0.2.2/.agents/skills/imagegen-frontend-web/SKILL.md +0 -987
- ness_agent-0.2.2/.agents/skills/industrial-brutalist-ui/SKILL.md +0 -92
- ness_agent-0.2.2/.agents/skills/minimalist-ui/SKILL.md +0 -85
- ness_agent-0.2.2/.agents/skills/redesign-existing-projects/SKILL.md +0 -178
- ness_agent-0.2.2/.agents/skills/stitch-design-taste/DESIGN.md +0 -121
- ness_agent-0.2.2/.agents/skills/stitch-design-taste/SKILL.md +0 -184
- ness_agent-0.2.2/.ness/NESS.md +0 -1
- ness_agent-0.2.2/.ness/agents/explore.md +0 -10
- ness_agent-0.2.2/.ness/hooks.json +0 -9
- ness_agent-0.2.2/.ness/mcp.json +0 -13
- ness_agent-0.2.2/.ness/permissions.json +0 -36
- ness_agent-0.2.2/.ness/skills/brandkit/SKILL.md +0 -798
- ness_agent-0.2.2/.ness/skills/design-taste-frontend/SKILL.md +0 -1206
- ness_agent-0.2.2/.ness/skills/gpt-taste/SKILL.md +0 -74
- ness_agent-0.2.2/.ness/skills/high-end-visual-design/SKILL.md +0 -98
- ness_agent-0.2.2/.ness/skills/image-to-code/SKILL.md +0 -1228
- ness_agent-0.2.2/.ness/skills/imagegen-frontend-web/SKILL.md +0 -987
- ness_agent-0.2.2/.ness/skills/industrial-brutalist-ui/SKILL.md +0 -92
- ness_agent-0.2.2/.ness/skills/minimalist-ui/SKILL.md +0 -85
- ness_agent-0.2.2/.ness/skills/redesign-existing-projects/SKILL.md +0 -178
- ness_agent-0.2.2/.ness/skills/stitch-design-taste/DESIGN.md +0 -121
- ness_agent-0.2.2/.ness/skills/stitch-design-taste/SKILL.md +0 -184
- ness_agent-0.2.2/src/ness_agent/instructions/compaction.py +0 -14
- ness_agent-0.2.2/src/ness_cli/instructions/compaction.md +0 -14
- ness_agent-0.2.2/website/.gitignore +0 -24
- ness_agent-0.2.2/website/.oxlintrc.json +0 -8
- ness_agent-0.2.2/website/AGENTS.md +0 -54
- ness_agent-0.2.2/website/README.md +0 -32
- ness_agent-0.2.2/website/assets/viewport.png +0 -0
- ness_agent-0.2.2/website/content/blog/inside-coding-agent-building-the-harness-around-the-model/assets/.gitkeep +0 -0
- ness_agent-0.2.2/website/content/blog/inside-coding-agent-building-the-harness-around-the-model/assets/flow1.png +0 -0
- ness_agent-0.2.2/website/content/blog/inside-coding-agent-building-the-harness-around-the-model/assets/flow2.png +0 -0
- ness_agent-0.2.2/website/content/blog/inside-coding-agent-building-the-harness-around-the-model/assets/flow3.png +0 -0
- ness_agent-0.2.2/website/content/blog/inside-coding-agent-building-the-harness-around-the-model/assets/flow4.png +0 -0
- ness_agent-0.2.2/website/content/blog/inside-coding-agent-building-the-harness-around-the-model/assets/flow5.png +0 -0
- ness_agent-0.2.2/website/content/blog/inside-coding-agent-building-the-harness-around-the-model/assets/flow6.png +0 -0
- ness_agent-0.2.2/website/content/blog/inside-coding-agent-building-the-harness-around-the-model/assets/flow7.png +0 -0
- ness_agent-0.2.2/website/content/blog/inside-coding-agent-building-the-harness-around-the-model/index.md +0 -736
- ness_agent-0.2.2/website/index.html +0 -13
- ness_agent-0.2.2/website/package-lock.json +0 -3848
- ness_agent-0.2.2/website/package.json +0 -39
- ness_agent-0.2.2/website/public/.ness/threads/threads.db +0 -0
- ness_agent-0.2.2/website/public/favicon.svg +0 -46
- ness_agent-0.2.2/website/public/icons.svg +0 -24
- ness_agent-0.2.2/website/public/install.ps1 +0 -241
- ness_agent-0.2.2/website/public/install.sh +0 -201
- ness_agent-0.2.2/website/src/App.css +0 -184
- ness_agent-0.2.2/website/src/App.tsx +0 -27
- ness_agent-0.2.2/website/src/assets/hero.png +0 -0
- ness_agent-0.2.2/website/src/assets/react.svg +0 -1
- ness_agent-0.2.2/website/src/assets/vite.svg +0 -1
- ness_agent-0.2.2/website/src/content/blog.ts +0 -86
- ness_agent-0.2.2/website/src/content/docsRoutes.ts +0 -10
- ness_agent-0.2.2/website/src/content/markdown.ts +0 -32
- ness_agent-0.2.2/website/src/index.css +0 -2641
- ness_agent-0.2.2/website/src/main.tsx +0 -18
- ness_agent-0.2.2/website/src/pages/BlogPage.tsx +0 -178
- ness_agent-0.2.2/website/src/pages/DocsPage.tsx +0 -259
- ness_agent-0.2.2/website/src/pages/HomePage.tsx +0 -80
- ness_agent-0.2.2/website/src/pages/NewsPage.tsx +0 -281
- ness_agent-0.2.2/website/src/pages/shared/InstallCommand.tsx +0 -84
- ness_agent-0.2.2/website/src/pages/shared/MarkdownDocument.tsx +0 -88
- ness_agent-0.2.2/website/src/pages/shared/SiteFooter.tsx +0 -36
- ness_agent-0.2.2/website/src/pages/shared/SiteShell.tsx +0 -19
- ness_agent-0.2.2/website/src/tui/NessLogo.tsx +0 -173
- ness_agent-0.2.2/website/src/tui/TuiShell.tsx +0 -711
- ness_agent-0.2.2/website/src/tui/VariantNavbar.tsx +0 -47
- ness_agent-0.2.2/website/src/tui/steps.ts +0 -200
- ness_agent-0.2.2/website/src/tui/types.ts +0 -39
- ness_agent-0.2.2/website/src/tui/useTheme.ts +0 -30
- ness_agent-0.2.2/website/tsconfig.app.json +0 -29
- ness_agent-0.2.2/website/tsconfig.json +0 -7
- ness_agent-0.2.2/website/tsconfig.node.json +0 -23
- ness_agent-0.2.2/website/vite.config.ts +0 -23
- {ness_agent-0.2.2 → ness_agent-0.2.4}/.env.example +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/.github/workflows/ci.yml +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/.github/workflows/pages.yml +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/.github/workflows/publish.yml +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/.python-version +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/AGENTS.md +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/LICENSE +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/SECURITY.md +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/assets/banner-dark-geo.svg +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/assets/banner-light-blue-geo.svg +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/assets/banner-light-geo-x.svg +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/assets/banner-light-geo.svg +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/assets/ness_agent_sc.png +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/docs/README.md +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/scripts/fetch_openrouter_models.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/skills-lock.json +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/__init__.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/compaction.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/context/__init__.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/context/coding_overlay.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/context/layers.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/context/overlay.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/defaults/__init__.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/defaults/agents/explore.md +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/graph/__init__.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/graph/builder.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/graph/state.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/hooks.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/instructions/__init__.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/instructions/act_mode.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/instructions/init_memory.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/instructions/l0_harness.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/instructions/l1_profile.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/instructions/plan_mode.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/instructions/reflection.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/instructions/subagent.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/instructions/thread_summary.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/mcp.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/memory.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/options.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/persistence.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/reflection.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/skills.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/tools/ask.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/tools/discover.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/tools/search.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/tools/shell.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/tools/skill.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/tools/subagents.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/tools/todo.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/tools/web.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/tracing/__init__.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/tracing/config.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/tracing/exporters/__init__.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/tracing/exporters/console.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/tracing/exporters/otlp.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/tracing/semconv.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/tracing/tracer.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/utils.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/workspace/__init__.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/workspace/bootstrap.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/workspace/git_context.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_agent/workspace/project_context.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/__init__.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/export.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/factory.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/goal.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/instructions/__init__.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/instructions/act_mode.md +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/instructions/goal_generic_repair.md +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/instructions/goal_judge.md +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/instructions/goal_repair.md +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/instructions/init_memory.md +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/instructions/l0_harness.md +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/instructions/persona.md +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/instructions/plan_mode.md +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/instructions/reflection.md +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/instructions/subagent.md +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/instructions/thread_summary.md +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/mcp_cli.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/mcp_import.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/mcp_manager.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/mcp_oauth.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/mcp_trust.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/mentions.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/paths.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/prompts.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/provider/__init__.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/provider/base.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/provider/codex/__init__.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/provider/codex/app_server.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/provider/codex/browser.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/provider/codex/catalog.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/provider/openrouter/__init__.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/provider/openrouter/adapter.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/provider/openrouter/catalog.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/provider/profile.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/rollback.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/terminal.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/tui/__init__.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/tui/command_catalog.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/tui/constants.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/tui/formatting.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/tui/header.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/tui/keys.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/tui/markdown.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/tui/mentions.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/tui/models.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/tui/prompts.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/tui/render.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/tui/stream.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/tui/theme.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/tui/tool_display.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/tui/utils.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/tui/widgets.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/src/ness_cli/worktree.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/mcp_echo_server.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/sdk_fixtures.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_ask.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_cli/__init__.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_cli/test_approval_cancel.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_cli/test_approval_prompt.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_cli/test_cancel.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_cli/test_codex_browser.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_cli/test_export.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_cli/test_header.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_cli/test_instructions.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_cli/test_markdown_render.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_cli/test_mcp_cli.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_cli/test_mcp_import.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_cli/test_mcp_oauth.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_cli/test_mcp_trust.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_cli/test_paste_state.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_cli/test_picker_layout.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_cli/test_print_mode.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_cli/test_question_cancel.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_cli/test_queue.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_cli/test_tool_display.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_cli/test_transcript_blocks.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_cli/test_transcript_fitcheck.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_cli/test_tui_subagent_todos.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_cli/test_tui_wiring.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_cli/test_turn_renderer.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_cli/test_version.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_git_context.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_goal.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_grep.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_mcp.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_mcp_runtime.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_memory.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_model.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_model_catalog.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_openrouter_live.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_options.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_packaging_smoke.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_paths.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_permissions.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_rollback.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_sdk_discover.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_sdk_parity.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_sdk_skill_view.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_sdk_smoke.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_session.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_shell.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_subagents.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_support_layer_wiring.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_thread_fork.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_todo.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/test_web.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/tracing/__init__.py +0 -0
- {ness_agent-0.2.2 → ness_agent-0.2.4}/tests/tracing/test_tracer.py +0 -0
|
@@ -13,6 +13,7 @@ wheels/
|
|
|
13
13
|
# Virtual environments
|
|
14
14
|
.venv
|
|
15
15
|
.env
|
|
16
|
+
.env.evals
|
|
16
17
|
|
|
17
18
|
# Ness Agent runtime data
|
|
18
19
|
.ness/worktrees/
|
|
@@ -20,4 +21,7 @@ wheels/
|
|
|
20
21
|
.ness/runtime/
|
|
21
22
|
|
|
22
23
|
# SDK Tests
|
|
23
|
-
sdk_perf/
|
|
24
|
+
sdk_perf/
|
|
25
|
+
|
|
26
|
+
# Harbor eval outputs
|
|
27
|
+
evals/jobs/
|
|
@@ -7,6 +7,42 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.2.4] - 2026-09-08 — Released
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Image-aware `read()` for vision models: PNG, JPEG, WebP, GIF, PPM, BMP, and TIFF files are normalized (EXIF orientation, 2000px long edge, PNG re-encode, 5 MB ceiling) and returned as structured text plus image blocks. Codex and OpenRouter project those tool results into the next model request; text-only sessions get a visible omission instead of a data URL. Base64 stays out of hooks, SQLite events, traces, TUI `tool_end` payloads, and token estimates. PDFs and videos remain unsupported, with a hint to render or extract frames and `read()` the resulting images.
|
|
15
|
+
- Harbor eval adapters for Terminal-Bench 2.1: OpenRouter (`evals.ness_harbor_agent:NessAgent`) and ChatGPT-authenticated Codex (`evals/codex`), plus configs and a `tb_bench.py` runner for the v0.2.3 text-only Codex baseline.
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
|
|
19
|
+
- Compaction can now summarize inside a long active turn. When the current continuation exceeds a retained-suffix budget (about 40% of usable context, clamped between 8k and 65k tokens), older in-turn work is summarized while a coherent recent suffix is kept verbatim, without splitting a tool-call batch from its results. Later tool loops treat the compacted-history boundary as the start of that continuation.
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
|
|
23
|
+
- Oversized active continuations now fail explicitly when no safe retained suffix can fit, instead of reaching the provider with an over-budget request. Compaction-call usage is isolated from parent-call context accounting, and image blocks receive a bounded token allowance without persisting their base64 payloads.
|
|
24
|
+
|
|
25
|
+
## [0.2.3] - 2026-08-23 — Released
|
|
26
|
+
|
|
27
|
+
### Added
|
|
28
|
+
|
|
29
|
+
- OpenCode Go as a built-in CLI model provider, with per-model Responses, Chat Completions, and Anthropic Messages routing, live model discovery, separate API-key storage, and rolling 5-hour/weekly/monthly subscription usage in `/status`.
|
|
30
|
+
- Per-session effective SDK configuration: `NessAgent.session()` now accepts main and reflection model overrides, `Session.config` / `Session.cost_tracker` expose the effective session view, and `Session.configure_models()` can rebind one live session without changing its siblings.
|
|
31
|
+
- `NessAgent.configure_default_models()` for updating the model defaults inherited by sessions created in the future.
|
|
32
|
+
|
|
33
|
+
### Changed
|
|
34
|
+
|
|
35
|
+
- A `NessAgent` now acts as a project-scoped owner of shared services and defaults while every `Session` receives isolated mutable runtime views for options, temporary permission rules, active MCP tools, and cost totals. Thread persistence, hooks, memory, tool definitions, persistent permission rules, tracing, and pricing remain shared.
|
|
36
|
+
- CLI model/provider/reasoning changes now update the selected thread and future sessions only; other live thread runtimes retain the model configuration with which they were created.
|
|
37
|
+
- Cost reporting is session-first: live usage accumulates in both the session tracker and the agent's current-process aggregate, while replayed durable usage restores only the session total.
|
|
38
|
+
|
|
39
|
+
### Fixed
|
|
40
|
+
|
|
41
|
+
- Concurrent `/new` and `/threads` runtimes no longer overwrite one another's effective models, temporary approvals, MCP activation, per-session callbacks, cost totals, or displayed model/provider metadata.
|
|
42
|
+
- Persistent permission updates are serialized and written atomically while `session` approval rules remain local to the session that created them.
|
|
43
|
+
- Resume restores historical thread cost without double-counting it as new agent spend, forks exclude inherited usage from child totals, and rollback preserves already-incurred session cost.
|
|
44
|
+
- The experimental ChatGPT-authenticated Codex transport now uses one stable UUID per thread for `prompt_cache_key` and the Codex Responses transport's session-routing header without sending public-API-only cache controls; cache reads and writes are reported per call, append-only prefixes can be verified through privacy-safe debug fingerprints, and backend validation errors include their response detail and request ID.
|
|
45
|
+
|
|
10
46
|
## [0.2.2] - 2026-08-15 — Released
|
|
11
47
|
|
|
12
48
|
### Added
|
|
@@ -20,7 +56,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
20
56
|
|
|
21
57
|
- The SDK `read` tool can now read absolute file paths outside the configured project root; relative paths still resolve from the project root, while write, edit, and delete paths remain project-bound.
|
|
22
58
|
- The TUI footer now labels Codex plan-backed usage as `subscription` instead of displaying the misleading `$0.0000`, while retaining dollar totals for usage-based providers.
|
|
23
|
-
- Codex
|
|
59
|
+
- ChatGPT-authenticated Codex transport requests now retry transient SSE failures such as `server_is_overloaded`, service-unavailable, server, and rate-limit errors with bounded exponential backoff, jitter, and `Retry-After` support; non-transient stream errors still fail immediately.
|
|
24
60
|
|
|
25
61
|
### Fixed
|
|
26
62
|
|
|
@@ -30,7 +66,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
30
66
|
|
|
31
67
|
### Added
|
|
32
68
|
|
|
33
|
-
- Codex
|
|
69
|
+
- Experimental Codex integration with ChatGPT browser and device-code authentication via `/login`, using the installed `codex` CLI app-server for authentication and isolated Ness global credentials (never reads or writes `~/.codex`). Model inference uses Ness's separate ChatGPT-authenticated Codex Responses transport.
|
|
34
70
|
- Pluggable model provider layer (`ness_cli/provider/`) with shared registry, profile selection, and separate Codex and OpenRouter adapters/chat models.
|
|
35
71
|
- Install scripts at `https://nessagent.dev/install.sh` (macOS/Linux) and `install.ps1` (Windows).
|
|
36
72
|
- Persistent session names through the SDK `Session.set_name()` / `ThreadStore.set_thread_name()` APIs and the interactive `/rename <name>` command.
|
|
@@ -41,7 +77,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
41
77
|
|
|
42
78
|
### Changed
|
|
43
79
|
|
|
44
|
-
- `/login` is the primary provider onboarding path:
|
|
80
|
+
- `/login` is the primary provider onboarding path: sign in to Codex with ChatGPT or configure an OpenRouter API key, switch active providers mid-session, and reconnect or log out from a dedicated picker.
|
|
45
81
|
- `/status` labels subscription usage as `subscription` rather than estimating it as API spend.
|
|
46
82
|
- TUI pickers now expand responsively to show up to 12 choices while retaining transcript space, with improved approval and question layouts.
|
|
47
83
|
- **Breaking:** the SQLite `threads` table now requires a `name` column. Automatic database migrations are intentionally unsupported; back up or remove `.ness/threads/threads.db` before using this version. Removing it permanently discards saved threads unless they were backed up externally.
|
|
@@ -87,7 +123,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
87
123
|
- SDK: LangGraph agent loop, built-in tools, permissions, memory, skills, hooks, MCP, compaction, reflection, and tracing.
|
|
88
124
|
- CLI: interactive TUI (`ness`), headless print mode (`-p`), plan/act modes, git worktrees, global config, and `.ness/` project layout.
|
|
89
125
|
|
|
90
|
-
[Unreleased]: https://github.com/Sagnnik/ness-agent/compare/v0.2.
|
|
126
|
+
[Unreleased]: https://github.com/Sagnnik/ness-agent/compare/v0.2.4...HEAD
|
|
127
|
+
[0.2.4]: https://github.com/Sagnnik/ness-agent/compare/v0.2.3...v0.2.4
|
|
128
|
+
[0.2.3]: https://github.com/Sagnnik/ness-agent/compare/v0.2.2...v0.2.3
|
|
91
129
|
[0.2.2]: https://github.com/Sagnnik/ness-agent/compare/v0.2.1...v0.2.2
|
|
92
130
|
[0.2.1]: https://github.com/Sagnnik/ness-agent/compare/v0.2.0...v0.2.1
|
|
93
131
|
[0.2.0]: https://github.com/Sagnnik/ness-agent/compare/v0.1.0...v0.2.0
|
|
@@ -44,7 +44,8 @@ PACKAGING_SMOKE=1 uv run pytest -q -m packaging
|
|
|
44
44
|
|
|
45
45
|
## Pull requests
|
|
46
46
|
|
|
47
|
-
1.
|
|
47
|
+
1. Small PRs only — keep changes focused and minimal. Large PRs will not be accepted.
|
|
48
|
+
2. Large feature requests — open an issue first to discuss the design before writing any code.
|
|
48
49
|
2. Branch from `main` (e.g. `feat/cli-cron`, `fix/session-resume`).
|
|
49
50
|
3. Keep changes focused; match existing code style in touched files.
|
|
50
51
|
4. Ensure tests pass before opening a PR.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: ness-agent
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.4
|
|
4
4
|
Summary: Ness Agent is an experimental, hackable agent harness.
|
|
5
5
|
Project-URL: Homepage, https://github.com/Sagnnik/ness-agent
|
|
6
6
|
Project-URL: Documentation, https://github.com/Sagnnik/ness-agent/tree/main/docs
|
|
@@ -61,6 +61,7 @@ Ness Agent is an experimental, hackable coding-agent harness for engineers who w
|
|
|
61
61
|
<p align="center">
|
|
62
62
|
<img src="assets/ness_agent_sc.png" alt="NessAgent terminal UI showing project context, tool execution, and Act mode" width="100%">
|
|
63
63
|
</p>
|
|
64
|
+
<p align="center"><a href="https://raw.githubusercontent.com/Sagnnik/ness-agent/main/assets/ness-demo6.mp4">Open the demo video</a></p>
|
|
64
65
|
<p align="center"><em>NessAgent TUI in Act mode.</em></p>
|
|
65
66
|
|
|
66
67
|
> **0.x experimental** — APIs may change until 1.0. See [CHANGELOG](https://github.com/Sagnnik/ness-agent/blob/main/CHANGELOG.md).
|
|
@@ -82,7 +83,6 @@ Ness Agent is an experimental, hackable coding-agent harness for engineers who w
|
|
|
82
83
|
| **Ness Agent SDK** | LangGraph agent loop, built-in tools, permissions, memory, skills, hooks, MCP, compaction, reflection, tracing |
|
|
83
84
|
| **Ness CLI** | Terminal UI (`ness`), plan/act modes, git worktrees, global config, `.ness/` project layout |
|
|
84
85
|
|
|
85
|
-
Both are included in the `ness-agent` PyPI package. OpenRouter-compatible chat models, native tool-calling, cache-safe summary compaction, and filesystem-driven extension points under `.ness/`.
|
|
86
86
|
|
|
87
87
|
## Installation
|
|
88
88
|
|
|
@@ -108,10 +108,15 @@ uv tool install --upgrade ness-agent
|
|
|
108
108
|
# or: pipx install ness-agent
|
|
109
109
|
```
|
|
110
110
|
|
|
111
|
-
Launch `ness` and run `/login` to
|
|
112
|
-
OpenRouter API key. Codex
|
|
113
|
-
browser/device flow and stores credentials in Ness's
|
|
114
|
-
directory; it never reads or changes `~/.codex`.
|
|
111
|
+
Launch `ness` and run `/login` to sign in to Codex with ChatGPT or configure an
|
|
112
|
+
OpenRouter API key. Codex authentication uses the installed `codex` CLI
|
|
113
|
+
app-server's managed browser/device flow and stores credentials in Ness's
|
|
114
|
+
isolated global config directory; it never reads or changes `~/.codex`.
|
|
115
|
+
|
|
116
|
+
> [!NOTE]
|
|
117
|
+
> Ness's Codex model transport is experimental. Authentication and credential
|
|
118
|
+
> management are handled by Codex app-server, while Ness sends inference
|
|
119
|
+
> requests directly to the ChatGPT Codex Responses endpoint used by Codex CLI.
|
|
115
120
|
|
|
116
121
|
For environment-based OpenRouter setup:
|
|
117
122
|
|
|
@@ -14,6 +14,7 @@ Ness Agent is an experimental, hackable coding-agent harness for engineers who w
|
|
|
14
14
|
<p align="center">
|
|
15
15
|
<img src="assets/ness_agent_sc.png" alt="NessAgent terminal UI showing project context, tool execution, and Act mode" width="100%">
|
|
16
16
|
</p>
|
|
17
|
+
<p align="center"><a href="https://raw.githubusercontent.com/Sagnnik/ness-agent/main/assets/ness-demo6.mp4">Open the demo video</a></p>
|
|
17
18
|
<p align="center"><em>NessAgent TUI in Act mode.</em></p>
|
|
18
19
|
|
|
19
20
|
> **0.x experimental** — APIs may change until 1.0. See [CHANGELOG](https://github.com/Sagnnik/ness-agent/blob/main/CHANGELOG.md).
|
|
@@ -35,7 +36,6 @@ Ness Agent is an experimental, hackable coding-agent harness for engineers who w
|
|
|
35
36
|
| **Ness Agent SDK** | LangGraph agent loop, built-in tools, permissions, memory, skills, hooks, MCP, compaction, reflection, tracing |
|
|
36
37
|
| **Ness CLI** | Terminal UI (`ness`), plan/act modes, git worktrees, global config, `.ness/` project layout |
|
|
37
38
|
|
|
38
|
-
Both are included in the `ness-agent` PyPI package. OpenRouter-compatible chat models, native tool-calling, cache-safe summary compaction, and filesystem-driven extension points under `.ness/`.
|
|
39
39
|
|
|
40
40
|
## Installation
|
|
41
41
|
|
|
@@ -61,10 +61,15 @@ uv tool install --upgrade ness-agent
|
|
|
61
61
|
# or: pipx install ness-agent
|
|
62
62
|
```
|
|
63
63
|
|
|
64
|
-
Launch `ness` and run `/login` to
|
|
65
|
-
OpenRouter API key. Codex
|
|
66
|
-
browser/device flow and stores credentials in Ness's
|
|
67
|
-
directory; it never reads or changes `~/.codex`.
|
|
64
|
+
Launch `ness` and run `/login` to sign in to Codex with ChatGPT or configure an
|
|
65
|
+
OpenRouter API key. Codex authentication uses the installed `codex` CLI
|
|
66
|
+
app-server's managed browser/device flow and stores credentials in Ness's
|
|
67
|
+
isolated global config directory; it never reads or changes `~/.codex`.
|
|
68
|
+
|
|
69
|
+
> [!NOTE]
|
|
70
|
+
> Ness's Codex model transport is experimental. Authentication and credential
|
|
71
|
+
> management are handled by Codex app-server, while Ness sends inference
|
|
72
|
+
> requests directly to the ChatGPT Codex Responses endpoint used by Codex CLI.
|
|
68
73
|
|
|
69
74
|
For environment-based OpenRouter setup:
|
|
70
75
|
|
|
Binary file
|
|
@@ -12,6 +12,20 @@ Ness Agent is split into a reusable **SDK** and a **coding CLI adapter** (Ness).
|
|
|
12
12
|
|
|
13
13
|
See also: [SDK guide](sdk.md) · [CLI guide](cli.md) · [Configuration](configuration.md)
|
|
14
14
|
|
|
15
|
+
### Runtime ownership
|
|
16
|
+
|
|
17
|
+
`NessAgent` represents one project/application runtime. It owns resolved defaults and services that are safe or useful to share across that project's sessions. `NessAgent.session()` takes a selective effective-config snapshot so live threads do not mutate one another.
|
|
18
|
+
|
|
19
|
+
| Scope | State |
|
|
20
|
+
|------|------|
|
|
21
|
+
| Agent/project | Thread persistence, memory backend, hooks, skill loader, tool definitions and MCP catalog, persistent permission file/lock, tracer, pricing, and defaults inherited by future sessions |
|
|
22
|
+
| Session/thread | Effective main/reflection models and options, temporary permission rules, active MCP tools and binding cache, cost totals, graph/checkpointer, event queue, cancellation token, mode, metadata, and adapter callbacks |
|
|
23
|
+
| Turn | User input, optional mode/skill overrides, usage aggregate, streamed events, and active cancellation state |
|
|
24
|
+
|
|
25
|
+
Live model usage is recorded in the session tracker and propagated once to the agent aggregate. Durable replay updates only the session tracker, so resuming a thread does not look like newly incurred provider spend. Persistent permission choices are shared through `permissions.json`; temporary `session` choices stay on the session-local view. Tool definitions are shared, while deferred MCP activation is session-local.
|
|
26
|
+
|
|
27
|
+
The Ness CLI keeps one `CodingSession` runtime per live thread. `/new` and `/threads` may therefore leave one turn running while another thread becomes selected. A `/config` model/provider/reasoning change rebuilds the selected runtime and updates agent defaults for future runtimes; already-live sibling threads remain pinned.
|
|
28
|
+
|
|
15
29
|
### MCP boundary
|
|
16
30
|
|
|
17
31
|
The SDK's `MCPRuntime` accepts fully resolved stdio or HTTP server specifications and owns connections, session lifecycle, tool discovery, LangChain tool conversion, calls, and structured connection state. It has no project-file, terminal, trust, or credential-storage policy, so it can be embedded in domain-specific or domain-agnostic applications.
|
|
@@ -55,6 +69,13 @@ Session tool tiers (same set bound in both modes):
|
|
|
55
69
|
- Advanced: `spawn_subagent`
|
|
56
70
|
- Loaded MCP tools: any `mcp__*` tool activated this session (deferred by default; load via `search_tools`/`add_tools` or `/mcp <server> [tool]`)
|
|
57
71
|
|
|
72
|
+
For vision-capable sessions, `read` accepts PNG, JPEG, WebP, GIF, PPM, BMP,
|
|
73
|
+
and TIFF files and returns a normalized image block to the model. Images are
|
|
74
|
+
oriented from EXIF metadata, resized to a 2000px maximum long edge, encoded as
|
|
75
|
+
PNG, and rejected if the normalized payload exceeds 5 MB. Text-only sessions
|
|
76
|
+
receive an explicit omission marker. PDFs and videos are not passed directly;
|
|
77
|
+
render PDF pages or extract video frames to a supported raster format first.
|
|
78
|
+
|
|
58
79
|
---
|
|
59
80
|
|
|
60
81
|
## Memory
|
|
@@ -92,8 +113,8 @@ Compaction is a cache-safe fork of the main conversation. At every boundary befo
|
|
|
92
113
|
| 70-80% | Warn that summary compaction is approaching |
|
|
93
114
|
| >= 80% | Summarize completed history |
|
|
94
115
|
|
|
95
|
-
Compaction also runs earlier when necessary to preserve `COMPACTION_BUFFER_TOKENS` for the instruction and capped summary output.
|
|
116
|
+
Compaction also runs earlier when necessary to preserve `COMPACTION_BUFFER_TOKENS` for the instruction and capped summary output. Normally the latest unanswered user turn and its assistant/tool trajectory remain verbatim. If that continuation itself exceeds about 40% of usable context (clamped between 8k and 65k tokens), Ness summarizes its older work and retains a coherent recent suffix without splitting a tool-call batch from its results. Old L3 reminders are visible to the cache-safe fork but explicitly excluded from summary semantics. The replacement branch contains one human `<compacted-history>` message, the retained active suffix, and one newly rendered current L3 reminder.
|
|
96
117
|
|
|
97
118
|
Image-bearing user messages remain structured in live and replayed canonical history after they are answered. They are removed only when their completed turn is replaced by summary compaction (or when vision is explicitly disabled).
|
|
98
119
|
|
|
99
|
-
Compaction is a separate graph node between `START`/`tools` and `agent`, so it never runs during tool execution and its state checkpoints before the next model request. Summary failures preserve the original history and may continue below the safety boundary; at the boundary the turn stops rather than using a lossy fallback. `/compact` forces this process at the next model boundary.
|
|
120
|
+
Compaction is a separate graph node between `START`/`tools` and `agent`, so it never runs during tool execution and its state checkpoints before the next model request. Summary-call usage is isolated from the parent agent call so it cannot distort later context-pressure accounting. Summary failures preserve the original history and may continue below the safety boundary; at the boundary the turn stops rather than using a lossy fallback. If no safe retained suffix can fit, the turn fails explicitly instead of sending an oversized request. `/compact` forces this process at the next model boundary.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Ness CLI
|
|
2
2
|
|
|
3
|
-
**Ness** is the interactive coding-agent CLI shipped with Ness Agent. It supports
|
|
3
|
+
**Ness** is the interactive coding-agent CLI shipped with Ness Agent. It supports plan/act modes, filesystem-driven extension points under `.ness/`, and a full TUI for approvals, thread history, and configuration.
|
|
4
4
|
|
|
5
5
|
See also: [Configuration](configuration.md) · [Architecture](architecture.md) · [SDK](sdk.md)
|
|
6
6
|
|
|
@@ -24,8 +24,8 @@ ness
|
|
|
24
24
|
|
|
25
25
|
`/init` creates project `.ness/` (dirs, permissions, hooks, mcp, default agent profiles, empty `NESS.md`) and ensures global config (`USER.md`, `instructions/`, `plans/<slug>/`).
|
|
26
26
|
|
|
27
|
-
Or skip the env var and run `/login`. Choose Codex
|
|
28
|
-
browser/device authentication, or OpenRouter for a masked API-key prompt. Device-code
|
|
27
|
+
Or skip the env var and run `/login`. Choose Codex to sign in with ChatGPT
|
|
28
|
+
using managed browser/device authentication, or OpenRouter/OpenCode Go for a masked API-key prompt. Device-code
|
|
29
29
|
login must first be enabled in ChatGPT **Settings > Security** by turning on
|
|
30
30
|
**Device code authorization for Codex**; browser login does not require that setting.
|
|
31
31
|
Selecting a connected provider makes it active and exposes only **Reconnect** and
|
|
@@ -246,19 +246,19 @@ Shift+Tab toggles plan/act mode without rebuilding the graph or invalidating the
|
|
|
246
246
|
|
|
247
247
|
- `/help`: show the command reference.
|
|
248
248
|
- `/login`: authenticate or manage model providers in a dedicated picker. Selecting a connected provider activates it and offers Reconnect/Log out; selecting a disconnected provider starts authentication immediately. Provider changes rebuild the model while preserving the thread.
|
|
249
|
-
- `/config`: edit provider keys/endpoints, model/reasoning, behavior toggles, compaction budgets, and advanced options (persisted to global `configs.json` / `secrets.json`).
|
|
249
|
+
- `/config`: edit provider keys/endpoints, model/reasoning, behavior toggles, compaction budgets, and advanced options (persisted to global `configs.json` / `secrets.json`). Model/provider/reasoning changes rebuild the selected thread and become defaults for future threads; other live thread runtimes keep their existing model configuration.
|
|
250
250
|
- `/exit` or `/quit`: end the session.
|
|
251
251
|
|
|
252
252
|
**Session**
|
|
253
253
|
|
|
254
|
-
- `/status`: show provider authentication, account email/tier, every available usage-limit window (including weekly), reset times/credits, and session token/cache/cost stats. Subscription calls are labeled `subscription` rather than estimated as API spend.
|
|
254
|
+
- `/status`: show provider authentication, account email/tier, every available usage-limit window (including OpenCode Go's rolling 5-hour, weekly, and monthly windows), reset times/credits, and the selected session's token/cache/cost stats. Subscription calls are labeled `subscription` rather than estimated as API spend.
|
|
255
255
|
- `/threads`: open a scrollable saved-thread picker, ordered by recent updates and prefixed with local `YYYY-MM-DD HH:mm` timestamps. Threads with active turns show an animated working indicator; switching away does not interrupt them.
|
|
256
256
|
- `/rename <name>`: set or update the current session's persistent display name (1–80 characters; requires thread autosave).
|
|
257
257
|
- `/fork`: choose a human message, copy the conversation state before it into a child thread, and prefill that message for editing. Forking copies session memory/checkpoints but leaves current working-tree files unchanged.
|
|
258
258
|
- `/goal <objective>`: run up to three worker attempts, each followed by an isolated read-only judge. Failed verdicts become repair instructions for the next attempt.
|
|
259
259
|
- `/save`: archive the current thread with a headline summary.
|
|
260
260
|
- `/new`: archive and start a fresh thread. During an active turn, the running thread stays in the background and the new thread starts independently.
|
|
261
|
-
- `/compact`: request a cache-safe summary at the next model boundary; the active user/tool turn remains verbatim.
|
|
261
|
+
- `/compact`: request a cache-safe summary at the next model boundary; the active user/tool turn remains verbatim unless it exceeds the retained-suffix budget, in which case older in-turn work is summarized and a coherent recent suffix is kept.
|
|
262
262
|
- `/reflection`: immediately reflect on conversation messages added since the last successful reflection and update session memory.
|
|
263
263
|
- `/export <path.html>`: write the current durable session as a self-contained, interactive HTML transcript. The export retains events from before compactions, includes an in-page normalized JSONL download, omits pasted image bytes, and refuses to overwrite an existing file. Quote paths that contain spaces.
|
|
264
264
|
|
|
@@ -310,7 +310,7 @@ Event kinds stored in `events.payload` (session threads only):
|
|
|
310
310
|
|
|
311
311
|
`/threads` lists user `session-*` threads only. Each row starts with its locally converted update datetime and uses an explicit `/rename` name when present, then falls back to the archived summary or first user message. The original conversation shows `×N` when it has forks; each fork shows `fork #k` in creation order. Fork lineage is stored explicitly on the thread row; inherited usage remains in the copied event history but is excluded from the child thread's cost totals. Subagent trajectories are not stored in `events`; subagent LLM usage rolls up into the parent session's `threads` aggregates. Subagent outputs are stored in the `subagents` table.
|
|
312
312
|
|
|
313
|
-
Selecting
|
|
313
|
+
Selecting an idle saved thread rebuilds user messages, assistant tool-call turns, and tool results from saved events. A thread that is already live keeps its own model, temporary approvals, MCP activation, graph, cancellation state, and cost total when selected again. The startup `--resume <thread_id>` flag remains available for automation. `spawn_subagent` tool output is supplemented from linked subagent outputs when available.
|
|
314
314
|
|
|
315
315
|
When a thread contains a successful new-format `compaction_llm` checkpoint, resume starts from its summary and replays only raw events after `source_event_seq`. Raw conversation events remain available for audit, rollback, and forks; L3 reminder messages are never written to the event log.
|
|
316
316
|
|
|
@@ -68,9 +68,10 @@ Project `.env` files are not loaded or migrated for Ness application settings. E
|
|
|
68
68
|
Use `/login` to authenticate, activate, reconnect, or log out of a model provider.
|
|
69
69
|
Selecting a connected provider activates it and opens its Reconnect/Log out menu;
|
|
70
70
|
selecting a disconnected provider starts authentication without an extra Connect step.
|
|
71
|
-
OpenRouter keys are stored in `secrets.json`.
|
|
72
|
-
are managed by the system `codex` CLI under
|
|
73
|
-
with file credential storage forced; Ness
|
|
71
|
+
OpenRouter and OpenCode Go keys are stored separately in `secrets.json`. ChatGPT credentials for Codex
|
|
72
|
+
are managed by the system `codex` CLI app-server under
|
|
73
|
+
`<NESS_AGENT_CONFIG_DIR>/codex/` with file credential storage forced; Ness
|
|
74
|
+
does not reuse `~/.codex`.
|
|
74
75
|
Codex device-code login additionally requires **Device code authorization for
|
|
75
76
|
Codex** to be enabled in ChatGPT **Settings > Security**. Use browser login if
|
|
76
77
|
that account setting is unavailable.
|
|
@@ -79,6 +80,12 @@ Provider-specific model and reasoning choices are nested under
|
|
|
79
80
|
`provider_profiles` in `configs.json`, so switching providers restores each
|
|
80
81
|
provider's last selection. Legacy top-level OpenRouter settings remain valid.
|
|
81
82
|
|
|
83
|
+
In the concurrent TUI, saved configuration is the default for new thread
|
|
84
|
+
runtimes. Changing the model, provider, or reasoning effort through `/config`
|
|
85
|
+
also rebuilds the currently selected thread, but it does not mutate sibling
|
|
86
|
+
threads that are already live. Selecting one of those threads later restores
|
|
87
|
+
its pinned runtime configuration.
|
|
88
|
+
|
|
82
89
|
---
|
|
83
90
|
|
|
84
91
|
## Environment variables
|
|
@@ -87,8 +94,8 @@ All except `NESS_DIR` are also editable via `/config` in the Ness TUI.
|
|
|
87
94
|
|
|
88
95
|
| Variable | Description |
|
|
89
96
|
|----------|-------------|
|
|
90
|
-
| `MODEL_PROVIDER` | Active provider (`openrouter` by default, or `
|
|
91
|
-
| `MODEL_NAME` |
|
|
97
|
+
| `MODEL_PROVIDER` | Active provider (`openrouter` by default, `codex`, or `opencode`) |
|
|
98
|
+
| `MODEL_NAME` | Active provider model ID (`deepseek/deepseek-v4-flash` by default) |
|
|
92
99
|
| `REFLECTION_MODEL_NAME` | Model for background session-memory reflection (defaults to `MODEL_NAME`) |
|
|
93
100
|
| `ENABLE_APPROVAL` | Require approval for destructive tools |
|
|
94
101
|
| `AUTO_SAVE_THREADS` | Write thread events to `.ness/threads/` |
|
|
@@ -105,6 +112,7 @@ All except `NESS_DIR` are also editable via `/config` in the Ness TUI.
|
|
|
105
112
|
| `GOAL_MAX_ATTEMPTS` | Maximum worker/judge attempts for `/goal` (default `3`) |
|
|
106
113
|
| `OPENAI_BASE_URL` | Optional custom OpenAI-compatible base URL |
|
|
107
114
|
| `OPENAI_API_KEY` | Provider API key (also stored in `secrets.json` via `/config`) |
|
|
115
|
+
| `OPENCODE_GO_API_KEY` / `OPENCODE_API_KEY` | OpenCode Go subscription key (also stored separately in `secrets.json`) |
|
|
108
116
|
| `FORMAT_ON_WRITE` | Auto-format supported file types after writes (default `true`) |
|
|
109
117
|
| `NESS_DIR` | Project config directory (default `.ness`) |
|
|
110
118
|
| `NESS_AGENT_CONFIG_DIR` | Override global config root |
|
|
@@ -123,9 +131,4 @@ advanced options; provider-only fields are hidden when they do not apply.
|
|
|
123
131
|
|
|
124
132
|
The `/config` model picker reads the active provider's catalog. OpenRouter's
|
|
125
133
|
global disk cache is reused for 24 hours with a packaged offline fallback;
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
Codex access tokens are refreshed through `account/read` shortly before JWT
|
|
129
|
-
expiry and once after an HTTP 401. Network, rate-limit, and server failures do
|
|
130
|
-
not trigger credential refresh. The subscription Responses transport is kept
|
|
131
|
-
inside `src/ness_cli/provider/codex/` because that endpoint is experimental.
|
|
134
|
+
`codex app-server` handles ChatGPT authentication and credential management for the signed-in account. Ness performs model inference separately through its experimental ChatGPT-authenticated Codex Responses transport.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# SDK API reference
|
|
2
2
|
|
|
3
|
-
This reference covers the symbols exported by `ness_agent.__all__` in the 0.2.
|
|
3
|
+
This reference covers the symbols exported by `ness_agent.__all__` in the 0.2.4 source tree. It is intentionally an API map rather than a second tutorial: start with the [SDK guide](sdk.md) for the shortest working example, then use this page when choosing a seam to own.
|
|
4
4
|
|
|
5
5
|
> **0.x experimental.** Names and signatures below describe the current public surface; pin a version before relying on it in production.
|
|
6
6
|
|
|
@@ -15,13 +15,18 @@ agent.session(*, thread_id: str, mode: str | None = None,
|
|
|
15
15
|
metadata: Mapping[str, Any] | None = None,
|
|
16
16
|
git_available: bool | None = None, vision: bool | None = None,
|
|
17
17
|
on_plan_turn: PlanTurnHandler | None = None,
|
|
18
|
-
on_interrupt: InterruptHandler | None = None
|
|
18
|
+
on_interrupt: InterruptHandler | None = None,
|
|
19
|
+
model: BaseChatModel | None = None,
|
|
20
|
+
reflection_model: BaseChatModel | None | object = _UNSET) -> Session
|
|
21
|
+
agent.configure_default_models(*, model: BaseChatModel,
|
|
22
|
+
reflection_model: BaseChatModel | None,
|
|
23
|
+
context_window: int | None) -> None
|
|
19
24
|
agent.new_thread_id(prefix: str = "session") -> str
|
|
20
25
|
```
|
|
21
26
|
|
|
22
|
-
The top-level SDK entry point owns
|
|
27
|
+
The top-level SDK entry point owns project services and resolved defaults, then creates an isolated effective configuration for each `Session`. `model` is a LangChain `BaseChatModel`; `prompt` accepts `PromptLayers`, `PromptLayersConfig`, or a mapping. With `tools=None`, the SDK resolves its built-in tool set. `agent.config` exposes project defaults and the live aggregate cost tracker; `session.config` exposes the effective session fork.
|
|
23
28
|
|
|
24
|
-
`session()` accepts optional per-thread metadata for the L3 overlay. `vision=True` sends supplied image URLs; `False` drops them to text and emits a warning event; `None` leaves content shape untouched. The two callback hooks live on a session, not on the shared agent, so concurrent threads do not overwrite each other.
|
|
29
|
+
`session()` accepts optional per-thread metadata for the L3 overlay and effective main/reflection model overrides. `vision=True` sends supplied image URLs; `False` drops them to text and emits a warning event; `None` leaves content shape untouched. The two callback hooks live on a session, not on the shared agent, so concurrent threads do not overwrite each other. `configure_default_models()` changes inheritance for sessions created later; it does not rebuild existing sessions.
|
|
25
30
|
|
|
26
31
|
```python
|
|
27
32
|
agent = NessAgent(model=model, prompt=PromptLayersConfig())
|
|
@@ -74,10 +79,19 @@ await session.run(message: str, *, images: Sequence[str] | None = None,
|
|
|
74
79
|
|
|
75
80
|
async for event in session.stream(message: str, *, images=None,
|
|
76
81
|
active_skills=None, mode=None): ...
|
|
82
|
+
|
|
83
|
+
session.config -> NessAgentConfig
|
|
84
|
+
session.cost_tracker -> CostTracker
|
|
85
|
+
session.configure_models(*, model: BaseChatModel,
|
|
86
|
+
reflection_model: BaseChatModel | None,
|
|
87
|
+
context_window: int | None,
|
|
88
|
+
vision: bool | None) -> None
|
|
77
89
|
```
|
|
78
90
|
|
|
79
91
|
`run()` collects one complete turn. It returns assistant text, an aggregate `usage_total` over every model call in the turn, the current todos, and every intermediate event. `stream()` yields those `SessionEvent` records as the graph advances. `mode=` is a one-turn override; otherwise the session’s current `act` or `plan` mode is used.
|
|
80
92
|
|
|
93
|
+
Each session owns a selective shallow fork of the agent configuration. Mutable runtime state—models and options, temporary permission rules, active MCP tools, and cost totals—is isolated. Project services such as thread persistence, hooks, memory, and the underlying permission/tool catalogs remain shared. `session.config` exposes the effective session view; `agent.config` remains the defaults inherited by future sessions plus the live agent-level cost aggregate.
|
|
94
|
+
|
|
81
95
|
Important control and inspection methods:
|
|
82
96
|
|
|
83
97
|
| Method | Purpose |
|
|
@@ -87,6 +101,7 @@ Important control and inspection methods:
|
|
|
87
101
|
| `bootstrap(messages)` | Seed prior messages into the next turn once; use for resume or rollback replay. |
|
|
88
102
|
| `cancel()` / `is_cancelled()` | Request and inspect cooperative cancellation of the active stream. |
|
|
89
103
|
| `request_compact()` | Request compaction on the next turn. |
|
|
104
|
+
| `configure_models(...)` | Replace this session's effective main/reflection models and context settings, then rebuild its graph. |
|
|
90
105
|
| `active_skills(names)` / `stage_skills(names)` | Replace or append one-shot skills for the next turn. |
|
|
91
106
|
| `get_state()`, `get_messages()`, `get_todos()` | Async snapshots of the checkpointed state. |
|
|
92
107
|
| `preview_context(mode=None) -> ContextPreview` | Assemble L0–L3 for debugging without running the model. |
|
|
@@ -175,23 +190,29 @@ Sources: `src/ness_agent/context/overlay.py`, `context/coding_overlay.py`, and `
|
|
|
175
190
|
|
|
176
191
|
```python
|
|
177
192
|
ToolRegistry(tools: Iterable[BaseTool] | None = None, *, include: Iterable[str] | None = None)
|
|
193
|
+
registry.fork_for_session() -> ToolRegistry
|
|
178
194
|
coding_tools(*, include: list[str] | None = None) -> ToolRegistry
|
|
179
195
|
```
|
|
180
196
|
|
|
181
197
|
The registry owns known tools and the currently bound active set. Core reads are `active_tools`, `tool_map()`, `tool_names()`, `all_tools()`, and `deferred_tool_names()`. Call `bind_model(model)` to return a tool-bound chat model, and `sync()` after a structural change. `register_dynamic(tools)` adds dynamic tools as known but inactive; `activate_mcp(names)` and `deactivate_mcp(names)` return `(changed, unknown)` lists and adjust the active MCP set.
|
|
182
198
|
|
|
199
|
+
`fork_for_session()` creates a registry view that shares tool definitions and the deferred MCP catalog while keeping its active MCP names, include filter, binding cache, and local generation independent. Structural catalog additions remain visible to all session views; activating a deferred MCP tool affects only that session.
|
|
200
|
+
|
|
183
201
|
`set_mcp_catalog()` and `deferred_mcp_summary()` maintain the lightweight deferred-MCP prompt catalog. `is_destructive(name, args)` and `is_read_only(name, args)` expose the registry’s policy classification. `coding_tools()` is the small convenience factory for name-selected SDK tools.
|
|
184
202
|
|
|
185
|
-
The default tool list includes file read/write/delete/edit/glob, search, web fetch/search, shell, todos, tool discovery, subagents, questions, and skill viewing.
|
|
203
|
+
The default tool list includes file read/write/delete/edit/glob, search, web fetch/search, shell, todos, tool discovery, subagents, questions, and skill viewing. In vision-capable sessions, `read` normalizes supported raster files and returns structured image content; PDFs and videos must first be rendered or split into raster frames. Image payloads are redacted from durable and display-facing events. This is not an API guarantee for every named tool; configure an explicit tool sequence when a host application needs a narrower contract.
|
|
186
204
|
|
|
187
205
|
### `PermissionStore`
|
|
188
206
|
|
|
189
207
|
```python
|
|
190
208
|
PermissionStore(*, ness_dir: Path = Path(".ness"), project_root: Path | None = None)
|
|
209
|
+
store.fork_for_session() -> PermissionStore
|
|
191
210
|
```
|
|
192
211
|
|
|
193
212
|
The file-backed policy store validates paths under the project root and resolves tool calls to `allow`, `deny`, or `ask` decisions. The main public operations are `check(tool, args)`, `check_with_rule(tool, args)`, `pattern_key(tool, args)`, `default_rule_for(tool, args)`, `persist_rule(...)`, `remove_rule(bucket, index)`, `list_rules()`, and `clear_session_rules()`. Use it when embedding an operator-approved policy rather than bypassing the tool executor.
|
|
194
213
|
|
|
214
|
+
`fork_for_session()` shares the persistent `permissions.json` path and synchronization lock while copying temporary allow/deny rules. A `session` decision therefore affects one session; `always`/`never` decisions are atomically persisted and become visible to every session on the project.
|
|
215
|
+
|
|
195
216
|
### `Hook` and `HookRunner`
|
|
196
217
|
|
|
197
218
|
```python
|
|
@@ -296,11 +317,15 @@ Sources: `src/ness_agent/memory.py` and `persistence.py`.
|
|
|
296
317
|
PricingDict = dict[str, tuple[float, float, float]]
|
|
297
318
|
CostTracker(pricing: PricingDict | None = None,
|
|
298
319
|
estimate_cost: Callable[[str, int, int, int], float | None] | None = None)
|
|
320
|
+
tracker.fork_for_session() -> CostTracker
|
|
299
321
|
tracker.add(usage, model_name=None, response_metadata=None) -> TokenUsage | None
|
|
322
|
+
tracker.restore(usage, model_name=None, response_metadata=None) -> TokenUsage | None
|
|
300
323
|
```
|
|
301
324
|
|
|
302
325
|
`TokenUsage` is a slots dataclass with model, input/uncached/cached/output/total tokens, `cost_usd`, `cost_source`, cache-hit rate, and calls. `as_dict()` serializes it. `CostTracker.add()` ingests provider usage and prefers provider-reported cost, then a supplied estimator, then a matching substring key in `pricing`. Pricing triples are USD per million tokens: `(input, output, cache_read_ratio)`.
|
|
303
326
|
|
|
327
|
+
`CostTracker.fork_for_session()` returns an empty tracker with shared pricing. New usage also rolls into the parent tracker; `restore()` loads durable historical usage locally without changing that live aggregate. Read per-thread totals from `session.cost_tracker` and current-process agent totals from `agent.config.cost_tracker`.
|
|
328
|
+
|
|
304
329
|
Use `for_model(model)`, `total()`, `models()`, or the scalar aggregate properties (`input_tokens`, `output_tokens`, `total_tokens`, `calls`, `cost_usd`, `cache_hit_rate`, `total_cost_usd`) to inspect accumulated data. `report()` returns a text report.
|
|
305
330
|
|
|
306
331
|
### `TracingConfig`, `Tracer`, `Span`, and implementations
|
|
@@ -56,6 +56,48 @@ asyncio.run(main())
|
|
|
56
56
|
|
|
57
57
|
`tools=` accepts a mix of `BaseTool` instances, plain callables (auto-wrapped), and built-in name strings (`"read"`, `"grep"`, `"shell"`, …). Pass `overlay=NoOverlay()` to drop L3 entirely. Instruction bodies are importable — e.g. `from ness_agent.instructions import L0_HARNESS, PLAN_MODE`.
|
|
58
58
|
|
|
59
|
+
In a vision-capable session, the built-in `read` tool returns supported raster
|
|
60
|
+
images (PNG, JPEG, WebP, GIF, PPM, BMP, and TIFF) as structured image content.
|
|
61
|
+
It applies EXIF orientation, limits the long edge to 2000px, re-encodes to PNG,
|
|
62
|
+
and enforces a 5 MB normalized-payload ceiling. With `vision=False`, the model
|
|
63
|
+
receives a visible omission marker instead. PDFs and videos must first be
|
|
64
|
+
rendered or have frames extracted to a supported raster format. Persisted
|
|
65
|
+
events, hooks, traces, and display events receive a redacted text form rather
|
|
66
|
+
than the base64 image payload.
|
|
67
|
+
|
|
68
|
+
### Project agents and concurrent sessions
|
|
69
|
+
|
|
70
|
+
A `NessAgent` is a project-scoped runtime: it owns shared persistence, memory, hooks, skill and tool catalogs, tracing, pricing, and defaults. Each call to `agent.session(...)` creates a separate effective runtime with its own graph/checkpointer, model fields, copied options, temporary permission rules, active MCP set, cancellation state, and cost tracker.
|
|
71
|
+
|
|
72
|
+
```python
|
|
73
|
+
agent = NessAgent(model=default_model, prompt=PromptLayersConfig())
|
|
74
|
+
|
|
75
|
+
first = agent.session(thread_id="thread-a")
|
|
76
|
+
second = agent.session(thread_id="thread-b", model=specialized_model)
|
|
77
|
+
|
|
78
|
+
await asyncio.gather(
|
|
79
|
+
first.run("inspect the API"),
|
|
80
|
+
second.run("inspect the database"),
|
|
81
|
+
)
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Use a different `Session` for each concurrent thread; two simultaneous `run()`/`stream()` calls on the same `Session` are unsupported. Use a different `NessAgent` for an unrelated project because project paths and shared stores belong to the agent.
|
|
85
|
+
|
|
86
|
+
Changing defaults affects future sessions only:
|
|
87
|
+
|
|
88
|
+
```python
|
|
89
|
+
agent.configure_default_models(
|
|
90
|
+
model=new_default,
|
|
91
|
+
reflection_model=new_reflection_default,
|
|
92
|
+
context_window=200_000,
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
# Existing sessions remain pinned. This session inherits the new defaults.
|
|
96
|
+
third = agent.session(thread_id="thread-c")
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
To deliberately change one live session, call `session.configure_models(...)`. Read thread usage from `session.cost_tracker`; `agent.config.cost_tracker` is the live current-process aggregate across sessions. Replayed history is restored into the session tracker without being counted as new aggregate spend.
|
|
100
|
+
|
|
59
101
|
### What the host owns
|
|
60
102
|
|
|
61
103
|
Bare `Session.run` is the turn engine only. Your application still needs to:
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# Harbor evals
|
|
2
|
+
|
|
3
|
+
The default adapter runs Ness through OpenRouter. The `evals/codex` adapter runs
|
|
4
|
+
the same Ness SDK through the ChatGPT-authenticated Codex Responses transport.
|
|
5
|
+
|
|
6
|
+
Install the eval dependencies:
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
uv sync --group evals
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Run one selected Terminal-Bench 2.1 task on Modal:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
PYTHONPATH=. uv run --group evals harbor run \
|
|
16
|
+
-d terminal-bench/terminal-bench-2-1 \
|
|
17
|
+
--include-task-name terminal-bench/headless-terminal \
|
|
18
|
+
--agent evals.ness_harbor_agent:NessAgent \
|
|
19
|
+
--model openrouter/deepseek/deepseek-v4-flash \
|
|
20
|
+
--env modal \
|
|
21
|
+
--env-file .env \
|
|
22
|
+
--jobs-dir evals/jobs \
|
|
23
|
+
--n-concurrent 3 \
|
|
24
|
+
--n-attempts 3
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Use another `--include-task-name` value to select a different task. Repeat the
|
|
28
|
+
flag to run several named tasks in one job. `--n-concurrent` is the number of concurrent sandboxes while
|
|
29
|
+
`--n-attempts` is the number of attempts on the same task. Rewards are averaged by the number of attempts.
|
|
30
|
+
|
|
31
|
+
Or run it with the config file:
|
|
32
|
+
```bash
|
|
33
|
+
PYTHONPATH=. uv run --group evals harbor run \
|
|
34
|
+
-c evals/configs/tb-single-task.yaml \
|
|
35
|
+
--env-file .env
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
To run the Ness SDK through the ChatGPT-authenticated Codex model, use the
|
|
39
|
+
separate Codex config. `CODEX_AUTH_JSON=true` makes the adapter read
|
|
40
|
+
`~/.codex/auth.json` on the host, upload it only for the agent phase, and remove
|
|
41
|
+
the temporary copy when the trial ends:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
CODEX_AUTH_JSON=true \
|
|
45
|
+
PYTHONPATH=. uv run --group evals harbor run \
|
|
46
|
+
-c evals/configs/tb-single-task-codex.yaml \
|
|
47
|
+
--env-file .env
|
|
48
|
+
```
|
|
49
|
+
The auth file is not committed and must not be placed under `evals/jobs`.
|
|
50
|
+
|
|
51
|
+
Codex subscription runs attach an API-equivalent cost estimate to each usage
|
|
52
|
+
event. The standard short-context rates (USD per 1M tokens) are:
|
|
53
|
+
|
|
54
|
+
| Model | Input | Cached input | Output | Cache write |
|
|
55
|
+
| --- | ---: | ---: | ---: | ---: |
|
|
56
|
+
| `gpt-5.6-sol` | $4.00 | $0.40 | $20.00 | $5.00 |
|
|
57
|
+
| `gpt-5.6-terra` | $2.00 | $0.20 | $12.00 | $2.50 |
|
|
58
|
+
| `gpt-5.6-luna` | $0.20 | $0.02 | $1.20 | $0.25 |
|
|
59
|
+
|
|
60
|
+
These mirror the [OpenAI API pricing schedule](https://developers.openai.com/api/docs/pricing)
|
|
61
|
+
for estimation only; they are not ChatGPT subscription charges. Prompts over
|
|
62
|
+
272K input tokens use the long-context multipliers from that schedule.
|
|
63
|
+
|
|
64
|
+
If you want to view the jobs info:
|
|
65
|
+
```bash
|
|
66
|
+
harbor view jobs
|
|
67
|
+
```
|
|
68
|
+
and visit `localhost:8080`
|