Skip to content

Commit 3ad9873

Browse files
committed
bump version 0.4.2 -> 0.5.0
Major Fixes and Improvements
1 parent c30944f commit 3ad9873

95 files changed

Lines changed: 14077 additions & 2681 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.agents/skills/acpkit-sdk/SKILL.md

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
---
2+
name: acpkit-sdk
3+
description: Use for ACP Kit SDK work that turns an existing agent surface into a truthful ACP server through acpkit, pydantic-acp, and the maintained docs/examples.
4+
---
5+
6+
# ACP Kit SDK
7+
8+
Use this skill when the task is about ACP Kit’s actual SDK surface rather than generic ACP theory.
9+
10+
ACP Kit’s primary job is to take an existing agent surface, usually a `pydantic_ai.Agent`, and expose it as an ACP server boundary without fabricating runtime state the source agent cannot really honor.
11+
12+
This file is the lightweight orchestration entrypoint. The repo-root `SKILL.md` is the longform one-file reference.
13+
14+
Typical triggers:
15+
16+
- `acpkit` CLI target resolution or launch behavior
17+
- `pydantic-acp` runtime behavior, extension seams, or examples
18+
- `codex-auth-helper`
19+
- SDK documentation, examples, and guides that must match the current implementation
20+
21+
## Start Here
22+
23+
Read [resources/intro.md](resources/intro.md) first.
24+
25+
That file explains:
26+
27+
- what ACP Kit currently ships
28+
- which seam to use (`run_acp`, `create_acp_agent`, providers, bridges, `AgentSource`)
29+
- what the adapter can actually do today
30+
- the current guardrails that often matter in real tasks
31+
32+
## Load Only The References You Need
33+
34+
- Public imports, package map, and canonical names:
35+
[references/package-surface.md](references/package-surface.md)
36+
- Runtime semantics, session behavior, plans, approvals, slash commands, MCP, projections:
37+
[references/runtime-capabilities.md](references/runtime-capabilities.md)
38+
- Docs pages, maintained examples, and showcase mapping:
39+
[references/docs-examples-map.md](references/docs-examples-map.md)
40+
41+
## Utility Scripts
42+
43+
Use the bundled scripts instead of guessing:
44+
45+
- `python3.11 .agents/skills/acpkit-sdk/scripts/list_public_exports.py`
46+
- `python3.11 .agents/skills/acpkit-sdk/scripts/list_examples.py`
47+
48+
## Working Rules
49+
50+
- Prefer current code over stale memory.
51+
- If docs and code disagree, trust code first and update docs.
52+
- Do not invent ACP surface the runtime cannot actually honor.
53+
- Keep examples runnable, explicit, and strongly typed.
54+
- `FileSessionStore` uses `root=Path(...)`.
55+
- Mode slash commands are dynamic, and mode ids must not collide with reserved names such as `model`, `thinking`, `tools`, `hooks`, or `mcp-servers`.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
interface:
2+
display_name: "ACP Kit SDK"
3+
short_description: "Turn agent surfaces into ACP servers"
4+
default_prompt: "Use $acpkit-sdk to update ACP Kit code, examples, or docs for turning an existing agent surface into a truthful ACP server."
5+
6+
policy:
7+
allow_implicit_invocation: true
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# ACP Kit SDK Intro
2+
3+
ACP Kit is a Python SDK and CLI for turning an existing agent surface into a truthful ACP server boundary.
4+
5+
Today that mostly means exposing `pydantic_ai.Agent` through `pydantic-acp`, while keeping models, modes, plans, approvals, MCP metadata, host tools, and session state aligned with what the underlying runtime can actually support.
6+
7+
This intro is intentionally short. The canonical deep references should come from the docs set in `docs/`, not from a second parallel skill-specific spec.
8+
9+
## Core Positioning
10+
11+
ACP Kit is not a new agent framework.
12+
13+
It sits between:
14+
15+
- an existing agent runtime
16+
- ACP clients such as editors and host applications
17+
18+
The central contract is:
19+
20+
> expose ACP state only when the underlying runtime can actually honor it.
21+
22+
That rule drives model selection, mode switching, slash commands, native plan state, approval flow, MCP metadata, and host-backed tooling.
23+
24+
## Start With The Real Docs
25+
26+
Published docs base URL:
27+
28+
- `https://vcoderun.github.io/acpkit/`
29+
30+
Use these docs pages as the primary references:
31+
32+
| Need | Local source | Published docs |
33+
| --- | --- | --- |
34+
| Product overview and package map | `docs/index.md` | `https://vcoderun.github.io/acpkit/` |
35+
| Construction seams and adapter overview | `docs/pydantic-acp.md` | `https://vcoderun.github.io/acpkit/pydantic-acp/` |
36+
| Runtime config and session ownership | `docs/pydantic-acp/adapter-config.md` | `https://vcoderun.github.io/acpkit/pydantic-acp/adapter-config/` |
37+
| Models, modes, slash commands, thinking | `docs/pydantic-acp/runtime-controls.md` | `https://vcoderun.github.io/acpkit/pydantic-acp/runtime-controls/` |
38+
| Plans, approvals, and cancellation | `docs/pydantic-acp/plans-thinking-approvals.md` | `https://vcoderun.github.io/acpkit/pydantic-acp/plans-thinking-approvals/` |
39+
| Host-owned state patterns | `docs/providers.md` | `https://vcoderun.github.io/acpkit/providers/` |
40+
| ACP-visible extension seams | `docs/bridges.md` | `https://vcoderun.github.io/acpkit/bridges/` |
41+
| Host-backed tools and projections | `docs/host-backends.md` | `https://vcoderun.github.io/acpkit/host-backends/` |
42+
| Maintained example ladder | `docs/examples/index.md` | `https://vcoderun.github.io/acpkit/examples/` |
43+
| Production showcase | `docs/examples/workspace-agent.md` | `https://vcoderun.github.io/acpkit/examples/workspace-agent/` |
44+
| API surface | `docs/api/pydantic_acp.md` | `https://vcoderun.github.io/acpkit/api/pydantic_acp/` |
45+
46+
## Construction Seams To Reach For
47+
48+
Use these seams intentionally:
49+
50+
| Seam | Use it when |
51+
| --- | --- |
52+
| `run_acp(agent=...)` | you want the smallest direct path from `pydantic_ai.Agent` to a running ACP server |
53+
| `create_acp_agent(...)` | you need the ACP-compatible agent object before running it |
54+
| `agent_factory=` | session context should influence agent construction, but a full custom source is unnecessary |
55+
| `agent_source=` | you need full control over agent build path, host binding, and session-specific dependencies |
56+
| built-in `AdapterConfig` fields | the adapter can own the relevant session state cleanly |
57+
| providers | the host or product layer should remain the source of truth |
58+
| bridges | the runtime needs ACP-visible capabilities without hard-coding them into the adapter core |
59+
60+
## High-Value Guardrails
61+
62+
- `FileSessionStore` takes `root=Path(...)`, not `base_dir=...`
63+
- slash mode commands are dynamic; `ask`, `plan`, and `agent` are examples, not built-in global names
64+
- mode ids must not collide with reserved slash command names like `model`, `thinking`, `tools`, `hooks`, or `mcp-servers`
65+
- only one `PrepareToolsMode(..., plan_mode=True)` is allowed
66+
- `plan_tools=True` is how a non-plan execution mode keeps plan progress tools visible
67+
- `/thinking` only exists when `ThinkingBridge()` is configured
68+
- native ACP plan state and `PlanProvider` are separate ownership paths
69+
- `HookBridge(hide_all=True)` suppresses hook listing output, not the underlying hook capability itself
70+
71+
## Reference Files In This Skill
72+
73+
These skill-local references are only routing aids back into the docs:
74+
75+
- `references/package-surface.md`
76+
- `references/runtime-capabilities.md`
77+
- `references/docs-examples-map.md`
78+
79+
Use them to find the right docs page quickly, not as independent source-of-truth specs.
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
from __future__ import annotations as _annotations
2+
3+
from pathlib import Path
4+
5+
_EXAMPLE_DESCRIPTIONS = {
6+
"approvals.py": "native deferred approval flow",
7+
"bridges.py": "bridge builder and ACP-visible capabilities",
8+
"factory_agent.py": "session-aware factory plus session-local model selection",
9+
"hook_projection.py": "hook event labels and visibility controls",
10+
"host_context.py": "client-backed filesystem and terminal helpers",
11+
"providers.py": "host-owned models, modes, config, plan state, and approval metadata",
12+
"static_agent.py": "smallest possible run_acp(agent=...) integration",
13+
"strong_agent.py": "full workspace coding-agent showcase",
14+
"strong_agent_v2.py": "alternative workspace integration shape",
15+
}
16+
17+
18+
def _repo_root() -> Path:
19+
return Path(__file__).resolve().parents[4]
20+
21+
22+
def main() -> None:
23+
examples_dir = _repo_root() / "examples" / "pydantic"
24+
for example_path in sorted(examples_dir.glob("*.py")):
25+
if example_path.name == "__init__.py":
26+
continue
27+
description = _EXAMPLE_DESCRIPTIONS.get(example_path.name, "no mapped description")
28+
print(f"{example_path.relative_to(_repo_root())}: {description}")
29+
30+
31+
if __name__ == "__main__":
32+
main()
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
from __future__ import annotations as _annotations
2+
3+
import ast
4+
from pathlib import Path
5+
6+
7+
def _repo_root() -> Path:
8+
return Path(__file__).resolve().parents[4]
9+
10+
11+
def _extract_exports(module_path: Path) -> tuple[str, ...]:
12+
module = ast.parse(module_path.read_text(encoding="utf-8"))
13+
for node in module.body:
14+
if isinstance(node, ast.Assign):
15+
if len(node.targets) != 1:
16+
continue
17+
target = node.targets[0]
18+
if isinstance(target, ast.Name) and target.id == "__all__":
19+
value = ast.literal_eval(node.value)
20+
if isinstance(value, tuple | list) and all(isinstance(item, str) for item in value):
21+
return tuple(value)
22+
raise ValueError(f"Could not locate __all__ in {module_path}")
23+
24+
25+
def main() -> None:
26+
root = _repo_root()
27+
module_paths = {
28+
"acpkit": root / "src" / "acpkit" / "__init__.py",
29+
"pydantic_acp": root
30+
/ "packages"
31+
/ "adapters"
32+
/ "pydantic-acp"
33+
/ "src"
34+
/ "pydantic_acp"
35+
/ "__init__.py",
36+
"codex_auth_helper": root
37+
/ "packages"
38+
/ "helpers"
39+
/ "codex-auth-helper"
40+
/ "src"
41+
/ "codex_auth_helper"
42+
/ "__init__.py",
43+
}
44+
for package_name, module_path in module_paths.items():
45+
print(f"[{package_name}]")
46+
for export_name in _extract_exports(module_path):
47+
print(f"- {export_name}")
48+
print()
49+
50+
51+
if __name__ == "__main__":
52+
main()

