Skip to content

Commit 1dc0be4

Browse files
committed
feat(hawk-sdk-python): align __version__ with pyproject, add User-Agent, full OSS bootstrap
The prior hardening commit bumped pyproject.toml to 0.2.0 but missed `src/hawk/_version.py`, which still reported 0.1.0. This commit fixes that inconsistency and lands the OSS standard files that were missing. Version surface (fixed + added): - src/hawk/_version.py — `__version__ = "0.2.0"` (was 0.1.0). pyproject.toml was already 0.2.0. - src/hawk/client.py — both `HawkClient._build_headers` and `AsyncHawkClient._build_headers` now set `User-Agent: hawk-sdk-python/<__version__>`. httpx merges client-default headers with per-request overrides, so this also covers the streaming endpoint without changing the per-request `headers={"Accept": "text/event-stream"}` override. New OSS files (this is the first PR to add them): - CHANGELOG.md — Keep-a-Changelog format with [Unreleased] capturing this PR + a backfilled [0.1.0] entry for the initial SDK and prior hardening pass. - CONTRIBUTING.md — quick start with venv + editable install, branch flow (this repo branches from main), conventional commits, code standards (mypy --strict, ruff, async-first, Pydantic v2, User-Agent rule), testing with respx, and the bump-both-version-files procedure. - SECURITY.md — vulnerability reporting via GitHub Security Advisories, in-scope examples (token leakage, TLS misuse, Pydantic deserialization issues, redirect host escape), out-of-scope pointers (daemon issues to hawk repo, third-party-package issues upstream). - CODE_OF_CONDUCT.md — Contributor Covenant 2.1. - .gitattributes — LF normalization, binary detection, linguist hints to collapse lock files. - .editorconfig — UTF-8, LF, 4-space indent for Python (PEP 8), 2-space for YAML/JSON/TOML, no-trim for Markdown. - .github/workflows/ci.yml — pytest matrix on Python 3.9 / 3.10 / 3.11 / 3.12 / 3.13, ruff (lint + format check), mypy --strict, build sdist + wheel + twine check. - .github/dependabot.yml — weekly pip + github-actions, pip grouped by pydantic and pytest to reduce PR noise. - .github/PULL_REQUEST_TEMPLATE.md — Summary / Changes / API impact (with bump-both-files reminder) / Daemon compatibility / Async compatibility (sync + async kept in lock-step) / Testing / Checklist (incl. User-Agent rule). - .github/ISSUE_TEMPLATE/bug_report.yml — surface dropdown (HawkClient / AsyncHawkClient / streaming / retry / tools / agent / workflow / typed errors / build), required SDK + daemon + Python versions, package-versions textarea. - .github/ISSUE_TEMPLATE/feature_request.yml — kind selector covering 9 areas (client method / streaming / retry / errors / tools / agent-workflow / pydantic / config / tooling) and solo-dev fit checks (incl. 'sync and async kept in lock-step', 'does not break wire-compatibility with existing daemon versions'). - .github/ISSUE_TEMPLATE/config.yml — routes security to advisories, questions to discussions, blocks blank issues. - .gitignore — expanded from 6 lines to cover the broader Python toolchain (venv dirs, .mypy_cache, .ruff_cache, .pytest_cache, .tox, .nox, htmlcov, coverage.xml, .env). Verification: - `pytest` — 65/65 pass (1 pre-existing cosmetic warning in test_workflow.py about an unawaited coroutine in a mock; not introduced by this PR) - `hawk.__version__` returns "0.2.0" - `HawkClient._build_headers()` returns {'Accept': 'application/json', 'User-Agent': 'hawk-sdk-python/0.2.0'}
1 parent 2560031 commit 1dc0be4

15 files changed

Lines changed: 833 additions & 6 deletions

