nighthawk-python 0.2.0__tar.gz → 0.3.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.
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/.claude/rules/docs.md +2 -0
- nighthawk_python-0.3.0/.claude/settings.json +5 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/CHANGELOG.md +13 -1
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/CONTRIBUTING.md +17 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/PKG-INFO +1 -1
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/docs/for-coding-agents.md +3 -33
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/pyproject.toml +1 -1
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/src/nighthawk/runtime/scoping.py +24 -2
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/src/nighthawk/runtime/step_executor.py +11 -25
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/tests/public/test_public_api.py +42 -1
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/.claude/rules/coding.md +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/.claude/unset_envs.sh +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/.devcontainer/Dockerfile.devcontainer +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/.devcontainer/Dockerfile.litellm +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/.devcontainer/devcontainer.json +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/.devcontainer/docker-compose.yaml +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/.devcontainer/litellm-config.yaml +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/.github/dependabot.yml +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/.github/workflows/ci.yml +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/.github/workflows/docs.yml +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/.github/workflows/publish.yml +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/.gitignore +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/.python-version +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/AGENTS.md +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/CLAUDE.md +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/LICENSE +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/README.md +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/docs/api.md +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/docs/assets/nighthawk_logo-128x128.png +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/docs/coding-agent-backends.md +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/docs/design.md +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/docs/index.md +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/docs/providers.md +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/docs/quickstart.md +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/docs/roadmap.md +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/docs/tutorial.md +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/mkdocs.yml +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/pyrightconfig.json +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/src/nighthawk/__init__.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/src/nighthawk/backends/__init__.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/src/nighthawk/backends/base.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/src/nighthawk/backends/claude_code_cli.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/src/nighthawk/backends/claude_code_sdk.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/src/nighthawk/backends/codex.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/src/nighthawk/backends/mcp_boundary.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/src/nighthawk/backends/mcp_server.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/src/nighthawk/backends/tool_bridge.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/src/nighthawk/configuration.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/src/nighthawk/errors.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/src/nighthawk/identifier_path.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/src/nighthawk/json_renderer.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/src/nighthawk/natural/__init__.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/src/nighthawk/natural/blocks.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/src/nighthawk/natural/decorator.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/src/nighthawk/natural/transform.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/src/nighthawk/runtime/__init__.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/src/nighthawk/runtime/async_bridge.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/src/nighthawk/runtime/prompt.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/src/nighthawk/runtime/runner.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/src/nighthawk/runtime/step_context.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/src/nighthawk/runtime/step_contract.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/src/nighthawk/runtime/tool_calls.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/src/nighthawk/tools/__init__.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/src/nighthawk/tools/assignment.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/src/nighthawk/tools/contracts.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/src/nighthawk/tools/execution.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/src/nighthawk/tools/provided.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/src/nighthawk/tools/registry.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/tests/__init__.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/tests/backends/__init__.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/tests/backends/test_claude_code_cli.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/tests/backends/test_claude_code_sdk.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/tests/backends/test_codex.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/tests/conftest.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/tests/docs/__init__.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/tests/docs/test_prompt_examples.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/tests/execution/__init__.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/tests/execution/prompt_test_helpers.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/tests/execution/stub_executor.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/tests/execution/test_execution_outcome_prompt_fragment.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/tests/execution/test_globals_prompt.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/tests/execution/test_natural_block_ordering.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/tests/execution/test_natural_traceback.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/tests/execution/test_runtime.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/tests/execution/test_variables_prompt.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/tests/integration/__init__.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/tests/integration/skip_helpers.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/tests/integration/test_carry_pattern.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/tests/integration/test_claude_code_cli_integration.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/tests/integration/test_claude_code_sdk_integration.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/tests/integration/test_codex_integration.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/tests/integration/test_llm_integration.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/tests/natural/__init__.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/tests/natural/test_blocks.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/tests/public/__init__.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/tests/public/test_readme_example.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/tests/test_renderer.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/tests/tools/__init__.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/tests/tools/test_assignment_async.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/tests/tools/test_contracts.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/tests/tools/test_registry.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/tests/tools/test_tool_boundary.py +0 -0
- {nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/uv.lock +0 -0
|
@@ -91,6 +91,8 @@ Each file has a distinct audience and scope. Content belongs in exactly one file
|
|
|
91
91
|
- This file should be self-contained: a coding agent reading only this file should be able to write correct Nighthawk code without consulting other docs.
|
|
92
92
|
- This file is consumed standalone (`@docs/for-coding-agents.md` in CLAUDE.md/AGENTS.md, GitHub raw URL, etc.). Do not assume sibling files exist at relative paths.
|
|
93
93
|
- All external references to other docs use absolute URLs based on `site_url` from `mkdocs.yml` (currently `https://kurusugawa-computer.github.io/nighthawk-python/`). If `site_url` changes, update the URLs in this file.
|
|
94
|
+
- `@nh.tool` is deprecated. Do not add examples, recommendations, or references to `@nh.tool` in this file. Binding functions are the only recommended callable exposure mechanism.
|
|
95
|
+
- Filter content for coding-agent relevance. Omit infrastructure-level concerns (scoped overrides parameter lists, exception hierarchy beyond `ExecutionError`, observability/tracing) that do not affect how an agent writes Natural blocks or binding functions. Mention existence and link to Tutorial or Design for details.
|
|
94
96
|
|
|
95
97
|
### api.md specifics
|
|
96
98
|
|
|
@@ -7,6 +7,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.3.0] - 2026-03-18
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- `system_prompt_suffix_fragment_scope` and `user_prompt_suffix_fragment_scope` context managers for lightweight prompt fragment management without full scope overhead.
|
|
14
|
+
- OpenTelemetry tracer now reports `instrumenting_library_version`.
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
- Simplified OpenTelemetry span hierarchy: removed implicit `nighthawk.scope` spans and `nighthawk.step_executor` spans. `nighthawk.scope` spans are now emitted only for explicit `nh.scope()` calls.
|
|
18
|
+
- `nighthawk.run` span no longer includes `scope.id` attribute; only `run.id` is emitted.
|
|
19
|
+
- Trimmed `for-coding-agents.md` for coding-agent relevance: removed deprecated `@nh.tool` references, condensed exception hierarchy, scoped overrides, and added debugging context to `StepContextLimits`.
|
|
20
|
+
|
|
10
21
|
## [0.2.0] - 2026-03-16
|
|
11
22
|
|
|
12
23
|
### Added
|
|
@@ -30,6 +41,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
30
41
|
- Step executor abstraction and provider integration foundation.
|
|
31
42
|
- Core documentation and project scaffolding.
|
|
32
43
|
|
|
33
|
-
[Unreleased]: https://github.com/kurusugawa-computer/nighthawk-python/compare/v0.
|
|
44
|
+
[Unreleased]: https://github.com/kurusugawa-computer/nighthawk-python/compare/v0.3.0...HEAD
|
|
45
|
+
[0.3.0]: https://github.com/kurusugawa-computer/nighthawk-python/compare/v0.2.0...v0.3.0
|
|
34
46
|
[0.2.0]: https://github.com/kurusugawa-computer/nighthawk-python/compare/v0.1.0...v0.2.0
|
|
35
47
|
[0.1.0]: https://github.com/kurusugawa-computer/nighthawk-python/tree/v0.1.0
|
|
@@ -53,6 +53,23 @@ Then run with your `.env` loaded:
|
|
|
53
53
|
set -a; source .env; set +a; uv run pytest -q
|
|
54
54
|
```
|
|
55
55
|
|
|
56
|
+
### Trace inspection with otel-tui
|
|
57
|
+
|
|
58
|
+
Nighthawk emits OpenTelemetry traces for step execution. You can inspect them
|
|
59
|
+
locally using [otel-tui](https://github.com/ymtdzzz/otel-tui):
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
docker run --rm -it -p 4318:4318 --name otel-tui ymtdzzz/otel-tui:latest
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Then run integration tests with the collector endpoint:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318 uv run pytest -q tests/integration/
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Traces appear in the otel-tui terminal UI in real time.
|
|
72
|
+
|
|
56
73
|
### Environment variables
|
|
57
74
|
|
|
58
75
|
- `OPENAI_API_KEY`: Required for OpenAI integration tests (also requires `pydantic-ai-slim[openai]`).
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nighthawk-python
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: An experimental Python library that embeds Natural blocks inside Python functions and executes them using an LLM.
|
|
5
5
|
Project-URL: Repository, https://github.com/kurusugawa-computer/nighthawk-python
|
|
6
6
|
Project-URL: Documentation, https://kurusugawa-computer.github.io/nighthawk-python/
|
|
@@ -64,10 +64,6 @@ Each Natural block should make exactly one independent judgment. If a block make
|
|
|
64
64
|
|
|
65
65
|
Binding functions (local or module-level callables) are the preferred way to expose functions to the LLM. The LLM discovers them from the LOCALS/GLOBALS sections of the prompt, rendered as their signature with the first docstring line as `# intent:`.
|
|
66
66
|
|
|
67
|
-
### Prefer binding functions over `@nh.tool`
|
|
68
|
-
|
|
69
|
-
`@nh.tool` is reserved strictly for cases requiring `RunContext[StepContext]` access. Binding functions incur no per-definition token overhead beyond a signature line. Always use binding functions unless `RunContext` access is needed.
|
|
70
|
-
|
|
71
67
|
### Keep locals minimal
|
|
72
68
|
|
|
73
69
|
Module-level names that are stable across invocations (constants, classes, utility functions) should stay in GLOBALS via `<name>` read bindings. Reserve function parameters for data that genuinely varies per call.
|
|
@@ -156,11 +152,7 @@ except nh.ExecutionError as e:
|
|
|
156
152
|
print(f"Validation failed: {e}")
|
|
157
153
|
```
|
|
158
154
|
|
|
159
|
-
Custom exception types referenced in step locals or globals are available as raise targets.
|
|
160
|
-
|
|
161
|
-
### Exception hierarchy
|
|
162
|
-
|
|
163
|
-
All exceptions inherit from `NighthawkError`: `ExecutionError`, `NaturalParseError`, `ToolEvaluationError`, `ToolValidationError`, `ToolRegistrationError`.
|
|
155
|
+
Custom exception types referenced in step locals or globals are available as raise targets. Catch `nh.ExecutionError` for Natural block failures; all Nighthawk exceptions inherit from `nh.NighthawkError`.
|
|
164
156
|
|
|
165
157
|
## 6. Cross-block composition
|
|
166
158
|
|
|
@@ -221,30 +213,9 @@ with nh.run(step_executor):
|
|
|
221
213
|
result = my_natural_function(data)
|
|
222
214
|
```
|
|
223
215
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
Use `nh.scope()` to override execution settings within an existing run. Each scope generates a new `scope_id` while keeping the current `run_id`.
|
|
227
|
-
|
|
228
|
-
Parameters:
|
|
229
|
-
|
|
230
|
-
- `step_executor_configuration`: replace the entire configuration.
|
|
231
|
-
- `step_executor_configuration_patch`: partially override specific fields.
|
|
232
|
-
- `step_executor`: replace the step executor entirely.
|
|
233
|
-
- `system_prompt_suffix_fragment`: append text to the system prompt for the scope.
|
|
234
|
-
- `user_prompt_suffix_fragment`: append text to the user prompt for the scope.
|
|
235
|
-
|
|
236
|
-
```python
|
|
237
|
-
with nh.scope(
|
|
238
|
-
step_executor_configuration_patch=nh.StepExecutorConfigurationPatch(
|
|
239
|
-
model="openai-responses:gpt-5-mini",
|
|
240
|
-
),
|
|
241
|
-
):
|
|
242
|
-
expensive_analysis(data)
|
|
243
|
-
```
|
|
244
|
-
|
|
245
|
-
### Context limits
|
|
216
|
+
Use `nh.scope()` to override model, prompts, or context limits within an existing run. For details, see [Tutorial](https://kurusugawa-computer.github.io/nighthawk-python/tutorial/).
|
|
246
217
|
|
|
247
|
-
LOCALS and GLOBALS sections are bounded by `StepContextLimits`.
|
|
218
|
+
LOCALS and GLOBALS sections are bounded by `StepContextLimits`. When bindings are missing or truncated (`<snipped>`), adjust the limits:
|
|
248
219
|
|
|
249
220
|
```python
|
|
250
221
|
configuration = nh.StepExecutorConfiguration(
|
|
@@ -304,7 +275,6 @@ def judge_review(review_data: str | nh.JsonableValue) -> ReviewVerdict:
|
|
|
304
275
|
| Use `<:carry>` (write binding) for mutable context | Rebinding breaks the caller's reference | Use `<carry>` (read binding); mutate in-place |
|
|
305
276
|
| Put two independent judgments in one block | Non-deterministic, hard to test, unclear contract | Split into two blocks connected by Python |
|
|
306
277
|
| Use Natural for deterministic computation | Wastes latency/cost, adds non-determinism | Use Python |
|
|
307
|
-
| Use `@nh.tool` when a binding function suffices | Unnecessary per-definition token overhead | Use binding functions; reserve `@nh.tool` for `RunContext[StepContext]` access |
|
|
308
278
|
| Forget type annotations on write bindings | No validation or coercion at commit time | Always annotate `<:name>` bindings |
|
|
309
279
|
| Duplicate module-level constants as function parameters | Moves stable values from GLOBALS to LOCALS, wastes tokens | Reference via `<name>` read binding |
|
|
310
280
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import importlib.metadata
|
|
3
4
|
import uuid
|
|
4
5
|
from collections.abc import Iterator
|
|
5
6
|
from contextlib import contextmanager
|
|
@@ -36,7 +37,9 @@ STEP_ID = "step.id"
|
|
|
36
37
|
TOOL_CALL_ID = "tool_call.id"
|
|
37
38
|
|
|
38
39
|
|
|
39
|
-
|
|
40
|
+
_LIBRARY_VERSION = importlib.metadata.version("nighthawk-python")
|
|
41
|
+
|
|
42
|
+
_tracer = get_tracer_provider().get_tracer("nighthawk", _LIBRARY_VERSION)
|
|
40
43
|
|
|
41
44
|
|
|
42
45
|
@contextmanager
|
|
@@ -108,6 +111,26 @@ def get_user_prompt_suffix_fragments() -> tuple[str, ...]:
|
|
|
108
111
|
return _user_prompt_suffix_fragments_var.get()
|
|
109
112
|
|
|
110
113
|
|
|
114
|
+
@contextmanager
|
|
115
|
+
def system_prompt_suffix_fragment_scope(fragment: str) -> Iterator[None]:
|
|
116
|
+
current = _system_prompt_suffix_fragments_var.get()
|
|
117
|
+
token = _system_prompt_suffix_fragments_var.set((*current, fragment))
|
|
118
|
+
try:
|
|
119
|
+
yield
|
|
120
|
+
finally:
|
|
121
|
+
_system_prompt_suffix_fragments_var.reset(token)
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
@contextmanager
|
|
125
|
+
def user_prompt_suffix_fragment_scope(fragment: str) -> Iterator[None]:
|
|
126
|
+
current = _user_prompt_suffix_fragments_var.get()
|
|
127
|
+
token = _user_prompt_suffix_fragments_var.set((*current, fragment))
|
|
128
|
+
try:
|
|
129
|
+
yield
|
|
130
|
+
finally:
|
|
131
|
+
_user_prompt_suffix_fragments_var.reset(token)
|
|
132
|
+
|
|
133
|
+
|
|
111
134
|
def _resolve_agent_step_executor(step_executor: StepExecutor) -> AgentStepExecutor:
|
|
112
135
|
from .step_executor import AgentStepExecutor
|
|
113
136
|
|
|
@@ -179,7 +202,6 @@ def run(
|
|
|
179
202
|
"nighthawk.run",
|
|
180
203
|
**{
|
|
181
204
|
RUN_ID: execution_context.run_id,
|
|
182
|
-
SCOPE_ID: execution_context.scope_id,
|
|
183
205
|
},
|
|
184
206
|
):
|
|
185
207
|
yield
|
|
@@ -13,13 +13,8 @@ from ..tools.registry import get_visible_tools
|
|
|
13
13
|
from .async_bridge import run_coroutine_synchronously
|
|
14
14
|
from .prompt import build_user_prompt, extract_references_and_program
|
|
15
15
|
from .scoping import (
|
|
16
|
-
RUN_ID,
|
|
17
|
-
SCOPE_ID,
|
|
18
|
-
STEP_ID,
|
|
19
|
-
get_execution_context,
|
|
20
16
|
get_system_prompt_suffix_fragments,
|
|
21
|
-
|
|
22
|
-
span,
|
|
17
|
+
system_prompt_suffix_fragment_scope,
|
|
23
18
|
)
|
|
24
19
|
from .step_context import (
|
|
25
20
|
_MISSING,
|
|
@@ -315,25 +310,16 @@ class AgentStepExecutor:
|
|
|
315
310
|
allowed_step_kinds=allowed_step_kinds,
|
|
316
311
|
)
|
|
317
312
|
|
|
318
|
-
with
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
),
|
|
329
|
-
step_context_scope(step_context),
|
|
330
|
-
):
|
|
331
|
-
result = await self._run_agent(
|
|
332
|
-
user_prompt=user_prompt,
|
|
333
|
-
step_context=step_context,
|
|
334
|
-
toolset=toolset,
|
|
335
|
-
structured_output_type=structured_output_type,
|
|
336
|
-
)
|
|
313
|
+
with (
|
|
314
|
+
system_prompt_suffix_fragment_scope(step_system_prompt_fragment),
|
|
315
|
+
step_context_scope(step_context),
|
|
316
|
+
):
|
|
317
|
+
result = await self._run_agent(
|
|
318
|
+
user_prompt=user_prompt,
|
|
319
|
+
step_context=step_context,
|
|
320
|
+
toolset=toolset,
|
|
321
|
+
structured_output_type=structured_output_type,
|
|
322
|
+
)
|
|
337
323
|
|
|
338
324
|
step_outcome = self._parse_agent_result(result)
|
|
339
325
|
bindings = self._extract_bindings(binding_names=binding_names, step_context=step_context)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
+
import importlib.metadata
|
|
2
3
|
from collections.abc import Generator
|
|
3
4
|
|
|
4
5
|
import pytest
|
|
@@ -26,7 +27,7 @@ def step_span_exporter() -> Generator[InMemorySpanExporter, None, None]:
|
|
|
26
27
|
tracer_provider.add_span_processor(SimpleSpanProcessor(span_exporter))
|
|
27
28
|
|
|
28
29
|
previous_tracer_provider = runtime_scoping._tracer
|
|
29
|
-
runtime_scoping._tracer = tracer_provider.get_tracer("nighthawk")
|
|
30
|
+
runtime_scoping._tracer = tracer_provider.get_tracer("nighthawk", importlib.metadata.version("nighthawk-python"))
|
|
30
31
|
try:
|
|
31
32
|
yield span_exporter
|
|
32
33
|
finally:
|
|
@@ -428,3 +429,43 @@ def test_step_span_failure_event_structure_is_compact(step_span_exporter: InMemo
|
|
|
428
429
|
assert "exception" in exception_event_name_set
|
|
429
430
|
assert "nighthawk.step.failed" in exception_event_name_set
|
|
430
431
|
assert len(step_span.events) == 2
|
|
432
|
+
|
|
433
|
+
|
|
434
|
+
def test_run_span_has_only_run_id_attribute(step_span_exporter: InMemorySpanExporter) -> None:
|
|
435
|
+
with nh.run(StubExecutor(), run_id="attr-test"):
|
|
436
|
+
|
|
437
|
+
@nh.natural_function
|
|
438
|
+
def natural_value_function() -> int:
|
|
439
|
+
"""natural
|
|
440
|
+
<:result>
|
|
441
|
+
{"step_outcome": {"kind": "pass"}, "bindings": {"result": 42}}
|
|
442
|
+
"""
|
|
443
|
+
return result # noqa: F821 # pyright: ignore[reportUndefinedVariable]
|
|
444
|
+
|
|
445
|
+
assert natural_value_function() == 42
|
|
446
|
+
|
|
447
|
+
run_span_list = [s for s in step_span_exporter.get_finished_spans() if s.name == "nighthawk.run"]
|
|
448
|
+
assert len(run_span_list) == 1
|
|
449
|
+
run_span = run_span_list[0]
|
|
450
|
+
assert _require_attribute_key_set(run_span) == {"run.id"}
|
|
451
|
+
assert _require_attribute_value(run_span, "run.id") == "attr-test"
|
|
452
|
+
|
|
453
|
+
|
|
454
|
+
def test_no_implicit_scope_or_step_executor_spans(step_span_exporter: InMemorySpanExporter) -> None:
|
|
455
|
+
with nh.run(StubExecutor()):
|
|
456
|
+
|
|
457
|
+
@nh.natural_function
|
|
458
|
+
def natural_value_function() -> int:
|
|
459
|
+
"""natural
|
|
460
|
+
<:result>
|
|
461
|
+
{"step_outcome": {"kind": "pass"}, "bindings": {"result": 7}}
|
|
462
|
+
"""
|
|
463
|
+
return result # noqa: F821 # pyright: ignore[reportUndefinedVariable]
|
|
464
|
+
|
|
465
|
+
assert natural_value_function() == 7
|
|
466
|
+
|
|
467
|
+
span_name_set = {s.name for s in step_span_exporter.get_finished_spans()}
|
|
468
|
+
assert "nighthawk.scope" not in span_name_set
|
|
469
|
+
assert "nighthawk.step_executor" not in span_name_set
|
|
470
|
+
assert "nighthawk.run" in span_name_set
|
|
471
|
+
assert "nighthawk.step" in span_name_set
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/tests/execution/test_natural_block_ordering.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{nighthawk_python-0.2.0 → nighthawk_python-0.3.0}/tests/integration/test_codex_integration.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|