agenthooksprotocol 0.6.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.
- {agenthooksprotocol-0.6.0/src/agenthooksprotocol.egg-info → agenthooksprotocol-0.7.0}/PKG-INFO +14 -9
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/README.md +13 -8
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/pyproject.toml +1 -1
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/_hooks.py +18 -1
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/_interop_hooks.py +3 -1
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/_models/__init__.py +273 -48
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/_models/event.py +2 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/_models/tool.py +8 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/ahp-codegen.lock.json +10 -10
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/catalogue.py +4 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/event.py +1 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/generated.py +326 -295
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/interop.py +6 -2
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/observation_chain.py +2 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/schemas.json +143 -16
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/tool.py +4 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0/src/agenthooksprotocol.egg-info}/PKG-INFO +14 -9
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol.egg-info/SOURCES.txt +1 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/tests/test_catalogue.py +1 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/tests/test_compaction_wire.py +1 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/tests/test_consumer_outcomes.py +4 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/tests/test_content_receipts.py +1 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/tests/test_event_types.py +2 -0
- agenthooksprotocol-0.7.0/tests/test_harness_identity.py +125 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/tests/test_inline_messages.py +7 -1
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/tests/test_integration.py +4 -1
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/tests/test_integration_edges.py +1 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/tests/test_interop.py +1 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/tests/test_lifecycle.py +2 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/tests/test_observation.py +1 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/tests/test_owned_content_hooks.py +6 -1
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/tests/test_public_content.py +3 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/tests/test_public_hooks.py +41 -4
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/tests/test_public_server.py +2 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/tests/test_schema_corrections.py +1 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/tests/test_sdk_unification.py +9 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/tests/test_session_manifest.py +13 -2
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/tests/test_stdio_env.py +2 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/tests/test_subscribes.py +13 -2
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/tests/test_typed_capabilities.py +34 -6
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/tests/test_typed_contract_regressions.py +2 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/tests/test_upload_planning.py +3 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/LICENSE +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/setup.cfg +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/__init__.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/_boundaries.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/_content.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/_diagnostics.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/_elicitation.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/_grants.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/_host_metadata.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/_interop_content.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/_models/capability.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/_models/content.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/_models/effect.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/_models/registration.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/_models/subscription.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/_models/transport.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/_outcomes.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/attachment.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/auth.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/candidate.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/capability.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/codec.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/compaction.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/content.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/contract.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/diagnostics.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/effect.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/elicitation.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/integrations/__init__.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/integrations/pydantic.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/lifecycle.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/lifecycle_client.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/lifecycle_server.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/lineage.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/path.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/permission.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/py.typed +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/registration.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/response.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/runtime.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/server/__init__.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/server/_admission.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/server/_framing.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/server/_handlers.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/server/_json.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/server/_slots.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/server/asgi.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/server/attachments.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/server/hooks.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/server/stdio.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/state.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/subscription.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/transport.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/transports/__init__.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/transports/http.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/transports/stdio.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/wire.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol.egg-info/dependency_links.txt +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol.egg-info/requires.txt +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol.egg-info/top_level.txt +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/tests/test_attachments.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/tests/test_codec.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/tests/test_compaction.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/tests/test_content.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/tests/test_content_lifetime.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/tests/test_correlated_core.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/tests/test_declared_contracts.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/tests/test_elicitation_adapter.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/tests/test_fixture_public.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/tests/test_handwritten_surface.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/tests/test_host_metadata.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/tests/test_lifecycle_auth.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/tests/test_observation_chain_transport.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/tests/test_owned_content.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/tests/test_package.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/tests/test_public_contract_surface.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/tests/test_public_examples.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/tests/test_registration_auth.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/tests/test_safety.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/tests/test_server_catch_all.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/tests/test_server_error_codes.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/tests/test_shared_materialization.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/tests/test_stdio_transport.py +0 -0
- {agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/tests/test_structural_facade.py +0 -0
{agenthooksprotocol-0.6.0/src/agenthooksprotocol.egg-info → agenthooksprotocol-0.7.0}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agenthooksprotocol
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.0
|
|
4
4
|
Summary: Official non-normative Python SDK for the Agent Hooks Protocol
|
|
5
5
|
Author: Agent Hooks Protocol maintainers
|
|
6
6
|
License:
|
|
@@ -250,13 +250,18 @@ with open("hooks.json") as file:
|
|
|
250
250
|
config = json.load(file)
|
|
251
251
|
|
|
252
252
|
async def review(existing_arguments):
|
|
253
|
-
async with Hooks(
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
253
|
+
async with Hooks(
|
|
254
|
+
config,
|
|
255
|
+
source="urn:example:harness",
|
|
256
|
+
harness=event.Harness(name="example", version="1"),
|
|
257
|
+
capabilities=capability.HostCapabilities(
|
|
258
|
+
tool_before=capability.ToolBeforeCapabilities(
|
|
259
|
+
intercept=capability.ToolBeforeIntercept(
|
|
260
|
+
allow=True, deny=True, modify_input=capability.Modify.REPLACE,
|
|
261
|
+
),
|
|
257
262
|
),
|
|
258
263
|
),
|
|
259
|
-
)
|
|
264
|
+
) as hooks:
|
|
260
265
|
result = await hooks.tool_before(event.ToolBeforeInput(
|
|
261
266
|
call_id="call-1", name="read_file", input=existing_arguments,
|
|
262
267
|
path="native", origin="native",
|
|
@@ -264,7 +269,7 @@ async def review(existing_arguments):
|
|
|
264
269
|
return result # Host validation and authorization still precede execution.
|
|
265
270
|
```
|
|
266
271
|
|
|
267
|
-
Generated `Input` objects are distinct from canonical wire events. They flatten only protocol-owned wrappers, never application arguments, and `to_wire()` performs the shared mapping. `path` and `origin` remain separate required facts. Optional host IDs, timestamps, parent IDs, and other facts are retained; `event_id=` overrides an input ID. The SDK supplies type/source and the configured session manifest. Low-level `dispatch` accepts canonical dictionaries and an `event_name: EventType`. `from agenthooksprotocol.event import EventType` exposes the catalogue-derived literal type shared by `dispatch`, `subscribes`, and contextual response parsing. Canonical name literals are accepted directly; static checking rejects dynamic strings, unknown names, and selectors in these event-name positions. Registration selectors remain separate and support their documented wildcard matching.
|
|
272
|
+
Generated `Input` objects are distinct from canonical wire events. They flatten only protocol-owned wrappers, never application arguments, and `to_wire()` performs the shared mapping. `path` and `origin` remain separate required facts. Optional host IDs, timestamps, parent IDs, and other facts are retained; `event_id=` overrides an input ID. The SDK supplies type/source, the configured harness identity, and the configured session manifest. Full canonical wire events must include a matching `harness` identity. Low-level `dispatch` accepts canonical dictionaries and an `event_name: EventType`. `from agenthooksprotocol.event import EventType` exposes the catalogue-derived literal type shared by `dispatch`, `subscribes`, and contextual response parsing. Canonical name literals are accepted directly; static checking rejects dynamic strings, unknown names, and selectors in these event-name positions. Registration selectors remain separate and support their documented wildcard matching.
|
|
268
273
|
|
|
269
274
|
Host capabilities are frozen, keyword-only dataclasses; there are no builder functions. Each event has its own `<Event>Capabilities` declaration. Events that support interception take `intercept=<Event>Intercept(...)` grants, and every declaration takes `observe`, which defaults to `False`, so to advertise both modes you must pass `observe=True` explicitly. Observation-only events such as `SessionEndCapabilities(observe=True)` accept only the flag. `modify_input=capability.Modify.REPLACE` supplies both the effect grant and its operation block, and form/URL elicitation grants are explicit (`elicitation=capability.Elicitation.FORM`, `URL`, or `FORM_AND_URL`). Interception without a control grant and declarations with neither mode are rejected at construction; boundary compatibility is validated before delivery. Omission never implies permission. Per-call `capabilities=` only narrows configured grants.
|
|
270
275
|
|
|
@@ -344,11 +349,11 @@ Registered stdio backends start with a minimal base environment rather than the
|
|
|
344
349
|
|
|
345
350
|
`hooks.subscribes("tool.before")` is a pure synchronous static-interest lookup. Use it before expensive input preparation: `False` means no eligible intercept or observe subscription selects the configured event. Exact selectors, `*`, and prefix selectors such as `tool.*` use the same matching as dispatch. Unknown or unconfigured events return `False`. Payload filters are conservatively ignored, so `True` means potential interest, not permission or guaranteed delivery. The lookup does not prepare input, authenticate, upload content, initialize transports, or contact backends.
|
|
346
351
|
|
|
347
|
-
Configure `Hooks(config, *, source, capabilities=capability.HostCapabilities(...), manifest_metadata=HostManifestMetadata(...))`. Typed host capabilities are the sole source of event modes and effect grants. Optional metadata declares transport/authentication facilities, tool paths, content categories, limits, managed policy, gaps, correlation fields, and opaque extras without granting event authority. Metadata cannot contain events or override known fields through extras. `hooks.manifest` returns a detached canonical snapshot.
|
|
352
|
+
Configure `Hooks(config, *, source, harness=event.Harness(name="example", version="1"), capabilities=capability.HostCapabilities(...), manifest_metadata=HostManifestMetadata(...))`. The required `source`, `harness`, and `capabilities` configure one host. Harness name and version identify the emitter on every event; SDK-generated events use a detached snapshot of that identity. Typed host capabilities are the sole source of event modes and effect grants. Optional metadata declares transport/authentication facilities, tool paths, content categories, limits, managed policy, gaps, correlation fields, and opaque extras without granting event authority. Metadata cannot contain events or override known fields through extras. `hooks.manifest` returns a detached canonical snapshot.
|
|
348
353
|
|
|
349
354
|
The frozen, keyword-only host capability model advertises only explicitly declared events and modes. Each event has its own declaration type: `ToolBeforeCapabilities(intercept=..., observe=True)` accepts typed interception options and an observation flag, while observation-only events such as `SessionEndCapabilities(observe=True)` accept only the flag. Empty declarations, empty interception, and invalid option values are rejected at construction, while an empty `HostCapabilities()` grants nothing and elicitation-only interception is a valid facility declaration. `Modify.REPLACE`, `Modify.MERGE`, and `Modify.REPLACE_AND_MERGE` declare complete modification grants. `HostCapabilities.to_wire()` returns fresh canonical declarations directly; it does not parse JSON. Runtime admission still validates registration, request-time grants, and responses. The derived manifest records gaps for omitted events and host-level facilities not supplied through metadata. Explicit empty metadata collections declare no such facility; they do not mean universal support.
|
|
350
355
|
|
|
351
|
-
`await hooks.session_start(event.SessionStartInput(session=..., trigger="startup",
|
|
356
|
+
`await hooks.session_start(event.SessionStartInput(session=..., trigger="startup", permission_mode="default", items=[]))` needs only occurrence-specific host facts. The SDK supplies `manifest`, `harness`, `type`, and `source`, and supplies `id`/`time` when absent; `event_id=` takes precedence over a supplied ID. Named host inputs do not expose harness identity; the constructor supplies it. Caller payload fields cannot override the configured type, source, or manifest. Configuration, manifest snapshots, and delivered occurrences are independent copies. See [`examples/session_manifest.py`](examples/session_manifest.py) for a runnable, typechecked receiver example.
|
|
352
357
|
|
|
353
358
|
## Backend servers
|
|
354
359
|
|
|
@@ -26,13 +26,18 @@ with open("hooks.json") as file:
|
|
|
26
26
|
config = json.load(file)
|
|
27
27
|
|
|
28
28
|
async def review(existing_arguments):
|
|
29
|
-
async with Hooks(
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
async with Hooks(
|
|
30
|
+
config,
|
|
31
|
+
source="urn:example:harness",
|
|
32
|
+
harness=event.Harness(name="example", version="1"),
|
|
33
|
+
capabilities=capability.HostCapabilities(
|
|
34
|
+
tool_before=capability.ToolBeforeCapabilities(
|
|
35
|
+
intercept=capability.ToolBeforeIntercept(
|
|
36
|
+
allow=True, deny=True, modify_input=capability.Modify.REPLACE,
|
|
37
|
+
),
|
|
33
38
|
),
|
|
34
39
|
),
|
|
35
|
-
)
|
|
40
|
+
) as hooks:
|
|
36
41
|
result = await hooks.tool_before(event.ToolBeforeInput(
|
|
37
42
|
call_id="call-1", name="read_file", input=existing_arguments,
|
|
38
43
|
path="native", origin="native",
|
|
@@ -40,7 +45,7 @@ async def review(existing_arguments):
|
|
|
40
45
|
return result # Host validation and authorization still precede execution.
|
|
41
46
|
```
|
|
42
47
|
|
|
43
|
-
Generated `Input` objects are distinct from canonical wire events. They flatten only protocol-owned wrappers, never application arguments, and `to_wire()` performs the shared mapping. `path` and `origin` remain separate required facts. Optional host IDs, timestamps, parent IDs, and other facts are retained; `event_id=` overrides an input ID. The SDK supplies type/source and the configured session manifest. Low-level `dispatch` accepts canonical dictionaries and an `event_name: EventType`. `from agenthooksprotocol.event import EventType` exposes the catalogue-derived literal type shared by `dispatch`, `subscribes`, and contextual response parsing. Canonical name literals are accepted directly; static checking rejects dynamic strings, unknown names, and selectors in these event-name positions. Registration selectors remain separate and support their documented wildcard matching.
|
|
48
|
+
Generated `Input` objects are distinct from canonical wire events. They flatten only protocol-owned wrappers, never application arguments, and `to_wire()` performs the shared mapping. `path` and `origin` remain separate required facts. Optional host IDs, timestamps, parent IDs, and other facts are retained; `event_id=` overrides an input ID. The SDK supplies type/source, the configured harness identity, and the configured session manifest. Full canonical wire events must include a matching `harness` identity. Low-level `dispatch` accepts canonical dictionaries and an `event_name: EventType`. `from agenthooksprotocol.event import EventType` exposes the catalogue-derived literal type shared by `dispatch`, `subscribes`, and contextual response parsing. Canonical name literals are accepted directly; static checking rejects dynamic strings, unknown names, and selectors in these event-name positions. Registration selectors remain separate and support their documented wildcard matching.
|
|
44
49
|
|
|
45
50
|
Host capabilities are frozen, keyword-only dataclasses; there are no builder functions. Each event has its own `<Event>Capabilities` declaration. Events that support interception take `intercept=<Event>Intercept(...)` grants, and every declaration takes `observe`, which defaults to `False`, so to advertise both modes you must pass `observe=True` explicitly. Observation-only events such as `SessionEndCapabilities(observe=True)` accept only the flag. `modify_input=capability.Modify.REPLACE` supplies both the effect grant and its operation block, and form/URL elicitation grants are explicit (`elicitation=capability.Elicitation.FORM`, `URL`, or `FORM_AND_URL`). Interception without a control grant and declarations with neither mode are rejected at construction; boundary compatibility is validated before delivery. Omission never implies permission. Per-call `capabilities=` only narrows configured grants.
|
|
46
51
|
|
|
@@ -120,11 +125,11 @@ Registered stdio backends start with a minimal base environment rather than the
|
|
|
120
125
|
|
|
121
126
|
`hooks.subscribes("tool.before")` is a pure synchronous static-interest lookup. Use it before expensive input preparation: `False` means no eligible intercept or observe subscription selects the configured event. Exact selectors, `*`, and prefix selectors such as `tool.*` use the same matching as dispatch. Unknown or unconfigured events return `False`. Payload filters are conservatively ignored, so `True` means potential interest, not permission or guaranteed delivery. The lookup does not prepare input, authenticate, upload content, initialize transports, or contact backends.
|
|
122
127
|
|
|
123
|
-
Configure `Hooks(config, *, source, capabilities=capability.HostCapabilities(...), manifest_metadata=HostManifestMetadata(...))`. Typed host capabilities are the sole source of event modes and effect grants. Optional metadata declares transport/authentication facilities, tool paths, content categories, limits, managed policy, gaps, correlation fields, and opaque extras without granting event authority. Metadata cannot contain events or override known fields through extras. `hooks.manifest` returns a detached canonical snapshot.
|
|
128
|
+
Configure `Hooks(config, *, source, harness=event.Harness(name="example", version="1"), capabilities=capability.HostCapabilities(...), manifest_metadata=HostManifestMetadata(...))`. The required `source`, `harness`, and `capabilities` configure one host. Harness name and version identify the emitter on every event; SDK-generated events use a detached snapshot of that identity. Typed host capabilities are the sole source of event modes and effect grants. Optional metadata declares transport/authentication facilities, tool paths, content categories, limits, managed policy, gaps, correlation fields, and opaque extras without granting event authority. Metadata cannot contain events or override known fields through extras. `hooks.manifest` returns a detached canonical snapshot.
|
|
124
129
|
|
|
125
130
|
The frozen, keyword-only host capability model advertises only explicitly declared events and modes. Each event has its own declaration type: `ToolBeforeCapabilities(intercept=..., observe=True)` accepts typed interception options and an observation flag, while observation-only events such as `SessionEndCapabilities(observe=True)` accept only the flag. Empty declarations, empty interception, and invalid option values are rejected at construction, while an empty `HostCapabilities()` grants nothing and elicitation-only interception is a valid facility declaration. `Modify.REPLACE`, `Modify.MERGE`, and `Modify.REPLACE_AND_MERGE` declare complete modification grants. `HostCapabilities.to_wire()` returns fresh canonical declarations directly; it does not parse JSON. Runtime admission still validates registration, request-time grants, and responses. The derived manifest records gaps for omitted events and host-level facilities not supplied through metadata. Explicit empty metadata collections declare no such facility; they do not mean universal support.
|
|
126
131
|
|
|
127
|
-
`await hooks.session_start(event.SessionStartInput(session=..., trigger="startup",
|
|
132
|
+
`await hooks.session_start(event.SessionStartInput(session=..., trigger="startup", permission_mode="default", items=[]))` needs only occurrence-specific host facts. The SDK supplies `manifest`, `harness`, `type`, and `source`, and supplies `id`/`time` when absent; `event_id=` takes precedence over a supplied ID. Named host inputs do not expose harness identity; the constructor supplies it. Caller payload fields cannot override the configured type, source, or manifest. Configuration, manifest snapshots, and delivered occurrences are independent copies. See [`examples/session_manifest.py`](examples/session_manifest.py) for a runnable, typechecked receiver example.
|
|
128
133
|
|
|
129
134
|
## Backend servers
|
|
130
135
|
|
|
@@ -11,7 +11,7 @@ from typing import Any, Callable, Generic, Mapping, TypeVar, cast, overload
|
|
|
11
11
|
from types import TracebackType
|
|
12
12
|
from .codec import ValueCodecs, Codec, Candidate, _decode_preserving
|
|
13
13
|
from .response import ContextualResponse
|
|
14
|
-
from .event import Event, EventType
|
|
14
|
+
from .event import Event, EventType, Harness
|
|
15
15
|
from .capability import HostCapabilities
|
|
16
16
|
from ._host_metadata import HostManifestMetadata
|
|
17
17
|
from . import _models as models
|
|
@@ -648,6 +648,7 @@ class Hooks(BoundaryMixin):
|
|
|
648
648
|
config: dict[str, Any],
|
|
649
649
|
*,
|
|
650
650
|
source: str,
|
|
651
|
+
harness: Harness,
|
|
651
652
|
capabilities: HostCapabilities,
|
|
652
653
|
manifest_metadata: HostManifestMetadata | None = None,
|
|
653
654
|
transport: Any = None,
|
|
@@ -665,6 +666,7 @@ class Hooks(BoundaryMixin):
|
|
|
665
666
|
self._configure(
|
|
666
667
|
config,
|
|
667
668
|
source=source,
|
|
669
|
+
harness=harness,
|
|
668
670
|
declarations=capabilities.to_wire(),
|
|
669
671
|
manifest_metadata=manifest_metadata,
|
|
670
672
|
transport=transport,
|
|
@@ -679,6 +681,7 @@ class Hooks(BoundaryMixin):
|
|
|
679
681
|
config: dict[str, Any],
|
|
680
682
|
*,
|
|
681
683
|
source: str,
|
|
684
|
+
harness: Harness,
|
|
682
685
|
declarations: dict[EventType, Any],
|
|
683
686
|
manifest_metadata: HostManifestMetadata | None = None,
|
|
684
687
|
transport: Any = None,
|
|
@@ -707,6 +710,15 @@ class Hooks(BoundaryMixin):
|
|
|
707
710
|
or not FormatChecker().conforms(source, "uri")
|
|
708
711
|
):
|
|
709
712
|
raise ProtocolError("source must be an absolute URI")
|
|
713
|
+
if not isinstance(harness, Harness):
|
|
714
|
+
raise TypeError("harness must be Harness")
|
|
715
|
+
identity = deepcopy(dict(harness))
|
|
716
|
+
common = self.validator.validators["common.schema.json"]
|
|
717
|
+
if not common.evolve(
|
|
718
|
+
schema={"$ref": common.schema["$id"] + "#/$defs/harness"}
|
|
719
|
+
).is_valid(identity):
|
|
720
|
+
raise ProtocolError("harness must contain canonical name and version")
|
|
721
|
+
self._harness = identity
|
|
710
722
|
self._pending: WeakSet[PendingInvocation] = WeakSet()
|
|
711
723
|
self.config = deepcopy(config)
|
|
712
724
|
self.source = source
|
|
@@ -950,6 +962,8 @@ class Hooks(BoundaryMixin):
|
|
|
950
962
|
) -> None:
|
|
951
963
|
if event["source"] != self.source:
|
|
952
964
|
raise ProtocolError("Occurrence source conflicts with configured source")
|
|
965
|
+
if not _json_equal(event["harness"], self._harness):
|
|
966
|
+
raise ProtocolError("Occurrence harness conflicts with configured harness")
|
|
953
967
|
declaration = self.capabilities.get(event["type"])
|
|
954
968
|
if declaration is None or mode not in declaration["modes"]:
|
|
955
969
|
raise ProtocolError("Occurrence event or delivery mode was not advertised")
|
|
@@ -1199,6 +1213,8 @@ class Hooks(BoundaryMixin):
|
|
|
1199
1213
|
event = deepcopy(input.to_wire() if hasattr(input, "to_wire") else input)
|
|
1200
1214
|
if not isinstance(event, dict):
|
|
1201
1215
|
raise TypeError("Event input must be a canonical event payload object")
|
|
1216
|
+
if "harness" in event and not _json_equal(event["harness"], self._harness):
|
|
1217
|
+
raise ProtocolError("Occurrence harness conflicts with configured harness")
|
|
1202
1218
|
from ._content import normalized_content_slots, normalized_values
|
|
1203
1219
|
|
|
1204
1220
|
paths, _ = normalized_content_slots().get(event_name, ((), ()))
|
|
@@ -1218,6 +1234,7 @@ class Hooks(BoundaryMixin):
|
|
|
1218
1234
|
event.update(
|
|
1219
1235
|
id=event_id if event_id is not None else event.get("id", str(uuid4())),
|
|
1220
1236
|
source=self.source,
|
|
1237
|
+
harness=deepcopy(self._harness),
|
|
1221
1238
|
type=event_name,
|
|
1222
1239
|
time=event.get("time", datetime.now(timezone.utc).isoformat()),
|
|
1223
1240
|
)
|
{agenthooksprotocol-0.6.0 → agenthooksprotocol-0.7.0}/src/agenthooksprotocol/_interop_hooks.py
RENAMED
|
@@ -6,7 +6,7 @@ uses the same validated core without making wire mappings a public Hooks input.
|
|
|
6
6
|
|
|
7
7
|
from typing import Any, cast, get_args
|
|
8
8
|
|
|
9
|
-
from .event import EventType
|
|
9
|
+
from .event import EventType, Harness
|
|
10
10
|
from .runtime import ProtocolError
|
|
11
11
|
|
|
12
12
|
from ._hooks import Hooks
|
|
@@ -16,6 +16,7 @@ def _hooks_for_wire(
|
|
|
16
16
|
config: dict[str, Any],
|
|
17
17
|
*,
|
|
18
18
|
source: str,
|
|
19
|
+
harness: Harness,
|
|
19
20
|
declarations: dict[str, Any],
|
|
20
21
|
transport: Any,
|
|
21
22
|
) -> Hooks:
|
|
@@ -25,6 +26,7 @@ def _hooks_for_wire(
|
|
|
25
26
|
hooks._configure(
|
|
26
27
|
config,
|
|
27
28
|
source=source,
|
|
29
|
+
harness=harness,
|
|
28
30
|
declarations=cast(dict[EventType, Any], declarations),
|
|
29
31
|
transport=transport,
|
|
30
32
|
)
|