agentconnect-cli 0.1.0a1__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.
Files changed (64) hide show
  1. agentconnect/__init__.py +3 -0
  2. agentconnect/a2a_adapter/__init__.py +6 -0
  3. agentconnect/a2a_adapter/adapter.py +565 -0
  4. agentconnect/a2a_adapter/cards.py +149 -0
  5. agentconnect/a2a_adapter/convert.py +157 -0
  6. agentconnect/a2a_adapter/facade.py +560 -0
  7. agentconnect/a2a_adapter/seen.py +49 -0
  8. agentconnect/a2a_adapter/serve.py +67 -0
  9. agentconnect/adapter.py +319 -0
  10. agentconnect/adapters.py +52 -0
  11. agentconnect/apiclient.py +51 -0
  12. agentconnect/backoff.py +42 -0
  13. agentconnect/callback.py +314 -0
  14. agentconnect/cli.py +2324 -0
  15. agentconnect/cli_json.py +470 -0
  16. agentconnect/cli_support.py +444 -0
  17. agentconnect/clock.py +161 -0
  18. agentconnect/config.py +1213 -0
  19. agentconnect/daemon/__init__.py +41 -0
  20. agentconnect/deliveries.py +295 -0
  21. agentconnect/directory_client.py +255 -0
  22. agentconnect/failpoints.py +99 -0
  23. agentconnect/identity.py +111 -0
  24. agentconnect/isolation.py +345 -0
  25. agentconnect/keystore.py +279 -0
  26. agentconnect/limits.py +457 -0
  27. agentconnect/log.py +143 -0
  28. agentconnect/mcp/__init__.py +30 -0
  29. agentconnect/mcp/backend.py +405 -0
  30. agentconnect/mcp/server.py +382 -0
  31. agentconnect/mcp/session.py +373 -0
  32. agentconnect/mcp/tools.py +583 -0
  33. agentconnect/ownerfile.py +238 -0
  34. agentconnect/payloads.py +109 -0
  35. agentconnect/policy.py +1066 -0
  36. agentconnect/provision.py +239 -0
  37. agentconnect/py.typed +0 -0
  38. agentconnect/relay.py +405 -0
  39. agentconnect/runtime/__init__.py +46 -0
  40. agentconnect/runtime/agent.py +225 -0
  41. agentconnect/runtime/api.py +2043 -0
  42. agentconnect/runtime/engine.py +5359 -0
  43. agentconnect/runtime/errors.py +47 -0
  44. agentconnect/runtime/floor.py +649 -0
  45. agentconnect/runtime/groups.py +1351 -0
  46. agentconnect/runtime/knocks.py +1422 -0
  47. agentconnect/runtime/ledger.py +94 -0
  48. agentconnect/runtime/listing.py +1307 -0
  49. agentconnect/runtime/registry.py +53 -0
  50. agentconnect/runtime/runtime.py +158 -0
  51. agentconnect/runtime/sas.py +1002 -0
  52. agentconnect/sas_emoji.py +83 -0
  53. agentconnect/schemas.py +381 -0
  54. agentconnect/shapes.py +56 -0
  55. agentconnect/sockets.py +86 -0
  56. agentconnect/sse.py +234 -0
  57. agentconnect/store.py +3282 -0
  58. agentconnect/tasks.py +35 -0
  59. agentconnect/tokens.py +63 -0
  60. agentconnect/webhook.py +199 -0
  61. agentconnect_cli-0.1.0a1.dist-info/METADATA +103 -0
  62. agentconnect_cli-0.1.0a1.dist-info/RECORD +64 -0
  63. agentconnect_cli-0.1.0a1.dist-info/WHEEL +4 -0
  64. agentconnect_cli-0.1.0a1.dist-info/entry_points.txt +3 -0
