Skip to content

Commit bdd7baa

Browse files
authored
Merge pull request #18 from EverMind-AI/sdk/v1.1.0-rc2
SDK 1.1.0-rc2
2 parents b60c683 + b4b081b commit bdd7baa

31 files changed

Lines changed: 2413 additions & 90 deletions

‎.github/workflows/ci.yml‎

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,16 +41,44 @@ jobs:
4141
if: steps.detect.outputs.has_pkg == 'true'
4242
run: |
4343
python - <<'PY'
44-
from everos_cloud import ApiClient, Configuration, MemoryApi, EverOS
44+
from everos_cloud import (
45+
ApiClient, Configuration, EverOS, KnowledgeApi, MemoryApi, StorageApi, TasksApi,
46+
)
4547
cfg = Configuration(access_token="sk-test")
4648
assert cfg.host == "https://api.evermind.ai", cfg.host
4749
assert cfg.auth_settings()["BearerAuth"]["value"] == "Bearer sk-test"
4850
MemoryApi(ApiClient(cfg))
49-
for m in ("add_memory", "search_memory", "get_memory", "delete_memory", "edit_profile"):
51+
# generated method names — these are the operationIds, NOT the facade's
52+
for m in ("add_memory", "search_memory", "get_memory", "delete_memory", "edit_profile",
53+
"bind_tags", "unbind_tags", "replace_tags"):
5054
assert hasattr(MemoryApi, m), m
55+
for m in ("create_knowledge_base", "search_knowledge", "create_document",
56+
"replace_document", "list_documents"):
57+
assert hasattr(KnowledgeApi, m), m
58+
for m in ("list_tasks", "get_task_status", "get_task_stats"):
59+
assert hasattr(TasksApi, m), m
5160
# ergonomic facade is exported at the top level
52-
for m in ("add", "search", "get", "flush", "edit", "delete", "upload", "close"):
61+
for m in ("add", "search", "get", "flush", "edit", "delete", "upload", "close",
62+
"tag_bind", "tag_unbind", "tag_replace",
63+
"kb_create", "kb_list", "kb_get", "kb_update", "kb_delete", "kb_search",
64+
"doc_ingest", "doc_list", "doc_get",
65+
"doc_update", "doc_delete",
66+
"task_get", "task_list", "task_wait"):
5367
assert hasattr(EverOS, m), m
68+
# the facade's names must stay disjoint from the generated ones, so a reader
69+
# never has to work out which layer a call went through
70+
generated = set()
71+
for cls in (KnowledgeApi, MemoryApi, StorageApi, TasksApi):
72+
generated |= {m for m in dir(cls) if not m.startswith("_")
73+
and not m.endswith(("_with_http_info", "_without_preload_content"))}
74+
facade = {m for m in dir(EverOS) if not m.startswith("_")}
75+
assert not (facade & generated), sorted(facade & generated)
76+
# every generated client is reachable through the facade (regression: the
77+
# knowledge / tasks handles were missing, so those surfaces were unusable)
78+
client = EverOS("sk-test")
79+
for attr, cls in (("memory", MemoryApi), ("storage", StorageApi),
80+
("knowledge", KnowledgeApi), ("tasks", TasksApi)):
81+
assert isinstance(getattr(client, attr), cls), attr
5482
print("import + config OK")
5583
PY
5684
@@ -64,9 +92,10 @@ jobs:
6492
python - <<'PY'
6593
import re
6694
import everos_cloud.models as models
67-
from everos_cloud import EverOS, MemoryApi, StorageApi
95+
from everos_cloud import EverOS, KnowledgeApi, MemoryApi, StorageApi, TasksApi
6896
69-
CLASSES = {"EverOS": EverOS, "MemoryApi": MemoryApi, "StorageApi": StorageApi}
97+
CLASSES = {"EverOS": EverOS, "MemoryApi": MemoryApi, "StorageApi": StorageApi,
98+
"KnowledgeApi": KnowledgeApi, "TasksApi": TasksApi}
7099
text = open("quickstart.md").read()
71100
blocks = re.findall(r"```python\n(.*?)```", text, re.S)
72101
assert blocks, "no python code blocks found in quickstart.md"
@@ -87,7 +116,7 @@ jobs:
87116
# 3) every method called on an EverOS / MemoryApi / StorageApi instance
88117
# must still exist (maps each instance var to its class from assignment).
89118
var_class = {v: CLASSES[c] for v, c in
90-
re.findall(r"(\w+)\s*=\s*(EverOS|MemoryApi|StorageApi)\(", code)}
119+
re.findall(r"(\w+)\s*=\s*(" + "|".join(CLASSES) + r")\(", code)}
91120
for var, cls in var_class.items():
92121
for meth in sorted(set(re.findall(rf"\b{re.escape(var)}\.(\w+)\(", code))):
93122
assert hasattr(cls, meth), f"quickstart drift: {cls.__name__} has no {meth!r}"

