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.
- agentconnect/__init__.py +3 -0
- agentconnect/a2a_adapter/__init__.py +6 -0
- agentconnect/a2a_adapter/adapter.py +565 -0
- agentconnect/a2a_adapter/cards.py +149 -0
- agentconnect/a2a_adapter/convert.py +157 -0
- agentconnect/a2a_adapter/facade.py +560 -0
- agentconnect/a2a_adapter/seen.py +49 -0
- agentconnect/a2a_adapter/serve.py +67 -0
- agentconnect/adapter.py +319 -0
- agentconnect/adapters.py +52 -0
- agentconnect/apiclient.py +51 -0
- agentconnect/backoff.py +42 -0
- agentconnect/callback.py +314 -0
- agentconnect/cli.py +2324 -0
- agentconnect/cli_json.py +470 -0
- agentconnect/cli_support.py +444 -0
- agentconnect/clock.py +161 -0
- agentconnect/config.py +1213 -0
- agentconnect/daemon/__init__.py +41 -0
- agentconnect/deliveries.py +295 -0
- agentconnect/directory_client.py +255 -0
- agentconnect/failpoints.py +99 -0
- agentconnect/identity.py +111 -0
- agentconnect/isolation.py +345 -0
- agentconnect/keystore.py +279 -0
- agentconnect/limits.py +457 -0
- agentconnect/log.py +143 -0
- agentconnect/mcp/__init__.py +30 -0
- agentconnect/mcp/backend.py +405 -0
- agentconnect/mcp/server.py +382 -0
- agentconnect/mcp/session.py +373 -0
- agentconnect/mcp/tools.py +583 -0
- agentconnect/ownerfile.py +238 -0
- agentconnect/payloads.py +109 -0
- agentconnect/policy.py +1066 -0
- agentconnect/provision.py +239 -0
- agentconnect/py.typed +0 -0
- agentconnect/relay.py +405 -0
- agentconnect/runtime/__init__.py +46 -0
- agentconnect/runtime/agent.py +225 -0
- agentconnect/runtime/api.py +2043 -0
- agentconnect/runtime/engine.py +5359 -0
- agentconnect/runtime/errors.py +47 -0
- agentconnect/runtime/floor.py +649 -0
- agentconnect/runtime/groups.py +1351 -0
- agentconnect/runtime/knocks.py +1422 -0
- agentconnect/runtime/ledger.py +94 -0
- agentconnect/runtime/listing.py +1307 -0
- agentconnect/runtime/registry.py +53 -0
- agentconnect/runtime/runtime.py +158 -0
- agentconnect/runtime/sas.py +1002 -0
- agentconnect/sas_emoji.py +83 -0
- agentconnect/schemas.py +381 -0
- agentconnect/shapes.py +56 -0
- agentconnect/sockets.py +86 -0
- agentconnect/sse.py +234 -0
- agentconnect/store.py +3282 -0
- agentconnect/tasks.py +35 -0
- agentconnect/tokens.py +63 -0
- agentconnect/webhook.py +199 -0
- agentconnect_cli-0.1.0a1.dist-info/METADATA +103 -0
- agentconnect_cli-0.1.0a1.dist-info/RECORD +64 -0
- agentconnect_cli-0.1.0a1.dist-info/WHEEL +4 -0
- agentconnect_cli-0.1.0a1.dist-info/entry_points.txt +3 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"""The owner's replay ledgers: one for invite JoinRequests (SPEC 6.2
|
|
2
|
+
"Replays"), one for knocks (SPEC 6.6.3 step 6).
|
|
3
|
+
|
|
4
|
+
Neither request carries freshness of its own and the relay sees both, so
|
|
5
|
+
every request that passed the owner's checks is remembered by its id and
|
|
6
|
+
its KeyPackageRef, whatever happens to it next, until no copy can pass the
|
|
7
|
+
checks again: a knock until ``ts + 3900``, a JoinRequest until its invite's
|
|
8
|
+
``expires_at`` plus the core's ``LEDGER_GRACE_SECS``. A remembered request
|
|
9
|
+
is dropped silently.
|
|
10
|
+
|
|
11
|
+
The core's bounded ``ReplayLedger`` answers "seen?"; its entries are
|
|
12
|
+
persisted in a table of the encrypted store, written in the transaction that
|
|
13
|
+
records what the request led to. The in-memory ledger has no remove, so a
|
|
14
|
+
transaction that rolls back is followed by :func:`load`. When the ledger is
|
|
15
|
+
full, new requests are refused (``busy``) and nothing live is evicted. Each
|
|
16
|
+
invite also has a share of the join ledger (:func:`join_quota`), and an
|
|
17
|
+
invite's entries are forgotten once it is revoked or has expired. Purges
|
|
18
|
+
run on the clock's current time on every pass and keep nothing from
|
|
19
|
+
earlier passes; loading purges nothing.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
from __future__ import annotations
|
|
23
|
+
|
|
24
|
+
from collections.abc import Callable
|
|
25
|
+
|
|
26
|
+
import agentconnect_core as ac
|
|
27
|
+
from agentconnect.config import MIN_JOIN_LEDGER_PER_INVITE
|
|
28
|
+
from agentconnect.relay import b64, unb64
|
|
29
|
+
from agentconnect.store import Ledger, Store
|
|
30
|
+
|
|
31
|
+
KNOCK_ID_LEN = 16
|
|
32
|
+
|
|
33
|
+
#: What a request the ledger refuses is dropped as, by its error kind.
|
|
34
|
+
REASONS: dict[Ledger, dict[str, str]] = {
|
|
35
|
+
"knock": {"replay": "knock_replay", "busy": "knock_ledger_full"},
|
|
36
|
+
"join": {"replay": "join_replay", "busy": "join_ledger_full"},
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def load(store: Store, ledger: Ledger, capacity: int) -> ac.ReplayLedger:
|
|
41
|
+
"""The ledger from the database, every row of it, even past a lowered
|
|
42
|
+
capacity: a request seen before a restart must never pass after it.
|
|
43
|
+
Loading purges nothing. A clock that is ahead at start and put right
|
|
44
|
+
before the next pass would otherwise forget live entries; the passes
|
|
45
|
+
purge (for joins right after marking expired invites, at the same now)."""
|
|
46
|
+
rows = store.ledger_rows(0, ledger=ledger)
|
|
47
|
+
core = ac.ReplayLedger(
|
|
48
|
+
max(capacity, len(rows)), id_len=KNOCK_ID_LEN if ledger == "knock" else None
|
|
49
|
+
)
|
|
50
|
+
for entry_id, kp_ref, forget_after in rows:
|
|
51
|
+
core.insert(entry_key(ledger, entry_id), unb64(kp_ref), forget_after)
|
|
52
|
+
return core
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def entry_key(ledger: Ledger, entry_id: str) -> bytes:
|
|
56
|
+
"""The bytes the core keys an entry by: a knock's raw ``knock_id``, a
|
|
57
|
+
join's request id (the envelope's ``msg_id``) as text."""
|
|
58
|
+
return unb64(entry_id) if ledger == "knock" else entry_id.encode()
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def remember( # noqa: PLR0913
|
|
62
|
+
store: Store,
|
|
63
|
+
ledger: Ledger,
|
|
64
|
+
core: ac.ReplayLedger,
|
|
65
|
+
remember_in: Callable[[ac.ReplayLedger], None],
|
|
66
|
+
*,
|
|
67
|
+
entry_id: str,
|
|
68
|
+
kp_ref: bytes,
|
|
69
|
+
forget_after: int,
|
|
70
|
+
invite_id: str | None = None,
|
|
71
|
+
) -> str | None:
|
|
72
|
+
"""Inside the transaction that records the request: ``None`` if it is
|
|
73
|
+
new (now remembered, in memory and in the store), else the reason code
|
|
74
|
+
to drop it with (``*_replay``, ``*_ledger_full``)."""
|
|
75
|
+
try:
|
|
76
|
+
remember_in(core)
|
|
77
|
+
except ac.AgentConnectError as e:
|
|
78
|
+
return REASONS[ledger].get(e.kind, f"{ledger}_check:{e.kind}")
|
|
79
|
+
store.ledger_add(entry_id, b64(kp_ref), forget_after, ledger=ledger, invite_id=invite_id)
|
|
80
|
+
return None
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def join_quota(max_uses: int, per_invite: int) -> int:
|
|
84
|
+
"""How many entries one invite may hold in the join ledger: 4 times its
|
|
85
|
+
uses, at least ``MIN_JOIN_LEDGER_PER_INVITE``, at most ``per_invite``
|
|
86
|
+
(``policy.join_ledger_per_invite``). A leaked link fills only its own
|
|
87
|
+
share."""
|
|
88
|
+
return min(max(4 * max_uses, MIN_JOIN_LEDGER_PER_INVITE), per_invite)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def purge(store: Store, ledger: Ledger, core: ac.ReplayLedger, now: int) -> None:
|
|
92
|
+
"""Forget what expired before ``now``: the clock's current time."""
|
|
93
|
+
store.ledger_purge(now, ledger=ledger)
|
|
94
|
+
core.purge(now)
|