Metadata-Version: 2.4
Name: dm-sparkSDK
Version: 0.1.1
Author: DeepModel
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Requires-Python: >=3.8
Description-Content-Type: text/markdown
Requires-Dist: httpx>=0.24.0
Dynamic: author
Dynamic: classifier
Dynamic: description
Dynamic: description-content-type
Dynamic: requires-dist
Dynamic: requires-python

# Spark SDK

**Spark SDK** is a lightweight Python client for the [DeepModel](https://deepmodel.ai) Spark API. It gives your application programmatic access to MCP tools and worker agents — allowing you to list available tools and invoke them directly, without any LLM inference overhead.

---

## Features

- List all available MCP tools and worker agents with connection status and payload schemas
- Directly invoke any MCP tool or worker agent with structured arguments
- Clean, async-first API built on `httpx`
- Consistent error handling — errors are returned in the response, never raised unexpectedly

---

## Requirements

- Python `>= 3.8`
- `httpx >= 0.24.0`

---

## Installation

```bash
pip install dm-sparkSDK
```

---

## Configuration

When initializing the client, you must provide the following:

| Parameter | Type  | Required | Description                                          |
|-----------|-------|----------|------------------------------------------------------|
| `api_key` | `str` | ✅ Yes   | Your DeepModel API key for authentication (`x-api-key`) |
| `api_url` | `str` | ✅ Yes   | The base URL of your DeepModel Spark API instance    |

```python
import dm-sparkSDK

client = dm-sparkSDK.Client(
    api_key="your_api_key",
    api_url="https://your-api-url.com"
)
```

> You can store these values as environment variables and load them with `os.environ` or a library like `python-dotenv`:

```python
import os
import dm-sparkSDK

client = dm-sparkSDK.Client(
    api_key=os.environ["SPARK_API_KEY"],
    api_url=os.environ["SPARK_API_URL"]
)
```

### Recommended Environment Variables

| Variable        | Description                              |
|-----------------|------------------------------------------|
| `SPARK_API_KEY` | Your DeepModel API key                   |
| `SPARK_API_URL` | The base URL of the Spark API instance   |

---

## Constants (Enums)

The SDK exposes target type constants used when invoking tools:

| Constant          | Value     | Description                        |
|-------------------|-----------|------------------------------------|
| `dm-sparkSDK.MCP`   | `"mcp"`   | Target an MCP tool                 |
| `dm-sparkSDK.AGENT` | `"agent"` | Target a worker agent              |

```python
import dm-sparkSDK

dm-sparkSDK.MCP    # "mcp"
dm-sparkSDK.AGENT  # "agent"
```

---

## Available Methods

### `client.get_unified_tools()`

Retrieves all MCP tools and worker agents accessible to the authenticated user, including their connection status and payload schemas.

```python
result = await client.get_unified_tools()
```

**Returns:** `dict`

| Field         | Type           | Description                                      |
|---------------|----------------|--------------------------------------------------|
| `success`     | `bool`         | Whether the request was successful               |
| `tools`       | `dict`         | Contains `mcp_tools` (grouped by server) and `worker_agents` |
| `status_code` | `int`          | HTTP status code of the response                 |
| `detail`      | `str` / `null` | Error message if the request failed              |

**Example response:**

```json
{
    "success": true,
    "tools": {
        "mcp_tools": {
            "github": [
                {
                    "tool_name": "create_issue",
                    "is_configured": true,
                    "connection_id": "uuid-here",
                    "description": "Creates a GitHub issue",
                    "payload_schema": {},
                    "icon_url": "https://..."
                }
            ]
        },
        "worker_agents": [
            {
                "tool_name": "My Agent",
                "is_configured": true,
                "connection_id": "uuid-here",
                "description": "A custom worker agent",
                "payload_schema": {},
                "agent_avatar_url": "https://..."
            }
        ]
    },
    "status_code": 200,
    "detail": null
}
```

---

### `client.invoke_tool()`

Directly invokes an MCP tool or worker agent with the provided arguments. No LLM inference is performed — arguments are passed as-is.

```python
result = await client.invoke_tool(
    connection_id="uuid-here",
    target_type=dm-sparkSDK.MCP,
    tool_or_agent_name="create_issue",
    arguments={"title": "Bug report", "body": "Something went wrong"},
    query="create a github issue"   # optional
)
```

**Parameters:**

| Parameter            | Type           | Required | Description                                                        |
|----------------------|----------------|----------|--------------------------------------------------------------------|
| `connection_id`      | `str` / `UUID` | ✅ Yes   | The connection ID of the tool or agent (from `get_unified_tools`)  |
| `target_type`        | `str`          | ✅ Yes   | `dm-sparkSDK.MCP` or `dm-sparkSDK.AGENT`                               |
| `tool_or_agent_name` | `str`          | ✅ Yes   | The exact name of the tool or agent to invoke                      |
| `arguments`          | `dict`         | ✅ Yes   | Key-value arguments matching the tool's `payload_schema`           |
| `query`              | `str`          | ❌ No    | Optional natural language context for agent invocations            |

**Returns:** `dict`

| Field                | Type           | Description                                        |
|----------------------|----------------|----------------------------------------------------|
| `success`            | `bool`         | Whether the invocation was successful              |
| `tool_or_agent_name` | `str`          | The name of the tool or agent invoked              |
| `connection_id`      | `str`          | The connection ID used                             |
| `result`             | `any`          | The output returned by the tool or agent           |
| `status_code`        | `int`          | HTTP status code of the response                   |
| `detail`             | `str` / `null` | Error message if the invocation failed             |

---

## Full Example

```python
import asyncio
import os
import dm-sparkSDK

async def main():
    client = dm-sparkSDK.Client(
        api_key=os.environ["SPARK_API_KEY"],
        api_url=os.environ["SPARK_API_URL"]
    )

    # Step 1: Get all available tools
    tools_result = await client.get_unified_tools()

    if not tools_result.get("success"):
        print(f"Failed to fetch tools: {tools_result.get('detail')}")
        return

    tools = tools_result["tools"]
    print("MCP Tools:", tools.get("mcp_tools"))
    print("Worker Agents:", tools.get("worker_agents"))

    # Step 2: Invoke an MCP tool
    invoke_result = await client.invoke_tool(
        connection_id="your-connection-id",
        target_type=dm-sparkSDK.MCP,
        tool_or_agent_name="create_issue",
        arguments={
            "title": "Bug report",
            "body": "Something went wrong"
        },
        query="create a github issue"
    )

    if not invoke_result.get("success"):
        print(f"Invocation failed [{invoke_result.get('status_code')}]: {invoke_result.get('detail')}")
    else:
        print("Result:", invoke_result.get("result"))

    # Step 3: Invoke a worker agent
    agent_result = await client.invoke_tool(
        connection_id="your-agent-id",
        target_type=dm-sparkSDK.AGENT,
        tool_or_agent_name="My Agent",
        arguments={"input": "Hello, agent!"}
    )
    print("Agent Result:", agent_result.get("result"))

asyncio.run(main())
```

---

## Error Handling

All errors are returned within the response dict — no exceptions are raised unexpectedly.

```python
result = await client.get_unified_tools()

if not result.get("success"):
    print(f"Error {result.get('status_code')}: {result.get('detail')}")
```

| Error Type       | `status_code` | `detail` Example                              |
|------------------|---------------|-----------------------------------------------|
| HTTP Error       | e.g. `401`    | `"No detail provided"`                        |
| Request Error    | `400`         | `"Request error: Connection refused"`         |
| Unexpected Error | `500`         | `"An unexpected error occurred: ..."`         |

---

## License

MIT License
