Metadata-Version: 2.4
Name: cogspace
Version: 0.5.2
Summary: Official Cogspace SDK — add a knowledge layer to any AI agent
Project-URL: Homepage, https://cogspace.ai
Project-URL: Documentation, https://docs.cogspace.ai
Project-URL: Repository, https://github.com/Jack-Pision/cogspace-ai
Project-URL: Issues, https://github.com/Jack-Pision/cogspace-ai/issues
Author-email: Cogspace <sdk@cogspace.ai>
License: MIT
Keywords: agents,ai,knowledge,memory,rag,sdk
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: httpx>=0.27
Requires-Dist: pydantic>=2.0
Provides-Extra: dev
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest>=8; extra == 'dev'
Requires-Dist: respx>=0.21; extra == 'dev'
Description-Content-Type: text/markdown

# cogspace

Official Python SDK for [Cogspace](https://cogspace.ai) — persistent knowledge layer for AI agents.

Published on PyPI as **`cogspace`**.

## Install

```bash
pip install cogspace
```

## Quickstart

```python
import asyncio
import os
from cogspace import AsyncCogspace

# Set your API key (or pass api_key= directly).
# In local dev with backend auth disabled, any non-empty value works.
os.environ["COGSPACE_API_KEY"] = "local-dev-token"

async def main():
    cog = AsyncCogspace()
    space = await cog.space("my-agent")

    # See what exists
    files = await space.list("expertise")
    print(f"Files: {files.file_count}")

    # Add knowledge
    await space.add(
        path="expertise/retry.md",
        content="# Retry Patterns\nUse exponential backoff with jitter.",
        layer="expertise",
        topic="retry-patterns",
        confidence=0.95,
    )

    # Search (vectors + BM25 + knowledge graph, per-source limits)
    results = await space.search_hybrid(
        "retry logic",
        vector_limit=10,  # max vector results
        bm25_limit=10,    # max keyword results
        kg_limit=5,       # max graph neighbors per result
    )
    for item in results.results:
        print(f"{item.file_path}: {item.score:.2f} ({item.source})")

    # Retrieve a file
    file = await space.retrieve("expertise/retry.md")
    print(file.content)

    # Delete
    await space.forget("expertise/retry.md")

    await cog.aclose()

asyncio.run(main())
```

## Sync client

```python
from cogspace import Cogspace

with Cogspace() as cog:
    space = cog.space("my-agent")
    files = space.list("expertise")
    results = space.search_hybrid("retry logic", vector_limit=10, bm25_limit=10)
    space.add(
        path="expertise/retry.md",
        content="# Retry Patterns\n...",
        layer="expertise",
        topic="retry-patterns",
    )
    space.forget("expertise/retry.md")
```

## API Reference

### `Cogspace(api_key, base_url, timeout, max_retries)`

Reads `COGSPACE_API_KEY` from environment if `api_key` not provided.
Defaults to `http://localhost:8000` for local development.

| Method | Description |
|---|---|
| `cog.space(name_or_id)` | Get a space client by name or ID |
| `cog.list_spaces()` | List all your spaces |
| `cog.create_space(name)` | Create a new space |

### `SpaceClient`

| Method | Args | Description |
|---|---|---|
| `space.list(folder)` | `folder=""` | List files in folder |
| `space.retrieve(path)` | `path` | Get one file with content + metadata |
| `space.search_hybrid(query, ...)` | see below | Unified search: vectors + BM25 + KG |
| `space.add(path, content, layer, topic, confidence, file_type, status, related, relates_to)` | see below | Add/update knowledge |
| `space.forget(path)` | `path` | Delete from all layers |

#### `add()` parameters

| Param | Type | Required | Description |
|---|---|---|---|
| `path` | str | yes | File path (e.g. "expertise/retry.md") |
| `content` | str | yes | Markdown content |
| `layer` | str | yes | "expertise", "memory", or "root" |
| `topic` | str | yes | Category/topic |
| `confidence` | float | no | 0.0-1.0, default 0.9 |
| `file_type` | str | no | Explicit file type override |
| `status` | str | no | Metadata status, default `active` |
| `related` | list[str] | no | Canonical related file paths |
| `relates_to` | list[str] | no | Backward-compatible alias for `related` |

## Layers

| Layer | Use for |
|---|---|
| `expertise` | Knowledge, patterns, guides, reference material |
| `memory` | Agent memory, user preferences, session notes |
| `root` | General knowledge that doesn't fit elsewhere |

## Search limits

`search_hybrid()` parameters (enforced at backend):

| Param | Type | Default | Range | Description |
|---|---|---|---|---|
| `vector_limit` | int | 100 | 0–100 | Max vector results. 0 = skip vectors. |
| `bm25_limit` | int | 100 | 0–100 | Max BM25 keyword results. 0 = skip BM25. |
| `kg_limit` | int | 100 | 0–100 | Max graph neighbors per result. 0 = skip KG. |
| `layer` | str | None | "expertise"/"memory"/"root" | Filter by layer. |
| `folder_path` | str | None | — | Restrict to folder. |

**Examples:**
```python
# Pure vector search (skip BM25)
results = await space.search_hybrid("query", bm25_limit=0)

# Pure keyword search (skip vectors)
results = await space.search_hybrid("query", vector_limit=0)

# Skip graph enrichment
results = await space.search_hybrid("query", kg_limit=0)

# Fine-grained control
results = await space.search_hybrid("query", vector_limit=5, bm25_limit=3, kg_limit=1)
```

## Errors

```python
from cogspace.exceptions import AuthError, NotFoundError, RateLimitError

try:
    results = await space.search_hybrid("query")
except AuthError:
    print("Invalid API key")
except NotFoundError:
    print("Space not found")
except RateLimitError:
    print("Rate limited, retry later")
```

## Local-first note

The Python SDK is local-first by default:

- Default base URL: `http://localhost:8000`
- Space lookup accepts either a space name or a space ID
- If backend auth is disabled locally, use any non-empty `COGSPACE_API_KEY`
