kraken-agent 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,35 @@
1
+ # Environment
2
+ .env
3
+ .env.local
4
+ .env.*.local
5
+
6
+ # Node
7
+ node_modules/
8
+ dist/
9
+
10
+ # Python
11
+ __pycache__/
12
+ *.pyc
13
+ *.egg-info/
14
+ .venv/
15
+ venv/
16
+ *.whl
17
+ sdk/python/dist/
18
+ sdk/python/build/
19
+
20
+ # Docker
21
+ .docker/
22
+
23
+ # IDE
24
+ .vscode/settings.json
25
+ .idea/
26
+
27
+ # OS
28
+ .DS_Store
29
+ Thumbs.db
30
+ *.log
31
+
32
+ # Build artifacts
33
+ site/
34
+ _site/
35
+ *.tgz
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Kraken Agent Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,246 @@
1
+ Metadata-Version: 2.4
2
+ Name: kraken-agent
3
+ Version: 0.1.0
4
+ Summary: Python SDK for the Kraken Agent API
5
+ Project-URL: Homepage, https://kraken-agent.com
6
+ Project-URL: Documentation, https://kraken-agent.com
7
+ Project-URL: Repository, https://github.com/kraken-agent/kraken-agent
8
+ Project-URL: Changelog, https://github.com/kraken-agent/kraken-agent/releases
9
+ Project-URL: Issues, https://github.com/kraken-agent/kraken-agent/issues
10
+ Author: Kraken Contributors
11
+ License-Expression: MIT
12
+ License-File: LICENSE
13
+ Keywords: agent,ai,graphrag,kraken,llm
14
+ Classifier: Development Status :: 3 - Alpha
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Typing :: Typed
23
+ Requires-Python: >=3.10
24
+ Requires-Dist: httpx<1,>=0.27
25
+ Requires-Dist: pydantic<3,>=2.0
26
+ Provides-Extra: async
27
+ Requires-Dist: httpx[http2]<1,>=0.27; extra == 'async'
28
+ Provides-Extra: dev
29
+ Requires-Dist: mypy>=1.13; extra == 'dev'
30
+ Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
31
+ Requires-Dist: pytest>=8.0; extra == 'dev'
32
+ Requires-Dist: respx>=0.22; extra == 'dev'
33
+ Requires-Dist: ruff>=0.8; extra == 'dev'
34
+ Description-Content-Type: text/markdown
35
+
36
+ <p align="center">
37
+ <h1 align="center">kraken-agent</h1>
38
+ </p>
39
+
40
+ <p align="center">
41
+ <strong>Python SDK for <a href="https://github.com/kraken-agent/kraken-agent">Kraken Agent</a> — an open-source AI assistant that remembers you.</strong>
42
+ </p>
43
+
44
+ <p align="center">
45
+ <a href="https://pypi.org/project/kraken-agent/"><img src="https://img.shields.io/pypi/v/kraken-agent?style=flat-square" alt="PyPI"></a>
46
+ <a href="https://pypi.org/project/kraken-agent/"><img src="https://img.shields.io/pypi/pyversions/kraken-agent?style=flat-square" alt="Python"></a>
47
+ <a href="https://github.com/kraken-agent/kraken-agent/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue?style=flat-square" alt="License"></a>
48
+ </p>
49
+
50
+ ---
51
+
52
+ ## What is Kraken?
53
+
54
+ Kraken is a self-hosted AI assistant that builds a **knowledge graph** of everything you tell it. Unlike stateless LLM wrappers, Kraken actually remembers — your projects, preferences, workflows, and goals — across every platform you connect (Discord, Telegram, CLI, or any HTTP client).
55
+
56
+ This package is the **official Python SDK**. It gives you a type-safe, batteries-included client for chat, memory, sessions, skills, and identity management.
57
+
58
+ ### Why use this SDK?
59
+
60
+ - **Persistent memory via GraphRAG** — query a Neo4j knowledge graph with 5 search modes (local, global, drift, auto, basic)
61
+ - **Session routing** — stable `session_key`-based conversations the server owns, not your client
62
+ - **Streaming** — real-time token streaming with a simple `for chunk in ...` loop
63
+ - **Self-improving skills** — the agent learns procedures from complex tasks and reuses them
64
+ - **Identity system** — editable personality (`SOUL.md`) and an auto-maintained model of *you*
65
+ - **Fully typed** — Pydantic models for every request and response, IDE autocompletion everywhere
66
+ - **Async-ready** — optional HTTP/2 support via `pip install kraken-agent[async]`
67
+
68
+ ---
69
+
70
+ ## Install
71
+
72
+ ```bash
73
+ pip install kraken-agent
74
+ ```
75
+
76
+ **Requirements:** Python 3.10+ and a running [Kraken Agent](https://github.com/kraken-agent/kraken-agent) server (`docker-compose up`).
77
+
78
+ ---
79
+
80
+ ## Quick Start
81
+
82
+ ```python
83
+ from kraken import KrakenClient
84
+
85
+ client = KrakenClient(
86
+ api_url="http://localhost:8080",
87
+ api_key="sk-kraken-...",
88
+ model="gpt-5.4",
89
+ )
90
+
91
+ # Simple chat
92
+ response = client.chat("Hello, what can you do?")
93
+ print(response.content)
94
+ ```
95
+
96
+ ### Streaming
97
+
98
+ ```python
99
+ for chunk in client.chat("Explain GraphRAG in simple terms", stream=True):
100
+ print(chunk, end="")
101
+ ```
102
+
103
+ ### Session Routing
104
+
105
+ Sessions are server-owned. Use a stable key and the agent remembers context across calls — no local state needed.
106
+
107
+ ```python
108
+ client.chat("My name is Alice", session_key="discord-12345", session_name="Discord DM")
109
+
110
+ r = client.chat("What's my name?", session_key="discord-12345")
111
+ print(r.content) # "Alice"
112
+ ```
113
+
114
+ ### Context Manager
115
+
116
+ ```python
117
+ with KrakenClient("http://localhost:8080") as client:
118
+ response = client.chat("Hello!")
119
+ print(response.content)
120
+ # Connection closed automatically
121
+ ```
122
+
123
+ ---
124
+
125
+ ## Memory (GraphRAG)
126
+
127
+ Kraken builds a knowledge graph from every conversation. Entities, relationships, and communities are extracted automatically — and you can query or modify them directly.
128
+
129
+ ```python
130
+ # Query the knowledge graph
131
+ results = client.memory.query("What do you know about my projects?")
132
+ for entity in results.entities:
133
+ print(f"{entity.type}: {entity.name}")
134
+ ```
135
+
136
+ ### Multi-mode search
137
+
138
+ | Mode | Best for | How it works |
139
+ |------|----------|--------------|
140
+ | `auto` | General questions | Analyzes intent, routes to best strategy |
141
+ | `local` | Specific entity questions | Fans out from entity to neighbors |
142
+ | `global` | Overview / holistic questions | Maps query over community summaries |
143
+ | `drift` | Entity + broader context | Local search enriched with community context |
144
+ | `basic` | Simple factual recall | Vector similarity over messages |
145
+
146
+ ```python
147
+ results = client.memory.query(
148
+ "What patterns do you see in my work?",
149
+ mode="global",
150
+ )
151
+ ```
152
+
153
+ ### Modify the graph
154
+
155
+ ```python
156
+ client.memory.add_entity("Kraken", "project", properties={"status": "active"})
157
+ client.memory.add_relationship("user", "kraken-id", "works_on")
158
+
159
+ # Visualize a neighborhood
160
+ graph = client.memory.graph(center="kraken-id", depth=3)
161
+ print(f"{len(graph.nodes)} nodes, {len(graph.edges)} edges")
162
+ ```
163
+
164
+ ---
165
+
166
+ ## Sessions
167
+
168
+ ```python
169
+ # List all sessions
170
+ for s in client.sessions.list():
171
+ print(f"{s.session_key or s.id} — {s.message_count} messages")
172
+
173
+ # Retrieve full history by stable key
174
+ detail = client.sessions.get_by_key("discord-12345")
175
+ for msg in detail.messages:
176
+ print(f"[{msg.role}] {msg.content}")
177
+ ```
178
+
179
+ ---
180
+
181
+ ## Skills
182
+
183
+ Skills are learned procedures the agent creates automatically after complex tasks. You can also create them manually.
184
+
185
+ ```python
186
+ # Create a skill
187
+ client.skills.create(
188
+ "git-workflow",
189
+ content="When committing: use conventional commits...",
190
+ tags=["git", "workflow"],
191
+ )
192
+
193
+ # List skills by tag
194
+ for skill in client.skills.list(tag="git"):
195
+ print(f"{skill.name} (v{skill.version})")
196
+ ```
197
+
198
+ ---
199
+
200
+ ## Identity
201
+
202
+ Kraken has two identity layers: an editable **personality** (`SOUL.md`) and an auto-maintained **user model** that tracks who you are.
203
+
204
+ ```python
205
+ # Read the agent's personality
206
+ soul = client.identity.get_soul()
207
+ print(soul.content)
208
+
209
+ # Customize it
210
+ client.identity.set_soul("You are Kraken, a concise and technical assistant...")
211
+
212
+ # See what the agent knows about you
213
+ user = client.identity.get_user_model()
214
+ print(user.content)
215
+ ```
216
+
217
+ ---
218
+
219
+ ## Architecture at a Glance
220
+
221
+ ```
222
+ Your Python App
223
+
224
+
225
+ ┌──────────────────────────┐
226
+ │ Kraken API (Hono) │
227
+ │ REST + WebSocket │
228
+ │ OpenAI-compatible │
229
+ └────────┬─────────────────┘
230
+ ┌────┼────────────┐
231
+ ▼ ▼ ▼
232
+ PostgreSQL Neo4j Redis
233
+ (sessions, (knowledge (queues,
234
+ vectors, graph) cache)
235
+ skills)
236
+ ```
237
+
238
+ The SDK talks to the Kraken API server, which coordinates PostgreSQL (sessions, embeddings, skills), Neo4j (knowledge graph), and Redis (job queues). A background worker handles entity extraction, community detection, user model updates, skill reflection, and scheduled task execution.
239
+
240
+ Full docs: **[kraken-agent.com](https://kraken-agent.com)**
241
+
242
+ ---
243
+
244
+ ## License
245
+
246
+ MIT
@@ -0,0 +1,211 @@
1
+ <p align="center">
2
+ <h1 align="center">kraken-agent</h1>
3
+ </p>
4
+
5
+ <p align="center">
6
+ <strong>Python SDK for <a href="https://github.com/kraken-agent/kraken-agent">Kraken Agent</a> — an open-source AI assistant that remembers you.</strong>
7
+ </p>
8
+
9
+ <p align="center">
10
+ <a href="https://pypi.org/project/kraken-agent/"><img src="https://img.shields.io/pypi/v/kraken-agent?style=flat-square" alt="PyPI"></a>
11
+ <a href="https://pypi.org/project/kraken-agent/"><img src="https://img.shields.io/pypi/pyversions/kraken-agent?style=flat-square" alt="Python"></a>
12
+ <a href="https://github.com/kraken-agent/kraken-agent/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue?style=flat-square" alt="License"></a>
13
+ </p>
14
+
15
+ ---
16
+
17
+ ## What is Kraken?
18
+
19
+ Kraken is a self-hosted AI assistant that builds a **knowledge graph** of everything you tell it. Unlike stateless LLM wrappers, Kraken actually remembers — your projects, preferences, workflows, and goals — across every platform you connect (Discord, Telegram, CLI, or any HTTP client).
20
+
21
+ This package is the **official Python SDK**. It gives you a type-safe, batteries-included client for chat, memory, sessions, skills, and identity management.
22
+
23
+ ### Why use this SDK?
24
+
25
+ - **Persistent memory via GraphRAG** — query a Neo4j knowledge graph with 5 search modes (local, global, drift, auto, basic)
26
+ - **Session routing** — stable `session_key`-based conversations the server owns, not your client
27
+ - **Streaming** — real-time token streaming with a simple `for chunk in ...` loop
28
+ - **Self-improving skills** — the agent learns procedures from complex tasks and reuses them
29
+ - **Identity system** — editable personality (`SOUL.md`) and an auto-maintained model of *you*
30
+ - **Fully typed** — Pydantic models for every request and response, IDE autocompletion everywhere
31
+ - **Async-ready** — optional HTTP/2 support via `pip install kraken-agent[async]`
32
+
33
+ ---
34
+
35
+ ## Install
36
+
37
+ ```bash
38
+ pip install kraken-agent
39
+ ```
40
+
41
+ **Requirements:** Python 3.10+ and a running [Kraken Agent](https://github.com/kraken-agent/kraken-agent) server (`docker-compose up`).
42
+
43
+ ---
44
+
45
+ ## Quick Start
46
+
47
+ ```python
48
+ from kraken import KrakenClient
49
+
50
+ client = KrakenClient(
51
+ api_url="http://localhost:8080",
52
+ api_key="sk-kraken-...",
53
+ model="gpt-5.4",
54
+ )
55
+
56
+ # Simple chat
57
+ response = client.chat("Hello, what can you do?")
58
+ print(response.content)
59
+ ```
60
+
61
+ ### Streaming
62
+
63
+ ```python
64
+ for chunk in client.chat("Explain GraphRAG in simple terms", stream=True):
65
+ print(chunk, end="")
66
+ ```
67
+
68
+ ### Session Routing
69
+
70
+ Sessions are server-owned. Use a stable key and the agent remembers context across calls — no local state needed.
71
+
72
+ ```python
73
+ client.chat("My name is Alice", session_key="discord-12345", session_name="Discord DM")
74
+
75
+ r = client.chat("What's my name?", session_key="discord-12345")
76
+ print(r.content) # "Alice"
77
+ ```
78
+
79
+ ### Context Manager
80
+
81
+ ```python
82
+ with KrakenClient("http://localhost:8080") as client:
83
+ response = client.chat("Hello!")
84
+ print(response.content)
85
+ # Connection closed automatically
86
+ ```
87
+
88
+ ---
89
+
90
+ ## Memory (GraphRAG)
91
+
92
+ Kraken builds a knowledge graph from every conversation. Entities, relationships, and communities are extracted automatically — and you can query or modify them directly.
93
+
94
+ ```python
95
+ # Query the knowledge graph
96
+ results = client.memory.query("What do you know about my projects?")
97
+ for entity in results.entities:
98
+ print(f"{entity.type}: {entity.name}")
99
+ ```
100
+
101
+ ### Multi-mode search
102
+
103
+ | Mode | Best for | How it works |
104
+ |------|----------|--------------|
105
+ | `auto` | General questions | Analyzes intent, routes to best strategy |
106
+ | `local` | Specific entity questions | Fans out from entity to neighbors |
107
+ | `global` | Overview / holistic questions | Maps query over community summaries |
108
+ | `drift` | Entity + broader context | Local search enriched with community context |
109
+ | `basic` | Simple factual recall | Vector similarity over messages |
110
+
111
+ ```python
112
+ results = client.memory.query(
113
+ "What patterns do you see in my work?",
114
+ mode="global",
115
+ )
116
+ ```
117
+
118
+ ### Modify the graph
119
+
120
+ ```python
121
+ client.memory.add_entity("Kraken", "project", properties={"status": "active"})
122
+ client.memory.add_relationship("user", "kraken-id", "works_on")
123
+
124
+ # Visualize a neighborhood
125
+ graph = client.memory.graph(center="kraken-id", depth=3)
126
+ print(f"{len(graph.nodes)} nodes, {len(graph.edges)} edges")
127
+ ```
128
+
129
+ ---
130
+
131
+ ## Sessions
132
+
133
+ ```python
134
+ # List all sessions
135
+ for s in client.sessions.list():
136
+ print(f"{s.session_key or s.id} — {s.message_count} messages")
137
+
138
+ # Retrieve full history by stable key
139
+ detail = client.sessions.get_by_key("discord-12345")
140
+ for msg in detail.messages:
141
+ print(f"[{msg.role}] {msg.content}")
142
+ ```
143
+
144
+ ---
145
+
146
+ ## Skills
147
+
148
+ Skills are learned procedures the agent creates automatically after complex tasks. You can also create them manually.
149
+
150
+ ```python
151
+ # Create a skill
152
+ client.skills.create(
153
+ "git-workflow",
154
+ content="When committing: use conventional commits...",
155
+ tags=["git", "workflow"],
156
+ )
157
+
158
+ # List skills by tag
159
+ for skill in client.skills.list(tag="git"):
160
+ print(f"{skill.name} (v{skill.version})")
161
+ ```
162
+
163
+ ---
164
+
165
+ ## Identity
166
+
167
+ Kraken has two identity layers: an editable **personality** (`SOUL.md`) and an auto-maintained **user model** that tracks who you are.
168
+
169
+ ```python
170
+ # Read the agent's personality
171
+ soul = client.identity.get_soul()
172
+ print(soul.content)
173
+
174
+ # Customize it
175
+ client.identity.set_soul("You are Kraken, a concise and technical assistant...")
176
+
177
+ # See what the agent knows about you
178
+ user = client.identity.get_user_model()
179
+ print(user.content)
180
+ ```
181
+
182
+ ---
183
+
184
+ ## Architecture at a Glance
185
+
186
+ ```
187
+ Your Python App
188
+
189
+
190
+ ┌──────────────────────────┐
191
+ │ Kraken API (Hono) │
192
+ │ REST + WebSocket │
193
+ │ OpenAI-compatible │
194
+ └────────┬─────────────────┘
195
+ ┌────┼────────────┐
196
+ ▼ ▼ ▼
197
+ PostgreSQL Neo4j Redis
198
+ (sessions, (knowledge (queues,
199
+ vectors, graph) cache)
200
+ skills)
201
+ ```
202
+
203
+ The SDK talks to the Kraken API server, which coordinates PostgreSQL (sessions, embeddings, skills), Neo4j (knowledge graph), and Redis (job queues). A background worker handles entity extraction, community detection, user model updates, skill reflection, and scheduled task execution.
204
+
205
+ Full docs: **[kraken-agent.com](https://kraken-agent.com)**
206
+
207
+ ---
208
+
209
+ ## License
210
+
211
+ MIT
@@ -0,0 +1,27 @@
1
+ """Kraken Agent Python SDK — connect to any Kraken API instance."""
2
+
3
+ from kraken.client import KrakenClient
4
+ from kraken.models import (
5
+ ChatResponse,
6
+ Entity,
7
+ MemoryQueryResult,
8
+ Relationship,
9
+ Session,
10
+ Skill,
11
+ Tool,
12
+ )
13
+ from kraken.tools import Tools
14
+
15
+ __all__ = [
16
+ "KrakenClient",
17
+ "Tools",
18
+ "ChatResponse",
19
+ "Entity",
20
+ "MemoryQueryResult",
21
+ "Relationship",
22
+ "Session",
23
+ "Skill",
24
+ "Tool",
25
+ ]
26
+
27
+ __version__ = "0.1.0"
@@ -0,0 +1,113 @@
1
+ """HTTP transport layer — thin wrapper around httpx."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections.abc import Iterator
6
+ from typing import Any
7
+
8
+ import httpx
9
+
10
+
11
+ class Transport:
12
+ """Manages HTTP communication with the Kraken API."""
13
+
14
+ def __init__(
15
+ self,
16
+ base_url: str,
17
+ api_key: str | None = None,
18
+ timeout: float = 120.0,
19
+ ) -> None:
20
+ headers: dict[str, str] = {"Content-Type": "application/json"}
21
+ if api_key:
22
+ headers["Authorization"] = f"Bearer {api_key}"
23
+
24
+ self._client = httpx.Client(
25
+ base_url=base_url.rstrip("/"),
26
+ headers=headers,
27
+ timeout=timeout,
28
+ )
29
+
30
+ # --- Core HTTP methods ---
31
+
32
+ def get(self, path: str, params: dict[str, Any] | None = None) -> Any:
33
+ resp = self._client.get(path, params=params)
34
+ resp.raise_for_status()
35
+ return resp.json()
36
+
37
+ def post(self, path: str, json: dict[str, Any] | None = None) -> Any:
38
+ resp = self._client.post(path, json=json)
39
+ resp.raise_for_status()
40
+ return resp.json()
41
+
42
+ def put(self, path: str, json: dict[str, Any] | None = None) -> Any:
43
+ resp = self._client.put(path, json=json)
44
+ resp.raise_for_status()
45
+ return resp.json()
46
+
47
+ def patch(self, path: str, json: dict[str, Any] | None = None) -> Any:
48
+ resp = self._client.patch(path, json=json)
49
+ resp.raise_for_status()
50
+ return resp.json()
51
+
52
+ def delete(self, path: str) -> Any:
53
+ resp = self._client.delete(path)
54
+ resp.raise_for_status()
55
+ return resp.json()
56
+
57
+ def post_stream(self, path: str, json: dict[str, Any] | None = None) -> Iterator[str]:
58
+ with self._client.stream("POST", path, json=json) as resp:
59
+ resp.raise_for_status()
60
+ for chunk in resp.iter_text():
61
+ if chunk:
62
+ yield chunk
63
+
64
+ def close(self) -> None:
65
+ self._client.close()
66
+
67
+
68
+ class AsyncTransport:
69
+ """Async HTTP transport using httpx.AsyncClient."""
70
+
71
+ def __init__(
72
+ self,
73
+ base_url: str,
74
+ api_key: str | None = None,
75
+ timeout: float = 120.0,
76
+ ) -> None:
77
+ headers: dict[str, str] = {"Content-Type": "application/json"}
78
+ if api_key:
79
+ headers["Authorization"] = f"Bearer {api_key}"
80
+
81
+ self._client = httpx.AsyncClient(
82
+ base_url=base_url.rstrip("/"),
83
+ headers=headers,
84
+ timeout=timeout,
85
+ )
86
+
87
+ async def get(self, path: str, params: dict[str, Any] | None = None) -> Any:
88
+ resp = await self._client.get(path, params=params)
89
+ resp.raise_for_status()
90
+ return resp.json()
91
+
92
+ async def post(self, path: str, json: dict[str, Any] | None = None) -> Any:
93
+ resp = await self._client.post(path, json=json)
94
+ resp.raise_for_status()
95
+ return resp.json()
96
+
97
+ async def put(self, path: str, json: dict[str, Any] | None = None) -> Any:
98
+ resp = await self._client.put(path, json=json)
99
+ resp.raise_for_status()
100
+ return resp.json()
101
+
102
+ async def patch(self, path: str, json: dict[str, Any] | None = None) -> Any:
103
+ resp = await self._client.patch(path, json=json)
104
+ resp.raise_for_status()
105
+ return resp.json()
106
+
107
+ async def delete(self, path: str) -> Any:
108
+ resp = await self._client.delete(path)
109
+ resp.raise_for_status()
110
+ return resp.json()
111
+
112
+ async def close(self) -> None:
113
+ await self._client.aclose()