watchlight-agent-sdk 0.5.0__py3-none-any.whl
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.
- watchlight_agent_sdk-0.5.0.dist-info/METADATA +221 -0
- watchlight_agent_sdk-0.5.0.dist-info/RECORD +31 -0
- watchlight_agent_sdk-0.5.0.dist-info/WHEEL +5 -0
- watchlight_agent_sdk-0.5.0.dist-info/entry_points.txt +2 -0
- watchlight_agent_sdk-0.5.0.dist-info/top_level.txt +1 -0
- watchlight_core/__init__.py +355 -0
- watchlight_core/__main__.py +18 -0
- watchlight_core/apdp_client.py +925 -0
- watchlight_core/conformance.py +2066 -0
- watchlight_core/connect_proxy.py +656 -0
- watchlight_core/credentials.py +652 -0
- watchlight_core/decision.py +1170 -0
- watchlight_core/declare_intent.py +360 -0
- watchlight_core/decorator.py +416 -0
- watchlight_core/env.py +22 -0
- watchlight_core/errors.py +276 -0
- watchlight_core/events_schema.py +808 -0
- watchlight_core/in_process_client.py +317 -0
- watchlight_core/kill_signal.py +479 -0
- watchlight_core/otlp.py +903 -0
- watchlight_core/plan.py +91 -0
- watchlight_core/plan_event.py +186 -0
- watchlight_core/py.typed +0 -0
- watchlight_core/results.py +207 -0
- watchlight_core/run_handle.py +3690 -0
- watchlight_core/scope.py +472 -0
- watchlight_core/sidecar.py +297 -0
- watchlight_core/state.py +113 -0
- watchlight_core/subagent_registry.py +443 -0
- watchlight_core/telemetry.py +83 -0
- watchlight_core/testing.py +729 -0
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: watchlight-agent-sdk
|
|
3
|
+
Version: 0.5.0
|
|
4
|
+
Summary: Watchlight Agent SDK — build governed AI-agent plugins for any framework
|
|
5
|
+
Author-email: Watchlight AI <team@watchlight.ai>
|
|
6
|
+
License: Apache-2.0
|
|
7
|
+
Project-URL: Homepage, https://www.watchlight.ai
|
|
8
|
+
Project-URL: Documentation, https://docs.watchlight.ai
|
|
9
|
+
Project-URL: Repository, https://github.com/watchlight-ai-beacon/watchlight
|
|
10
|
+
Project-URL: Plugin SDK Guide, https://github.com/watchlight-ai-beacon/watchlight/tree/main/plugins
|
|
11
|
+
Keywords: watchlight,ai-governance,agent-runtime,ai-agents,agent-sdk,policy-decision-point,cedar-policy
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
21
|
+
Classifier: Topic :: System :: Monitoring
|
|
22
|
+
Classifier: Topic :: Security
|
|
23
|
+
Classifier: Typing :: Typed
|
|
24
|
+
Requires-Python: >=3.10
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
Requires-Dist: httpx>=0.27
|
|
27
|
+
Requires-Dist: pydantic>=2.0
|
|
28
|
+
Requires-Dist: typing-extensions>=4.5; python_version < "3.12"
|
|
29
|
+
Provides-Extra: dev
|
|
30
|
+
Requires-Dist: pytest>=7; extra == "dev"
|
|
31
|
+
Requires-Dist: pytest-asyncio>=0.21; extra == "dev"
|
|
32
|
+
Requires-Dist: mypy>=1.8; extra == "dev"
|
|
33
|
+
Requires-Dist: cryptography>=42; extra == "dev"
|
|
34
|
+
Requires-Dist: requests>=2.32; extra == "dev"
|
|
35
|
+
Provides-Extra: otlp
|
|
36
|
+
Requires-Dist: opentelemetry-api>=1.20; extra == "otlp"
|
|
37
|
+
Requires-Dist: opentelemetry-sdk>=1.20; extra == "otlp"
|
|
38
|
+
Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.20; extra == "otlp"
|
|
39
|
+
|
|
40
|
+
# watchlight-core
|
|
41
|
+
|
|
42
|
+
Shared HTTP client and governance primitives used by every Watchlight
|
|
43
|
+
AI framework plugin (`watchlight-adk`, `watchlight-langgraph`,
|
|
44
|
+
`watchlight-bedrock`, …).
|
|
45
|
+
|
|
46
|
+
## Why this exists
|
|
47
|
+
|
|
48
|
+
Until #312, the same APDP HTTP client lived as three near-identical
|
|
49
|
+
copies under each framework plugin. As the contract stabilised across
|
|
50
|
+
ADK / LangGraph / Bedrock, three copies became the right trigger for
|
|
51
|
+
extraction. This package is the single source of truth for:
|
|
52
|
+
|
|
53
|
+
- The HTTP wire format with WL-APDP (`ApdpClient`)
|
|
54
|
+
- Plan-validation / preflight result wrappers (`PlanResult`,
|
|
55
|
+
`PreflightResult`)
|
|
56
|
+
- The plan-normalisation contract (`normalize_plan`)
|
|
57
|
+
- The framework-agnostic `GovernanceState` shape consumed by the
|
|
58
|
+
Beacon Dashboard / Streamlit governance card
|
|
59
|
+
- The base run-handle lifecycle (`BaseRunHandle`)
|
|
60
|
+
- Shared error types and the `governance_mode` env reader
|
|
61
|
+
- Plugin telemetry contract (`GovernanceTelemetry`)
|
|
62
|
+
|
|
63
|
+
## What's intentionally NOT here
|
|
64
|
+
|
|
65
|
+
Framework-specific behaviour stays in the plugin packages:
|
|
66
|
+
|
|
67
|
+
- ADK lifecycle callbacks + `PlanReActPlanner` parser + `BaseToolset`
|
|
68
|
+
— `watchlight-adk`
|
|
69
|
+
- LangGraph plan-and-execute primitives — `watchlight-langgraph`
|
|
70
|
+
- AWS Bedrock event parsing + Lambda action-group decorator +
|
|
71
|
+
`bedrock_session_attributes()` helper — `watchlight-bedrock`
|
|
72
|
+
|
|
73
|
+
## Install
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
# Minimal — APDP client + governance primitives only
|
|
77
|
+
pip install watchlight-core
|
|
78
|
+
|
|
79
|
+
# With OpenTelemetry export support (adds ~50MB of OTel SDK deps)
|
|
80
|
+
pip install 'watchlight-core[otlp]'
|
|
81
|
+
|
|
82
|
+
# Or in this monorepo:
|
|
83
|
+
pip install -e plugins/watchlight-core
|
|
84
|
+
pip install -e 'plugins/watchlight-core[otlp]'
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Plugins depend on it explicitly via their `pyproject.toml`; the core
|
|
88
|
+
package depends only on `httpx` and (on Python 3.10) `typing-extensions`.
|
|
89
|
+
The `[otlp]` extra pulls in `opentelemetry-api`, `opentelemetry-sdk`, and
|
|
90
|
+
`opentelemetry-exporter-otlp-proto-http` — optional so cold-start-
|
|
91
|
+
sensitive environments (Lambda, Cloudflare Workers) don't pay the install
|
|
92
|
+
weight when they're not exporting to OTel.
|
|
93
|
+
|
|
94
|
+
## Public API
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
from watchlight_core import (
|
|
98
|
+
# HTTP client
|
|
99
|
+
ApdpClient,
|
|
100
|
+
|
|
101
|
+
# Errors
|
|
102
|
+
WatchlightError,
|
|
103
|
+
AgentNotRegistered,
|
|
104
|
+
GovernanceUnavailable,
|
|
105
|
+
|
|
106
|
+
# Result wrappers
|
|
107
|
+
PlanResult,
|
|
108
|
+
PreflightResult,
|
|
109
|
+
|
|
110
|
+
# Plan / state
|
|
111
|
+
normalize_plan,
|
|
112
|
+
GovernanceState,
|
|
113
|
+
GovernanceTelemetry,
|
|
114
|
+
state_from_attrs,
|
|
115
|
+
|
|
116
|
+
# Lifecycle
|
|
117
|
+
BaseRunHandle,
|
|
118
|
+
GovernedPlugin,
|
|
119
|
+
|
|
120
|
+
# Custom-agent SDK (EN.6)
|
|
121
|
+
watchlight,
|
|
122
|
+
|
|
123
|
+
# OpenTelemetry export (EN.6) — requires [otlp] extra at construction
|
|
124
|
+
OtlpConfig,
|
|
125
|
+
OtlpProfile,
|
|
126
|
+
WatchlightOtlpExporter,
|
|
127
|
+
|
|
128
|
+
# Env
|
|
129
|
+
governance_mode,
|
|
130
|
+
)
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Custom-agent SDK (`@watchlight`)
|
|
134
|
+
|
|
135
|
+
For agents NOT built on a framework with a Watchlight plugin (LangGraph,
|
|
136
|
+
ADK, Bedrock), the `@watchlight` decorator emits the canonical lineage
|
|
137
|
+
events for any Python function:
|
|
138
|
+
|
|
139
|
+
```python
|
|
140
|
+
from watchlight_core import ApdpClient, watchlight
|
|
141
|
+
|
|
142
|
+
client = ApdpClient(base_url="http://localhost:8081")
|
|
143
|
+
|
|
144
|
+
@watchlight(agent_id="custom-research", apdp_client=client)
|
|
145
|
+
async def run_research(query: str) -> str:
|
|
146
|
+
# Your agent logic — emits execution_started / completed / failed
|
|
147
|
+
return result
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### OpenTelemetry export
|
|
151
|
+
|
|
152
|
+
Opt-in customer observability — sends a deliberate **subset** of the
|
|
153
|
+
lineage stream to your OTel collector. Default is `profile=off`; the
|
|
154
|
+
exporter is a no-op until you turn it on.
|
|
155
|
+
|
|
156
|
+
```python
|
|
157
|
+
from watchlight_core import OtlpConfig, WatchlightOtlpExporter
|
|
158
|
+
|
|
159
|
+
# Profile ladder: off ⊂ metrics ⊂ standard ⊂ governance
|
|
160
|
+
otlp = WatchlightOtlpExporter(OtlpConfig.from_env())
|
|
161
|
+
# WL_OTLP_PROFILE=standard
|
|
162
|
+
# WL_OTLP_ENDPOINT=http://otel-collector:4318
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Tool arguments, LLM prompts, ABR raw scores, drift baselines, and
|
|
166
|
+
security-internal anomalies never leave Watchlight. The exported subset
|
|
167
|
+
is documented in `dev-docs/architecture/otlp-export.md`.
|
|
168
|
+
|
|
169
|
+
The package exposes a `py.typed` marker so type checkers (mypy, pyright)
|
|
170
|
+
pick up the inline annotations directly.
|
|
171
|
+
|
|
172
|
+
## Contract stability
|
|
173
|
+
|
|
174
|
+
Anything in `watchlight_core/__init__.py`'s `__all__` is a **stable
|
|
175
|
+
public API** under SemVer minor-version compatibility. Anything else
|
|
176
|
+
is internal and may move between minor versions.
|
|
177
|
+
|
|
178
|
+
When changing the wire format with WL-APDP (e.g. adding a route or
|
|
179
|
+
field), update `ApdpClient` here — the plugins inherit it for free.
|
|
180
|
+
|
|
181
|
+
## Building a new plugin
|
|
182
|
+
|
|
183
|
+
Implement the framework integration surface (lifecycle hooks, native
|
|
184
|
+
plan format, etc.) in your plugin package and use this package for
|
|
185
|
+
everything else:
|
|
186
|
+
|
|
187
|
+
1. Inherit `GovernanceTelemetry` to satisfy the `last_*` contract.
|
|
188
|
+
2. For frameworks with explicit primitives (LangGraph, Bedrock):
|
|
189
|
+
subclass `BaseRunHandle` and add framework-specific helpers; expose
|
|
190
|
+
`start_run(slug)` returning your subclass.
|
|
191
|
+
3. For frameworks with lifecycle callbacks (ADK): use `ApdpClient`
|
|
192
|
+
directly and populate the `last_*` attributes from your callbacks.
|
|
193
|
+
4. Provide a one-line `state_from_<framework>_plugin` state helper
|
|
194
|
+
using `state_from_attrs(plugin, framework="<name>")`.
|
|
195
|
+
|
|
196
|
+
The `GovernanceState` shape parity test in your plugin's test suite
|
|
197
|
+
guarantees the dashboard renders consistently across frameworks.
|
|
198
|
+
|
|
199
|
+
## Cross-references
|
|
200
|
+
|
|
201
|
+
- Multi-framework contract: `dev-docs/architecture/proxy-plugin-interop.md` §6
|
|
202
|
+
- Threat model: `dev-docs/security/HARDENING.md` (entries #301, #312, plus this PR's entry)
|
|
203
|
+
|
|
204
|
+
## Open-source by design — the plugin is glue
|
|
205
|
+
|
|
206
|
+
This package (and the framework plugins built on it) ships as readable,
|
|
207
|
+
Apache-2.0 source. That's safe because **all authorization decisions, scope
|
|
208
|
+
strict-subset attenuation, lineage/audit signing, and drift/anomaly scoring are
|
|
209
|
+
server-side** — in the compiled Rust core (`wl-apdp`) and the governed platform.
|
|
210
|
+
The plugin registers hooks, shapes a request, round-trips it to the PDP, and
|
|
211
|
+
projects the answer.
|
|
212
|
+
|
|
213
|
+
There is **no differentiating IP to strip** for a community build: the
|
|
214
|
+
difference between Developer Edition and Enterprise is the *backend* the plugin
|
|
215
|
+
talks to (the in-process DE engine vs. the full governed plane), never the
|
|
216
|
+
plugin code. And because any decision made client-side is *bypassable*, keeping
|
|
217
|
+
enforcement server-side is a security rule, not just an IP one.
|
|
218
|
+
|
|
219
|
+
This boundary is documented in [`plugins/CONTRIBUTING.md`](../CONTRIBUTING.md)
|
|
220
|
+
and enforced in CI by the plugin IP-boundary gate
|
|
221
|
+
(`scripts/ci/check_plugin_ip_boundary.py`).
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
watchlight_core/__init__.py,sha256=eQ13zudOF7ke3wzdzagyYEUCvlsh6nXe41o0HOVv1FQ,10364
|
|
2
|
+
watchlight_core/__main__.py,sha256=lmWetuNAdAjx-hRhPB-OLEG44yj-qZ-aOYuPmf398uA,397
|
|
3
|
+
watchlight_core/apdp_client.py,sha256=m5BIlWSfIDzIe75ertnbGh521ADyq8GRVPjNSapQFpo,40039
|
|
4
|
+
watchlight_core/conformance.py,sha256=jsPa5BE1_EkgcwMeBYy4mGLXybRUwmBY9UBJ1bj2-zM,94460
|
|
5
|
+
watchlight_core/connect_proxy.py,sha256=T0kvze0OAeb27kAwJBRog3WkCRdt4h21rxmRdOY8NlA,26246
|
|
6
|
+
watchlight_core/credentials.py,sha256=qYDpcEye2uHDv_ooNJvAz0XZFYerqiYFn6x1ccIxYzQ,25452
|
|
7
|
+
watchlight_core/decision.py,sha256=fWJQNNrKB3VCYqTLpwvKkL6-Juw91a3FSknB48rWj5I,49198
|
|
8
|
+
watchlight_core/declare_intent.py,sha256=qXlvuHfToYM0M8o3l74lv7qkkf4vQFhqs1aZx0Vwfdw,14043
|
|
9
|
+
watchlight_core/decorator.py,sha256=hKNBKCKx7pWw2xmRR833QPy5NMnHWgyGHkfj4StHz9I,15332
|
|
10
|
+
watchlight_core/env.py,sha256=ff-jDECh0-NhW8c52EzHek7NY8IZZovYPtipyXWEuk4,832
|
|
11
|
+
watchlight_core/errors.py,sha256=Txfox_uwoXC3pm0vxmigvpqZ7D_yJ6WrbsMzLio4_68,11458
|
|
12
|
+
watchlight_core/events_schema.py,sha256=JLppEas6jdJ3gMA83TtNagOgvo8l3C3t39OuyrhbajI,30209
|
|
13
|
+
watchlight_core/in_process_client.py,sha256=x58KGszayu0iqFqNz9BsM1INTCPlHy95v6sQg1H6QqM,11812
|
|
14
|
+
watchlight_core/kill_signal.py,sha256=1p9ytEm_CaMmjHeZDPbDQn-anOzn09AVIE4hEW0bQOw,19474
|
|
15
|
+
watchlight_core/otlp.py,sha256=1dWvn8bAo4qkZhNoiHILZMChMHUPwZU8N8wf9LJIC14,36485
|
|
16
|
+
watchlight_core/plan.py,sha256=yZL3DxZTp0uXxxLdn0bNz7dw9xCsC2ssmVVHgZPyiAQ,3437
|
|
17
|
+
watchlight_core/plan_event.py,sha256=Nm7xzqMLRr9_78VT-tQW6CcTZBRg-EHOCrs1pmmtUFc,6353
|
|
18
|
+
watchlight_core/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
19
|
+
watchlight_core/results.py,sha256=Gb2x8BomDXL7TC3opiY2hwyrYXK83vttkSS0SakKz-A,8491
|
|
20
|
+
watchlight_core/run_handle.py,sha256=wgVe-CeTTksyo1DbQy5Q56oHBHnWdzgPaN0XuIWrz3s,179209
|
|
21
|
+
watchlight_core/scope.py,sha256=AwAp-12Kv21a_T_m08e3hRNm83JiEUCuIL9RKewUNHc,19007
|
|
22
|
+
watchlight_core/sidecar.py,sha256=QU4ST4CQyz3o-EnJeqREkWjrRZSxv74VMuQe5O_BNnU,9476
|
|
23
|
+
watchlight_core/state.py,sha256=CNWdklncaNB0z2Kw9E5rOnb1Nzsji8xGlUg8p9Mq4Dw,4380
|
|
24
|
+
watchlight_core/subagent_registry.py,sha256=jdUo72zkeBPd8XCpsttbccWneo2Sz8XXONX0DBwrbBI,19613
|
|
25
|
+
watchlight_core/telemetry.py,sha256=5oC9LgLisMZco3H4yXZweD0WBH8mJXRVjzBEeRMxl58,3162
|
|
26
|
+
watchlight_core/testing.py,sha256=czSvy5xfYl5uWICbc6RzQJ8ihlS-Me4jfm1FqNffZPg,31639
|
|
27
|
+
watchlight_agent_sdk-0.5.0.dist-info/METADATA,sha256=jH-Abcl07GjCJdM0H7ob7heBC_Dm1yT6zU5vCK9TjBw,8159
|
|
28
|
+
watchlight_agent_sdk-0.5.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
|
|
29
|
+
watchlight_agent_sdk-0.5.0.dist-info/entry_points.txt,sha256=ZQf77xM52PLaOlyLLIJ9S2hC6uURm3zCzxHI6_ez1ts,77
|
|
30
|
+
watchlight_agent_sdk-0.5.0.dist-info/top_level.txt,sha256=rdAml4jKiOja7d6WmXx57XXRLO1lIbPmtlmjOu0mw-k,16
|
|
31
|
+
watchlight_agent_sdk-0.5.0.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
watchlight_core
|
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
"""Watchlight AI shared governance primitives — used by every framework plugin.
|
|
2
|
+
|
|
3
|
+
This package is the single source of truth for:
|
|
4
|
+
|
|
5
|
+
- The HTTP wire format with WL-APDP (``ApdpClient``)
|
|
6
|
+
- The plan-validation / preflight result wrappers
|
|
7
|
+
- The plan-normalisation contract
|
|
8
|
+
- The framework-agnostic ``GovernanceState`` shape rendered by the
|
|
9
|
+
Streamlit / Beacon Dashboard governance card
|
|
10
|
+
- The base run-handle lifecycle (resolve → session → manifest → close)
|
|
11
|
+
- Shared error types and the ``governance_mode`` env reader
|
|
12
|
+
|
|
13
|
+
Framework-specific behaviour stays in the plugin packages
|
|
14
|
+
(``watchlight-adk``, ``watchlight-langgraph``, ``watchlight-bedrock``,
|
|
15
|
+
…). When you bring up a new plugin, you only own the framework
|
|
16
|
+
integration surface; everything in this module is reused.
|
|
17
|
+
|
|
18
|
+
Public API is intentionally narrow. Anything not re-exported here is
|
|
19
|
+
considered internal to a future minor release.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
from .apdp_client import ApdpClient
|
|
23
|
+
from .in_process_client import GovernanceBackend, InProcessClient
|
|
24
|
+
from .connect_proxy import (
|
|
25
|
+
install_connect_proxy,
|
|
26
|
+
is_connect_proxy_installed,
|
|
27
|
+
uninstall_connect_proxy,
|
|
28
|
+
)
|
|
29
|
+
from .sidecar import (
|
|
30
|
+
install_sidecar,
|
|
31
|
+
is_sidecar_installed,
|
|
32
|
+
uninstall_sidecar,
|
|
33
|
+
)
|
|
34
|
+
from .credentials import (
|
|
35
|
+
Credential,
|
|
36
|
+
CredentialKind,
|
|
37
|
+
CredentialNotFound,
|
|
38
|
+
InvalidCredential,
|
|
39
|
+
PluginCredential,
|
|
40
|
+
ServiceCredential,
|
|
41
|
+
)
|
|
42
|
+
from .declare_intent import (
|
|
43
|
+
BROWNFIELD,
|
|
44
|
+
DECLARE_INTENT_RESPONSE_STATUS,
|
|
45
|
+
DECLARE_INTENT_TOOL_DESCRIPTION,
|
|
46
|
+
DECLARE_INTENT_TOOL_NAME,
|
|
47
|
+
GREENFIELD,
|
|
48
|
+
INTENT_ENFORCEMENT_MODE_ENV_VAR,
|
|
49
|
+
WATCHLIGHT_DECLARE_INTENT_TOOL,
|
|
50
|
+
handle_declare_intent_call,
|
|
51
|
+
is_declare_intent_tool_call,
|
|
52
|
+
is_declare_intent_tool_name,
|
|
53
|
+
resolve_intent_enforcement_mode,
|
|
54
|
+
should_inject_synthetic_tool,
|
|
55
|
+
truncate_intent_objective,
|
|
56
|
+
)
|
|
57
|
+
from .decision import (
|
|
58
|
+
AgentQuarantinedError,
|
|
59
|
+
AgentRevokedError,
|
|
60
|
+
AllowDecision,
|
|
61
|
+
Attenuation,
|
|
62
|
+
AuthorizationDecision,
|
|
63
|
+
DenyDecision,
|
|
64
|
+
Escalation,
|
|
65
|
+
ExecutionTerminatedError,
|
|
66
|
+
NeedsApprovalDecision,
|
|
67
|
+
Observation,
|
|
68
|
+
QuarantineDecision,
|
|
69
|
+
RevokeDecision,
|
|
70
|
+
RunHandleState,
|
|
71
|
+
SeverSubtreeDecision,
|
|
72
|
+
SubtreeSeveredError,
|
|
73
|
+
TerminateDecision,
|
|
74
|
+
parse_authorization_decision,
|
|
75
|
+
)
|
|
76
|
+
from .decorator import watchlight
|
|
77
|
+
from .errors import (
|
|
78
|
+
AgentNotRegistered,
|
|
79
|
+
CredentialProbeFailed,
|
|
80
|
+
GovernanceUnavailable,
|
|
81
|
+
InsecureChannelError,
|
|
82
|
+
RunHandleInvalidated,
|
|
83
|
+
ScopeAttenuationDenied,
|
|
84
|
+
ScopeViolationDimension,
|
|
85
|
+
WatchlightContractError,
|
|
86
|
+
WatchlightError,
|
|
87
|
+
)
|
|
88
|
+
from .env import governance_mode
|
|
89
|
+
from .events_schema import (
|
|
90
|
+
EVENT_ID_PATTERN,
|
|
91
|
+
EVENT_ID_RE,
|
|
92
|
+
ERROR_MESSAGE_MAX_CHARS,
|
|
93
|
+
INPUT_SUMMARY_MAX_CHARS,
|
|
94
|
+
INTENT_OBJECTIVE_MAX_BYTES,
|
|
95
|
+
LIFT_REASON_MAX_BYTES,
|
|
96
|
+
MAX_CONTRIBUTING_FEATURES,
|
|
97
|
+
REASON_MAX_BYTES,
|
|
98
|
+
ActionRef,
|
|
99
|
+
CredentialRef,
|
|
100
|
+
EventEnvelope,
|
|
101
|
+
EventType,
|
|
102
|
+
ExecutionEvent,
|
|
103
|
+
ExecutionQuarantinedPayload,
|
|
104
|
+
ExecutionResumedPayload,
|
|
105
|
+
FeatureContribution,
|
|
106
|
+
IntentProvenance,
|
|
107
|
+
PrincipalRef,
|
|
108
|
+
ResourceRef,
|
|
109
|
+
summarize_arg_keys,
|
|
110
|
+
truncate_error_message,
|
|
111
|
+
truncate_summary,
|
|
112
|
+
)
|
|
113
|
+
from .kill_signal import (
|
|
114
|
+
DISPOSITION_GRACEFUL,
|
|
115
|
+
DISPOSITION_PROXY_HARD_KILL,
|
|
116
|
+
InterceptorKillRegistry,
|
|
117
|
+
KILL_SIGNAL_GRACEFUL_WINDOW_MS,
|
|
118
|
+
KillSignalResult,
|
|
119
|
+
LLM_CALL_INTERRUPTED_REASON_HARD_TIMEOUT,
|
|
120
|
+
LLM_CALL_INTERRUPTED_REASON_MANUAL_TERMINATE,
|
|
121
|
+
LLM_CALL_INTERRUPTED_REASON_POLICY_TERMINATE,
|
|
122
|
+
LLM_CALL_INTERRUPTED_REASON_QUARANTINE,
|
|
123
|
+
LLM_CALL_INTERRUPTED_REASON_REVOKE,
|
|
124
|
+
LLM_CALL_INTERRUPTED_REASON_SCOPE_VIOLATION,
|
|
125
|
+
LLM_CALL_INTERRUPTED_REASON_SEVER_SUBTREE,
|
|
126
|
+
LlmCallInterruptedPayload,
|
|
127
|
+
LlmCallInterruptedValidationError,
|
|
128
|
+
RegisterRequestOptions,
|
|
129
|
+
httpx_hard_kill_escalator,
|
|
130
|
+
)
|
|
131
|
+
from .otlp import (
|
|
132
|
+
OtlpConfig,
|
|
133
|
+
OtlpProfile,
|
|
134
|
+
WatchlightOtlpExporter,
|
|
135
|
+
)
|
|
136
|
+
from .plan import normalize_plan
|
|
137
|
+
from .plan_event import (
|
|
138
|
+
PLAN_INTENDED_TOOLS_MAX,
|
|
139
|
+
PLAN_RATIONALE_MAX_BYTES,
|
|
140
|
+
PLAN_TOOL_NAME_PATTERN,
|
|
141
|
+
PLAN_TOOL_NAME_RE,
|
|
142
|
+
PlanKind,
|
|
143
|
+
PlanValidationError,
|
|
144
|
+
build_plan_payload,
|
|
145
|
+
filter_valid_tool_names,
|
|
146
|
+
is_valid_tool_name,
|
|
147
|
+
truncate_rationale,
|
|
148
|
+
)
|
|
149
|
+
from .results import AuthorizeResult, PlanResult, PreflightResult
|
|
150
|
+
from .run_handle import (
|
|
151
|
+
BaseRunHandle,
|
|
152
|
+
GovernedPlugin,
|
|
153
|
+
HandleLineage,
|
|
154
|
+
current_handle_lineage,
|
|
155
|
+
current_subagent_handle,
|
|
156
|
+
)
|
|
157
|
+
from .scope import (
|
|
158
|
+
GrantedScope,
|
|
159
|
+
ParentSignature,
|
|
160
|
+
RequestedScope,
|
|
161
|
+
ResourceMatcher,
|
|
162
|
+
SpawnSubagentRequest,
|
|
163
|
+
SpawnSubagentResponse,
|
|
164
|
+
granted_scope_from_dict,
|
|
165
|
+
granted_scope_to_dict,
|
|
166
|
+
parent_signature_from_dict,
|
|
167
|
+
parent_signature_to_dict,
|
|
168
|
+
requested_scope_from_dict,
|
|
169
|
+
requested_scope_to_dict,
|
|
170
|
+
resource_matcher_from_dict,
|
|
171
|
+
resource_matcher_to_dict,
|
|
172
|
+
spawn_subagent_request_from_dict,
|
|
173
|
+
spawn_subagent_request_to_dict,
|
|
174
|
+
spawn_subagent_response_from_dict,
|
|
175
|
+
spawn_subagent_response_to_dict,
|
|
176
|
+
)
|
|
177
|
+
from .state import GovernanceState, state_from_attrs
|
|
178
|
+
from .subagent_registry import (
|
|
179
|
+
DEFAULT_SUBAGENT_SCOPE_ENV_VAR,
|
|
180
|
+
SubagentRegistry,
|
|
181
|
+
default_subagent_scope_from_env,
|
|
182
|
+
)
|
|
183
|
+
from .telemetry import GovernanceTelemetry
|
|
184
|
+
|
|
185
|
+
__all__ = [
|
|
186
|
+
# Client
|
|
187
|
+
"ApdpClient",
|
|
188
|
+
"InProcessClient",
|
|
189
|
+
"GovernanceBackend",
|
|
190
|
+
# CONNECT local sidecar proxy (M37-B3)
|
|
191
|
+
"install_connect_proxy",
|
|
192
|
+
"is_connect_proxy_installed",
|
|
193
|
+
"uninstall_connect_proxy",
|
|
194
|
+
"install_sidecar",
|
|
195
|
+
"is_sidecar_installed",
|
|
196
|
+
"uninstall_sidecar",
|
|
197
|
+
# Credentials
|
|
198
|
+
"Credential",
|
|
199
|
+
"CredentialKind",
|
|
200
|
+
"CredentialNotFound",
|
|
201
|
+
"InvalidCredential",
|
|
202
|
+
"PluginCredential",
|
|
203
|
+
"ServiceCredential",
|
|
204
|
+
# Decorator (custom-agent SDK)
|
|
205
|
+
"watchlight",
|
|
206
|
+
# Errors
|
|
207
|
+
"WatchlightError",
|
|
208
|
+
"WatchlightContractError",
|
|
209
|
+
"AgentNotRegistered",
|
|
210
|
+
"CredentialProbeFailed",
|
|
211
|
+
"GovernanceUnavailable",
|
|
212
|
+
"InsecureChannelError",
|
|
213
|
+
# M43-E — sub-agent scope attenuation typed errors
|
|
214
|
+
"RunHandleInvalidated",
|
|
215
|
+
"ScopeAttenuationDenied",
|
|
216
|
+
"ScopeViolationDimension",
|
|
217
|
+
# OTLP export (EN.6)
|
|
218
|
+
"OtlpConfig",
|
|
219
|
+
"OtlpProfile",
|
|
220
|
+
"WatchlightOtlpExporter",
|
|
221
|
+
# Result wrappers
|
|
222
|
+
"AuthorizeResult",
|
|
223
|
+
"PlanResult",
|
|
224
|
+
"PreflightResult",
|
|
225
|
+
# Plan
|
|
226
|
+
"normalize_plan",
|
|
227
|
+
# PlanObserved event helpers (MCP.1)
|
|
228
|
+
"PLAN_INTENDED_TOOLS_MAX",
|
|
229
|
+
"PLAN_RATIONALE_MAX_BYTES",
|
|
230
|
+
"PLAN_TOOL_NAME_PATTERN",
|
|
231
|
+
"PLAN_TOOL_NAME_RE",
|
|
232
|
+
"PlanKind",
|
|
233
|
+
"PlanValidationError",
|
|
234
|
+
"build_plan_payload",
|
|
235
|
+
"filter_valid_tool_names",
|
|
236
|
+
"is_valid_tool_name",
|
|
237
|
+
"truncate_rationale",
|
|
238
|
+
# State + telemetry
|
|
239
|
+
"GovernanceState",
|
|
240
|
+
"GovernanceTelemetry",
|
|
241
|
+
"state_from_attrs",
|
|
242
|
+
# Lifecycle base
|
|
243
|
+
"BaseRunHandle",
|
|
244
|
+
"GovernedPlugin",
|
|
245
|
+
# M43-E — sub-agent contextvar accessor
|
|
246
|
+
"current_subagent_handle",
|
|
247
|
+
# #889 — lineage propagation contextvar (CONNECT sidecar reads this
|
|
248
|
+
# to inject ``X-Wl-Execution-Id`` headers on outbound CONNECTs so
|
|
249
|
+
# wl-proxy emits per-tunnel events with the orchestrator's
|
|
250
|
+
# execution_id instead of phantom fallbacks).
|
|
251
|
+
"HandleLineage",
|
|
252
|
+
"current_handle_lineage",
|
|
253
|
+
# Env
|
|
254
|
+
"governance_mode",
|
|
255
|
+
# Events schema (SDK 0.4.0 — pydantic mirror of wl-lineage::events)
|
|
256
|
+
"ActionRef",
|
|
257
|
+
"CredentialRef",
|
|
258
|
+
"EventEnvelope",
|
|
259
|
+
"EventType",
|
|
260
|
+
"ExecutionEvent",
|
|
261
|
+
"PrincipalRef",
|
|
262
|
+
"ResourceRef",
|
|
263
|
+
"EVENT_ID_PATTERN",
|
|
264
|
+
"EVENT_ID_RE",
|
|
265
|
+
"INPUT_SUMMARY_MAX_CHARS",
|
|
266
|
+
"ERROR_MESSAGE_MAX_CHARS",
|
|
267
|
+
"summarize_arg_keys",
|
|
268
|
+
"truncate_error_message",
|
|
269
|
+
"truncate_summary",
|
|
270
|
+
# M46-B — intent provenance enum + byte cap (mirror of
|
|
271
|
+
# wl-lineage::events::IntentProvenance + INTENT_OBJECTIVE_MAX_BYTES)
|
|
272
|
+
"INTENT_OBJECTIVE_MAX_BYTES",
|
|
273
|
+
"IntentProvenance",
|
|
274
|
+
# M45-E — quarantine event payload mirrors + size constants
|
|
275
|
+
"ExecutionQuarantinedPayload",
|
|
276
|
+
"ExecutionResumedPayload",
|
|
277
|
+
"FeatureContribution",
|
|
278
|
+
"LIFT_REASON_MAX_BYTES",
|
|
279
|
+
"MAX_CONTRIBUTING_FEATURES",
|
|
280
|
+
"REASON_MAX_BYTES",
|
|
281
|
+
# M45-F — typed authorization decision + handle state machine
|
|
282
|
+
"AgentQuarantinedError",
|
|
283
|
+
"AgentRevokedError",
|
|
284
|
+
"AllowDecision",
|
|
285
|
+
"Attenuation",
|
|
286
|
+
"AuthorizationDecision",
|
|
287
|
+
"DenyDecision",
|
|
288
|
+
"Escalation",
|
|
289
|
+
"ExecutionTerminatedError",
|
|
290
|
+
"NeedsApprovalDecision",
|
|
291
|
+
"Observation",
|
|
292
|
+
"QuarantineDecision",
|
|
293
|
+
"RevokeDecision",
|
|
294
|
+
"RunHandleState",
|
|
295
|
+
"SeverSubtreeDecision",
|
|
296
|
+
"SubtreeSeveredError",
|
|
297
|
+
"TerminateDecision",
|
|
298
|
+
"parse_authorization_decision",
|
|
299
|
+
# M45-I — kill-signal protocol for HTTP interceptors
|
|
300
|
+
"InterceptorKillRegistry",
|
|
301
|
+
"KILL_SIGNAL_GRACEFUL_WINDOW_MS",
|
|
302
|
+
"DISPOSITION_GRACEFUL",
|
|
303
|
+
"DISPOSITION_PROXY_HARD_KILL",
|
|
304
|
+
"LLM_CALL_INTERRUPTED_REASON_QUARANTINE",
|
|
305
|
+
"LLM_CALL_INTERRUPTED_REASON_SCOPE_VIOLATION",
|
|
306
|
+
"LLM_CALL_INTERRUPTED_REASON_MANUAL_TERMINATE",
|
|
307
|
+
"LLM_CALL_INTERRUPTED_REASON_HARD_TIMEOUT",
|
|
308
|
+
"LLM_CALL_INTERRUPTED_REASON_POLICY_TERMINATE",
|
|
309
|
+
"LLM_CALL_INTERRUPTED_REASON_SEVER_SUBTREE",
|
|
310
|
+
"LLM_CALL_INTERRUPTED_REASON_REVOKE",
|
|
311
|
+
"LlmCallInterruptedPayload",
|
|
312
|
+
"LlmCallInterruptedValidationError",
|
|
313
|
+
"KillSignalResult",
|
|
314
|
+
"RegisterRequestOptions",
|
|
315
|
+
"httpx_hard_kill_escalator",
|
|
316
|
+
# M46-K — synthetic ``watchlight.declare_intent`` tool contract.
|
|
317
|
+
"BROWNFIELD",
|
|
318
|
+
"DECLARE_INTENT_RESPONSE_STATUS",
|
|
319
|
+
"DECLARE_INTENT_TOOL_DESCRIPTION",
|
|
320
|
+
"DECLARE_INTENT_TOOL_NAME",
|
|
321
|
+
"GREENFIELD",
|
|
322
|
+
"INTENT_ENFORCEMENT_MODE_ENV_VAR",
|
|
323
|
+
"WATCHLIGHT_DECLARE_INTENT_TOOL",
|
|
324
|
+
"handle_declare_intent_call",
|
|
325
|
+
"is_declare_intent_tool_call",
|
|
326
|
+
"is_declare_intent_tool_name",
|
|
327
|
+
"resolve_intent_enforcement_mode",
|
|
328
|
+
"should_inject_synthetic_tool",
|
|
329
|
+
"truncate_intent_objective",
|
|
330
|
+
# M43-B — sub-agent scope attenuation wire shapes.
|
|
331
|
+
"GrantedScope",
|
|
332
|
+
"ParentSignature",
|
|
333
|
+
"RequestedScope",
|
|
334
|
+
"ResourceMatcher",
|
|
335
|
+
"SpawnSubagentRequest",
|
|
336
|
+
"SpawnSubagentResponse",
|
|
337
|
+
"granted_scope_from_dict",
|
|
338
|
+
"granted_scope_to_dict",
|
|
339
|
+
"parent_signature_from_dict",
|
|
340
|
+
"parent_signature_to_dict",
|
|
341
|
+
"requested_scope_from_dict",
|
|
342
|
+
"requested_scope_to_dict",
|
|
343
|
+
"resource_matcher_from_dict",
|
|
344
|
+
"resource_matcher_to_dict",
|
|
345
|
+
"spawn_subagent_request_from_dict",
|
|
346
|
+
"spawn_subagent_request_to_dict",
|
|
347
|
+
"spawn_subagent_response_from_dict",
|
|
348
|
+
"spawn_subagent_response_to_dict",
|
|
349
|
+
# Uniform governed-spawn routing primitive.
|
|
350
|
+
"SubagentRegistry",
|
|
351
|
+
"DEFAULT_SUBAGENT_SCOPE_ENV_VAR",
|
|
352
|
+
"default_subagent_scope_from_env",
|
|
353
|
+
]
|
|
354
|
+
|
|
355
|
+
__version__ = "0.5.0"
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"""Module-level CLI dispatch for ``python -m watchlight_core``.
|
|
2
|
+
|
|
3
|
+
Currently dispatches to the conformance runner; future commands
|
|
4
|
+
(scaffold new plugin, validate event schema, etc.) plug in here.
|
|
5
|
+
|
|
6
|
+
Usage:
|
|
7
|
+
|
|
8
|
+
python -m watchlight_core.conformance my_plugin_package
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import sys
|
|
14
|
+
|
|
15
|
+
from .conformance import _main
|
|
16
|
+
|
|
17
|
+
if __name__ == "__main__":
|
|
18
|
+
sys.exit(_main())
|