.editorconfig

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
root = true
2+
3+
[*]
4+
charset = utf-8
5+
end_of_line = lf
6+
insert_final_newline = true
7+
trim_trailing_whitespace = true
8+
indent_style = space
9+
indent_size = 2
10+
11+
# Python: 4 spaces (PEP 8).
12+
[*.py]
13+
indent_style = space
14+
indent_size = 4
15+
max_line_length = 100
16+
17+
# Makefile-likes use tabs by language convention.
18+
[{Makefile,*.mk,**.mk}]
19+
indent_style = tab
20+
indent_size = 4
21+
22+
# YAML / JSON / TOML: 2 spaces.
23+
[*.{yml,yaml,json,toml}]
24+
indent_style = space
25+
indent_size = 2
26+
27+
# Markdown: trailing whitespace can be significant (line break with two spaces).
28+
[*.md]
29+
trim_trailing_whitespace = false

.gitattributes

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Default: normalize line endings to LF on commit, leave the working copy alone.
2+
* text=auto eol=lf
3+
4+
# Explicitly LF for source, scripts, and config — never CRLF.
5+
*.py text eol=lf
6+
*.md text eol=lf
7+
*.yml text eol=lf
8+
*.yaml text eol=lf
9+
*.json text eol=lf
10+
*.toml text eol=lf
11+
*.cfg text eol=lf
12+
*.ini text eol=lf
13+
*.sh text eol=lf
14+
Makefile text eol=lf
15+
16+
# Windows-only files keep CRLF.
17+
*.bat text eol=crlf
18+
*.cmd text eol=crlf
19+
*.ps1 text eol=crlf
20+
21+
# Binary files — never diffed, never EOL-normalized.
22+
*.png binary
23+
*.jpg binary
24+
*.jpeg binary
25+
*.gif binary
26+
*.ico binary
27+
*.zip binary
28+
*.tar binary
29+
*.tar.gz binary
30+
*.gz binary
31+
*.pdf binary
32+
*.whl binary
33+
34+
# Generated / lock files — collapse in PR diffs (GitHub linguist hint).
35+
poetry.lock linguist-generated=true
36+
Pipfile.lock linguist-generated=true
37+
uv.lock linguist-generated=true
38+
requirements*.txt linguist-generated=true
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
name: Bug report
2+
description: Something is broken or behaving unexpectedly.
3+
title: "bug: <one-line summary>"
4+
labels: ["bug", "triage"]
5+
6+
body:
7+
- type: markdown
8+
attributes:
9+
value: |
10+
Thanks for taking the time to file a bug report. Please fill in as much
11+
of the form as you can — the more we know, the faster we can fix it.
12+
13+
Before submitting:
14+
- Search [existing issues](https://github.com/GrayCodeAI/hawk-sdk-python/issues) to avoid duplicates.
15+
- If this is a security issue, please **do not** file a public issue. See `SECURITY.md`.
16+
17+
- type: textarea
18+
id: what-happened
19+
attributes:
20+
label: What happened?
21+
description: A clear, concise description of the bug.
22+
placeholder: When I call HawkClient.<method>, I expected X but got Y.
23+
validations:
24+
required: true
25+
26+
- type: dropdown
27+
id: surface
28+
attributes:
29+
label: Surface
30+
description: Which SDK surface is affected?
31+
options:
32+
- "HawkClient (sync)"
33+
- "AsyncHawkClient (async)"
34+
- "Streaming (chat_stream / StreamReader)"
35+
- "Retry / backoff"
36+
- "Tools (chat_with_tools, @tool decorator)"
37+
- "Agent / AsyncAgent"
38+
- "Workflow / AsyncWorkflow"
39+
- "Typed errors (HawkAPIError hierarchy)"
40+
- "Build / packaging"
41+
validations:
42+
required: true
43+
44+
- type: textarea
45+
id: reproduce
46+
attributes:
47+
label: Steps to reproduce
48+
description: Minimal Python snippet that reliably reproduces the problem.
49+
render: python
50+
placeholder: |
51+
from hawk import HawkClient
52+
with HawkClient() as c:
53+
resp = c.chat("hello")
54+
# ^ wrong shape / panic / hang / etc.
55+
validations:
56+
required: true
57+
58+
- type: textarea
59+
id: expected
60+
attributes:
61+
label: Expected behavior
62+
description: What did you expect to happen instead?
63+
validations:
64+
required: true
65+
66+
- type: input
67+
id: sdk-version
68+
attributes:
69+
label: hawk-sdk version
70+
description: Output of `python -c "import hawk; print(hawk.__version__)"`.
71+
placeholder: "0.2.0"
72+
validations:
73+
required: true
74+
75+
- type: input
76+
id: daemon-version
77+
attributes:
78+
label: hawk daemon version
79+
description: Output of `hawk version` (the daemon you're hitting).
80+
placeholder: "0.2.0"
81+
validations:
82+
required: true
83+
84+
- type: input
85+
id: python-version
86+
attributes:
87+
label: Python version
88+
description: Output of `python --version`.
89+
placeholder: "Python 3.11.9"
90+
validations:
91+
required: true
92+
93+
- type: input
94+
id: os
95+
attributes:
96+
label: Operating system
97+
description: e.g. macOS 14.5 (arm64), Ubuntu 24.04 (amd64), Windows 11 (amd64).
98+
placeholder: "macOS 14.5 (arm64)"
99+
validations:
100+
required: true
101+
102+
- type: textarea
103+
id: deps
104+
attributes:
105+
label: Relevant package versions
106+
description: |
107+
Paste the output of `pip freeze | grep -E "^(httpx|pydantic|hawk-sdk)"` (or `uv pip list` equivalent).
108+
render: shell
109+
110+
- type: textarea
111+
id: logs
112+
attributes:
113+
label: Logs / traceback
114+
description: |
115+
Paste any relevant output, including the full traceback.
116+
**Redact API tokens, session IDs, and any private data first.**
117+
render: shell
118+
119+
- type: checkboxes
120+
id: confirm
121+
attributes:
122+
label: Confirmation
123+
options:
124+
- label: I searched existing issues and did not find a duplicate.
125+
required: true
126+
- label: I redacted any secrets, tokens, or private data from logs.
127+
required: true

.github/ISSUE_TEMPLATE/config.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
blank_issues_enabled: false
2+
contact_links:
3+
- name: Security vulnerability
4+
url: https://github.com/GrayCodeAI/hawk-sdk-python/security/advisories/new
5+
about: Please report security issues privately via a GitHub Security Advisory. See SECURITY.md.
6+
- name: Question / discussion
7+
url: https://github.com/GrayCodeAI/hawk-sdk-python/discussions
8+
about: Have a question or want to discuss an idea? Open a discussion instead of an issue.
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
name: Feature request
2+
description: Suggest an improvement or a new SDK capability.
3+
title: "feat: <one-line summary>"
4+
labels: ["enhancement", "triage"]
5+
6+
body:
7+
- type: markdown
8+
attributes:
9+
value: |
10+
Thanks for proposing a feature. hawk-sdk is a thin Python client for
11+
the local hawk daemon. Every feature is evaluated against whether it
12+
serves **a single developer** running their own hawk daemon — i.e.
13+
it improves ergonomics, lowers latency, or simplifies integration.
14+
15+
Before submitting:
16+
- Search [existing issues](https://github.com/GrayCodeAI/hawk-sdk-python/issues) to avoid duplicates.
17+
- For new daemon endpoints, the daemon side must land first.
18+
19+
- type: dropdown
20+
id: kind
21+
attributes:
22+
label: Kind of feature
23+
description: What flavour of change is this?
24+
options:
25+
- "New client method (wraps a daemon endpoint)"
26+
- "Streaming / SSE handling"
27+
- "Retry / backoff / resilience"
28+
- "Typed errors / error categories"
29+
- "Tools (chat_with_tools, @tool decorator)"
30+
- "Agent / Workflow orchestration"
31+
- "Pydantic model / type-hint improvement"
32+
- "Configuration (httpx transport, timeouts, etc.)"
33+
- "Tooling / CI / docs / packaging"
34+
validations:
35+
required: true
36+
37+
- type: textarea
38+
id: problem
39+
attributes:
40+
label: What problem are you trying to solve?
41+
description: Describe the user problem first. Solutions can come later.
42+
placeholder: When I call <method>, I have to write boilerplate Y because the SDK doesn't expose X.
43+
validations:
44+
required: true
45+
46+
- type: textarea
47+
id: proposal
48+
attributes:
49+
label: Proposed solution
50+
description: How would you like the SDK to behave? Snippet of API you'd want.
51+
render: python
52+
validations:
53+
required: true
54+
55+
- type: textarea
56+
id: alternatives
57+
attributes:
58+
label: Alternatives considered
59+
description: |
60+
What did you try? What do other SDKs (`openai-python`,
61+
`anthropic-sdk-python`, `langchain`, `llama-index`, `dspy`,
62+
`instructor`, `marvin`, `pydantic-ai`, `mirascope`, `magentic`)
63+
do? Why isn't that enough?
64+
65+
- type: checkboxes
66+
id: principles
67+
attributes:
68+
label: Solo-developer fit
69+
description: hawk-sdk avoids enterprise scope. Confirm this feature respects that.
70+
options:
71+
- label: Works with zero configuration (sensible defaults).
72+
- label: Does not introduce a third-party network dependency.
73+
- label: Does not break wire-compatibility with existing daemon versions.
74+
- label: Sync and async variants are kept in lock-step.
75+
- label: Has an escape hatch (override via parameter, transport, or env).

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
<!--
2+
Thanks for your contribution! Please fill out this template so reviewers can
3+
understand the change quickly. Anything that does not apply can be left in
4+
place; do not delete unanswered sections — write "n/a".
5+
-->
6+
7+
## Summary
8+
9+
<!--
10+
One paragraph describing what this PR does and why. Link the related
11+
issue(s) with `Fixes #N` or `Refs #N` if applicable.
12+
-->
13+
14+
## Changes
15+
16+
<!--
17+
Bullet list of what changed, grouped by area (client, agent, tools,
18+
workflow, streaming, errors, retry, types, version, CI, docs).
19+
Reviewers should be able to skim this and know what to look at first.
20+
-->
21+
22+
-
23+
24+
## API impact
25+
26+
<!--
27+
Did you add, remove, rename, or change the signature of any exported
28+
symbol? List them here. If yes, confirm whether this is a breaking
29+
change and bump the version accordingly in `pyproject.toml` and
30+
`src/hawk/_version.py` (both must agree). If no exported surface
31+
changed, write "n/a".
32+
-->
33+
34+
## Daemon compatibility
35+
36+
<!--
37+
This SDK targets the hawk daemon `v1` API. Did you change endpoints,
38+
request/response shapes, headers, or status-code handling?
39+
40+
- Which daemon versions did you test against (commit SHA / tag)?
41+
- Is the change wire-compatible with the latest released daemon?
42+
- If not, link the corresponding daemon PR.
43+
-->
44+
45+
## Async compatibility
46+
47+
<!--
48+
Every public client method has both a sync and an async variant.
49+
Did you change one without the other? If yes, explain why. Otherwise
50+
confirm both `HawkClient.<method>` and `AsyncHawkClient.<method>`
51+
were updated together.
52+
-->
53+
54+
## Testing
55+
56+
<!--
57+
Describe how you tested. Paste output of `make test` and `make lint`.
58+
If you added new tests, list them.
59+
-->
60+
61+
```text
62+
$ make test
63+
...
64+
$ make lint
65+
...
66+
$ make typecheck
67+
...
68+
```
69+
70+
## Checklist
71+
72+
- [ ] Commits follow [Conventional Commits](https://www.conventionalcommits.org/)
73+
(`feat:`, `fix:`, `perf:`, `refactor:`, `docs:`, `test:`, etc.)
74+
- [ ] `make test` passes locally
75+
- [ ] `make lint` (ruff check + ruff format --check) passes
76+
- [ ] `make typecheck` (mypy --strict) passes
77+
- [ ] New or changed code has tests (table-driven / parametrized where
78+
appropriate, using `respx` for HTTP mocking)
79+
- [ ] Public APIs have docstrings and type hints
80+
- [ ] `CHANGELOG.md` updated under `## [Unreleased]` if user-visible
81+
- [ ] **Both `pyproject.toml` and `src/hawk/_version.py` are bumped
82+
together** if this is a release-eligible change
83+
- [ ] Sync and async client variants are kept in lock-step
84+
- [ ] Every new outbound HTTP request inherits `User-Agent:
85+
hawk-sdk-python/<__version__>` via `_build_headers()`
86+
- [ ] No secrets, tokens, or PII added to the repo
87+
- [ ] No `Co-authored-by:` trailers (this is solo-developer work)

0 commit comments

Comments
 (0)