Metadata-Version: 2.5
Name: cognimemo-client
Version: 0.9.2
Summary: Python client for Cognimemo - Semantic memory system with personality-driven thinking
Author: Cognimemo Team
License-Expression: MIT
Requires-Python: >=3.10
Requires-Dist: aiohttp-retry>=2.8.3
Requires-Dist: aiohttp>=3.8.4
Requires-Dist: pydantic>=2
Requires-Dist: python-dateutil>=2.8.2
Requires-Dist: typing-extensions>=4.7.1
Requires-Dist: urllib3<3.0.0,>=2.1.0
Provides-Extra: test
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'test'
Requires-Dist: pytest>=7.0.0; extra == 'test'
Requires-Dist: requests>=2.33.0; extra == 'test'
Description-Content-Type: text/markdown

# Cognimemo Python Client

`@cognimemo/client` — the official Python SDK for the Cognimemo memory layer.
Talks to the Cognimemo gateway with a per-project API key (Bearer auth).

> **Verified working (2026-08-30):** installs clean; every typed helper below and
> type-filtered / layered recall were smoke-tested against a live gateway. Recall
> round-trips through the full stack in ~70 ms.

## Install

```bash
pip install cognimemo-client        # published as @cognimemo/client
```

## Quickstart

```python
from cognimemo_client.cognimemo_client import Cognimemo

cm = Cognimemo(base_url="https://api.cognimemo.com", api_key="cmk_live_…")

cm.retain(bank_id="jane@acme.com", content="Jane ships on Fridays.")
res = cm.recall(bank_id="jane@acme.com", query="when does jane ship?")
for r in res.results:
    print(r.type, r.text, r.occurred_start, r.scores)
```

Prefer `await cm.aretain(...)` / `await cm.arecall(...)` in async code; the
non-`a` methods are sync wrappers.

## Data model — space (org) → bank (person) → memories

Pass `space=` to `retain` / `recall` / `reflect` to scope a bank into its
organization (the bank is attached on first use), or manage spaces explicitly:

```python
cm.create_space("acme", name="Acme Corp")
cm.retain(bank_id="jane@acme.com", content="Jane prefers dark mode", space="acme")
cm.recall(bank_id="jane@acme.com", query="what does jane prefer?", space="acme")

cm.list_spaces()                    # orgs with per-org person counts
cm.list_space_banks("acme")         # people inside an org
cm.add_bank_to_space("acme", "raj@acme.com")
cm.remove_bank_from_space("acme", "raj@acme.com")   # person + memories kept
cm.delete_space("acme")             # people become unassigned, never deleted
```

## Typed memory blocks

Beyond auto-extracted facts/observations, store first-class blocks directly
(verbatim, no LLM rewrite) — recallable and filterable by type. The eight types
are `world`, `experience`, `observation`, `procedure`, `reasoning`,
`preference`, `correction`, `profile`.

```python
cm.retain_preference("jane@acme.com", "For day-planning, use personal Gmail, never work mail.")
cm.retain_procedure("jane@acme.com", ["tag main", "sync Argo", "run sims", "promote"], rationale="never on Friday")
cm.retain_reasoning("jane@acme.com", "Chose gRPC over REST: p99 latency mattered more than tooling.")
cm.retain_correction("jane@acme.com", "No — use Xero, not QuickBooks.")
cm.update_profile("jane@acme.com", "Uses Xero + Slack; admin on the orion cluster.")

# any type directly:
cm.retain(bank_id="jane@acme.com", content="Acme HQ is in Berlin.", fact_type="world")

cm.recall(bank_id="jane@acme.com", query="how to deploy", types=["procedure"])   # type-filtered
cm.recall_layered("jane@acme.com", "policy", space="acme")  # blend person + org (__org__:acme)
```

Typed helpers put the bank in verbatim (`chunks`) mode on first use so the block
is stored exactly as written.

## Layered / org memory

Each space has an implicit org bank at `__org__:{space}`. Retain shared knowledge
there, then blend it into a person's recall (person wins on conflict):

```python
cm.retain(bank_id="__org__:acme", content="Deploy freeze every December.")
cm.recall(bank_id="jane@acme.com", query="deploy policy",
          space="acme", include_org=True)          # or cm.recall_layered(...)
```

## Entities

Supply entities explicitly (the note-taker model — the agent knows them):

```python
cm.retain(bank_id="jane@acme.com",
          content="Jane joined the DeepMind team on Gemini.",
          entities=[{"text": "Jane", "type": "PERSON"},
                    {"text": "DeepMind", "type": "ORG"},
                    {"text": "Gemini", "type": "PROJECT"}])

cm.entities.list_entities("jane@acme.com")     # canonicalized, deduped, with mention_count
```

For verbatim ingest without supplied entities, enable no-LLM auto-extraction on
the bank (off by default): set config `retain_auto_entities: true` and it derives
proper-noun/acronym entities from the text.

## Recall response shape

`recall(...)` returns `RecallResponse` with `.results` (a list of `MemoryFact`)
and `.usage`. Each `MemoryFact` carries:

| field | meaning |
|---|---|
| `type` | the fact type (world … profile) |
| `text`, `context` | the memory body (decrypted transparently if encryption is on) |
| `occurred_start` / `occurred_end` / `mentioned_at` | temporal anchors |
| `entities` | linked entity names |
| `scores` | `{final, semantic, keyword}` |
| `metadata`, `tags`, `document_id`, `chunk_id` | provenance |

`.usage` reports `{tokens_used, max_tokens, truncated}` (and `org_blended` for
layered recall).
