Metadata-Version: 2.4
Name: ikc-converter-sdk
Version: 0.1.1
Summary: IKC 转换引擎（ikc-converter-service）客户端 SDK：typed 转换资源方法 + 统一壳解包 + 身份信任头/traceId/幂等重试装配
Author: SITECH-iKM
Requires-Python: >=3.12
Requires-Dist: httpx<1.0,>=0.27
Requires-Dist: ikc-sdk-lib==0.12.1
Requires-Dist: pydantic<3.0,>=2.7
Description-Content-Type: text/markdown

# ikc-converter-sdk

IKC 转换引擎（`ikc-converter-service`）的官方 Python 客户端：把服务端 HTTP 面
（C-01 提交转换 / C-02 格式清单 / C-03 任务清单 / C-04 任务详情 + 系统路由）封装为
类型化调用，自动完成统一壳解包、错误码映射、身份信任头/traceId 装配与幂等重试。

- 同步客户端 `IkCConverterClient`、异步客户端 `AsyncIkCConverterClient`（API 同名）。
- 跨层能力（traceId、线缆头常量、稳定码、异常基类）**复用 `ikc-sdk-lib`**，不自定义。
- 安装包名 `ikc-converter-sdk`，导入名 `ikc_converter_sdk`。

## 安装

```bash
pip install ikc-converter-sdk==0.1.1        # 公共 PyPI（连带安装 ikc-sdk-lib==0.12.1）
```

内网/离线环境可用随仓库归档的 wheel：

```bash
pip install dist/ikc_converter_sdk-0.1.1-py3-none-any.whl
```

## 快速开始

```python
from ikc_converter_sdk import IkCConverterClient

with IkCConverterClient("http://127.0.0.1:19300", token="dev-token") as client:
    # 1) 支持的格式对（用于给用户做下拉选择）
    for item in client.conversion.formats():
        print(item.source, "->", item.target, item.plugin)

    # 2) 异步提交：立即拿到 task_id，结果由 Celery 结果后端/回调获取
    accepted = client.conversion.submit(
        task_name="kb-import-2026-09-25",
        files=[{
            "source_format": "docx",          # target_format 缺省 → 服务端按 formats 推断
            "file_id": "0f0c1c4e-…",          # PyUploadX 上传返回的 id（也可用 object_key）
            "size_mb": 2.4,
        }],
        klgId="klg_123",
        valid_time=7,
    )
    print(accepted.status, accepted.task_id)

    # 3) 同步转换（单文件）：直接拿下载地址（read timeout 缺省 1800s）
    result = client.conversion.submit(
        task_name="adhoc",
        files=[{"source_format": "pdf", "target_format": "md",
                "object_key": "kms/rag/upload/a.pdf", "size_mb": 8.0, "page_limit": 50}],
        mode="sync",
    )
    print(result.results[0].download_url)
```

## 关键行为

| 主题 | 行为 |
| --- | --- |
| 统一壳 | 响应 `{errCode, errMsg, data, traceId}` 自动解包；`errCode != 000000` 抛类型化异常 |
| 异常 | 域码 270001~270009 → `IkCConverterFormatUnsupportedError` 等；下游 509101/509102 |
| 重试 | GET/HEAD/OPTIONS 幂等重试（502/503/504 + 网络错误）；POST 默认不重试（无 `reqId`），避免重复投递任务 |
| traceId | 可传 `trace_id=`，写入 `X-Request-Id`/`X-Trace-Id`；服务端 23 位 traceId 原样回显 |
| 身份 | `static` 模式传 `token=`；`gateway_header` 模式传 `CallerIdentity(user_id=...)` |
| 超时 | 缺省 `connect=5s / read=1800s`（同步转换可能跑十几分钟）；`timeout=(connect, read)` 可覆盖 |

## 与 Celery 结果后端配合

异步提交返回的 `task_id` 同时用作 Celery 任务 id，可直接用 `AsyncResult(task_id)` 查询：

```python
from celery import Celery
celery_app = Celery(broker="redis://127.0.0.1:6379/9", backend="redis://127.0.0.1:6379/10")
payload = celery_app.AsyncResult(accepted.task_id).get(timeout=1800)
print(payload["data"]["status"], len(payload["data"]["results"]))
```

## 发布（维护方）

```bash
cp config/pypi.env.example config/pypi.env   # 填 token（已 gitignore）
bash scripts/publish_sdk.sh --upload         # 构建 wheel + twine check + 上传
```

只发布 wheel（不上传 sdist）：sdist 无法由自身重建 wheel（`force-include` 相对路径失效），
且契约禁止复制一份 SDK 源码。维护方文档见 `docs/SDK开发手册.md`。