.github/workflows/docs.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@ jobs:
2525
- name: Install dependencies
2626
run: |
2727
uv venv
28-
uv pip install -e ".[docs]"
28+
uv pip install -e ".[docs,pydantic,codex]"
2929
3030
- name: Deploy MkDocs
3131
run: |
3232
source .venv/bin/activate
33-
mkdocs gh-deploy --force
33+
mkdocs gh-deploy --force --strict

.gitignore

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ htmlcov/
5454
.Python
5555
build/
5656
dist/
57+
site/
5758
*.egg-info/
5859
tmp/
5960

@@ -68,12 +69,14 @@ references
6869
pydantic-acp.md
6970
AGENTS.md
7071
SPEC.md
71-
AGENTS.md
72-
AGENTS.md
73-
AGENTS.md
72+
73+
# Sessions
74+
.acp-sessions/
75+
.demo-sessions/
7476

7577
# Temporary
7678
tmp
7779
*.snapshot
7880
bump.sh
7981
local.sh
82+
coverage.json

.pre-commit-config.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,16 @@ repos:
33
rev: v4.5.0
44
hooks:
55
- id: check-yaml
6+
args: [--unsafe]
67
- id: check-toml
78

89
- repo: local
910
hooks:
11+
- id: check-coverage
12+
name: check coverage thresholds
13+
entry: make check-coverage
14+
language: system
15+
pass_filenames: false
1016
- id: make-prod
1117
name: verify build
1218
entry: make prod

