Metadata-Version: 2.4
Name: claude-chat-client-py
Version: 0.1.1
Summary: Shared Python Anthropic client: per-app API key/model config + a streaming tool-use loop, extracted from careboard/HomeManagement
Requires-Python: >=3.10
Requires-Dist: anthropic>=0.69
Description-Content-Type: text/markdown

# claude-chat-client-py

Shared Python Anthropic client for careboard, HomeManagement, and medsync's
backends. HomeManagement already streams via
`anthropic.AsyncAnthropic().messages.stream(...)` — this package is that
same pattern, with the tool-use round-trip loop factored out so it's
written once instead of per app. careboard currently calls the Messages
API directly via `httpx`; migrating it to this package also gets it onto
the official SDK.

## Usage

```python
from claude_chat_client import ClaudeClient, ClaudeClientConfig

claude = ClaudeClient(ClaudeClientConfig(
    api_key=settings.anthropic_api_key,  # this app's own key, unchanged
    model=settings.anthropic_model,      # this app's own model, unchanged
))

async def execute_tool(call):
    if call.name == "log_medication_dose":
        return await log_dose(call.input)
    raise ValueError(f"unknown tool {call.name}")

result = await claude.chat(
    system="You are ...",
    messages=conversation_so_far,
    tools=MY_APP_TOOLS,
    on_text_delta=lambda delta: response_writer.write(delta),
    execute_tool=execute_tool,
)

# result.messages -> persist as the new conversation history
# result.final_text -> full assistant text across all tool-loop rounds
```

Requires `anthropic>=0.69` (verified against 0.117.0). Tool execution
stays app-specific by design — this package only owns the stream/detect
`tool_use`/await `execute_tool`/loop plumbing, capped by `max_tool_rounds`
(default 8).

## Image attachments

`image_content_block()` builds a Claude image content block from base64 +
media type (mirrors homeclaude's own `buildAttachmentBlock()`), for
including in a user message's content list alongside a text block:

```python
from claude_chat_client import image_content_block, is_supported_image_type

content = [{"type": "text", "text": user_text}]
for img in images:  # each: media_type, base64
    content.append(image_content_block(ImageAttachment(img.media_type, img.base64)))
```

Only `image/jpeg`, `image/png`, `image/gif`, and `image/webp` are
supported (`SUPPORTED_IMAGE_MEDIA_TYPES`) — check with
`is_supported_image_type()` before calling `image_content_block()` on
user-supplied media types. Document/PDF attachments (which homeclaude
also supports today) aren't covered yet.

## Install

Not published to PyPI — installs from this Forgejo instance's own
PyPI-compatible package registry instead. Add to `pyproject.toml`:

```toml
dependencies = [
  "claude-chat-client-py>=0.1.0,<0.2",
]
```

and point pip at the registry (see `PIP_EXTRA_INDEX_URL` in any consuming
app's Dockerfile/CI — e.g. HomeManagement's or careboard's).
