acpkit 0.5.0__tar.gz → 0.7.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (217) hide show
  1. acpkit-0.7.0/.agents/skills/acpkit-sdk/SKILL.md +830 -0
  2. acpkit-0.7.0/.agents/skills/acpkit-sdk/resources/intro.md +171 -0
  3. acpkit-0.7.0/.github/workflows/codecov.yml +30 -0
  4. {acpkit-0.5.0 → acpkit-0.7.0}/.github/workflows/test.yml +2 -2
  5. {acpkit-0.5.0 → acpkit-0.7.0}/.gitignore +8 -2
  6. {acpkit-0.5.0 → acpkit-0.7.0}/.pre-commit-config.yaml +12 -0
  7. acpkit-0.7.0/CONTRIBUTING.md +117 -0
  8. acpkit-0.7.0/COVERAGE +2 -0
  9. {acpkit-0.5.0 → acpkit-0.7.0}/Makefile +1 -1
  10. {acpkit-0.5.0 → acpkit-0.7.0}/PKG-INFO +41 -6
  11. {acpkit-0.5.0 → acpkit-0.7.0}/README.md +40 -5
  12. acpkit-0.7.0/VERSION +1 -0
  13. {acpkit-0.5.0 → acpkit-0.7.0}/docs/about/index.md +8 -1
  14. {acpkit-0.5.0 → acpkit-0.7.0}/docs/api/acpkit.md +8 -0
  15. {acpkit-0.5.0 → acpkit-0.7.0}/docs/api/pydantic_acp.md +34 -0
  16. acpkit-0.7.0/docs/bridges.md +346 -0
  17. acpkit-0.7.0/docs/compatibility-matrix-template.md +246 -0
  18. acpkit-0.7.0/docs/examples/index.md +43 -0
  19. acpkit-0.7.0/docs/host-backends.md +302 -0
  20. {acpkit-0.5.0 → acpkit-0.7.0}/docs/index.md +9 -4
  21. acpkit-0.7.0/docs/integration-audit.md +136 -0
  22. acpkit-0.7.0/docs/integration-readiness.md +70 -0
  23. acpkit-0.7.0/docs/integration-testing.md +277 -0
  24. {acpkit-0.5.0 → acpkit-0.7.0}/docs/llms-full.txt +750 -17
  25. {acpkit-0.5.0 → acpkit-0.7.0}/docs/llms.txt +3 -0
  26. acpkit-0.7.0/docs/projection-cookbook.md +222 -0
  27. {acpkit-0.5.0 → acpkit-0.7.0}/docs/pydantic-acp/adapter-config.md +8 -0
  28. {acpkit-0.5.0 → acpkit-0.7.0}/docs/pydantic-acp/plans-thinking-approvals.md +14 -0
  29. acpkit-0.7.0/docs/pydantic-acp/prompt-resources.md +214 -0
  30. {acpkit-0.5.0 → acpkit-0.7.0}/docs/pydantic-acp/session-state.md +17 -0
  31. {acpkit-0.5.0 → acpkit-0.7.0}/docs/pydantic-acp.md +27 -3
  32. {acpkit-0.5.0 → acpkit-0.7.0}/docs/testing.md +19 -1
  33. {acpkit-0.5.0 → acpkit-0.7.0}/examples/pydantic/strong_agent.py +93 -17
  34. {acpkit-0.5.0 → acpkit-0.7.0}/examples/pydantic/strong_agent_v2.py +158 -17
  35. {acpkit-0.5.0 → acpkit-0.7.0}/mkdocs.yml +6 -0
  36. {acpkit-0.5.0 → acpkit-0.7.0}/packages/adapters/pydantic-acp/README.md +16 -0
  37. acpkit-0.7.0/packages/adapters/pydantic-acp/VERSION +1 -0
  38. {acpkit-0.5.0 → acpkit-0.7.0}/packages/adapters/pydantic-acp/pyproject.toml +4 -1
  39. {acpkit-0.5.0 → acpkit-0.7.0}/packages/adapters/pydantic-acp/src/pydantic_acp/__init__.py +56 -1
  40. acpkit-0.7.0/packages/adapters/pydantic-acp/src/pydantic_acp/_projection_risk.py +48 -0
  41. acpkit-0.7.0/packages/adapters/pydantic-acp/src/pydantic_acp/_projection_text.py +118 -0
  42. acpkit-0.7.0/packages/adapters/pydantic-acp/src/pydantic_acp/_version.py +5 -0
  43. {acpkit-0.5.0 → acpkit-0.7.0}/packages/adapters/pydantic-acp/src/pydantic_acp/bridges/__init__.py +2 -0
  44. acpkit-0.7.0/packages/adapters/pydantic-acp/src/pydantic_acp/bridges/_hook_capability.py +497 -0
  45. {acpkit-0.5.0 → acpkit-0.7.0}/packages/adapters/pydantic-acp/src/pydantic_acp/bridges/history_processor.py +11 -8
  46. acpkit-0.7.0/packages/adapters/pydantic-acp/src/pydantic_acp/bridges/hooks.py +66 -0
  47. {acpkit-0.5.0 → acpkit-0.7.0}/packages/adapters/pydantic-acp/src/pydantic_acp/bridges/mcp.py +12 -1
  48. {acpkit-0.5.0 → acpkit-0.7.0}/packages/adapters/pydantic-acp/src/pydantic_acp/builders/agent.py +6 -10
  49. {acpkit-0.5.0 → acpkit-0.7.0}/packages/adapters/pydantic-acp/src/pydantic_acp/config.py +7 -1
  50. {acpkit-0.5.0 → acpkit-0.7.0}/packages/adapters/pydantic-acp/src/pydantic_acp/hook_projection.py +3 -3
  51. {acpkit-0.5.0 → acpkit-0.7.0}/packages/adapters/pydantic-acp/src/pydantic_acp/host/__init__.py +12 -0
  52. acpkit-0.7.0/packages/adapters/pydantic-acp/src/pydantic_acp/host/_policy_commands.py +82 -0
  53. acpkit-0.7.0/packages/adapters/pydantic-acp/src/pydantic_acp/host/_policy_paths.py +28 -0
  54. acpkit-0.7.0/packages/adapters/pydantic-acp/src/pydantic_acp/host/context.py +69 -0
  55. {acpkit-0.5.0 → acpkit-0.7.0}/packages/adapters/pydantic-acp/src/pydantic_acp/host/filesystem.py +15 -0
  56. acpkit-0.7.0/packages/adapters/pydantic-acp/src/pydantic_acp/host/policy.py +409 -0
  57. {acpkit-0.5.0 → acpkit-0.7.0}/packages/adapters/pydantic-acp/src/pydantic_acp/host/terminal.py +22 -0
  58. {acpkit-0.5.0 → acpkit-0.7.0}/packages/adapters/pydantic-acp/src/pydantic_acp/projection.py +156 -91
  59. acpkit-0.7.0/packages/adapters/pydantic-acp/src/pydantic_acp/projection_helpers.py +24 -0
  60. {acpkit-0.5.0 → acpkit-0.7.0}/packages/adapters/pydantic-acp/src/pydantic_acp/providers.py +16 -2
  61. acpkit-0.7.0/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_adapter_prompt.py +273 -0
  62. acpkit-0.7.0/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_native_plan_runtime.py +335 -0
  63. acpkit-0.7.0/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_prompt_execution.py +384 -0
  64. acpkit-0.7.0/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_prompt_model_runtime.py +157 -0
  65. acpkit-0.7.0/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_prompt_runtime.py +349 -0
  66. acpkit-0.7.0/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_session_lifecycle.py +137 -0
  67. acpkit-0.7.0/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_session_model_runtime.py +187 -0
  68. acpkit-0.7.0/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_session_runtime.py +609 -0
  69. acpkit-0.7.0/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_session_surface_runtime.py +459 -0
  70. {acpkit-0.5.0 → acpkit-0.7.0}/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/adapter.py +41 -173
  71. {acpkit-0.5.0 → acpkit-0.7.0}/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/hook_introspection.py +90 -4
  72. {acpkit-0.5.0 → acpkit-0.7.0}/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/prompts.py +107 -4
  73. {acpkit-0.5.0 → acpkit-0.7.0}/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/slash_commands.py +3 -1
  74. acpkit-0.7.0/packages/adapters/pydantic-acp/src/pydantic_acp/session/store.py +248 -0
  75. acpkit-0.7.0/packages/adapters/pydantic-acp/src/pydantic_acp/testing/__init__.py +11 -0
  76. acpkit-0.7.0/packages/adapters/pydantic-acp/src/pydantic_acp/testing/fakes.py +246 -0
  77. acpkit-0.7.0/packages/adapters/pydantic-acp/src/pydantic_acp/testing/harness.py +162 -0
  78. acpkit-0.7.0/packages/helpers/codex-auth-helper/VERSION +1 -0
  79. {acpkit-0.5.0 → acpkit-0.7.0}/packages/helpers/codex-auth-helper/pyproject.toml +4 -1
  80. {acpkit-0.5.0 → acpkit-0.7.0}/packages/helpers/codex-auth-helper/src/codex_auth_helper/__init__.py +2 -0
  81. acpkit-0.7.0/packages/helpers/codex-auth-helper/src/codex_auth_helper/_version.py +5 -0
  82. {acpkit-0.5.0 → acpkit-0.7.0}/pyproject.toml +4 -1
  83. acpkit-0.7.0/scripts/check_pypi_versions.py +159 -0
  84. {acpkit-0.5.0 → acpkit-0.7.0}/scripts/generate_llms_docs.py +6 -0
  85. {acpkit-0.5.0 → acpkit-0.7.0}/src/acpkit/__init__.py +6 -2
  86. acpkit-0.7.0/src/acpkit/_compatibility_schema.py +111 -0
  87. acpkit-0.7.0/src/acpkit/_version.py +5 -0
  88. acpkit-0.7.0/src/acpkit/compatibility.py +15 -0
  89. acpkit-0.7.0/tests/conftest.py +30 -0
  90. {acpkit-0.5.0 → acpkit-0.7.0}/tests/pydantic/support.py +2 -0
  91. {acpkit-0.5.0 → acpkit-0.7.0}/tests/pydantic/test_adapter_helpers.py +110 -40
  92. {acpkit-0.5.0 → acpkit-0.7.0}/tests/pydantic/test_bridge_mcp.py +40 -0
  93. {acpkit-0.5.0 → acpkit-0.7.0}/tests/pydantic/test_bridge_thinking.py +9 -1
  94. {acpkit-0.5.0 → acpkit-0.7.0}/tests/pydantic/test_hook_introspection.py +39 -0
  95. acpkit-0.7.0/tests/pydantic/test_host_policy.py +247 -0
  96. {acpkit-0.5.0 → acpkit-0.7.0}/tests/pydantic/test_low_level_helpers.py +273 -22
  97. {acpkit-0.5.0 → acpkit-0.7.0}/tests/pydantic/test_models.py +8 -2
  98. acpkit-0.7.0/tests/pydantic/test_projection_helpers.py +126 -0
  99. {acpkit-0.5.0 → acpkit-0.7.0}/tests/pydantic/test_runtime.py +182 -0
  100. {acpkit-0.5.0 → acpkit-0.7.0}/tests/pydantic/test_slash_commands.py +41 -6
  101. acpkit-0.7.0/tests/pydantic/test_testing_fakes.py +165 -0
  102. acpkit-0.7.0/tests/pydantic/test_testing_harness.py +118 -0
  103. {acpkit-0.5.0 → acpkit-0.7.0}/tests/test_acpkit_cli.py +34 -0
  104. acpkit-0.7.0/tests/test_compatibility_manifest.py +103 -0
  105. acpkit-0.5.0/.agents/skills/acpkit-sdk/SKILL.md +0 -57
  106. acpkit-0.5.0/.agents/skills/acpkit-sdk/resources/intro.md +0 -79
  107. acpkit-0.5.0/CONTRIBUTING.md +0 -41
  108. acpkit-0.5.0/COVERAGE +0 -2
  109. acpkit-0.5.0/SKILL.md +0 -452
  110. acpkit-0.5.0/VERSION +0 -1
  111. acpkit-0.5.0/docs/bridges.md +0 -186
  112. acpkit-0.5.0/docs/examples/index.md +0 -43
  113. acpkit-0.5.0/docs/host-backends.md +0 -109
  114. acpkit-0.5.0/packages/adapters/pydantic-acp/VERSION +0 -1
  115. acpkit-0.5.0/packages/adapters/pydantic-acp/src/pydantic_acp/bridges/hooks.py +0 -507
  116. acpkit-0.5.0/packages/adapters/pydantic-acp/src/pydantic_acp/host/context.py +0 -40
  117. acpkit-0.5.0/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_prompt_runtime.py +0 -803
  118. acpkit-0.5.0/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_session_runtime.py +0 -1015
  119. acpkit-0.5.0/packages/adapters/pydantic-acp/src/pydantic_acp/session/store.py +0 -165
  120. acpkit-0.5.0/packages/helpers/codex-auth-helper/VERSION +0 -1
  121. acpkit-0.5.0/tests/conftest.py +0 -18
  122. {acpkit-0.5.0 → acpkit-0.7.0}/.agents/skills/acpkit-sdk/agents/openai.yaml +0 -0
  123. {acpkit-0.5.0 → acpkit-0.7.0}/.agents/skills/acpkit-sdk/scripts/list_examples.py +0 -0
  124. {acpkit-0.5.0 → acpkit-0.7.0}/.agents/skills/acpkit-sdk/scripts/list_public_exports.py +0 -0
  125. {acpkit-0.5.0 → acpkit-0.7.0}/.cursorrules +0 -0
  126. {acpkit-0.5.0 → acpkit-0.7.0}/.editorconfig +0 -0
  127. {acpkit-0.5.0 → acpkit-0.7.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  128. {acpkit-0.5.0 → acpkit-0.7.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  129. {acpkit-0.5.0 → acpkit-0.7.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  130. {acpkit-0.5.0 → acpkit-0.7.0}/.github/dependabot.yml +0 -0
  131. /acpkit-0.5.0/.github/workflows/monorepo-ci.yml → /acpkit-0.7.0/.github/workflows/ci.yml +0 -0
  132. {acpkit-0.5.0 → acpkit-0.7.0}/.github/workflows/docs.yml +0 -0
  133. {acpkit-0.5.0 → acpkit-0.7.0}/.github/workflows/publish.yml +0 -0
  134. {acpkit-0.5.0 → acpkit-0.7.0}/.python-version +0 -0
  135. {acpkit-0.5.0 → acpkit-0.7.0}/CODE_OF_CONDUCT.md +0 -0
  136. {acpkit-0.5.0 → acpkit-0.7.0}/LICENSE +0 -0
  137. {acpkit-0.5.0 → acpkit-0.7.0}/SECURITY.md +0 -0
  138. {acpkit-0.5.0 → acpkit-0.7.0}/context7.json +0 -0
  139. {acpkit-0.5.0 → acpkit-0.7.0}/docs/.partials/index-header.html +0 -0
  140. {acpkit-0.5.0 → acpkit-0.7.0}/docs/api/codex_auth_helper.md +0 -0
  141. {acpkit-0.5.0 → acpkit-0.7.0}/docs/cli.md +0 -0
  142. {acpkit-0.5.0 → acpkit-0.7.0}/docs/examples/factory.md +0 -0
  143. {acpkit-0.5.0 → acpkit-0.7.0}/docs/examples/minimal.md +0 -0
  144. {acpkit-0.5.0 → acpkit-0.7.0}/docs/examples/providers.md +0 -0
  145. {acpkit-0.5.0 → acpkit-0.7.0}/docs/examples/workspace-agent.md +0 -0
  146. {acpkit-0.5.0 → acpkit-0.7.0}/docs/getting-started/installation.md +0 -0
  147. {acpkit-0.5.0 → acpkit-0.7.0}/docs/getting-started/quickstart.md +0 -0
  148. {acpkit-0.5.0 → acpkit-0.7.0}/docs/helpers.md +0 -0
  149. {acpkit-0.5.0 → acpkit-0.7.0}/docs/providers.md +0 -0
  150. {acpkit-0.5.0 → acpkit-0.7.0}/docs/pydantic-acp/runtime-controls.md +0 -0
  151. {acpkit-0.5.0 → acpkit-0.7.0}/docs/stylesheets/tweaks.css +0 -0
  152. {acpkit-0.5.0 → acpkit-0.7.0}/examples/__init__.py +0 -0
  153. {acpkit-0.5.0 → acpkit-0.7.0}/examples/pydantic/.gitignore +0 -0
  154. {acpkit-0.5.0 → acpkit-0.7.0}/examples/pydantic/README.md +0 -0
  155. {acpkit-0.5.0 → acpkit-0.7.0}/examples/pydantic/__init__.py +0 -0
  156. {acpkit-0.5.0 → acpkit-0.7.0}/examples/pydantic/approvals.py +0 -0
  157. {acpkit-0.5.0 → acpkit-0.7.0}/examples/pydantic/bridges.py +0 -0
  158. {acpkit-0.5.0 → acpkit-0.7.0}/examples/pydantic/factory_agent.py +0 -0
  159. {acpkit-0.5.0 → acpkit-0.7.0}/examples/pydantic/hook_projection.py +0 -0
  160. {acpkit-0.5.0 → acpkit-0.7.0}/examples/pydantic/host_context.py +0 -0
  161. {acpkit-0.5.0 → acpkit-0.7.0}/examples/pydantic/providers.py +0 -0
  162. {acpkit-0.5.0 → acpkit-0.7.0}/examples/pydantic/static_agent.py +0 -0
  163. {acpkit-0.5.0 → acpkit-0.7.0}/packages/adapters/pydantic-acp/src/pydantic_acp/_slash_commands.py +0 -0
  164. {acpkit-0.5.0 → acpkit-0.7.0}/packages/adapters/pydantic-acp/src/pydantic_acp/agent_source.py +0 -0
  165. {acpkit-0.5.0 → acpkit-0.7.0}/packages/adapters/pydantic-acp/src/pydantic_acp/agent_types.py +0 -0
  166. {acpkit-0.5.0 → acpkit-0.7.0}/packages/adapters/pydantic-acp/src/pydantic_acp/approvals.py +0 -0
  167. {acpkit-0.5.0 → acpkit-0.7.0}/packages/adapters/pydantic-acp/src/pydantic_acp/awaitables.py +0 -0
  168. {acpkit-0.5.0 → acpkit-0.7.0}/packages/adapters/pydantic-acp/src/pydantic_acp/bridges/base.py +0 -0
  169. {acpkit-0.5.0 → acpkit-0.7.0}/packages/adapters/pydantic-acp/src/pydantic_acp/bridges/prepare_tools.py +0 -0
  170. {acpkit-0.5.0 → acpkit-0.7.0}/packages/adapters/pydantic-acp/src/pydantic_acp/bridges/thinking.py +0 -0
  171. {acpkit-0.5.0 → acpkit-0.7.0}/packages/adapters/pydantic-acp/src/pydantic_acp/builders/__init__.py +0 -0
  172. {acpkit-0.5.0 → acpkit-0.7.0}/packages/adapters/pydantic-acp/src/pydantic_acp/models.py +0 -0
  173. {acpkit-0.5.0 → acpkit-0.7.0}/packages/adapters/pydantic-acp/src/pydantic_acp/py.typed +0 -0
  174. {acpkit-0.5.0 → acpkit-0.7.0}/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/__init__.py +0 -0
  175. {acpkit-0.5.0 → acpkit-0.7.0}/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/_agent_state.py +0 -0
  176. {acpkit-0.5.0 → acpkit-0.7.0}/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/bridge_manager.py +0 -0
  177. {acpkit-0.5.0 → acpkit-0.7.0}/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/server.py +0 -0
  178. {acpkit-0.5.0 → acpkit-0.7.0}/packages/adapters/pydantic-acp/src/pydantic_acp/runtime/session_surface.py +0 -0
  179. {acpkit-0.5.0 → acpkit-0.7.0}/packages/adapters/pydantic-acp/src/pydantic_acp/serialization.py +0 -0
  180. {acpkit-0.5.0 → acpkit-0.7.0}/packages/adapters/pydantic-acp/src/pydantic_acp/session/__init__.py +0 -0
  181. {acpkit-0.5.0 → acpkit-0.7.0}/packages/adapters/pydantic-acp/src/pydantic_acp/session/state.py +0 -0
  182. {acpkit-0.5.0 → acpkit-0.7.0}/packages/helpers/codex-auth-helper/.gitignore +0 -0
  183. {acpkit-0.5.0 → acpkit-0.7.0}/packages/helpers/codex-auth-helper/LICENSE +0 -0
  184. {acpkit-0.5.0 → acpkit-0.7.0}/packages/helpers/codex-auth-helper/README.md +0 -0
  185. {acpkit-0.5.0 → acpkit-0.7.0}/packages/helpers/codex-auth-helper/src/codex_auth_helper/auth/__init__.py +0 -0
  186. {acpkit-0.5.0 → acpkit-0.7.0}/packages/helpers/codex-auth-helper/src/codex_auth_helper/auth/config.py +0 -0
  187. {acpkit-0.5.0 → acpkit-0.7.0}/packages/helpers/codex-auth-helper/src/codex_auth_helper/auth/manager.py +0 -0
  188. {acpkit-0.5.0 → acpkit-0.7.0}/packages/helpers/codex-auth-helper/src/codex_auth_helper/auth/state.py +0 -0
  189. {acpkit-0.5.0 → acpkit-0.7.0}/packages/helpers/codex-auth-helper/src/codex_auth_helper/auth/store.py +0 -0
  190. {acpkit-0.5.0 → acpkit-0.7.0}/packages/helpers/codex-auth-helper/src/codex_auth_helper/client.py +0 -0
  191. {acpkit-0.5.0 → acpkit-0.7.0}/packages/helpers/codex-auth-helper/src/codex_auth_helper/factory.py +0 -0
  192. {acpkit-0.5.0 → acpkit-0.7.0}/packages/helpers/codex-auth-helper/src/codex_auth_helper/model.py +0 -0
  193. {acpkit-0.5.0 → acpkit-0.7.0}/packages/helpers/codex-auth-helper/src/codex_auth_helper/py.typed +0 -0
  194. {acpkit-0.5.0 → acpkit-0.7.0}/pyrightconfig.json +0 -0
  195. {acpkit-0.5.0 → acpkit-0.7.0}/scripts/demo_mcp_server.py +0 -0
  196. {acpkit-0.5.0 → acpkit-0.7.0}/scripts/mock_hook_audit.py +0 -0
  197. {acpkit-0.5.0 → acpkit-0.7.0}/scripts/mock_hook_snapshot.py +0 -0
  198. {acpkit-0.5.0 → acpkit-0.7.0}/scripts/run_if_major_change.py +0 -0
  199. {acpkit-0.5.0 → acpkit-0.7.0}/scripts/save_coverage_summary.py +0 -0
  200. {acpkit-0.5.0 → acpkit-0.7.0}/src/acpkit/__main__.py +0 -0
  201. {acpkit-0.5.0 → acpkit-0.7.0}/src/acpkit/adapters.py +0 -0
  202. {acpkit-0.5.0 → acpkit-0.7.0}/src/acpkit/cli.py +0 -0
  203. {acpkit-0.5.0 → acpkit-0.7.0}/src/acpkit/py.typed +0 -0
  204. {acpkit-0.5.0 → acpkit-0.7.0}/src/acpkit/runtime.py +0 -0
  205. {acpkit-0.5.0 → acpkit-0.7.0}/tests/__init__.py +0 -0
  206. {acpkit-0.5.0 → acpkit-0.7.0}/tests/codex_auth_helper/__init__.py +0 -0
  207. {acpkit-0.5.0 → acpkit-0.7.0}/tests/codex_auth_helper/support.py +0 -0
  208. {acpkit-0.5.0 → acpkit-0.7.0}/tests/codex_auth_helper/test_factory.py +0 -0
  209. {acpkit-0.5.0 → acpkit-0.7.0}/tests/pydantic/__init__.py +0 -0
  210. {acpkit-0.5.0 → acpkit-0.7.0}/tests/pydantic/test_approvals.py +0 -0
  211. {acpkit-0.5.0 → acpkit-0.7.0}/tests/pydantic/test_bridge_builder.py +0 -0
  212. {acpkit-0.5.0 → acpkit-0.7.0}/tests/pydantic/test_bridge_hooks.py +0 -0
  213. {acpkit-0.5.0 → acpkit-0.7.0}/tests/pydantic/test_bridge_prepare_tools.py +0 -0
  214. {acpkit-0.5.0 → acpkit-0.7.0}/tests/pydantic/test_host.py +0 -0
  215. {acpkit-0.5.0 → acpkit-0.7.0}/tests/pydantic/test_projection.py +0 -0
  216. {acpkit-0.5.0 → acpkit-0.7.0}/tests/pydantic/test_sources.py +0 -0
  217. {acpkit-0.5.0 → acpkit-0.7.0}/tests/test_native_pydantic_agent.py +0 -0
@@ -0,0 +1,830 @@
1
+ ---
2
+ name: acpkit-sdk
3
+ description: Use for ACP Kit SDK tasks that turn an existing agent surface into a truthful ACP server through acpkit, pydantic-acp, the published docs, and the maintained examples.
4
+ ---
5
+
6
+ # ACP Kit SDK
7
+
8
+ ACP Kit is the adapter toolkit and monorepo for turning an existing agent surface into a truthful ACP server boundary.
9
+
10
+ Today the stable production focus is `pydantic-acp`: exposing `pydantic_ai.Agent` through ACP
11
+ while keeping models, modes, plans, approvals, MCP metadata, host tools, and session state
12
+ aligned with what the underlying runtime can actually support.
13
+
14
+ Additional adapters such as `langchain-acp` and `dspy-acp` are planned after `pydantic-acp`
15
+ reaches 1.0 stability.
16
+
17
+ This skill file is the longform, high-context entrypoint for the packaged `acpkit-sdk` skill and
18
+ should be treated as the primary skill surface when the skill is selected.
19
+
20
+ When you need the docs map or the full docs corpus in one place, read [llms.txt](https://vcoderun.github.io/acpkit/llms.txt) or [llms-full.txt](https://vcoderun.github.io/acpkit/llms-full.txt).
21
+
22
+ ## What ACP Kit Ships
23
+
24
+ ACP Kit currently has three main Python packages:
25
+
26
+ | Package | Role | Typical use |
27
+ | --- | --- | --- |
28
+ | `acpkit` | root CLI and target resolver | `acpkit run ...`, `acpkit launch ...`, target loading |
29
+ | `pydantic-acp` | ACP adapter for `pydantic_ai.Agent` | expose an existing agent through ACP without rewriting it |
30
+ | `codex-auth-helper` | Codex-backed Pydantic AI helper | build Codex-backed Responses models from a local Codex login |
31
+
32
+ The core contract across the repo is:
33
+
34
+ > expose ACP state only when the underlying runtime can actually honor it.
35
+
36
+ That rule affects model selection, mode switching, slash commands, native plan state, approval
37
+ flow, MCP metadata, hook rendering, cancellation, and host-backed tooling.
38
+
39
+ ## Use The Right Construction Seam
40
+
41
+ Pick the narrowest seam that matches the job:
42
+
43
+ | Seam | Use it when |
44
+ | --- | --- |
45
+ | `run_acp(agent=...)` | you want the smallest direct path from `pydantic_ai.Agent` to a running ACP server |
46
+ | `create_acp_agent(...)` | you need the ACP-compatible agent object before running it |
47
+ | `agent_factory=` | the current session should influence agent construction, but a full custom source is unnecessary |
48
+ | `agent_source=` | you need full control over the agent build path, host binding, and session-specific dependencies |
49
+ | built-in `AdapterConfig` fields | the adapter can own the relevant runtime state cleanly |
50
+ | providers | the host or product layer should remain the source of truth |
51
+ | bridges | the runtime needs ACP-visible capabilities without hard-coding them into the adapter core |
52
+
53
+ ## CLI And Target Resolution
54
+
55
+ The root `acpkit` package resolves Python targets and dispatches them to the matching adapter.
56
+
57
+ ```bash
58
+ acpkit run my_agent
59
+ acpkit run my_agent:agent
60
+ acpkit run app.agents.demo:agent -p ./examples
61
+ acpkit launch my_agent:agent -p ./examples
62
+ acpkit launch --command "python3.11 strong_agent.py"
63
+ ```
64
+
65
+ Target resolution behavior:
66
+
67
+ 1. add the current working directory to `sys.path`
68
+ 2. add any `-p/--path` roots
69
+ 3. import the requested module
70
+ 4. if `module:attribute` was given, resolve the attribute path
71
+ 5. if only `module` was given, select the last defined `pydantic_ai.Agent` in that module
72
+
73
+ Current built-in auto-dispatch support is centered on `pydantic_ai.Agent`.
74
+
75
+ ## Smallest Adapter Path: `run_acp(...)`
76
+
77
+ Use `run_acp(...)` when one existing agent instance is enough.
78
+
79
+ ```python
80
+ from pydantic_ai import Agent
81
+ from pydantic_acp import run_acp
82
+
83
+ agent = Agent(
84
+ 'openai:gpt-5',
85
+ name='weather-agent',
86
+ instructions='Answer briefly and ask for clarification when location is missing.',
87
+ )
88
+
89
+
90
+ @agent.tool_plain
91
+ def lookup_weather(city: str) -> str:
92
+ """Return a canned weather response for demos."""
93
+
94
+ return f'Weather in {city}: sunny'
95
+
96
+
97
+ run_acp(agent=agent)
98
+ ```
99
+
100
+ This is the narrowest path from an existing agent surface to a live ACP server.
101
+
102
+ ## ACP Agent Without Running: `create_acp_agent(...)`
103
+
104
+ Use `create_acp_agent(...)` when you need the ACP-compatible agent object first.
105
+
106
+ ```python
107
+ from acp import run_agent
108
+ from pydantic_ai import Agent
109
+ from pydantic_acp import AdapterConfig, MemorySessionStore, create_acp_agent
110
+
111
+ agent = Agent('openai:gpt-5', name='composable-agent')
112
+
113
+ acp_agent = create_acp_agent(
114
+ agent=agent,
115
+ config=AdapterConfig(
116
+ agent_name='my-service',
117
+ agent_title='My Service Agent',
118
+ session_store=MemorySessionStore(),
119
+ ),
120
+ )
121
+
122
+ # later:
123
+ # await run_agent(acp_agent)
124
+ ```
125
+
126
+ Use this seam when ACP is only one part of a larger async service boundary.
127
+
128
+ ## `AdapterConfig` Is The Main Runtime Surface
129
+
130
+ `AdapterConfig` is where the adapter’s built-in ownership lives:
131
+
132
+ - session storage
133
+ - model selection
134
+ - approval bridging
135
+ - capability bridges
136
+ - plan persistence callbacks
137
+ - hook projection and runtime shaping
138
+
139
+ ```python
140
+ from pathlib import Path
141
+
142
+ from pydantic_ai import Agent
143
+ from pydantic_acp import (
144
+ AdapterConfig,
145
+ AdapterModel,
146
+ FileSessionStore,
147
+ NativeApprovalBridge,
148
+ ThinkingBridge,
149
+ run_acp,
150
+ )
151
+
152
+ agent = Agent('openai:gpt-5', name='configured-agent')
153
+
154
+ config = AdapterConfig(
155
+ agent_name='my-agent',
156
+ agent_title='My Agent Title',
157
+ allow_model_selection=True,
158
+ available_models=[
159
+ AdapterModel(
160
+ model_id='fast',
161
+ name='Fast',
162
+ description='Lower-latency responses.',
163
+ override='openai:gpt-5-mini',
164
+ ),
165
+ AdapterModel(
166
+ model_id='smart',
167
+ name='Smart',
168
+ description='Higher-quality responses.',
169
+ override='openai:gpt-5',
170
+ ),
171
+ ],
172
+ capability_bridges=[ThinkingBridge()],
173
+ approval_bridge=NativeApprovalBridge(enable_persistent_choices=True),
174
+ session_store=FileSessionStore(root=Path('.acp-sessions')),
175
+ )
176
+
177
+ run_acp(agent=agent, config=config)
178
+ ```
179
+
180
+ High-value detail:
181
+
182
+ - `FileSessionStore` takes `root=Path(...)`, not `base_dir=...`
183
+
184
+ ## Session Stores
185
+
186
+ ACP Kit currently ships two session stores:
187
+
188
+ - `MemorySessionStore`
189
+ - `FileSessionStore`
190
+
191
+ `MemorySessionStore` is ephemeral. `FileSessionStore` persists ACP sessions across restarts and
192
+ supports:
193
+
194
+ - save
195
+ - get
196
+ - list
197
+ - fork
198
+ - delete
199
+
200
+ Use `FileSessionStore(root=Path(...))` when real ACP clients need durable session state.
201
+
202
+ Current `FileSessionStore` behavior is tuned for durable local-host ACP use:
203
+
204
+ - atomic temp-file write plus replace
205
+ - local process lock and filesystem advisory lock when available
206
+ - malformed saved session files are skipped in public load/list flows
207
+ - stale temp files are cleaned up on startup
208
+
209
+ It is a strong default for editors and single-host services, not a distributed shared-state backend.
210
+
211
+ ## Agent Factories And `AgentSource`
212
+
213
+ Use an agent factory when session context changes agent construction but you do not need a full
214
+ custom source object.
215
+
216
+ ```python
217
+ from pydantic_ai import Agent
218
+ from pydantic_acp import AcpSessionContext, AdapterConfig, run_acp
219
+
220
+
221
+ def build_agent(session: AcpSessionContext) -> Agent[None, str]:
222
+ workspace_name = session.cwd.name
223
+ return Agent(
224
+ 'openai:gpt-5',
225
+ name=f'agent-{workspace_name}',
226
+ instructions=f'You are working in {workspace_name}.',
227
+ )
228
+
229
+
230
+ run_acp(
231
+ agent_factory=build_agent,
232
+ config=AdapterConfig(agent_name='factory-agent'),
233
+ )
234
+ ```
235
+
236
+ Use `AgentSource` when you need full control over both the agent and the dependency object:
237
+
238
+ ```python
239
+ from dataclasses import dataclass
240
+
241
+ from pydantic_ai import Agent
242
+ from pydantic_acp import AcpSessionContext, AgentSource, AdapterConfig, run_acp
243
+
244
+
245
+ @dataclass(frozen=True, slots=True)
246
+ class Deps:
247
+ workspace_name: str
248
+
249
+
250
+ class WorkspaceSource(AgentSource[Deps]):
251
+ async def get_agent(self, session: AcpSessionContext) -> Agent[Deps, str]:
252
+ return Agent(
253
+ 'openai:gpt-5',
254
+ name='workspace-agent',
255
+ instructions='Use the provided workspace dependencies.',
256
+ )
257
+
258
+ async def get_deps(self, session: AcpSessionContext) -> Deps:
259
+ return Deps(workspace_name=session.cwd.name)
260
+
261
+
262
+ run_acp(
263
+ agent_source=WorkspaceSource(),
264
+ config=AdapterConfig(agent_name='workspace-agent'),
265
+ )
266
+ ```
267
+
268
+ Reach for `AgentSource` in production-style examples where:
269
+
270
+ - session cwd matters
271
+ - model ids or modes come from the host
272
+ - tools depend on host-backed services
273
+ - you need a richer dependency object than the adapter can infer on its own
274
+
275
+ ## Models, Modes, And Slash Commands
276
+
277
+ ACP Kit can expose session-local model and mode switching through two different ownership paths.
278
+
279
+ ### Built-in model selection
280
+
281
+ Use built-in model selection when the adapter can own the available model set:
282
+
283
+ ```python
284
+ from pydantic_acp import AdapterConfig, AdapterModel
285
+
286
+ config = AdapterConfig(
287
+ allow_model_selection=True,
288
+ available_models=[
289
+ AdapterModel(
290
+ model_id='fast',
291
+ name='Fast',
292
+ description='Lower latency.',
293
+ override='openai:gpt-5-mini',
294
+ ),
295
+ AdapterModel(
296
+ model_id='smart',
297
+ name='Smart',
298
+ description='Higher quality.',
299
+ override='openai:gpt-5',
300
+ ),
301
+ ],
302
+ )
303
+ ```
304
+
305
+ ### Provider-owned model or mode state
306
+
307
+ Use providers when the host already owns that state:
308
+
309
+ - `SessionModelsProvider`
310
+ - `SessionModesProvider`
311
+ - `ConfigOptionsProvider`
312
+
313
+ Mode slash commands are dynamic. They are derived from the configured mode ids rather than from a
314
+ hard-coded global set.
315
+
316
+ Important guardrail:
317
+
318
+ - mode ids must not collide with reserved slash-command names such as `model`, `thinking`,
319
+ `tools`, `hooks`, or `mcp-servers`
320
+
321
+ ## Capability Bridges
322
+
323
+ Capability bridges are how ACP-visible runtime behavior gets added without hard-coding everything
324
+ into the adapter core.
325
+
326
+ Common bridges:
327
+
328
+ - `PrepareToolsBridge`
329
+ - `ThinkingBridge`
330
+ - `McpBridge`
331
+ - `HookBridge`
332
+ - `HistoryProcessorBridge`
333
+
334
+ Use `PrepareToolsBridge` to define dynamic modes and tool surfaces:
335
+
336
+ ```python
337
+ from pydantic_acp import PrepareToolsBridge, PrepareToolsMode
338
+ from pydantic_ai.tools import RunContext, ToolDefinition
339
+
340
+
341
+ def ask_tools(
342
+ ctx: RunContext[None],
343
+ tool_defs: list[ToolDefinition],
344
+ ) -> list[ToolDefinition]:
345
+ del ctx
346
+ return [tool_def for tool_def in tool_defs if not tool_def.name.startswith('write_')]
347
+
348
+
349
+ def agent_tools(
350
+ ctx: RunContext[None],
351
+ tool_defs: list[ToolDefinition],
352
+ ) -> list[ToolDefinition]:
353
+ del ctx
354
+ return list(tool_defs)
355
+
356
+
357
+ bridge = PrepareToolsBridge(
358
+ default_mode_id='ask',
359
+ modes=[
360
+ PrepareToolsMode(
361
+ id='ask',
362
+ name='Ask',
363
+ description='Read-only inspection mode.',
364
+ prepare_func=ask_tools,
365
+ ),
366
+ PrepareToolsMode(
367
+ id='plan',
368
+ name='Plan',
369
+ description='Native ACP plan mode.',
370
+ prepare_func=ask_tools,
371
+ plan_mode=True,
372
+ ),
373
+ PrepareToolsMode(
374
+ id='agent',
375
+ name='Agent',
376
+ description='Full tool surface.',
377
+ prepare_func=agent_tools,
378
+ plan_tools=True,
379
+ ),
380
+ ],
381
+ )
382
+ ```
383
+
384
+ High-value guardrails:
385
+
386
+ - only one `PrepareToolsMode(..., plan_mode=True)` is allowed
387
+ - `plan_tools=True` is how a non-plan execution mode keeps plan progress tools visible
388
+ - `ThinkingBridge()` is what makes `/thinking` and the ACP-visible effort selector exist
389
+ - `HookBridge(hide_all=True)` suppresses hook listing output without removing the hook seam itself
390
+ - custom `run_event_stream` hooks or wrappers must return an async iterable; returning a coroutine will break stream execution
391
+
392
+ ## Plans, Approvals, Cancellation, And Host Tools
393
+
394
+ Native ACP plan state is separate from provider-owned plan state.
395
+
396
+ Use native plan state when you want the adapter to own the ACP-visible plan lifecycle. Use
397
+ `PlanProvider` when the host should remain the source of truth.
398
+
399
+ Current plan behavior to remember:
400
+
401
+ - `plan_mode=True` exposes native ACP plan creation tools
402
+ - `plan_tools=True` lets execution modes keep plan progress tools visible
403
+ - native plan persistence can be mirrored outward through `NativePlanPersistenceProvider`
404
+
405
+ Approval behavior:
406
+
407
+ - `NativeApprovalBridge` powers the live ACP approval flow
408
+ - `ApprovalStateProvider` exposes extra approval metadata when the host already owns approval state
409
+
410
+ Cancellation behavior:
411
+
412
+ - ACP cancellation is wired through the runtime now
413
+ - cancellation preserves session state and transcript integrity instead of leaving the session in a broken partial state
414
+
415
+ Host-backed tools:
416
+
417
+ - ACP Kit can expose client-backed filesystem and shell helpers
418
+ - projection maps change how tools are rendered in ACP clients without changing the underlying tool contract
419
+
420
+ ### HostAccessPolicy
421
+
422
+ `HostAccessPolicy` is ACP Kit's native typed guardrail surface for host-backed filesystem and terminal access.
423
+
424
+ Reach for it first when an integration has started inventing ad hoc rules such as:
425
+
426
+ - "warn for absolute paths but deny workspace escapes"
427
+ - "show one caution in the client but enforce a different rule in the backend"
428
+ - "treat command cwd and file paths as unrelated policy domains"
429
+
430
+ Use it:
431
+
432
+ - when host-backed file and terminal tools already exist
433
+ - when approvals or projection warnings need to describe the same risk model that enforcement uses
434
+ - when downstream code has started to accumulate one-off path checks
435
+
436
+ Do not reach for it:
437
+
438
+ - when the integration does not expose host-backed file or terminal tools at all
439
+ - when the problem is product-specific approval wording rather than reusable access policy
440
+
441
+ Use it when an integration needs one reusable place to decide:
442
+
443
+ - whether absolute paths should only warn or hard fail
444
+ - whether paths outside the active session cwd should warn or deny
445
+ - whether workspace-root escapes should always deny
446
+ - whether command cwd and command path arguments should follow the same policy language as file paths
447
+
448
+ Important distinction:
449
+
450
+ - `evaluate_path(...)` and `evaluate_command(...)` are for UI and approval surfaces
451
+ - `enforce_path(...)` and `enforce_command(...)` are for actual blocking before ACP host requests are sent
452
+
453
+ The evaluation objects are intentionally UI-friendly. They expose:
454
+
455
+ - `disposition`
456
+ - `headline`
457
+ - `message`
458
+ - `recommendation`
459
+ - `risks`
460
+ - `risk_codes`
461
+ - `primary_risk`
462
+ - `summary_lines()`
463
+
464
+ That means downstream integrations do not need to invent their own warning strings just to show a clear caution card.
465
+
466
+ Typical use:
467
+
468
+ ```python
469
+ from pydantic_acp import ClientHostContext, HostAccessPolicy
470
+
471
+ policy = HostAccessPolicy.strict()
472
+
473
+ host = ClientHostContext.from_session(
474
+ client=client,
475
+ session=session,
476
+ access_policy=policy,
477
+ workspace_root=session.cwd,
478
+ )
479
+ ```
480
+
481
+ Small verified evaluation example:
482
+
483
+ ```python
484
+ from pathlib import Path
485
+
486
+ from pydantic_acp import HostAccessPolicy
487
+
488
+ policy = HostAccessPolicy.strict()
489
+ evaluation = policy.evaluate_path(
490
+ '../notes.txt',
491
+ session_cwd=Path('/workspace/app'),
492
+ workspace_root=Path('/workspace/app'),
493
+ )
494
+
495
+ assert evaluation.disposition == 'deny'
496
+ assert evaluation.should_deny
497
+ assert 'outside_cwd' in evaluation.risk_codes
498
+ ```
499
+
500
+ Current presets:
501
+
502
+ - `HostAccessPolicy()` is conservative default behavior
503
+ - `HostAccessPolicy.strict()` denies more aggressively outside the active cwd
504
+ - `HostAccessPolicy.permissive()` keeps more paths executable but still surfaces risk
505
+
506
+ Current scope:
507
+
508
+ - file path evaluation
509
+ - command cwd evaluation
510
+ - heuristic detection of obvious path-like command arguments
511
+ - native backend-side deny enforcement
512
+
513
+ Current limit:
514
+
515
+ - it is not a full shell parser
516
+ - it does not automatically wire itself through every integration seam yet
517
+
518
+ Primary references:
519
+
520
+ - [Host Backends and Projections](https://vcoderun.github.io/acpkit/host-backends/)
521
+ - [Projection Cookbook](https://vcoderun.github.io/acpkit/projection-cookbook/)
522
+
523
+ ## Black-box Integration Harness
524
+
525
+ `BlackBoxHarness` exists so downstream integrations can prove the ACP boundary without rebuilding test plumbing from scratch.
526
+
527
+ Reach for it when the integration already "works" but still lacks proof for:
528
+
529
+ - approval replay
530
+ - host-backed side effects
531
+ - session reload correctness
532
+ - ACP-visible transcript truthfulness
533
+
534
+ Use it:
535
+
536
+ - after the integration already has a real adapter construction seam
537
+ - when you need one reusable way to drive approvals, prompts, reloads, and visible updates
538
+ - when a normal unit test would miss ACP-visible behavior
539
+
540
+ Do not use it:
541
+
542
+ - to inspect private helper ordering
543
+ - as a substitute for product-level end-to-end testing
544
+ - before the integration has a coherent ownership model for sessions, approvals, and host tools
545
+
546
+ Use it when you want to verify:
547
+
548
+ - session create/load behavior
549
+ - visible ACP updates
550
+ - approval roundtrips
551
+ - host-backed file or terminal flows
552
+ - replay after reload
553
+
554
+ What it gives you:
555
+
556
+ - adapter construction plus a recording ACP client in one object
557
+ - `new_session(...)`
558
+ - `load_session(...)`
559
+ - `prompt_text(...)`
560
+ - `set_mode(...)`
561
+ - `set_model(...)`
562
+ - permission response queueing helpers
563
+ - update filtering
564
+ - reconstructed agent messages
565
+
566
+ Typical use:
567
+
568
+ ```python
569
+ import asyncio
570
+
571
+ from pydantic_acp import AdapterConfig, BlackBoxHarness, FileSessionStore
572
+
573
+ harness = BlackBoxHarness.create(
574
+ agent_factory=build_agent,
575
+ config=AdapterConfig(session_store=FileSessionStore(tmp_path / 'sessions')),
576
+ )
577
+
578
+ session = asyncio.run(harness.new_session(cwd=str(tmp_path)))
579
+ harness.queue_permission_selected('allow_once')
580
+ response = asyncio.run(harness.prompt_text('Write the workspace note.'))
581
+
582
+ assert response.stop_reason == 'end_turn'
583
+ assert harness.tool_updates(session_id=session.session_id)
584
+ assert harness.agent_messages(session_id=session.session_id)
585
+ ```
586
+
587
+ Small verified example from the harness test shape:
588
+
589
+ ```python
590
+ session = asyncio.run(harness.new_session(cwd=str(tmp_path)))
591
+ harness.queue_permission_selected('allow_once')
592
+ response = asyncio.run(harness.prompt_text('Write the workspace note.'))
593
+
594
+ assert response.stop_reason == 'end_turn'
595
+ assert harness.agent_messages(session_id=session.session_id) == ['done']
596
+ ```
597
+
598
+ The harness is intentionally black-box.
599
+
600
+ Prefer asserting on:
601
+
602
+ - ACP return values
603
+ - emitted `ToolCallStart` / `ToolCallProgress` updates
604
+ - reconstructed visible messages
605
+ - persisted replay behavior
606
+ - real host-backed side effects
607
+
608
+ Do not use it to:
609
+
610
+ - inspect private helper choreography
611
+ - lock internal runtime call order
612
+ - replace product-level end-to-end tests
613
+
614
+ Good default scenario ladder for a new integration:
615
+
616
+ 1. session create -> prompt -> reload
617
+ 2. approval required -> allow once
618
+ 3. approval required -> deny once
619
+ 4. host-backed file read/write
620
+ 5. host-backed terminal execution
621
+ 6. mode switch changes behavior
622
+ 7. model switch changes session-local state
623
+
624
+ Primary references:
625
+
626
+ - [Integration Testing](https://vcoderun.github.io/acpkit/integration-testing/)
627
+ - [Examples Overview](https://vcoderun.github.io/acpkit/examples/)
628
+
629
+ ## Projection Maps And Hook Rendering
630
+
631
+ Projection maps make ACP clients see richer file or command behavior than a raw generic tool card.
632
+
633
+ Common maps:
634
+
635
+ - filesystem maps
636
+ - bash / command maps
637
+ - hook projection maps
638
+
639
+ Use them when the client should see more structured output, but avoid pretending a tool is
640
+ something it is not.
641
+
642
+ ### Projection Helper Primitives
643
+
644
+ ACP Kit now also ships small reusable projection helpers for integrations that need consistent shaping but do not want to rebuild truncation and warning logic repeatedly.
645
+
646
+ High-value helpers:
647
+
648
+ - `truncate_text(...)`
649
+ - `truncate_lines(...)`
650
+ - `single_line_summary(...)`
651
+ - `format_code_block(...)`
652
+ - `format_diff_preview(...)`
653
+ - `format_terminal_status(...)`
654
+ - `caution_for_path(...)`
655
+ - `caution_for_command(...)`
656
+
657
+ Use these helpers when:
658
+
659
+ - a chat client needs a plain-text diff preview
660
+ - command titles should stay compact and consistent
661
+ - long stdout/stderr content needs predictable truncation
662
+ - caution text should come from the same `HostAccessPolicy` evaluation model as backend enforcement
663
+
664
+ These helpers are intentionally small. They are building blocks, not a full rendering framework.
665
+
666
+ ## Examples That Matter
667
+
668
+ High-value maintained examples live under `examples/pydantic/`:
669
+
670
+ | Example | Purpose |
671
+ | --- | --- |
672
+ | [`examples/pydantic/acp_agent.py`](https://github.com/vcoderun/acpkit/blob/main/examples/pydantic/acp_agent.py) | smallest direct `run_acp(...)` path |
673
+ | [`examples/pydantic/factory_agent.py`](https://github.com/vcoderun/acpkit/blob/main/examples/pydantic/factory_agent.py) | session-aware factory |
674
+ | [`examples/pydantic/providers.py`](https://github.com/vcoderun/acpkit/blob/main/examples/pydantic/providers.py) | host-owned models, modes, config, plan, and approval metadata |
675
+ | [`examples/pydantic/approvals.py`](https://github.com/vcoderun/acpkit/blob/main/examples/pydantic/approvals.py) | deferred approval flow |
676
+ | [`examples/pydantic/bridges.py`](https://github.com/vcoderun/acpkit/blob/main/examples/pydantic/bridges.py) | bridge builder and ACP-visible capabilities |
677
+ | [`examples/pydantic/host_context.py`](https://github.com/vcoderun/acpkit/blob/main/examples/pydantic/host_context.py) | client-backed filesystem and terminal helpers |
678
+ | [`examples/pydantic/hook_projection.py`](https://github.com/vcoderun/acpkit/blob/main/examples/pydantic/hook_projection.py) | hook rendering and `HookProjectionMap` behavior |
679
+ | [`examples/pydantic/strong_agent.py`](https://github.com/vcoderun/acpkit/blob/main/examples/pydantic/strong_agent.py) | production-style workspace coding-agent showcase |
680
+ | [`examples/pydantic/strong_agent_v2.py`](https://github.com/vcoderun/acpkit/blob/main/examples/pydantic/strong_agent_v2.py) | alternative workspace integration shape |
681
+
682
+ Use [`strong_agent.py`](https://github.com/vcoderun/acpkit/blob/main/examples/pydantic/strong_agent.py) when the docs or code need to highlight:
683
+
684
+ - mode-aware tool shaping
685
+ - provider-owned model and mode state
686
+ - native plan persistence
687
+ - host-backed tools
688
+ - MCP metadata mapping
689
+ - bridge composition
690
+ - projection maps
691
+ - final `create_acp_agent(...)` assembly
692
+
693
+ ## Documentation Sources
694
+
695
+ High-value docs pages:
696
+
697
+ - [ACP Kit Overview](https://vcoderun.github.io/acpkit/)
698
+ - [Pydantic ACP Overview](https://vcoderun.github.io/acpkit/pydantic-acp/)
699
+ - [AdapterConfig](https://vcoderun.github.io/acpkit/pydantic-acp/adapter-config/)
700
+ - [Session State and Lifecycle](https://vcoderun.github.io/acpkit/pydantic-acp/session-state/)
701
+ - [Models, Modes, and Slash Commands](https://vcoderun.github.io/acpkit/pydantic-acp/runtime-controls/)
702
+ - [Plans, Thinking, and Approvals](https://vcoderun.github.io/acpkit/pydantic-acp/plans-thinking-approvals/)
703
+ - [Providers](https://vcoderun.github.io/acpkit/providers/)
704
+ - [Bridges](https://vcoderun.github.io/acpkit/bridges/)
705
+ - [Host Backends and Projections](https://vcoderun.github.io/acpkit/host-backends/)
706
+ - [Integration Testing](https://vcoderun.github.io/acpkit/integration-testing/)
707
+ - [Projection Cookbook](https://vcoderun.github.io/acpkit/projection-cookbook/)
708
+ - [Examples Overview](https://vcoderun.github.io/acpkit/examples/)
709
+ - [Workspace Agent](https://vcoderun.github.io/acpkit/examples/workspace-agent/)
710
+ - [pydantic_acp API](https://vcoderun.github.io/acpkit/api/pydantic_acp/)
711
+
712
+ ## Compatibility Manifest
713
+
714
+ ACP Kit now also ships a typed root-level compatibility manifest schema through `acpkit`.
715
+
716
+ Reach for it after the integration already has real seams and at least one black-box proof path.
717
+
718
+ Do not use it as a speculative roadmap scratchpad. Use it as a reviewable declaration of what is actually wired today.
719
+
720
+ Use it:
721
+
722
+ - after at least one black-box proof path exists
723
+ - when reviews need one typed declaration of supported ACP surfaces
724
+ - when docs should be generated from validated code instead of prose drift
725
+
726
+ Do not use it:
727
+
728
+ - before the integration can already demonstrate the behavior it claims
729
+ - as a replacement for proof tests
730
+ - as a vague backlog matrix with no mapping seam
731
+
732
+ Use it when a real integration needs one reviewable declaration of:
733
+
734
+ - which ACP surfaces are implemented
735
+ - which are partial
736
+ - which are intentionally not used
737
+ - which are only planned
738
+
739
+ Core types:
740
+
741
+ - `CompatibilityManifest`
742
+ - `SurfaceSupport`
743
+ - `SurfaceStatus`
744
+ - `SurfaceOwner`
745
+
746
+ Typical use:
747
+
748
+ ```python
749
+ from acpkit import CompatibilityManifest, SurfaceSupport
750
+
751
+ manifest = CompatibilityManifest(
752
+ integration_name='workspace-agent',
753
+ adapter='pydantic-acp',
754
+ surfaces={
755
+ 'session.load': SurfaceSupport(
756
+ status='implemented',
757
+ owner='adapter',
758
+ mapping='FileSessionStore + load_session',
759
+ ),
760
+ 'mode.switch': SurfaceSupport(
761
+ status='partial',
762
+ owner='bridge',
763
+ mapping='PrepareToolsBridge dynamic modes',
764
+ rationale='Only explicitly exposed runtime modes are surfaced.',
765
+ ),
766
+ 'authenticate': SurfaceSupport(
767
+ status='planned',
768
+ rationale='No auth handshake has been added yet.',
769
+ ),
770
+ },
771
+ )
772
+
773
+ manifest.validate()
774
+ ```
775
+
776
+ Minimal review rule:
777
+
778
+ - every `implemented` surface should point to one concrete mapping seam
779
+ - every `partial`, `intentionally_not_used`, and `planned` surface should explain why
780
+ - `mixed` ownership is only acceptable when the split is named explicitly
781
+
782
+ Important rule:
783
+
784
+ - do not generate this from guesses
785
+ - derive it from a real integration audit
786
+ - then validate it in tests
787
+
788
+ Recommended workflow:
789
+
790
+ 1. inventory real seams
791
+ 2. declare surfaces in code
792
+ 3. call `manifest.validate()` in tests or CI
793
+ 4. optionally publish `manifest.to_markdown()` into docs
794
+
795
+ This is not a runtime feature. It is an integration review and documentation hygiene feature.
796
+
797
+ Primary reference:
798
+
799
+ - [Compatibility Manifest Guide](https://vcoderun.github.io/acpkit/compatibility-matrix-template/)
800
+
801
+ ## Skill-Local Routing Aids
802
+
803
+ These files exist to route you quickly into the right part of the codebase or docs set when the
804
+ task is narrow:
805
+
806
+ - [resources/intro.md](resources/intro.md)
807
+ - [references/package-surface.md](references/package-surface.md)
808
+ - [references/runtime-capabilities.md](references/runtime-capabilities.md)
809
+ - [references/docs-examples-map.md](references/docs-examples-map.md)
810
+
811
+ ## Utility Scripts
812
+
813
+ Use the bundled scripts instead of guessing:
814
+
815
+ - `python3.11 .agents/skills/acpkit-sdk/scripts/list_public_exports.py`
816
+ - `python3.11 .agents/skills/acpkit-sdk/scripts/list_examples.py`
817
+
818
+ ## Working Rules
819
+
820
+ - Prefer current code over stale memory.
821
+ - If docs and code disagree, trust code first and update docs.
822
+ - Do not invent ACP surface the runtime cannot actually honor.
823
+ - Keep examples runnable, explicit, and strongly typed.
824
+ - Treat adapter-owned state and host-owned state as different design choices.
825
+ - Prefer the narrowest seam that matches the user’s need.
826
+ - Use the compatibility manifest when an integration needs one typed, reviewable ACP surface declaration instead of a loose prose matrix.
827
+ - `FileSessionStore` uses `root=Path(...)`.
828
+ - `FileSessionStore` is the hardened local durable store, not a distributed session backend.
829
+ - Mode slash commands are dynamic, and mode ids must not collide with reserved names such as `model`, `thinking`, `tools`, `hooks`, or `mcp-servers`.
830
+ - `run_event_stream` hooks must return async iterables, not coroutines.