COVERAGE

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Line coverage: 97.89% (3519 / 3566)
2+
Branch coverage: 95.55% (1160 / 1214)

Makefile

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ GREEN := \033[1;32m
33
RESET := \033[0m
44
PYTHON_VERSIONS := 3.11.13 3.12.10 3.13.9
55

6-
.PHONY: tests format check-formatted check check-matrix all prod rename serve
6+
.PHONY: tests coverage-branch check-coverage save-coverage format check-formatted check check-matrix all prod rename serve
77

88
# Hack to allow passing arguments to make commands (e.g. make rename my_project)
99
ifeq (rename,$(firstword $(MAKECMDGOALS)))
@@ -47,7 +47,7 @@ check-matrix:
4747
printf "$(BLUE)==>$(RESET) Running validation matrix for Python $$version...\n"; \
4848
uv run --extra dev --python $$version ruff check src/acpkit tests || exit $$?; \
4949
uv run --extra dev --python $$version ty check --python-version $$short_version || exit $$?; \
50-
uv run --extra dev --python $$version basedpyright --pythonversion $$short_version || exit $$?; \
50+
uv run --extra dev --python $$version python -m basedpyright --pythonversion $$short_version src packages tests || exit $$?; \
5151
done
5252
@printf "$(GREEN)✔ Matrix checking complete.$(RESET)\n"
5353

@@ -56,10 +56,36 @@ tests:
5656
@uv run --extra dev pytest
5757
@printf "$(GREEN)✔ Tests complete.$(RESET)\n"
5858

59+
coverage-branch:
60+
@printf "$(BLUE)==>$(RESET) Running branch coverage for pydantic-acp...\n"
61+
@uv run --extra dev pytest -p pytest_cov tests/pydantic tests/test_acpkit_cli.py tests/test_native_pydantic_agent.py --cov=packages/adapters/pydantic-acp/src/pydantic_acp --cov-branch --cov-report=json -q
62+
@printf "$(GREEN)✔ Branch coverage complete. See coverage.json.$(RESET)\n"
63+
64+
check-coverage:
65+
@printf "$(BLUE)==>$(RESET) Checking line and branch coverage thresholds for pydantic-acp...\n"
66+
@set -e; \
67+
tmp_file=$$(mktemp -t acpkit-coverage); \
68+
trap 'rm -f "$$tmp_file"' EXIT; \
69+
uv run --extra dev pytest -p pytest_cov tests/pydantic tests/test_acpkit_cli.py tests/test_native_pydantic_agent.py --cov=packages/adapters/pydantic-acp/src/pydantic_acp --cov-branch --cov-report=json:$$tmp_file -q; \
70+
uv run --extra dev python scripts/save_coverage_summary.py --input "$$tmp_file" --check-only
71+
@printf "$(GREEN)✔ Coverage thresholds satisfied.$(RESET)\n"
72+
73+
save-coverage:
74+
@printf "$(BLUE)==>$(RESET) Running line and branch coverage for pydantic-acp...\n"
75+
@uv run --extra dev pytest -p pytest_cov tests/pydantic tests/test_acpkit_cli.py tests/test_native_pydantic_agent.py --cov=packages/adapters/pydantic-acp/src/pydantic_acp --cov-branch --cov-report=json -q
76+
@printf "$(BLUE)==>$(RESET) Saving coverage summary to COVERAGE...\n"
77+
@uv run --extra dev python scripts/save_coverage_summary.py
78+
@printf "$(GREEN)✔ Coverage summary written to COVERAGE.$(RESET)\n"
79+
5980
serve:
6081
@printf "$(BLUE)==>$(RESET) Serving docs with mkdocs...\n"
61-
@uv run --extra docs mkdocs serve --dev-addr 127.0.0.1:8080
82+
@uv run --extra docs --extra pydantic --extra codex mkdocs serve --dev-addr 127.0.0.1:8080
6283

6384
all: format check
6485

6586
prod: tests format check-matrix
87+
88+
pre-commit:
89+
@printf "$(BLUE)==>$(RESET) Running pre-commit checks...\n"
90+
@uv run --extra dev pre-commit
91+
@printf "$(GREEN)✔ Pre-commit checks complete.$(RESET)\n"

0 commit comments

Comments
 (0)