copass-core 0.1.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.
@@ -0,0 +1,38 @@
1
+ # Dependencies
2
+ node_modules/
3
+
4
+ # Build output
5
+ dist/
6
+ *.tsbuildinfo
7
+
8
+ # Environment
9
+ .env
10
+ .env.*
11
+
12
+ # IDE
13
+ .vscode/
14
+ .idea/
15
+ *.swp
16
+ *.swo
17
+ *~
18
+
19
+ # OS
20
+ .DS_Store
21
+ Thumbs.db
22
+
23
+ # Test
24
+ coverage/
25
+
26
+ # Lerna
27
+ lerna-debug.log
28
+ .nx/cache
29
+ .nx/workspace-data
30
+
31
+ # Python
32
+ __pycache__/
33
+ *.pyc
34
+ *.pyo
35
+ *.egg-info/
36
+ .venv/
37
+ venv/
38
+ .olane
@@ -0,0 +1,102 @@
1
+ Metadata-Version: 2.4
2
+ Name: copass-core
3
+ Version: 0.1.0
4
+ Summary: Core client SDK for the Copass platform (Python mirror of @copass/core)
5
+ Project-URL: Homepage, https://github.com/olane-labs/copass-harness
6
+ Project-URL: Repository, https://github.com/olane-labs/copass-harness.git
7
+ Author: Olane Inc.
8
+ License: MIT
9
+ Keywords: client,copass,knowledge-graph,retrieval,sdk
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Requires-Python: >=3.10
16
+ Requires-Dist: httpx>=0.27
17
+ Provides-Extra: dev
18
+ Requires-Dist: mypy>=1.10; extra == 'dev'
19
+ Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
20
+ Requires-Dist: pytest>=8.0; extra == 'dev'
21
+ Requires-Dist: respx>=0.21; extra == 'dev'
22
+ Requires-Dist: ruff>=0.5; extra == 'dev'
23
+ Description-Content-Type: text/markdown
24
+
25
+ # copass-core
26
+
27
+ Core client SDK for the Copass platform. Python mirror of [`@copass/core`](../../typescript/packages/core) — shared foundation for every Python Copass adapter.
28
+
29
+ ## Install
30
+
31
+ ```bash
32
+ pip install copass-core
33
+ ```
34
+
35
+ Requires `httpx>=0.27`. Python ≥ 3.10.
36
+
37
+ ## Quickstart
38
+
39
+ ```python
40
+ import asyncio
41
+ from copass_core import CopassClient, ApiKeyAuth
42
+
43
+ async def main():
44
+ client = CopassClient(auth=ApiKeyAuth(key="olk_..."))
45
+
46
+ # Retrieval
47
+ menu = await client.retrieval.discover(
48
+ sandbox_id="sb_...",
49
+ query="How does auth work?",
50
+ )
51
+ print(menu["items"])
52
+
53
+ # Context for agent
54
+ context = await client.context.for_agent(
55
+ sandbox_id="sb_...",
56
+ tier="adaptive",
57
+ query="auth flow",
58
+ )
59
+ print(context)
60
+
61
+ asyncio.run(main())
62
+ ```
63
+
64
+ ## Auth options
65
+
66
+ ```python
67
+ from copass_core import CopassClient, ApiKeyAuth, BearerAuth, ProviderAuth
68
+
69
+ # Long-lived API key (olk_ prefix)
70
+ CopassClient(auth=ApiKeyAuth(key="olk_..."))
71
+
72
+ # Raw Bearer JWT (caller owns refresh)
73
+ CopassClient(auth=BearerAuth(token="eyJ..."))
74
+
75
+ # Custom AuthProvider implementation
76
+ class MyProvider:
77
+ async def get_session(self):
78
+ from copass_core import SessionContext
79
+ return SessionContext(access_token=await _mint_token())
80
+
81
+ CopassClient(auth=ProviderAuth(provider=MyProvider()))
82
+ ```
83
+
84
+ ## v0.1.0 scope
85
+
86
+ **Shipped:**
87
+ - `CopassClient` top-level entry point
88
+ - Auth providers: `ApiKeyAuthProvider`, `BearerAuthProvider`
89
+ - `HttpClient` with retry + request/response middleware
90
+ - `RetrievalResource` — `discover` / `interpret` / `search`
91
+ - `ContextResource` — `/context/for-agent/{minimal,adaptive,comprehensive}`
92
+
93
+ **Deferred to a future release:**
94
+ - Crypto primitives (HKDF, AES-GCM, session tokens, DEK) + Supabase auth provider
95
+ - `ContextWindow` + `SourcesResource` + `IngestResource`
96
+ - `MatrixResource`, `SandboxesResource`, `ProjectsResource`, `EntitiesResource`, `VaultResource`, `UsageResource`, `ApiKeysResource`, `UsersResource`
97
+
98
+ Add incrementally when a concrete Python consumer needs each. Opening a PR with a scoped addition is the expected path.
99
+
100
+ ## License
101
+
102
+ MIT.
@@ -0,0 +1,78 @@
1
+ # copass-core
2
+
3
+ Core client SDK for the Copass platform. Python mirror of [`@copass/core`](../../typescript/packages/core) — shared foundation for every Python Copass adapter.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ pip install copass-core
9
+ ```
10
+
11
+ Requires `httpx>=0.27`. Python ≥ 3.10.
12
+
13
+ ## Quickstart
14
+
15
+ ```python
16
+ import asyncio
17
+ from copass_core import CopassClient, ApiKeyAuth
18
+
19
+ async def main():
20
+ client = CopassClient(auth=ApiKeyAuth(key="olk_..."))
21
+
22
+ # Retrieval
23
+ menu = await client.retrieval.discover(
24
+ sandbox_id="sb_...",
25
+ query="How does auth work?",
26
+ )
27
+ print(menu["items"])
28
+
29
+ # Context for agent
30
+ context = await client.context.for_agent(
31
+ sandbox_id="sb_...",
32
+ tier="adaptive",
33
+ query="auth flow",
34
+ )
35
+ print(context)
36
+
37
+ asyncio.run(main())
38
+ ```
39
+
40
+ ## Auth options
41
+
42
+ ```python
43
+ from copass_core import CopassClient, ApiKeyAuth, BearerAuth, ProviderAuth
44
+
45
+ # Long-lived API key (olk_ prefix)
46
+ CopassClient(auth=ApiKeyAuth(key="olk_..."))
47
+
48
+ # Raw Bearer JWT (caller owns refresh)
49
+ CopassClient(auth=BearerAuth(token="eyJ..."))
50
+
51
+ # Custom AuthProvider implementation
52
+ class MyProvider:
53
+ async def get_session(self):
54
+ from copass_core import SessionContext
55
+ return SessionContext(access_token=await _mint_token())
56
+
57
+ CopassClient(auth=ProviderAuth(provider=MyProvider()))
58
+ ```
59
+
60
+ ## v0.1.0 scope
61
+
62
+ **Shipped:**
63
+ - `CopassClient` top-level entry point
64
+ - Auth providers: `ApiKeyAuthProvider`, `BearerAuthProvider`
65
+ - `HttpClient` with retry + request/response middleware
66
+ - `RetrievalResource` — `discover` / `interpret` / `search`
67
+ - `ContextResource` — `/context/for-agent/{minimal,adaptive,comprehensive}`
68
+
69
+ **Deferred to a future release:**
70
+ - Crypto primitives (HKDF, AES-GCM, session tokens, DEK) + Supabase auth provider
71
+ - `ContextWindow` + `SourcesResource` + `IngestResource`
72
+ - `MatrixResource`, `SandboxesResource`, `ProjectsResource`, `EntitiesResource`, `VaultResource`, `UsageResource`, `ApiKeysResource`, `UsersResource`
73
+
74
+ Add incrementally when a concrete Python consumer needs each. Opening a PR with a scoped addition is the expected path.
75
+
76
+ ## License
77
+
78
+ MIT.
@@ -0,0 +1,52 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "copass-core"
7
+ version = "0.1.0"
8
+ description = "Core client SDK for the Copass platform (Python mirror of @copass/core)"
9
+ readme = "README.md"
10
+ license = { text = "MIT" }
11
+ authors = [{ name = "Olane Inc." }]
12
+ requires-python = ">=3.10"
13
+ keywords = ["copass", "knowledge-graph", "sdk", "client", "retrieval"]
14
+ classifiers = [
15
+ "License :: OSI Approved :: MIT License",
16
+ "Programming Language :: Python :: 3",
17
+ "Programming Language :: Python :: 3.10",
18
+ "Programming Language :: Python :: 3.11",
19
+ "Programming Language :: Python :: 3.12",
20
+ ]
21
+ dependencies = [
22
+ "httpx>=0.27",
23
+ ]
24
+
25
+ [project.optional-dependencies]
26
+ dev = [
27
+ "pytest>=8.0",
28
+ "pytest-asyncio>=0.23",
29
+ "respx>=0.21",
30
+ "mypy>=1.10",
31
+ "ruff>=0.5",
32
+ ]
33
+
34
+ [project.urls]
35
+ Homepage = "https://github.com/olane-labs/copass-harness"
36
+ Repository = "https://github.com/olane-labs/copass-harness.git"
37
+
38
+ [tool.hatch.build.targets.wheel]
39
+ packages = ["src/copass_core"]
40
+
41
+ [tool.pytest.ini_options]
42
+ asyncio_mode = "auto"
43
+ testpaths = ["tests"]
44
+
45
+ [tool.ruff]
46
+ line-length = 100
47
+ target-version = "py310"
48
+
49
+ [tool.mypy]
50
+ python_version = "3.10"
51
+ strict = true
52
+ packages = ["copass_core"]
@@ -0,0 +1,99 @@
1
+ """Copass Python client SDK.
2
+
3
+ Python mirror of `@copass/core`_. v0.1.0 scope:
4
+
5
+ - ``CopassClient`` top-level entry point
6
+ - Auth providers: ``ApiKeyAuthProvider``, ``BearerAuthProvider``
7
+ - ``HttpClient`` with retry + middleware
8
+ - Retrieval resource: ``discover`` / ``interpret`` / ``search``
9
+ - Context resource: ``/context/for-agent/{minimal,adaptive,comprehensive}``
10
+
11
+ Deferred to a future release (``v0.2+``): crypto primitives + Supabase
12
+ auth provider, ContextWindow / SourcesResource / IngestResource,
13
+ full resource coverage (matrix, sandboxes, projects, entities, vault,
14
+ usage, api-keys, users).
15
+
16
+ .. _`@copass/core`: https://github.com/olane-labs/copass-harness/tree/main/typescript/packages/core
17
+ """
18
+
19
+ from copass_core.auth import (
20
+ ApiKeyAuthProvider,
21
+ AuthProvider,
22
+ BearerAuthProvider,
23
+ SessionContext,
24
+ )
25
+ from copass_core.client import (
26
+ DEFAULT_API_URL,
27
+ ApiKeyAuth,
28
+ AuthConfig,
29
+ BearerAuth,
30
+ CopassClient,
31
+ ProviderAuth,
32
+ )
33
+ from copass_core.http import (
34
+ CopassApiError,
35
+ CopassNetworkError,
36
+ CopassValidationError,
37
+ HttpClient,
38
+ HttpClientOptions,
39
+ RequestContext,
40
+ RequestMiddleware,
41
+ RequestOptions,
42
+ ResponseContext,
43
+ ResponseMiddleware,
44
+ retry_with_backoff,
45
+ )
46
+ from copass_core.resources import (
47
+ BaseResource,
48
+ ContextResource,
49
+ ContextTier,
50
+ RetrievalResource,
51
+ )
52
+ from copass_core.types import (
53
+ ChatMessage,
54
+ ChatRole,
55
+ RetryConfig,
56
+ SearchPreset,
57
+ WindowLike,
58
+ )
59
+
60
+ __version__ = "0.1.0"
61
+
62
+ __all__ = [
63
+ "__version__",
64
+ # Client
65
+ "CopassClient",
66
+ "AuthConfig",
67
+ "ApiKeyAuth",
68
+ "BearerAuth",
69
+ "ProviderAuth",
70
+ "DEFAULT_API_URL",
71
+ # Auth
72
+ "AuthProvider",
73
+ "SessionContext",
74
+ "ApiKeyAuthProvider",
75
+ "BearerAuthProvider",
76
+ # HTTP
77
+ "HttpClient",
78
+ "HttpClientOptions",
79
+ "RequestOptions",
80
+ "RequestContext",
81
+ "ResponseContext",
82
+ "RequestMiddleware",
83
+ "ResponseMiddleware",
84
+ "CopassApiError",
85
+ "CopassNetworkError",
86
+ "CopassValidationError",
87
+ "retry_with_backoff",
88
+ # Resources
89
+ "BaseResource",
90
+ "RetrievalResource",
91
+ "ContextResource",
92
+ "ContextTier",
93
+ # Types
94
+ "RetryConfig",
95
+ "ChatMessage",
96
+ "ChatRole",
97
+ "WindowLike",
98
+ "SearchPreset",
99
+ ]
@@ -0,0 +1,12 @@
1
+ """Authentication providers."""
2
+
3
+ from copass_core.auth.api_key import ApiKeyAuthProvider
4
+ from copass_core.auth.bearer import BearerAuthProvider
5
+ from copass_core.auth.types import AuthProvider, SessionContext
6
+
7
+ __all__ = [
8
+ "AuthProvider",
9
+ "SessionContext",
10
+ "ApiKeyAuthProvider",
11
+ "BearerAuthProvider",
12
+ ]
@@ -0,0 +1,27 @@
1
+ """API key auth provider.
2
+
3
+ Hand-ported from ``typescript/packages/core/src/auth/api-key.ts``.
4
+ """
5
+
6
+ from __future__ import annotations
7
+
8
+ from copass_core.auth.types import AuthProvider, SessionContext
9
+
10
+
11
+ class ApiKeyAuthProvider:
12
+ """Sends a long-lived API key (``olk_...``) as a bearer token.
13
+
14
+ No session token; API keys don't support DEK wrapping in this
15
+ release.
16
+ """
17
+
18
+ def __init__(self, key: str) -> None:
19
+ if not key:
20
+ raise ValueError("ApiKeyAuthProvider requires a non-empty key")
21
+ self._key = key
22
+
23
+ async def get_session(self) -> SessionContext:
24
+ return SessionContext(access_token=self._key)
25
+
26
+
27
+ __all__ = ["ApiKeyAuthProvider"]
@@ -0,0 +1,36 @@
1
+ """Bearer JWT auth provider.
2
+
3
+ Hand-ported from ``typescript/packages/core/src/auth/bearer.ts``. In
4
+ v0.1.0 the encryption-key path is deferred — the provider simply
5
+ forwards the caller-supplied JWT. A later release will add
6
+ ``createSessionToken`` integration once the crypto module lands.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ from typing import Optional
12
+
13
+ from copass_core.auth.types import AuthProvider, SessionContext
14
+
15
+
16
+ class BearerAuthProvider:
17
+ """Forwards a caller-managed JWT as the bearer token.
18
+
19
+ The caller is responsible for refreshing the JWT when it expires —
20
+ mint a new provider with the new token or wrap your own refresh
21
+ logic in a custom :class:`AuthProvider` implementation.
22
+ """
23
+
24
+ def __init__(self, token: str, encryption_key: Optional[str] = None) -> None:
25
+ if not token:
26
+ raise ValueError("BearerAuthProvider requires a non-empty token")
27
+ self._token = token
28
+ # Stored but unused in v0.1.0 — reserved for the forthcoming
29
+ # crypto module (session-token derivation for vault access).
30
+ self._encryption_key = encryption_key
31
+
32
+ async def get_session(self) -> SessionContext:
33
+ return SessionContext(access_token=self._token)
34
+
35
+
36
+ __all__ = ["BearerAuthProvider"]
@@ -0,0 +1,47 @@
1
+ """Authentication interfaces.
2
+
3
+ Hand-ported from ``typescript/packages/core/src/auth/types.ts``. The
4
+ Python port drops the session-token / encryption fields that aren't
5
+ needed by v0.1.0 consumers; add them back when the crypto module
6
+ lands in a later release.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ from dataclasses import dataclass
12
+ from typing import Optional, Protocol, runtime_checkable
13
+
14
+
15
+ @dataclass(frozen=True)
16
+ class SessionContext:
17
+ """Active session context with resolved credentials.
18
+
19
+ Attributes:
20
+ access_token: The JWT or API key for the ``Authorization``
21
+ header.
22
+ session_token: Optional wrapped DEK for the
23
+ ``X-Encryption-Token`` header. ``None`` in v0.1.0 — the
24
+ crypto module is deferred.
25
+ user_id: User id extracted from the token. ``None`` for API
26
+ keys (not decoded).
27
+ """
28
+
29
+ access_token: str
30
+ session_token: Optional[str] = None
31
+ user_id: Optional[str] = None
32
+
33
+
34
+ @runtime_checkable
35
+ class AuthProvider(Protocol):
36
+ """Structural contract for authentication providers.
37
+
38
+ Each auth strategy (API key, bearer JWT, future Supabase) exposes
39
+ :meth:`get_session`. The HTTP client calls it before each request
40
+ to obtain fresh credentials; providers are free to cache + refresh
41
+ under the hood.
42
+ """
43
+
44
+ async def get_session(self) -> SessionContext: ...
45
+
46
+
47
+ __all__ = ["AuthProvider", "SessionContext"]
@@ -0,0 +1,119 @@
1
+ """CopassClient — top-level entry point.
2
+
3
+ Hand-ported from ``typescript/packages/core/src/client.ts``. v0.1.0
4
+ exposes the two resources that v0.1.0 consumers need:
5
+ :class:`RetrievalResource` (``discover`` / ``interpret`` / ``search``)
6
+ and :class:`ContextResource` (``/context/for-agent/*``). Additional
7
+ resources (``sandboxes``, ``sources``, ``ingest``, ``vault``, etc.)
8
+ land incrementally.
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ from dataclasses import dataclass
14
+ from typing import List, Optional, Union
15
+
16
+ from copass_core.auth.api_key import ApiKeyAuthProvider
17
+ from copass_core.auth.bearer import BearerAuthProvider
18
+ from copass_core.auth.types import AuthProvider
19
+ from copass_core.http.http_client import (
20
+ HttpClient,
21
+ HttpClientOptions,
22
+ RequestMiddleware,
23
+ ResponseMiddleware,
24
+ )
25
+ from copass_core.resources.context import ContextResource
26
+ from copass_core.resources.retrieval import RetrievalResource
27
+ from copass_core.types import RetryConfig
28
+
29
+
30
+ DEFAULT_API_URL = "https://ai.copass.id"
31
+
32
+
33
+ @dataclass(frozen=True)
34
+ class ApiKeyAuth:
35
+ """``auth=ApiKeyAuth(key="olk_...")``."""
36
+
37
+ key: str
38
+
39
+
40
+ @dataclass(frozen=True)
41
+ class BearerAuth:
42
+ """``auth=BearerAuth(token="eyJ...")``. Caller owns refresh."""
43
+
44
+ token: str
45
+ encryption_key: Optional[str] = None
46
+
47
+
48
+ @dataclass(frozen=True)
49
+ class ProviderAuth:
50
+ """``auth=ProviderAuth(provider=MyCustomAuthProvider(...))``."""
51
+
52
+ provider: AuthProvider
53
+
54
+
55
+ AuthConfig = Union[ApiKeyAuth, BearerAuth, ProviderAuth]
56
+ """Discriminated-union of auth configurations. Supabase OTP auth is
57
+ deferred to a later release."""
58
+
59
+
60
+ def _build_auth_provider(auth: AuthConfig) -> AuthProvider:
61
+ if isinstance(auth, ApiKeyAuth):
62
+ return ApiKeyAuthProvider(auth.key)
63
+ if isinstance(auth, BearerAuth):
64
+ return BearerAuthProvider(auth.token, auth.encryption_key)
65
+ if isinstance(auth, ProviderAuth):
66
+ return auth.provider
67
+ raise TypeError(f"Unsupported AuthConfig type: {type(auth).__name__}")
68
+
69
+
70
+ class CopassClient:
71
+ """Main entry point for the Copass Python SDK.
72
+
73
+ Resources are accessed as instance attributes (Stripe-style).
74
+
75
+ Example:
76
+ >>> client = CopassClient(auth=ApiKeyAuth(key="olk_..."))
77
+ >>> menu = await client.retrieval.discover(
78
+ ... sandbox_id="sb-1",
79
+ ... query="How does auth work?",
80
+ ... )
81
+ """
82
+
83
+ retrieval: RetrievalResource
84
+ context: ContextResource
85
+
86
+ def __init__(
87
+ self,
88
+ *,
89
+ auth: AuthConfig,
90
+ api_url: str = DEFAULT_API_URL,
91
+ retry: Optional[RetryConfig] = None,
92
+ on_request: Optional[List[RequestMiddleware]] = None,
93
+ on_response: Optional[List[ResponseMiddleware]] = None,
94
+ timeout: float = 30.0,
95
+ ) -> None:
96
+ auth_provider = _build_auth_provider(auth)
97
+ http = HttpClient(
98
+ HttpClientOptions(
99
+ api_url=api_url,
100
+ auth_provider=auth_provider,
101
+ retry=retry,
102
+ on_request=list(on_request or []),
103
+ on_response=list(on_response or []),
104
+ timeout=timeout,
105
+ )
106
+ )
107
+ self._http = http
108
+ self.retrieval = RetrievalResource(http)
109
+ self.context = ContextResource(http)
110
+
111
+
112
+ __all__ = [
113
+ "CopassClient",
114
+ "AuthConfig",
115
+ "ApiKeyAuth",
116
+ "BearerAuth",
117
+ "ProviderAuth",
118
+ "DEFAULT_API_URL",
119
+ ]
@@ -0,0 +1,31 @@
1
+ """HTTP client primitives."""
2
+
3
+ from copass_core.http.errors import (
4
+ CopassApiError,
5
+ CopassNetworkError,
6
+ CopassValidationError,
7
+ )
8
+ from copass_core.http.http_client import (
9
+ HttpClient,
10
+ HttpClientOptions,
11
+ RequestContext,
12
+ RequestMiddleware,
13
+ RequestOptions,
14
+ ResponseContext,
15
+ ResponseMiddleware,
16
+ )
17
+ from copass_core.http.retry import retry_with_backoff
18
+
19
+ __all__ = [
20
+ "HttpClient",
21
+ "HttpClientOptions",
22
+ "RequestOptions",
23
+ "RequestContext",
24
+ "ResponseContext",
25
+ "RequestMiddleware",
26
+ "ResponseMiddleware",
27
+ "CopassApiError",
28
+ "CopassNetworkError",
29
+ "CopassValidationError",
30
+ "retry_with_backoff",
31
+ ]