‎README.md‎

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ Add a conversation; EverOS turns it into structured, retrievable memory you can
3939
- **Structured memory, not chat logs** — extracts episodes, user profiles, and reusable
4040
agent cases & skills from raw conversations, so retrieval returns meaning, not transcripts.
4141
- **Retrieval that fits the query** — keyword, vector, hybrid (default), or agentic multi-step search.
42+
- **Knowledge bases** — ingest documents into a searchable topic library alongside
43+
conversational memory; ingest is async and reports progress through the task API.
4244
- **Multimodal** — attach images, audio, and documents to any message.
4345
- **Built for production** — fully managed (no vector DB or extraction pipeline to run),
4446
with low-latency retrieval and high-concurrency throughput. The engineering guarantees
@@ -74,9 +76,39 @@ with EverOS(api_key="sk-...") as client:
7476
print(results)
7577
```
7678

77-
**Full usage** — every memory operation, profile editing, and multimodal upload — is in
79+
Knowledge bases work the same way — ingest is asynchronous, so wait on the task:
80+
81+
```python
82+
kb = client.kb_create("Employee Handbook")
83+
ack = client.doc_ingest(kb.id, "Leave policy", "Employees accrue 20 days...")
84+
task = client.task_wait(ack.task_id) # polls until the document is queryable
85+
86+
hits = client.kb_search(kb.id, "how much leave do I get")
87+
```
88+
89+
**Full usage** — every memory operation, knowledge base, async task, profile editing, and
90+
multimodal upload — is in
7891
**[quickstart.md](https://github.com/EverMind-AI/everos-cloud-sdk-python/blob/v1/quickstart.md)**.
79-
Prefer typed control? The generated low-level client is exposed as `client.memory` / `client.storage`.
92+
93+
### Two ways to call the API
94+
95+
`EverOS` covers the common calls with plain kwargs in and the response's `.data` out.
96+
New methods are named `<resource>_<verb>` (`kb_create`, `doc_ingest`, `task_wait`,
97+
`tag_bind`), so typing `client.kb` lists the knowledge-base surface; the methods 1.0.0
98+
shipped are bare verbs (`add`, `search`, `get`, `flush`, `edit`, `delete`, `upload`).
99+
100+
Everything the API offers — all 31 operations, including knowledge-base categories and
101+
document topics — is on the generated typed clients, reachable as `client.memory`,
102+
`client.storage`, `client.knowledge`, `client.tasks`. Those take and return the full
103+
typed models, so responses arrive as an envelope you read `.data` from. The
104+
per-endpoint reference for them is under
105+
[`docs/`](https://github.com/EverMind-AI/everos-cloud-sdk-python/tree/v1/docs).
106+
107+
```python
108+
client.kb_create("Handbook") # facade -> KbData
109+
client.knowledge.create_knowledge_base({"name": "…"}) # generated -> envelope, .data
110+
client.knowledge.list_topics(kb_id, doc_id) # generated only
111+
```
80112

81113
## Documentation
82114

‎docs/DocIngestData.md‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66

77
Name | Type | Description | Notes
88
------------ | ------------- | ------------- | -------------
9-
**id** | **str** | Document id (engine-minted on create) |
10-
**status** | **str** | Async task status (contract-nominal at the engine) | [optional] [default to 'queued']
11-
**task_id** | **str** | Async task handle (contract-nominal at the engine) | [optional] [default to '']
9+
**id** | **str** | Document id. Present only when the engine is called directly; the gateway&#39;s async ack omits it (the id is minted downstream), so SDK callers resolve it from GET .../documents by title. | [optional]
10+
**status** | **str** | Async task status (contract-nominal at the engine) | [default to 'queued']
11+
**task_id** | **str** | Async task handle (contract-nominal at the engine) | [default to '']
1212

1313
## Example
1414

0 commit comments

Comments
 (0)