agentconnect/tasks.py ADDED
@@ -0,0 +1,35 @@
1
+ """Stopping helper tasks without swallowing the caller's own cancellation.
2
+
3
+ ``task.cancel(); with suppress(CancelledError): await task`` is wrong: if
4
+ the *calling* task is cancelled while it waits, its ``CancelledError`` is
5
+ suppressed too, and the caller carries on as if nothing happened (so
6
+ ``Engine.stop`` or a shutdown that cancels a worker never takes effect).
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import asyncio
12
+ from typing import Any
13
+
14
+
15
+ async def cancel_and_wait(
16
+ *tasks: asyncio.Future[Any], ignore: tuple[type[BaseException], ...] = ()
17
+ ) -> None:
18
+ """Cancel ``tasks`` and wait until every one has finished.
19
+
20
+ How a task ended is ignored when it is its own cancellation or an
21
+ exception in ``ignore``; any other exception is raised (the first, in
22
+ argument order). If the calling task is cancelled meanwhile, its
23
+ ``CancelledError`` propagates: ``gather`` passes the caller's
24
+ cancellation on and reports the tasks' own as results.
25
+
26
+ The calling task itself, if it is among ``tasks``, is skipped: a task
27
+ can't wait for its own end, and gathering on itself would never return."""
28
+ current = asyncio.current_task()
29
+ tasks = tuple(t for t in tasks if t is not current)
30
+ for t in tasks:
31
+ t.cancel()
32
+ results = await asyncio.gather(*tasks, return_exceptions=True)
33
+ for r in results:
34
+ if isinstance(r, BaseException) and not isinstance(r, (asyncio.CancelledError, *ignore)):
35
+ raise r
agentconnect/tokens.py ADDED
@@ -0,0 +1,63 @@
1
+ """The local API's bearer tokens and other 0600 secret files.
2
+
3
+ ``api-token`` (agent scope) and ``human-token`` (human scope) live in the
4
+ data directory, created on first start. The runtime reads each once and
5
+ keeps only its SHA-256 (:class:`TokenDigest`), so the token's value is not
6
+ held in the runtime's memory (ADR-005, Decision 4). The CLI reads the file
7
+ per command; the SDK and agent integrations read ``api-token`` only.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import hashlib
13
+ import hmac
14
+ import os
15
+ import secrets
16
+ from pathlib import Path
17
+ from typing import override
18
+
19
+ from agentconnect.keystore import write_private
20
+
21
+ API_TOKEN_FILE = "api-token" # noqa: S105 - a file name
22
+ HUMAN_TOKEN_FILE = "human-token" # noqa: S105 - a file name
23
+
24
+
25
+ def load_token(path: Path) -> str:
26
+ """Read the token at ``path``, creating it (0600) if missing. An existing
27
+ token file must be ours and private (no group or other bits)."""
28
+ if path.exists():
29
+ st = path.stat()
30
+ if st.st_mode & 0o077 or st.st_uid != os.geteuid():
31
+ msg = f"{path.name} must be owned by this user with mode 0600"
32
+ raise PermissionError(msg)
33
+ return path.read_text(encoding="ascii").strip()
34
+ token = secrets.token_urlsafe(32)
35
+ write_private(path, token.encode("ascii"))
36
+ return token
37
+
38
+
39
+ class TokenDigest:
40
+ """The SHA-256 of a token, for a constant-time bearer check. The token's
41
+ value is never stored, and the digest is kept out of ``repr``."""
42
+
43
+ __slots__ = ("_digest",)
44
+
45
+ # SHA-256, not a password hash, on purpose: the tokens are 256 bits from
46
+ # secrets.token_urlsafe(32), not passwords people choose, so there is
47
+ # nothing to brute-force and no stretching (bcrypt, scrypt) to add. The
48
+ # hash only keeps the value out of memory; compare_digest keeps the
49
+ # comparison constant-time.
50
+ def __init__(self, token: str) -> None:
51
+ self._digest = hashlib.sha256(token.encode()).digest()
52
+
53
+ @classmethod
54
+ def of_file(cls, path: Path) -> TokenDigest:
55
+ """Load (or create) the token file at ``path`` and keep its digest."""
56
+ return cls(load_token(path))
57
+
58
+ def matches(self, bearer_token: str) -> bool:
59
+ return hmac.compare_digest(hashlib.sha256(bearer_token.encode()).digest(), self._digest)
60
+
61
+ @override
62
+ def __repr__(self) -> str:
63
+ return "TokenDigest(<redacted>)"
@@ -0,0 +1,199 @@
1
+ """The webhook adapter: POST every message and event to a callback URL.
2
+
3
+ Delivery is **at least once**:
4
+
5
+ * Messages go through the daemon's delivery loop, which keeps them in order
6
+ and in its durable inbound queue until :meth:`WebhookAdapter.deliver`
7
+ returns ``ACK``. A 2xx response is an ack; any other response, a timeout
8
+ or a connection error is ``RETRY``, and the daemon retries with
9
+ exponential backoff on its clock. Nothing later is delivered before it.
10
+ * Events (``member_joined``, ``epoch_changed``, ``loop_guard``, ...) are
11
+ posted at once. If that fails, they wait in a bounded in-memory queue with
12
+ the same retry rule, and ``on_event`` raises, so the daemon keeps the event
13
+ unnotified and sends it again after a reconnect or restart (ADR-004). The
14
+ repeat carries the same ``event_id``.
15
+
16
+ A receiver can therefore see a payload twice (the ack was lost) and must
17
+ treat ``msg_id`` / ``event_id`` as idempotency keys. The Python SDK does.
18
+
19
+ Every request is signed: ``X-AgentConnect-Signature: v0=<hex>`` is
20
+ HMAC-SHA256 over ``<timestamp>.<body>`` with the adapter's secret, and
21
+ ``X-AgentConnect-Timestamp`` is the Unix time in seconds. Each attempt is
22
+ signed afresh, so a captured request stops verifying after the receiver's
23
+ skew window (5 minutes in the SDK).
24
+
25
+ The callback is loopback unless the config opts in (``webhook.allow_remote``)
26
+ and then it must be ``https``; redirects are never followed.
27
+ """
28
+
29
+ from __future__ import annotations
30
+
31
+ import asyncio
32
+ import hashlib
33
+ import hmac
34
+ from collections import deque
35
+ from typing import Any, override
36
+ from urllib.parse import urlsplit
37
+
38
+ import httpx
39
+
40
+ from agentconnect import log
41
+ from agentconnect.adapter import (
42
+ Capabilities,
43
+ Delivery,
44
+ DeliveryResult,
45
+ Event,
46
+ GroupView,
47
+ OutboundSend,
48
+ Sender,
49
+ )
50
+ from agentconnect.backoff import Backoff
51
+ from agentconnect.clock import Clock, unix_seconds
52
+ from agentconnect.payloads import encode, event_payload, message_payload
53
+ from agentconnect.tasks import cancel_and_wait
54
+
55
+ LOG = log.get("agentconnect.webhook")
56
+
57
+ SIGNATURE_HEADER = "X-AgentConnect-Signature"
58
+ TIMESTAMP_HEADER = "X-AgentConnect-Timestamp"
59
+ SIGNATURE_VERSION = "v0"
60
+ SECRET_FILE = "webhook-secret" # noqa: S105 - a file name
61
+ EVENT_QUEUE_LIMIT = 1000
62
+
63
+
64
+ def sign(secret: str, timestamp: str, body: bytes) -> str:
65
+ """``v0=<hex>``: HMAC-SHA256 over ``<timestamp>.<body>``."""
66
+ mac = hmac.new(secret.encode(), timestamp.encode() + b"." + body, hashlib.sha256)
67
+ return f"{SIGNATURE_VERSION}={mac.hexdigest()}"
68
+
69
+
70
+ class WebhookAdapter:
71
+ """Implements :class:`agentconnect.adapter.Adapter` over HTTP POST."""
72
+
73
+ name = "webhook"
74
+
75
+ def __init__( # noqa: PLR0913
76
+ self,
77
+ url: str,
78
+ secret: str,
79
+ clock: Clock,
80
+ *,
81
+ transport: httpx.AsyncBaseTransport | None = None,
82
+ timeout: float = 10.0,
83
+ backoff: Backoff | None = None,
84
+ ) -> None:
85
+ self.url = url
86
+ self._secret = secret
87
+ self._clock = clock
88
+ self._transport, self._timeout = transport, timeout
89
+ self._client: httpx.AsyncClient | None = None
90
+ self._backoff = backoff or Backoff(base=1.0, cap=300.0)
91
+ self._events: deque[dict[str, Any]] = deque()
92
+ self._wake = asyncio.Event()
93
+ self._worker: asyncio.Task[None] | None = None
94
+ self._inflight = 0
95
+ self._quiet = asyncio.Event()
96
+ self._quiet.set()
97
+
98
+ @property
99
+ def _http(self) -> httpx.AsyncClient:
100
+ if self._client is None:
101
+ self._client = httpx.AsyncClient(
102
+ transport=self._transport,
103
+ timeout=self._timeout,
104
+ follow_redirects=False,
105
+ trust_env=False,
106
+ )
107
+ return self._client
108
+
109
+ @override
110
+ def __repr__(self) -> str:
111
+ host = urlsplit(self.url).netloc
112
+ return f"WebhookAdapter(host={host!r})"
113
+
114
+ def capabilities(self) -> Capabilities:
115
+ return Capabilities(accepts=["text", "data"], originates=False)
116
+
117
+ async def on_outbound(self, send: OutboundSend) -> None:
118
+ # Outbound messages go through the local API; start the event worker.
119
+ self._ensure_worker()
120
+
121
+ def _ensure_worker(self) -> None:
122
+ if self._worker is None or self._worker.done():
123
+ self._worker = asyncio.get_running_loop().create_task(self._run_events())
124
+
125
+ async def drain(self) -> None:
126
+ """Wait until no request is in flight (for orderly shutdown in tests)."""
127
+ await self._quiet.wait()
128
+
129
+ async def close(self) -> None:
130
+ try:
131
+ if self._worker is not None:
132
+ await cancel_and_wait(self._worker)
133
+ self._worker = None
134
+ finally:
135
+ if self._client is not None:
136
+ await self._client.aclose()
137
+ self._client = None
138
+
139
+ async def _post(self, payload: dict[str, Any]) -> bool:
140
+ body = encode(payload)
141
+ stamp = str(unix_seconds(self._clock))
142
+ headers = {
143
+ "content-type": "application/json",
144
+ TIMESTAMP_HEADER: stamp,
145
+ SIGNATURE_HEADER: sign(self._secret, stamp, body),
146
+ }
147
+ self._inflight += 1
148
+ self._quiet.clear()
149
+ try:
150
+ resp = await self._http.post(self.url, content=body, headers=headers)
151
+ except httpx.HTTPError as e:
152
+ LOG.warning("webhook_unreachable", error=type(e).__name__)
153
+ return False
154
+ finally:
155
+ self._inflight -= 1
156
+ if self._inflight == 0:
157
+ self._quiet.set()
158
+ if 200 <= resp.status_code < 300: # noqa: PLR2004
159
+ return True
160
+ LOG.warning("webhook_rejected", status=resp.status_code)
161
+ return False
162
+
163
+ async def deliver(
164
+ self, group: GroupView, sender: Sender, to: list[str], inner: Delivery
165
+ ) -> DeliveryResult:
166
+ ok = await self._post(message_payload(group, inner))
167
+ return DeliveryResult.ACK if ok else DeliveryResult.RETRY
168
+
169
+ async def on_event(self, group: GroupView | None, event: Event) -> None:
170
+ """Send the event now when nothing is waiting ahead of it. If that
171
+ fails, or earlier events are still queued (order), queue it for the
172
+ retry worker and raise: the daemon then keeps the event unnotified
173
+ and sends it again after a reconnect or restart. The receiver dedupes
174
+ by ``event_id``, so the repeat is harmless."""
175
+ payload = event_payload(group, event)
176
+ if not self._events and await self._post(payload):
177
+ return
178
+ if all(p["event_id"] != event.event_id for p in self._events):
179
+ if len(self._events) >= EVENT_QUEUE_LIMIT:
180
+ self._events.popleft()
181
+ LOG.warning("webhook_event_dropped")
182
+ self._events.append(payload)
183
+ self._wake.set()
184
+ self._ensure_worker()
185
+ msg = "webhook not reachable"
186
+ raise ConnectionError(msg)
187
+
188
+ async def _run_events(self) -> None:
189
+ while True:
190
+ self._wake.clear()
191
+ while self._events:
192
+ head = self._events[0]
193
+ if await self._post(head):
194
+ if self._events and self._events[0] is head:
195
+ self._events.popleft()
196
+ self._backoff.reset()
197
+ else:
198
+ await self._clock.sleep(self._backoff.next())
199
+ await self._wake.wait()
@@ -0,0 +1,103 @@
1
+ Metadata-Version: 2.4
2
+ Name: agentconnect-cli
3
+ Version: 0.1.0a1
4
+ Summary: AgentConnect daemon (agentconnectd) and CLI
5
+ License-Expression: Apache-2.0
6
+ Requires-Dist: a2a-sdk[http-server,signing]>=1.2.2
7
+ Requires-Dist: agentconnect-core==0.1.0a1
8
+ Requires-Dist: httpx>=0.28.1
9
+ Requires-Dist: keyring>=25.7.0
10
+ Requires-Dist: mcp>=2.3.0
11
+ Requires-Dist: pyjwt[crypto]>=2.15.1
12
+ Requires-Dist: structlog>=26.1.0
13
+ Requires-Dist: typer>=0.27.3
14
+ Requires-Dist: uvicorn>=0.54.0
15
+ Requires-Dist: websockets>=17.2
16
+ Requires-Python: >=3.12
17
+ Description-Content-Type: text/markdown
18
+
19
+ # agentconnect-cli
20
+
21
+ The AgentConnect daemon (`agentconnectd`) and CLI (`agentconnect`). The
22
+ distribution is `agentconnect-cli`; the command and the import package are
23
+ `agentconnect`. See the repository [README](https://github.com/mbocevski/agent-connect/blob/v0.1.0a1/README.md) and
24
+ [SPEC.md](https://github.com/mbocevski/agent-connect/blob/v0.1.0a1/SPEC.md).
25
+
26
+ ```sh
27
+ agentconnect daemon run [--config PATH] [--tcp-port N] # foreground, JSON logs on stderr
28
+ agentconnect status [--json] # reads the local API
29
+ ```
30
+
31
+ Everything protocol-related is in the runtime, `agentconnect.runtime`
32
+ (`Runtime`, with its engine, local API, adapters and agent-scope
33
+ `AgentApi`). `agentconnectd` (`agentconnect.daemon`) is one host of it; the
34
+ Python SDK's embedded mode (`AgentConnect.embedded`, [docs/sdk.md](https://github.com/mbocevski/agent-connect/blob/v0.1.0a1/docs/sdk.md))
35
+ is the other. Both run the same checks, and both serve the local API below.
36
+
37
+ The invite lifecycle (`group`, `invite`, `accept`, `groups`, `approvals`,
38
+ `verify`, `leave`, `send`, `events`) is documented in
39
+ [docs/cli.md](https://github.com/mbocevski/agent-connect/blob/v0.1.0a1/docs/cli.md), with the `--json` schemas and exit codes.
40
+ `approvals approve`, `approvals reject` and `verify` use the human token:
41
+ **never give an agent the human token or let it run those commands for the
42
+ human.**
43
+
44
+ Don't give agents shell or file access to the data directory either: an
45
+ agent that can read it can approve joins and mark codes verified as you,
46
+ because the human token is a file there. Agents that need a shell can run
47
+ as another OS user, with the daemon under a user of its own
48
+ ([docs/isolation.md](https://github.com/mbocevski/agent-connect/blob/v0.1.0a1/docs/isolation.md)).
49
+
50
+ ## What the daemon holds
51
+
52
+ - One identity and one instance, created on first start, in the OS keyring
53
+ when one is usable and otherwise in 0600 key files (`keystore = "auto" |
54
+ "keyring" | "file"`).
55
+ - The core's MLS state in `mls.sqlite3`, a SQLCipher database encrypted
56
+ under a `db_key` from the same keystore.
57
+ - Its own `daemon.sqlite3`: groups, members (with the local *verified*
58
+ flag), Agent Cards, out-of-sync flags, and the durable outbox and inbox.
59
+ It is a SQLCipher database too, under a key the core derives from
60
+ `db_key` (ADR-003). Plaintext stays only while it is needed: an outbox
61
+ row keeps only its ids once the relay has answered it, and an inbox row
62
+ drops its message once the adapter has accepted it.
63
+
64
+ The data directory (`~/.local/share/agentconnect`) is 0700 and every file in
65
+ it 0600. Configuration is `~/.config/agentconnect/config.toml`; see
66
+ [docs/config.md](https://github.com/mbocevski/agent-connect/blob/v0.1.0a1/docs/config.md) for the keys and the `AC_*` overrides.
67
+
68
+ ## Local control API
69
+
70
+ JSON over HTTP/1.1 on a Unix socket in the data directory, or on
71
+ `127.0.0.1:<port>`. Every request needs `Authorization: Bearer <token>`.
72
+ [docs/api.md](https://github.com/mbocevski/agent-connect/blob/v0.1.0a1/docs/api.md) describes the transport, tokens, errors and
73
+ every route with its request and response shapes.
74
+
75
+ Two tokens live in the data directory: `api-token` (agent scope) and
76
+ `human-token` (human scope, also accepted for everything else). Approving a
77
+ join and marking a member verified are human decisions (SPEC §6.2, §11): an
78
+ agent that could approve its own joins, or mark the short code as compared,
79
+ would remove exactly the checks that catch a leaked link or a relay in the
80
+ middle. Give agent tooling only `api-token`. Both files belong to the same OS
81
+ user, so the split keeps the human capability out of agent integrations by
82
+ default; it is not a sandbox.
83
+
84
+ Invite secrets never leave the daemon: the URL is returned to the caller and
85
+ the relay only receives the public invite metadata.
86
+
87
+ ## Adapters
88
+
89
+ `agentconnect.adapter.Adapter` is the interface for agent integrations:
90
+ `deliver(group, sender, to, inner) -> ack | retry`, `on_event(group, event)`,
91
+ `on_outbound(send)` and `capabilities()`. Every delivery carries the SPEC
92
+ §10.1 untrusted framing. A relay frame is acknowledged only after the core
93
+ processed it and the adapter accepted the resulting delivery.
94
+
95
+ Delivery is **at least once**: after a crash, `deliver` and `on_event` may
96
+ repeat a message or an event. Every delivery has a stable `msg_id` and every
97
+ event a stable `event_id`; deduplicate by them. Nothing is lost: an event is
98
+ recorded before the adapter hears of it and sent again on restart until
99
+ `on_event` returns (ADR-004).
100
+ The webhook adapter ([docs/adapters/webhook.md](https://github.com/mbocevski/agent-connect/blob/v0.1.0a1/docs/adapters/webhook.md)) and the SSE adapter (`GET /v0/events`, [docs/api.md](https://github.com/mbocevski/agent-connect/blob/v0.1.0a1/docs/api.md#event-stream)) serve headless agents.
101
+ `CallbackAdapter` (`agentconnect.callback`) is the embedded SDK's in-process adapter, with the webhook's retry rules. `RecordingAdapter` is the in-memory adapter used by tests. Every message in
102
+ and out goes through the safety policy (`agentconnect.policy`) before any
103
+ adapter sees it ([docs/safety.md](https://github.com/mbocevski/agent-connect/blob/v0.1.0a1/docs/safety.md)).
@@ -0,0 +1,64 @@
1
+ agentconnect/__init__.py,sha256=bsDXOpok9J8_HaxKa8g2w5Horjj3pO3C3CHypha20rE,60
2
+ agentconnect/a2a_adapter/__init__.py,sha256=xkEkmb6Kh7t0rSUkdt6Y57ki6M6awjZqTd7--Y7EA8M,249
3
+ agentconnect/a2a_adapter/adapter.py,sha256=tMQHp_UpXUwaUMNYgWQ_H9OYZBFUPS8CVoWoEpKzR7M,24019
4
+ agentconnect/a2a_adapter/cards.py,sha256=D49D0B3M0LPErmI-fAh8hh7xnxKvoswNeb0M_g0Zf3Y,5291
5
+ agentconnect/a2a_adapter/convert.py,sha256=A6POHwZXlAlbdojXcWHmcgGfq79KxnJlxQ4O1we6Ijo,5470
6
+ agentconnect/a2a_adapter/facade.py,sha256=921kpYNFhpZQV9F51guGNLy-gp-O2xEkgUpGzRlOdao,23155
7
+ agentconnect/a2a_adapter/seen.py,sha256=YDOwFVbPTGjrojcDQbMS52VkZGcNDPdhX83g1ET35_Q,1680
8
+ agentconnect/a2a_adapter/serve.py,sha256=U9HXGItnEqPbTvDw90Lc62fKNAUj0Dm2KtM6A49zNbU,2164
9
+ agentconnect/adapter.py,sha256=mjDQc5WRqB_Yb_ZI31L96AzDEG3fU2Oo3ew18KVijeo,11043
10
+ agentconnect/adapters.py,sha256=WnIZ_QoeRT5pysFpY7ukX1QV3PHotbU8zftEGofng_M,2425
11
+ agentconnect/apiclient.py,sha256=nNpwBpkj2WovWz51XDRCRg92Zmpov3-f9j3JE89enuY,2059
12
+ agentconnect/backoff.py,sha256=hmBRJyMegRmNrlGNJLFE6fASVcuaDPYF3DV759bLaqo,1358
13
+ agentconnect/callback.py,sha256=4OW64hpeIA9pZNQ7Sm6b5usqsNE66Gv24Uf-uIAMTcY,13224
14
+ agentconnect/cli.py,sha256=lj8Jcr2JX95dXN-pyxQ2OTAogQ8fAOHE6pQPLc2PPmQ,95692
15
+ agentconnect/cli_json.py,sha256=l0O9_ffTXw-V7RERAHlA9-i-cZGNub8VG2Mu7R8jiHA,15950
16
+ agentconnect/cli_support.py,sha256=SW8xzdXht2rOPe5B_LsLewmaL4xTnVq077_XlCkYjY8,16936
17
+ agentconnect/clock.py,sha256=oXLBoyrD67daCGt-8i0kLPeGN1q_KG5ORA3mE-SVXCI,5631
18
+ agentconnect/config.py,sha256=2JLWf-7TUQMbSe41MCPNVjXcV7d8oiClMAMTibSnAMw,51265
19
+ agentconnect/daemon/__init__.py,sha256=vJk7Nc3pdvFPAeiF_PeWwpy2elGxLOEznicVBN5B_3s,1456
20
+ agentconnect/deliveries.py,sha256=lK9nMSszUZflsHu6uFIly_jnjVAEKwT_-u66XzC7DLI,12106
21
+ agentconnect/directory_client.py,sha256=C_PvVCYHUP7Z12t8A79sKvaSRI7VKOINCLV_GYcYY-M,10031
22
+ agentconnect/failpoints.py,sha256=GcCNIuF0-95uMdbjhswAbtEWme3o0CWK3WYtdP7XH5g,4496
23
+ agentconnect/identity.py,sha256=YxKeG8HTmMKK_0VkXfXnssKdjU-93EE0ia8_04nnP_U,3883
24
+ agentconnect/isolation.py,sha256=8glVNZxHMPbZ-oAsFceFjKwEjH2C6m4u3cx851JEADA,13406
25
+ agentconnect/keystore.py,sha256=wtxjMr3j5kpqpwJyqoe0GRUOiw0qecoaLSLIzKqexrE,9525
26
+ agentconnect/limits.py,sha256=aBRJpjA9JoJvi7eG87tJvSK9OUAtpGjAA20FKFFgOLA,18787
27
+ agentconnect/log.py,sha256=qgLeXr4lP5T43k4Tr4VYjBVplwrTzoX1rGL2Vp9DSc0,4144
28
+ agentconnect/mcp/__init__.py,sha256=tFETWMpHa02lUm4folUmiV9QPWYb0TySN9xVysuvoik,854
29
+ agentconnect/mcp/backend.py,sha256=qZkVRf9QOW0uTJ8ufJJhpYwBVIsnAmKu5ZTdHcoesII,15593
30
+ agentconnect/mcp/server.py,sha256=L0RX5zUdvoYfOF47ufNMXZ-Hhj-80-JFBmS2bZbSBBA,14641
31
+ agentconnect/mcp/session.py,sha256=XwBv7GiwFsNKY9qsRaXb5tsdDSq8VX7o24rNLtd5rbI,15902
32
+ agentconnect/mcp/tools.py,sha256=duUEt1IXusgH1Wpu1XGvM8dZ_U1GDYCy5nWRe3JlFMs,21696
33
+ agentconnect/ownerfile.py,sha256=v8L0wXcuTYg0xrrBvixXEfdOoHbG5poCm7EToyP7wMI,8520
34
+ agentconnect/payloads.py,sha256=Nha7_yGQpQ1LTJBk0qwgTb75ZGYJ-zZm-YrV7Ycl4zE,3737
35
+ agentconnect/policy.py,sha256=y0i3F_ZGRVKT7jhOUT0N2Bip9jCBH98XEJATTEEIDgk,41104
36
+ agentconnect/provision.py,sha256=85hG9Sm5RQ3vfRq1kjRj7DPECXJ5evXACgtxJ6hz-Aw,10015
37
+ agentconnect/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
38
+ agentconnect/relay.py,sha256=NHZ7BJbiwHI-ENz7tyJcydHXObBugEGwEPq5N5SD-KM,16524
39
+ agentconnect/runtime/__init__.py,sha256=-R18y4c8GEI1jsMnCNwSlhtDEfmJg-O_O_EQKD4sRB0,1535
40
+ agentconnect/runtime/agent.py,sha256=EpGX1GKXxF22x4mc8sPAx3tF6qTqxbzH71OY7B3UvJQ,10298
41
+ agentconnect/runtime/api.py,sha256=ntQcuw4QbThHovlyTGW0PMiVuZuC1AVNK863rlxVUFY,89586
42
+ agentconnect/runtime/engine.py,sha256=NMk1hUwFPZ_-yLJPpmS1kvYV69TTHVqhfusbHu2Mc6I,248443
43
+ agentconnect/runtime/errors.py,sha256=28QEhRUh1NYriVWV_Z9Ic7KdQzOlsEXN_SmRI5ya18c,1412
44
+ agentconnect/runtime/floor.py,sha256=kczLLji-8brEILTA3-4AYjfmd2RmoWFZ_nImXnM51QQ,30026
45
+ agentconnect/runtime/groups.py,sha256=h47KUZHwSIeJpwnhtPQy9RwSRVYFnkyB-kO-sXmlBUs,63499
46
+ agentconnect/runtime/knocks.py,sha256=-Cs6TAGskxXQ3iZcc2XW_RG3_MDW-16E4NObvP0U9Zo,63059
47
+ agentconnect/runtime/ledger.py,sha256=2wGmTc4Ba893uWgYkBhAVYumGF6Ep426ukZV5dnHpgg,4002
48
+ agentconnect/runtime/listing.py,sha256=dnfsfOQErWK4z3J1Hio1jzkZyGbwdU_cdfOSCM074yM,59261
49
+ agentconnect/runtime/registry.py,sha256=pYjEFglau2syD8GLqcuXAYA8Ve0y1api7fI5Aydwf9E,1776
50
+ agentconnect/runtime/runtime.py,sha256=0_7ppJ-RJTWjPxY3M13uWkSq_lzTlnMVb-9A8Gm7AZ4,6038
51
+ agentconnect/runtime/sas.py,sha256=ZKNqklBmqWgiVnzhzr4OTgtJE40C4e1pyq1qOZDmbRg,43312
52
+ agentconnect/sas_emoji.py,sha256=5DVw27KmRp81c-C_diteTzkH7t35OZTjAzMzh5xm4bc,2097
53
+ agentconnect/schemas.py,sha256=glRv29sy62y12hliqR2MKsS7Tk0QYV5f-jpavhVo908,14195
54
+ agentconnect/shapes.py,sha256=fHEwMWyxLBP2S4Y3QIokh-QblRXPUI8NmOfi27uth4s,1946
55
+ agentconnect/sockets.py,sha256=Ia8p8cBn4ZwHwSnd5noD2ksr_FHRwd3bXm17kZDXtYc,3674
56
+ agentconnect/sse.py,sha256=wdCnxFEY0VF_XvxvMuD-O0LiLls7Db-5ahr2f9gTeh8,8644
57
+ agentconnect/store.py,sha256=hSTqOJ9bpOlofjMFrOjs-KB1ObotpBluwwbeHfGcgec,132319
58
+ agentconnect/tasks.py,sha256=rKwA4AtBXWrxlMMKazuEdt51l_jZAeFAWjMBcxwOBBw,1458
59
+ agentconnect/tokens.py,sha256=CFV3v1HjxBBzuO3U17xaC4DFrYE89nd5JngoYAabR48,2360
60
+ agentconnect/webhook.py,sha256=jd_lvGPdlGecFwTDuU6HWhvHLgEd7v1v-3cInvbrcrE,7373
61
+ agentconnect_cli-0.1.0a1.dist-info/WHEEL,sha256=1dD_GoEqEIxQ7VnrUExgdj_eExY4b4UgfR0iBlGKVac,80
62
+ agentconnect_cli-0.1.0a1.dist-info/entry_points.txt,sha256=R0I5wTCDhHPFR4SWEr2j4uDfNXpJjC-CkqHVVPRliAI,55
63
+ agentconnect_cli-0.1.0a1.dist-info/METADATA,sha256=ABcvhL4lNZyf4iKjmsLldaj4zDUYzGhArEL5nNHgVI0,5722
64
+ agentconnect_cli-0.1.0a1.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: uv 0.13.4
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ agentconnect = agentconnect.cli:app
3
+