Metadata-Version: 2.4
Name: crawler4j-sdk
Version: 2.1.1
Summary: Crawler4j Task Script SDK - 用于开发任务脚本的开发工具包
Requires-Python: >=3.12
Requires-Dist: aiohttp>=3.13.0
Requires-Dist: crawler4j-contracts<2.0.0,>=1.0.1
Requires-Dist: pyyaml>=6.0.3
Description-Content-Type: text/markdown

# Crawler4j SDK

任务脚本开发工具包（Software Development Kit）。

## 使用 CLI 的两种方式

方式 1：安装后长期使用

```bash
uv tool install crawler4j-sdk
crawler4j --help
```

方式 2：不安装，直接一次性运行

```bash
uvx --from crawler4j-sdk crawler4j --help
```

如果你已经创建了 model 项目，并且项目目录里执行过 `uv sync`，由于项目依赖中包含 `crawler4j-sdk`，也可以在项目内使用：

```bash
uv run crawler4j --help
```

## 快速开始

```python
from crawler4j_sdk import TaskScript, TaskContext, TaskResult


class MyTask(TaskScript):
    """示例任务"""
    
    name = "my_task"
    display_name = "我的任务"
    description = "这是一个示例任务"
    default_config = {"timeout": 30}

    async def execute(self, ctx: TaskContext) -> TaskResult:
        # 使用浏览器
        await ctx.page.goto("https://example.com")
        
        # 使用配置
        timeout = ctx.get_config("timeout", 30)
        
        # 使用日志
        ctx.logger.info("任务执行中...")
        
        return TaskResult.ok(message="完成")

    async def on_error(self, ctx: TaskContext, error: Exception) -> None:
        await ctx.screenshot("error")
        ctx.logger.error(f"任务失败: {error}")
```

## 核心 API

### 稳定契约（同 MAJOR 版本内冻结）

| 类型 | 说明 |
|:---|:---|
| `TaskScript` | 原子任务基类 |
| `TaskFlow` | 工作流编排基类 |
| `TaskContext` | 任务执行上下文 |
| `TaskResult` | 任务结果模型 |
| `DatabaseCapability` | Core 注入的数据能力接口 |

## 2.0.0 升级要求

`crawler4j-sdk 2.0.0` 起，SDK 不再保留任何仅用于兼容旧模块的导出。

升级现有模块时，至少完成下面 4 件事：

- 删除 `from crawler4j_sdk import DataService`
- 如需类型标注，改用 `DatabaseCapability`
- 把 `ctx.db.storage`、`ctx.db.accounts`、`ctx.db.tasks` 改成 `ctx.db` 的最小能力接口
- 停止直接连接宿主数据库，只通过 Core 注入的 `ctx.db` 读写数据

### TaskScript 生命周期

```
on_init(ctx) → execute(ctx) → on_cleanup(ctx)
                   ↓
              on_error(ctx, error)  [仅异常时]
```

### TaskContext 能力

| 属性/方法 | 说明 |
|:---|:---|
| `ctx.page` | Playwright Page 对象 |
| `ctx.logger` | 日志记录器 |
| `ctx.http` | HTTP 客户端 |
| `ctx.config` | 任务配置 |
| `ctx.state` | 共享状态 |
| `ctx.run_subtask()` | 调用子任务 |
| `ctx.should_stop()` | 检查停止标志 |
| `ctx.screenshot()` | 截图 |
| `ctx.db` | 模块数据查询/写入、轻量状态、幂等锁 |

### `ctx.db` 当前真实边界

当前模块只应通过 Core 注入的 `ctx.db` 使用数据能力，不应直接连接宿主数据库，也不应假设存在 ORM Session 或原生 SQLite 连接。

稳定支持的方法只有：

- `list_records(dataset)`
- `replace_records(dataset, records)`
- `acquire_lock(scope, key, ttl, owner=None)`
- `release_lock(scope, key)`
- `is_locked(scope, key)`
- `get_state(key)`
- `set_state(key, value, ttl=None)`
- `exists_state(key)`

如果你看到历史资料里出现 `ctx.db.storage`、`ctx.db.accounts` 或 `ctx.db.tasks`，请以当前代码和 `TaskContext.db` 的真实接口为准。
这些旧写法在 SDK 2.0.0 起不再作为兼容接口保留。

## CLI 命令

```bash
# 初始化完整 model 项目
uvx --from crawler4j-sdk crawler4j init-model my_model

# 进入模块目录并安装依赖后，创建任务脚本（交互式）
uv run crawler4j add

# 进入模块目录后，创建任务脚本（快速）
uv run crawler4j new my_task

# 进入模块目录后，列出任务脚本
uv run crawler4j list

# 创建工作流并写入 module.yaml
uv run crawler4j add-workflow sync_orders

# 创建/补齐 declarative UI
uv run crawler4j add-ui
```

`init-model` 默认会进入一轮初始化向导，并在创建后自动：

- 生成 `.gitignore`
- 生成 `.python-version`
- 执行 `git init`
- 执行 `uv sync`

如果你在 CI 或脚本里使用 CLI，可以加 `--defaults` 跳过交互；如需跳过自动初始化动作，可额外使用 `--no-git` 或 `--no-install`。

调试主路径已经收敛到 Core 调试会话。CLI 不再生成 `debug_runner.py`。

## 工作流示例

```python
from crawler4j_sdk import TaskFlow, TaskContext


class MyWorkflow(TaskFlow):
    name = "my_workflow"
    
    async def run(self, ctx: TaskContext) -> None:
        # 登录
        await ctx.run_subtask("login")
        
        # 循环处理
        while not ctx.should_stop():
            ctx.state["phase"] = "claim"
            task = await ctx.run_subtask("claim_task")
            if not task:
                break
            
            ctx.state["phase"] = "process"
            await ctx.run_subtask("process", task=task)
```

## 版本兼容

- Python: `>= 3.12`
- 遵循语义化版本（SemVer）
