zeriq-team 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.
- zeriq_team-0.1.0/.gitignore +3 -0
- zeriq_team-0.1.0/CHANGELOG.md +12 -0
- zeriq_team-0.1.0/PKG-INFO +118 -0
- zeriq_team-0.1.0/README.md +101 -0
- zeriq_team-0.1.0/examples/action_items_to_linear.py +43 -0
- zeriq_team-0.1.0/examples/kb/onboarding.md +4 -0
- zeriq_team-0.1.0/examples/kb/refunds.md +5 -0
- zeriq_team-0.1.0/examples/kb_sync.py +23 -0
- zeriq_team-0.1.0/examples/room_bot.py +25 -0
- zeriq_team-0.1.0/pyproject.toml +26 -0
- zeriq_team-0.1.0/scripts/generate.sh +9 -0
- zeriq_team-0.1.0/src/zeriq_team/__init__.py +36 -0
- zeriq_team-0.1.0/src/zeriq_team/_client.py +116 -0
- zeriq_team-0.1.0/src/zeriq_team/_core.py +356 -0
- zeriq_team-0.1.0/src/zeriq_team/_errors.py +107 -0
- zeriq_team-0.1.0/src/zeriq_team/_resources.py +511 -0
- zeriq_team-0.1.0/src/zeriq_team/_version.py +1 -0
- zeriq_team-0.1.0/src/zeriq_team/py.typed +0 -0
- zeriq_team-0.1.0/src/zeriq_team/types.py +617 -0
- zeriq_team-0.1.0/src/zeriq_team/webhooks.py +57 -0
- zeriq_team-0.1.0/tests/test_client.py +228 -0
- zeriq_team-0.1.0/tests/test_stream.py +99 -0
- zeriq_team-0.1.0/tests/test_webhooks.py +39 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.0 — first published release
|
|
4
|
+
|
|
5
|
+
First release: knowledge (documents, upsert, search), personas and ask, conversations, rooms
|
|
6
|
+
(create with AI teammates and people, messages, end, summarize, reports), action items and
|
|
7
|
+
meeting reads. Retries, idempotency keys, typed errors, pagination, `wait_until_ready`,
|
|
8
|
+
`wait_for_replies` and `wait_for_report`; sync and async clients.
|
|
9
|
+
|
|
10
|
+
Room streams: `rooms.stream` (server-sent events: `persona.thinking`, `message.created`, `run.completed`, `run.failed`), resuming with Last-Event-ID; `messages.send` returns the reply `run_id`.
|
|
11
|
+
|
|
12
|
+
Webhooks: endpoints (create, update, rotate secret, test, delete), the deliveries log and redelivery, and signature verification (`zeriq_team.webhooks.verify`).
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: zeriq-team
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Official Python SDK for the Zeriq Teams API
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
Classifier: Programming Language :: Python :: 3
|
|
7
|
+
Classifier: Typing :: Typed
|
|
8
|
+
Requires-Python: >=3.9
|
|
9
|
+
Requires-Dist: httpx<1,>=0.24
|
|
10
|
+
Requires-Dist: typing-extensions>=4.7
|
|
11
|
+
Provides-Extra: dev
|
|
12
|
+
Requires-Dist: black==24.10.0; extra == 'dev'
|
|
13
|
+
Requires-Dist: datamodel-code-generator==0.26.5; extra == 'dev'
|
|
14
|
+
Requires-Dist: isort==5.13.2; extra == 'dev'
|
|
15
|
+
Requires-Dist: pytest>=7; extra == 'dev'
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
|
|
18
|
+
# zeriq-team
|
|
19
|
+
|
|
20
|
+
The official Python SDK for the [Zeriq Teams API](../../docs/developers/README.md): your AI teammates' knowledge, answers, rooms, action items and meetings, from your own systems.
|
|
21
|
+
|
|
22
|
+
- Python 3.9+, sync and async clients, built on `httpx`.
|
|
23
|
+
- Results are plain dicts, typed with `TypedDict`s generated from the API's OpenAPI spec (`zeriq_team.types`).
|
|
24
|
+
- Retries 429, 5xx and network errors with backoff, and honours `Retry-After`. Every POST gets an `Idempotency-Key`, so retries never create anything twice.
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
pip install zeriq-team
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Quick start
|
|
31
|
+
|
|
32
|
+
```python
|
|
33
|
+
from zeriq_team import Zeriq
|
|
34
|
+
|
|
35
|
+
zq = Zeriq() # reads ZERIQ_TEAM_API_KEY (and ZERIQ_TEAM_BASE_URL)
|
|
36
|
+
|
|
37
|
+
# Knowledge: upsert by your own id, then search (no AI model, no credits)
|
|
38
|
+
zq.knowledge.documents.upsert(external_id="wiki:refunds", title="Refunds", text="…")
|
|
39
|
+
hits = zq.knowledge.search(query="refund policy", top_k=5)["data"]
|
|
40
|
+
|
|
41
|
+
# Ask an AI teammate (no tools unless you allow them)
|
|
42
|
+
answer = zq.personas.ask("prs_…", input="Draft a reply to this customer: …")
|
|
43
|
+
print(answer["answer"], answer["usage"])
|
|
44
|
+
|
|
45
|
+
# Rooms: create, post, stream the replies as they arrive, end
|
|
46
|
+
room = zq.rooms.create(title="Pricing review", personas=["prs_…"])
|
|
47
|
+
sent = zq.rooms.messages.send(room["id"], content="Should we add annual plans?")
|
|
48
|
+
for event in zq.rooms.stream(room["id"], run_id=sent["run_id"]): # ends with the run
|
|
49
|
+
if event["event"] == "message.created":
|
|
50
|
+
print(event["data"]["message"]["content"])
|
|
51
|
+
zq.rooms.end(room["id"])
|
|
52
|
+
|
|
53
|
+
# Lists return the first page; iterate to walk every page
|
|
54
|
+
for item in zq.action_items.list(status="open"):
|
|
55
|
+
zq.action_items.update(item["id"], external_ref="https://linear.app/…")
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Async is the same API, awaited:
|
|
59
|
+
|
|
60
|
+
```python
|
|
61
|
+
from zeriq_team import AsyncZeriq
|
|
62
|
+
|
|
63
|
+
async with AsyncZeriq() as zq:
|
|
64
|
+
answer = await zq.personas.ask("prs_…", input="…")
|
|
65
|
+
async for item in zq.action_items.list(status="open"):
|
|
66
|
+
...
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
For QA, set `base_url="https://api.qa.zeriq.app"`.
|
|
70
|
+
|
|
71
|
+
## Webhooks
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
endpoint = zq.webhooks.endpoints.create(url="https://example.com/zeriq", event_types=["action_item.created"])
|
|
75
|
+
secret = endpoint["secret"] # shown only now
|
|
76
|
+
|
|
77
|
+
# In your handler, with the raw request body:
|
|
78
|
+
from zeriq_team import webhooks, WebhookVerificationError
|
|
79
|
+
|
|
80
|
+
event = webhooks.verify(raw_body, headers["Zeriq-Signature"], secret)
|
|
81
|
+
if event["type"] == "action_item.created":
|
|
82
|
+
...
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Errors
|
|
86
|
+
|
|
87
|
+
Every API error is an `APIError` with `status`, `code`, `param` and `request_id`. Subclasses:
|
|
88
|
+
`InvalidRequestError` (400), `AuthenticationError` (401), `CreditsExhaustedError` (402 — retry with
|
|
89
|
+
`allow_downgrade=True`), `PlanLimitError` (402), `InsufficientScopeError` (403, `param` is the
|
|
90
|
+
missing scope), `ToolNotPermittedError` (403), `NotFoundError` (404, also for other workspaces'
|
|
91
|
+
objects), `RateLimitError` (429 after retries), plus `APIConnectionError` / `APITimeoutError`.
|
|
92
|
+
Results carry the ID too: `answer.request_id`.
|
|
93
|
+
|
|
94
|
+
## Options
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
Zeriq(api_key=..., base_url=..., timeout=60.0, max_retries=2, http_client=httpx.Client(...))
|
|
98
|
+
zq.rooms.create(title="x", idempotency_key="my-key")
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Examples
|
|
102
|
+
|
|
103
|
+
[`examples/`](examples): a knowledge-base sync, an async room bot, and action items → Linear.
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
ZERIQ_TEAM_API_KEY=zqt_sk_… python examples/kb_sync.py
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Development
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
python -m venv .venv && .venv/bin/pip install -e '.[dev]'
|
|
113
|
+
scripts/generate.sh # types from ../team-api-spec/openapi.json
|
|
114
|
+
.venv/bin/python -m pytest
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
The contract tests that run this SDK against the real API app live in
|
|
118
|
+
`services/team-agent/tests/test_sdk_contract.py`.
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# zeriq-team
|
|
2
|
+
|
|
3
|
+
The official Python SDK for the [Zeriq Teams API](../../docs/developers/README.md): your AI teammates' knowledge, answers, rooms, action items and meetings, from your own systems.
|
|
4
|
+
|
|
5
|
+
- Python 3.9+, sync and async clients, built on `httpx`.
|
|
6
|
+
- Results are plain dicts, typed with `TypedDict`s generated from the API's OpenAPI spec (`zeriq_team.types`).
|
|
7
|
+
- Retries 429, 5xx and network errors with backoff, and honours `Retry-After`. Every POST gets an `Idempotency-Key`, so retries never create anything twice.
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pip install zeriq-team
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Quick start
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
from zeriq_team import Zeriq
|
|
17
|
+
|
|
18
|
+
zq = Zeriq() # reads ZERIQ_TEAM_API_KEY (and ZERIQ_TEAM_BASE_URL)
|
|
19
|
+
|
|
20
|
+
# Knowledge: upsert by your own id, then search (no AI model, no credits)
|
|
21
|
+
zq.knowledge.documents.upsert(external_id="wiki:refunds", title="Refunds", text="…")
|
|
22
|
+
hits = zq.knowledge.search(query="refund policy", top_k=5)["data"]
|
|
23
|
+
|
|
24
|
+
# Ask an AI teammate (no tools unless you allow them)
|
|
25
|
+
answer = zq.personas.ask("prs_…", input="Draft a reply to this customer: …")
|
|
26
|
+
print(answer["answer"], answer["usage"])
|
|
27
|
+
|
|
28
|
+
# Rooms: create, post, stream the replies as they arrive, end
|
|
29
|
+
room = zq.rooms.create(title="Pricing review", personas=["prs_…"])
|
|
30
|
+
sent = zq.rooms.messages.send(room["id"], content="Should we add annual plans?")
|
|
31
|
+
for event in zq.rooms.stream(room["id"], run_id=sent["run_id"]): # ends with the run
|
|
32
|
+
if event["event"] == "message.created":
|
|
33
|
+
print(event["data"]["message"]["content"])
|
|
34
|
+
zq.rooms.end(room["id"])
|
|
35
|
+
|
|
36
|
+
# Lists return the first page; iterate to walk every page
|
|
37
|
+
for item in zq.action_items.list(status="open"):
|
|
38
|
+
zq.action_items.update(item["id"], external_ref="https://linear.app/…")
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Async is the same API, awaited:
|
|
42
|
+
|
|
43
|
+
```python
|
|
44
|
+
from zeriq_team import AsyncZeriq
|
|
45
|
+
|
|
46
|
+
async with AsyncZeriq() as zq:
|
|
47
|
+
answer = await zq.personas.ask("prs_…", input="…")
|
|
48
|
+
async for item in zq.action_items.list(status="open"):
|
|
49
|
+
...
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
For QA, set `base_url="https://api.qa.zeriq.app"`.
|
|
53
|
+
|
|
54
|
+
## Webhooks
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
endpoint = zq.webhooks.endpoints.create(url="https://example.com/zeriq", event_types=["action_item.created"])
|
|
58
|
+
secret = endpoint["secret"] # shown only now
|
|
59
|
+
|
|
60
|
+
# In your handler, with the raw request body:
|
|
61
|
+
from zeriq_team import webhooks, WebhookVerificationError
|
|
62
|
+
|
|
63
|
+
event = webhooks.verify(raw_body, headers["Zeriq-Signature"], secret)
|
|
64
|
+
if event["type"] == "action_item.created":
|
|
65
|
+
...
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Errors
|
|
69
|
+
|
|
70
|
+
Every API error is an `APIError` with `status`, `code`, `param` and `request_id`. Subclasses:
|
|
71
|
+
`InvalidRequestError` (400), `AuthenticationError` (401), `CreditsExhaustedError` (402 — retry with
|
|
72
|
+
`allow_downgrade=True`), `PlanLimitError` (402), `InsufficientScopeError` (403, `param` is the
|
|
73
|
+
missing scope), `ToolNotPermittedError` (403), `NotFoundError` (404, also for other workspaces'
|
|
74
|
+
objects), `RateLimitError` (429 after retries), plus `APIConnectionError` / `APITimeoutError`.
|
|
75
|
+
Results carry the ID too: `answer.request_id`.
|
|
76
|
+
|
|
77
|
+
## Options
|
|
78
|
+
|
|
79
|
+
```python
|
|
80
|
+
Zeriq(api_key=..., base_url=..., timeout=60.0, max_retries=2, http_client=httpx.Client(...))
|
|
81
|
+
zq.rooms.create(title="x", idempotency_key="my-key")
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Examples
|
|
85
|
+
|
|
86
|
+
[`examples/`](examples): a knowledge-base sync, an async room bot, and action items → Linear.
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
ZERIQ_TEAM_API_KEY=zqt_sk_… python examples/kb_sync.py
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Development
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
python -m venv .venv && .venv/bin/pip install -e '.[dev]'
|
|
96
|
+
scripts/generate.sh # types from ../team-api-spec/openapi.json
|
|
97
|
+
.venv/bin/python -m pytest
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
The contract tests that run this SDK against the real API app live in
|
|
101
|
+
`services/team-agent/tests/test_sdk_contract.py`.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"""Mirror open action items into Linear and link them back with ``external_ref``.
|
|
2
|
+
Without LINEAR_API_KEY it's a dry run that only lists what it would create.
|
|
3
|
+
|
|
4
|
+
ZERIQ_TEAM_API_KEY=zqt_sk_… [LINEAR_API_KEY=… LINEAR_TEAM_ID=…] python examples/action_items_to_linear.py
|
|
5
|
+
Scopes: tasks:read, tasks:write (plus rooms:read:all to see rooms the key didn't create)
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import os
|
|
9
|
+
from datetime import datetime, timedelta, timezone
|
|
10
|
+
|
|
11
|
+
import httpx
|
|
12
|
+
|
|
13
|
+
from zeriq_team import Zeriq
|
|
14
|
+
|
|
15
|
+
zq = Zeriq()
|
|
16
|
+
linear_key = os.environ.get("LINEAR_API_KEY")
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def create_linear_issue(title: str, description: str) -> str:
|
|
20
|
+
resp = httpx.post(
|
|
21
|
+
"https://api.linear.app/graphql",
|
|
22
|
+
headers={"Authorization": linear_key or ""},
|
|
23
|
+
json={"query": "mutation($input: IssueCreateInput!) { issueCreate(input: $input) { issue { url } } }",
|
|
24
|
+
"variables": {"input": {"teamId": os.environ.get("LINEAR_TEAM_ID"), "title": title, "description": description}}},
|
|
25
|
+
).json()
|
|
26
|
+
url = (((resp.get("data") or {}).get("issueCreate") or {}).get("issue") or {}).get("url")
|
|
27
|
+
if not url:
|
|
28
|
+
raise RuntimeError(f"Linear: {resp.get('errors')}")
|
|
29
|
+
return url
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
count = 0
|
|
33
|
+
for item in zq.action_items.list(status="open", since=datetime.now(timezone.utc) - timedelta(days=7)):
|
|
34
|
+
if item.get("external_ref"):
|
|
35
|
+
continue # already tracked somewhere
|
|
36
|
+
count += 1
|
|
37
|
+
if not linear_key:
|
|
38
|
+
print(f"[dry run] would create: {item['title']} ({item.get('assignee') or 'unassigned'})")
|
|
39
|
+
continue
|
|
40
|
+
url = create_linear_issue(item["title"], f"From Zeriq room {item['room_id']}")
|
|
41
|
+
zq.action_items.update(item["id"], external_ref=url)
|
|
42
|
+
print(f"{item['title']} → {url}")
|
|
43
|
+
print(f"{count} open action item(s) without a link in the last 7 days")
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"""Keep your docs in Zeriq's knowledge base: upsert each file by its own id, wait until it's
|
|
2
|
+
searchable, then search. Safe to re-run.
|
|
3
|
+
|
|
4
|
+
ZERIQ_TEAM_API_KEY=zqt_sk_… python examples/kb_sync.py
|
|
5
|
+
Scopes: knowledge:read, knowledge:write
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
from zeriq_team import Zeriq
|
|
11
|
+
|
|
12
|
+
zq = Zeriq()
|
|
13
|
+
for path in sorted((Path(__file__).parent / "kb").glob("*.md")):
|
|
14
|
+
text = path.read_text()
|
|
15
|
+
title = text.splitlines()[0].lstrip("# ").strip()
|
|
16
|
+
doc = zq.knowledge.documents.upsert(external_id=f"sdk-example:kb:{path.name}", title=title, text=text)
|
|
17
|
+
ready = zq.knowledge.documents.wait_until_ready(doc["id"])
|
|
18
|
+
print(f"synced {path.name} → {ready['id']} ({ready['status']}, {ready['chunk_count']} chunks)")
|
|
19
|
+
|
|
20
|
+
hits = zq.knowledge.search(query="How long do refunds take?", top_k=3)["data"]
|
|
21
|
+
for hit in hits:
|
|
22
|
+
print(f"{hit['score']:.2f} {hit['title']}: {hit['content'][:80]}…")
|
|
23
|
+
assert any(h["title"].startswith("Refund policy") for h in hits), "Expected the refund policy in the results"
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"""Run a room from your own system: create it with an AI teammate, post a question, wait for
|
|
2
|
+
the replies, then end it. Uses the async client.
|
|
3
|
+
|
|
4
|
+
ZERIQ_TEAM_API_KEY=zqt_sk_… python examples/room_bot.py
|
|
5
|
+
Scopes: personas:read, rooms:read, rooms:write
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import asyncio
|
|
9
|
+
import os
|
|
10
|
+
|
|
11
|
+
from zeriq_team import AsyncZeriq
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
async def main() -> None:
|
|
15
|
+
async with AsyncZeriq() as zq:
|
|
16
|
+
persona_id = os.environ.get("ZERIQ_EXAMPLE_PERSONA") or (await zq.personas.list())["data"][0]["id"]
|
|
17
|
+
room = await zq.rooms.create(title="[SDK example] Launch check", personas=[persona_id])
|
|
18
|
+
print(f"room {room['id']} with {', '.join(p['name'] for p in room['personas'])}")
|
|
19
|
+
sent = await zq.rooms.messages.send(room["id"], content="In two sentences: what should a launch checklist cover?")
|
|
20
|
+
for m in await zq.rooms.wait_for_replies(room["id"], sent["id"]):
|
|
21
|
+
print(f"{m['sender']['name']}: {m['content']}")
|
|
22
|
+
print("ended:", (await zq.rooms.end(room["id"], outcome="success"))["status"])
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
asyncio.run(main())
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling>=1.18"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "zeriq-team"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Official Python SDK for the Zeriq Teams API"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
requires-python = ">=3.9"
|
|
12
|
+
dependencies = ["httpx>=0.24,<1", "typing_extensions>=4.7"]
|
|
13
|
+
classifiers = [
|
|
14
|
+
"Programming Language :: Python :: 3",
|
|
15
|
+
"Typing :: Typed",
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
[project.optional-dependencies]
|
|
19
|
+
dev = ["pytest>=7", "datamodel-code-generator==0.26.5", "black==24.10.0", "isort==5.13.2"]
|
|
20
|
+
|
|
21
|
+
[tool.hatch.build.targets.wheel]
|
|
22
|
+
packages = ["src/zeriq_team"]
|
|
23
|
+
|
|
24
|
+
[tool.pytest.ini_options]
|
|
25
|
+
testpaths = ["tests"]
|
|
26
|
+
markers = ["req(id): plan task this test covers"]
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
#!/usr/bin/env sh
|
|
2
|
+
# Regenerates src/zeriq_team/types.py (TypedDicts) from the committed OpenAPI spec.
|
|
3
|
+
set -e
|
|
4
|
+
cd "$(dirname "$0")/.."
|
|
5
|
+
datamodel-codegen --input ../team-api-spec/openapi.json --input-file-type openapi \
|
|
6
|
+
--output-model-type typing.TypedDict --target-python-version 3.9 \
|
|
7
|
+
--use-schema-description --use-field-description --disable-timestamp \
|
|
8
|
+
--enum-field-as-literal all --use-standard-collections --use-union-operator \
|
|
9
|
+
--output src/zeriq_team/types.py
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"""Zeriq Teams API — official Python SDK.
|
|
2
|
+
|
|
3
|
+
from zeriq_team import Zeriq
|
|
4
|
+
|
|
5
|
+
zq = Zeriq() # reads ZERIQ_TEAM_API_KEY
|
|
6
|
+
answer = zq.personas.ask("prs_…", input="What changed in our refund policy?")
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from ._client import AsyncZeriq, Zeriq
|
|
10
|
+
from ._core import AsyncPager, Page, SyncPage, ZeriqObject
|
|
11
|
+
from ._errors import (
|
|
12
|
+
APIConnectionError,
|
|
13
|
+
APIError,
|
|
14
|
+
APITimeoutError,
|
|
15
|
+
AuthenticationError,
|
|
16
|
+
ConflictError,
|
|
17
|
+
CreditsExhaustedError,
|
|
18
|
+
InsufficientScopeError,
|
|
19
|
+
InternalServerError,
|
|
20
|
+
InvalidRequestError,
|
|
21
|
+
NotFoundError,
|
|
22
|
+
PermissionDeniedError,
|
|
23
|
+
PlanLimitError,
|
|
24
|
+
RateLimitError,
|
|
25
|
+
ToolNotPermittedError,
|
|
26
|
+
ZeriqError,
|
|
27
|
+
)
|
|
28
|
+
from ._version import __version__
|
|
29
|
+
from .webhooks import WebhookVerificationError
|
|
30
|
+
|
|
31
|
+
__all__ = [
|
|
32
|
+
"APIConnectionError", "APIError", "APITimeoutError", "AsyncPager", "AsyncZeriq", "AuthenticationError",
|
|
33
|
+
"ConflictError", "CreditsExhaustedError", "InsufficientScopeError", "InternalServerError", "InvalidRequestError",
|
|
34
|
+
"NotFoundError", "Page", "PermissionDeniedError", "PlanLimitError", "RateLimitError", "SyncPage",
|
|
35
|
+
"ToolNotPermittedError", "WebhookVerificationError", "Zeriq", "ZeriqError", "ZeriqObject", "__version__",
|
|
36
|
+
]
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"""The sync (``Zeriq``) and async (``AsyncZeriq``) clients."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import TYPE_CHECKING, Any, Mapping, Optional
|
|
6
|
+
|
|
7
|
+
import httpx
|
|
8
|
+
|
|
9
|
+
from ._core import DEFAULT_MAX_RETRIES, DEFAULT_TIMEOUT, AsyncCore, SyncCore
|
|
10
|
+
from ._resources import (
|
|
11
|
+
ActionItems,
|
|
12
|
+
AsyncBots,
|
|
13
|
+
AsyncDocuments,
|
|
14
|
+
AsyncRooms,
|
|
15
|
+
Bots,
|
|
16
|
+
Conversations,
|
|
17
|
+
Documents,
|
|
18
|
+
Knowledge,
|
|
19
|
+
Meetings,
|
|
20
|
+
Personas,
|
|
21
|
+
RoomMessages,
|
|
22
|
+
Rooms,
|
|
23
|
+
Webhooks,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
if TYPE_CHECKING:
|
|
27
|
+
from .types import Me
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class Zeriq:
|
|
31
|
+
"""Zeriq Teams API client.
|
|
32
|
+
|
|
33
|
+
>>> zq = Zeriq() # reads ZERIQ_TEAM_API_KEY
|
|
34
|
+
>>> zq.personas.ask("prs_…", input="What changed in our refund policy?")["answer"]
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
def __init__(
|
|
38
|
+
self,
|
|
39
|
+
*,
|
|
40
|
+
api_key: Optional[str] = None,
|
|
41
|
+
base_url: Optional[str] = None,
|
|
42
|
+
timeout: float = DEFAULT_TIMEOUT,
|
|
43
|
+
max_retries: int = DEFAULT_MAX_RETRIES,
|
|
44
|
+
default_headers: Optional[Mapping[str, str]] = None,
|
|
45
|
+
http_client: Optional[httpx.Client] = None,
|
|
46
|
+
) -> None:
|
|
47
|
+
self._core = SyncCore(api_key=api_key, base_url=base_url, timeout=timeout, max_retries=max_retries,
|
|
48
|
+
default_headers=default_headers, http_client=http_client)
|
|
49
|
+
self.knowledge = Knowledge(self._core, Documents(self._core))
|
|
50
|
+
self.personas = Personas(self._core)
|
|
51
|
+
self.conversations = Conversations(self._core)
|
|
52
|
+
self.rooms = Rooms(self._core, RoomMessages(self._core))
|
|
53
|
+
self.action_items = ActionItems(self._core)
|
|
54
|
+
self.meetings = Meetings(Bots(self._core))
|
|
55
|
+
self.webhooks = Webhooks(self._core)
|
|
56
|
+
|
|
57
|
+
def me(self) -> "Me":
|
|
58
|
+
"""The workspace, key, scopes and tool access behind this API key."""
|
|
59
|
+
return self._core.request("GET", "/v1/me") # type: ignore[no-any-return]
|
|
60
|
+
|
|
61
|
+
def request(self, method: str, path: str, **kwargs: Any) -> Any:
|
|
62
|
+
"""Low-level access for endpoints the SDK doesn't wrap yet."""
|
|
63
|
+
return self._core.request(method, path, **kwargs)
|
|
64
|
+
|
|
65
|
+
def close(self) -> None:
|
|
66
|
+
self._core.close()
|
|
67
|
+
|
|
68
|
+
def __enter__(self) -> "Zeriq":
|
|
69
|
+
return self
|
|
70
|
+
|
|
71
|
+
def __exit__(self, *exc: object) -> None:
|
|
72
|
+
self.close()
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class AsyncZeriq:
|
|
76
|
+
"""Async Zeriq Teams API client: the same API, awaited.
|
|
77
|
+
|
|
78
|
+
>>> async with AsyncZeriq() as zq:
|
|
79
|
+
... async for item in zq.action_items.list(status="open"):
|
|
80
|
+
... print(item["title"])
|
|
81
|
+
"""
|
|
82
|
+
|
|
83
|
+
def __init__(
|
|
84
|
+
self,
|
|
85
|
+
*,
|
|
86
|
+
api_key: Optional[str] = None,
|
|
87
|
+
base_url: Optional[str] = None,
|
|
88
|
+
timeout: float = DEFAULT_TIMEOUT,
|
|
89
|
+
max_retries: int = DEFAULT_MAX_RETRIES,
|
|
90
|
+
default_headers: Optional[Mapping[str, str]] = None,
|
|
91
|
+
http_client: Optional[httpx.AsyncClient] = None,
|
|
92
|
+
) -> None:
|
|
93
|
+
self._core = AsyncCore(api_key=api_key, base_url=base_url, timeout=timeout, max_retries=max_retries,
|
|
94
|
+
default_headers=default_headers, http_client=http_client)
|
|
95
|
+
self.knowledge = Knowledge(self._core, AsyncDocuments(self._core))
|
|
96
|
+
self.personas = Personas(self._core)
|
|
97
|
+
self.conversations = Conversations(self._core)
|
|
98
|
+
self.rooms = AsyncRooms(self._core, RoomMessages(self._core))
|
|
99
|
+
self.action_items = ActionItems(self._core)
|
|
100
|
+
self.meetings = Meetings(AsyncBots(self._core))
|
|
101
|
+
self.webhooks = Webhooks(self._core)
|
|
102
|
+
|
|
103
|
+
async def me(self) -> "Me":
|
|
104
|
+
return await self._core.request("GET", "/v1/me") # type: ignore[no-any-return]
|
|
105
|
+
|
|
106
|
+
async def request(self, method: str, path: str, **kwargs: Any) -> Any:
|
|
107
|
+
return await self._core.request(method, path, **kwargs)
|
|
108
|
+
|
|
109
|
+
async def close(self) -> None:
|
|
110
|
+
await self._core.close()
|
|
111
|
+
|
|
112
|
+
async def __aenter__(self) -> "AsyncZeriq":
|
|
113
|
+
return self
|
|
114
|
+
|
|
115
|
+
async def __aexit__(self, *exc: object) -> None:
|
|
116
|
+
await self.close()
|