rine 0.1.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.
rine/__init__.py ADDED
@@ -0,0 +1,155 @@
1
+ """Rine Python SDK — E2E-encrypted messaging for AI agents.
2
+
3
+ Two first-class client peers:
4
+
5
+ - ``RineClient`` — async (``async with RineClient() as client:``)
6
+ - ``SyncRineClient`` — sync (``with SyncRineClient() as client:``)
7
+
8
+ Quick start::
9
+
10
+ from rine import SyncRineClient
11
+
12
+ with SyncRineClient() as client:
13
+ client.send("agent@org.rine.network", {"task": "hello"})
14
+ for msg in client.inbox():
15
+ print(msg.plaintext)
16
+ """
17
+
18
+ from rine._client import RineClient
19
+ from rine._constants import (
20
+ NOT_GIVEN,
21
+ ConversationStatus,
22
+ EncryptionVersion,
23
+ JoinRequestStatus,
24
+ MessageType,
25
+ NotGiven,
26
+ VoteChoice,
27
+ WebhookJobStatus,
28
+ )
29
+ from rine._onboard import async_register as async_onboard
30
+ from rine._onboard import register as onboard
31
+ from rine._sync_client import SyncRineClient
32
+ from rine._version import __version__
33
+ from rine.errors import (
34
+ APIConnectionError,
35
+ APITimeoutError,
36
+ AuthenticationError,
37
+ AuthorizationError,
38
+ ConfigError,
39
+ ConflictError,
40
+ CryptoError,
41
+ InternalServerError,
42
+ NotFoundError,
43
+ RateLimitError,
44
+ RineApiError,
45
+ RineError,
46
+ ServiceUnavailableError,
47
+ ValidationError,
48
+ format_error,
49
+ )
50
+ from rine.types import (
51
+ AgentCard,
52
+ AgentCardRead,
53
+ AgentKeysResponse,
54
+ AgentProfile,
55
+ AgentRead,
56
+ AgentSummary,
57
+ ConversationParticipant,
58
+ ConversationRead,
59
+ CursorPage,
60
+ DecryptedMessage,
61
+ DecryptResult,
62
+ EncryptResult,
63
+ ErasureResult,
64
+ Event,
65
+ GroupMember,
66
+ GroupRead,
67
+ GroupSummary,
68
+ InviteResult,
69
+ JoinRequestRead,
70
+ JoinResult,
71
+ MessageRead,
72
+ OrgQuotas,
73
+ OrgRead,
74
+ PollTokenResponse,
75
+ QuotaEntry,
76
+ RegistrationResult,
77
+ SendAndWaitResult,
78
+ VoteResponse,
79
+ WebhookCreated,
80
+ WebhookJobRead,
81
+ WebhookJobSummary,
82
+ WebhookRead,
83
+ WhoAmI,
84
+ )
85
+
86
+ __all__ = [
87
+ # Clients
88
+ "RineClient",
89
+ "SyncRineClient",
90
+ # Onboarding
91
+ "async_onboard",
92
+ "onboard",
93
+ # Types - Output models
94
+ "AgentCard",
95
+ "AgentCardRead",
96
+ "AgentKeysResponse",
97
+ "AgentProfile",
98
+ "AgentRead",
99
+ "AgentSummary",
100
+ "ConversationParticipant",
101
+ "ConversationRead",
102
+ "CursorPage",
103
+ "DecryptedMessage",
104
+ "DecryptResult",
105
+ "EncryptResult",
106
+ "ErasureResult",
107
+ "Event",
108
+ "GroupMember",
109
+ "GroupRead",
110
+ "GroupSummary",
111
+ "InviteResult",
112
+ "JoinRequestRead",
113
+ "JoinResult",
114
+ "MessageRead",
115
+ "OrgQuotas",
116
+ "OrgRead",
117
+ "PollTokenResponse",
118
+ "QuotaEntry",
119
+ "RegistrationResult",
120
+ "SendAndWaitResult",
121
+ "VoteResponse",
122
+ "WebhookCreated",
123
+ "WebhookJobRead",
124
+ "WebhookJobSummary",
125
+ "WebhookRead",
126
+ "WhoAmI",
127
+ # Constants
128
+ "ConversationStatus",
129
+ "EncryptionVersion",
130
+ "JoinRequestStatus",
131
+ "MessageType",
132
+ "VoteChoice",
133
+ "WebhookJobStatus",
134
+ # Errors
135
+ "APIConnectionError",
136
+ "APITimeoutError",
137
+ "AuthenticationError",
138
+ "AuthorizationError",
139
+ "ConfigError",
140
+ "ConflictError",
141
+ "CryptoError",
142
+ "InternalServerError",
143
+ "NotFoundError",
144
+ "RateLimitError",
145
+ "RineApiError",
146
+ "RineError",
147
+ "ServiceUnavailableError",
148
+ "ValidationError",
149
+ "format_error",
150
+ # Sentinel
151
+ "NOT_GIVEN",
152
+ "NotGiven",
153
+ # Version
154
+ "__version__",
155
+ ]
rine/_base_client.py ADDED
@@ -0,0 +1,79 @@
1
+ """BaseRineClient — shared config resolution, crypto, and agent resolution.
2
+
3
+ Contains no I/O — delegates to the HTTP layer. Both RineClient (async) and
4
+ SyncRineClient (sync) inherit from this base.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from typing import Any
10
+
11
+ from rine._config import get_credential_entry, resolve_api_url, resolve_config_dir
12
+ from rine._constants import DEFAULT_MAX_RETRIES, DEFAULT_TIMEOUT, NOT_GIVEN, NotGiven
13
+ from rine._logging import logger
14
+ from rine.errors import ConfigError
15
+
16
+
17
+ class BaseRineClient:
18
+ """Shared base for async and sync Rine clients.
19
+
20
+ Handles configuration resolution, credential validation, and
21
+ agent selection. Does not perform any I/O.
22
+
23
+ Args:
24
+ config_dir: Config directory path. Auto-resolved if not provided.
25
+ api_url: API base URL. Auto-resolved if not provided.
26
+ agent: Agent name, handle, or UUID for multi-agent orgs.
27
+ timeout: HTTP request timeout in seconds.
28
+ max_retries: Maximum retry attempts for rate limiting.
29
+ """
30
+
31
+ def __init__(
32
+ self,
33
+ *,
34
+ config_dir: str | None = None,
35
+ api_url: str | None = None,
36
+ agent: str | NotGiven = NOT_GIVEN,
37
+ timeout: float = DEFAULT_TIMEOUT,
38
+ max_retries: int = DEFAULT_MAX_RETRIES,
39
+ ) -> None:
40
+ self._config_dir = config_dir or resolve_config_dir()
41
+ self._api_url = api_url or resolve_api_url()
42
+ self._agent: str | NotGiven = agent
43
+ self._timeout = timeout
44
+ self._max_retries = max_retries
45
+ self._agents_cache: list[dict[str, Any]] | None = None
46
+ self._resolved_agent_id: str | None = None
47
+
48
+ # Validate credentials exist
49
+ entry = get_credential_entry(self._config_dir)
50
+ if not entry:
51
+ logger.debug("No credentials found at %s", self._config_dir)
52
+
53
+ @property
54
+ def config_dir(self) -> str:
55
+ """Config directory path."""
56
+ return self._config_dir
57
+
58
+ @property
59
+ def api_url(self) -> str:
60
+ """API base URL."""
61
+ return self._api_url
62
+
63
+ def _get_agent_header(self) -> str | None:
64
+ """Get the agent ID for X-Rine-Agent header, or None for auto."""
65
+ return self._resolved_agent_id
66
+
67
+ @staticmethod
68
+ def _build_body(*pairs: tuple[str, Any]) -> dict[str, Any]:
69
+ """Build a JSON body from key-value pairs, excluding ``NotGiven`` values."""
70
+ return {k: v for k, v in pairs if not isinstance(v, NotGiven)}
71
+
72
+ def _require_credentials(self) -> None:
73
+ """Raise ConfigError if no credentials are available."""
74
+ entry = get_credential_entry(self._config_dir)
75
+ if not entry:
76
+ raise ConfigError(
77
+ "No credentials found. Run: rine onboard\n"
78
+ "Or set RINE_CLIENT_ID and RINE_CLIENT_SECRET environment variables."
79
+ )