Metadata-Version: 2.4
Name: cli-302ai
Version: 1.0.2b1
Summary: 302.ai unified CLI
Requires-Python: >=3.10
Requires-Dist: httpx>=0.27
Requires-Dist: ruamel-yaml>=0.18
Requires-Dist: typer>=0.12
Description-Content-Type: text/markdown

# ai302 CLI

302.ai 统一命令行工具（输出均为单行 JSON，方便脚本处理）。

## Project architecture

代码按职责拆分为三层：

- `ai302/cli/`：Typer CLI 命令层（参数解析、统一 JSON 输出、写 history/快照）
  - `ai302/cli/app.py`：CLI 根入口（挂载 model/video/image/tts/history 子命令）
  - `ai302/cli/common.py`：公共工具（`resolve_api_key` / `print_json` / `parse_extra`）
  - `ai302/cli/model.py`：默认模型配置（set/list）
  - `ai302/cli/video.py`：视频异步任务（create/fetch）
  - `ai302/cli/image.py`：图片同步生成（generate）
  - `ai302/cli/tts.py`：TTS（refresh/providers/voices/create/fetch）
  - `ai302/cli/history.py`：本地 history 查询（path/list）

- `ai302/api/`：HTTP API 封装层（只负责请求/返回 JSON，不做 CLI 交互）
  - `ai302/api/http_client.py`：httpx 客户端、重试、统一错误 `AI302ApiError`、Base URL（`AI302_BASE_URL`）
  - `ai302/api/video.py`：视频 create/fetch 请求封装
  - `ai302/api/image.py`：图片 generate 请求封装
  - `ai302/api/tts.py`：TTS provider/create/fetch 请求封装

- `ai302/core/`：本地能力层（配置/模型表/history/快照/缓存）
  - `ai302/core/config.py`：本地配置读写（`$AI302_CONFIG_DIR/config.json`，默认模型等）
  - `ai302/core/models.py`：内置 `SUPPORTED_MODELS` 静态表
  - `ai302/core/history.py`：`history.jsonl` 追加与查询
  - `ai302/core/task_store.py`：任务快照 `tasks/<taskid>.json` 写入/更新
  - `ai302/core/tts_cache.py`：TTS providers 缓存读写与 voices 扁平化

入口文件：
- `ai302/__main__.py`：支持 `python -m ai302 ...`
- `pyproject.toml`：安装后命令 `ai302 ...` 的脚本入口（同时也是 `-v/--version` 的版本来源）

## Release (GitHub Actions → TestPyPI/PyPI)

发布版本号以 `pyproject.toml` 的 `version = "X.Y.Z"` 为准，**发版前务必先更新它**。

一次完整发版流程：

```bash
# 1) 修改版本号（必须）
#    编辑 pyproject.toml，把 [project].version 改成目标版本，例如 0.1.8

# 2) 提交并推送到远程分支（示例：remote=302ai, 本地 master → 远程 dev）

# 3) 先发布到 TestPyPI（触发 CI）
#    tag 必须是 test-vX.Y.Z，并且 X.Y.Z 必须与 pyproject.toml 的 version 一致
git tag test-v0.1.8
git push 302ai test-v0.1.8

# 4) TestPyPI 验证通过后，再发布到 PyPI（触发 CI）
#    tag 必须是 vX.Y.Z，并且 X.Y.Z 必须与 pyproject.toml 的 version 一致
git tag v0.1.8
git push 302ai v0.1.8
```

GitHub Secrets 需要配置：
- `TESTPYPI_API_TOKEN`：TestPyPI token
- `PYPI_API_TOKEN`：PyPI token

## Skills / Claude Code integration

本项目内置了一组 Claude Code skills/commands 模板，用于把 302ai 的媒体能力接入 Claude Code 工作流。

- 源模板目录：
  - `ai302/assets/skills/`
  - `ai302/assets/commands/`
  - `ai302/assets/docs/`
  - `ai302/assets/CLAUDE.md`

初始化（把模板复制到指定目录；同时会把 docs/ 与 CLAUDE.md 写到 `/home/user/workspace/...`）：

```bash
ai302 skills init <dest>
# 例如：ai302 skills init ~/.claude
```

## Install (dev)

```bash
python -m pip install -U pip
python -m pip install -e .
```

## Run (no install)

```bash
python -m ai302 -h
```

## Environment

- API Key：`AI302_KEY`（也可以每次传 `--api_key`）
- Base URL：`AI302_BASE_URL`（默认 `https://api.302.ai`）
- Config dir：`AI302_CONFIG_DIR`（默认 `~/.ai302`）

PowerShell:

```powershell
$env:AI302_KEY="YOUR_KEY"
```

## Models

模型按任务类型分组：
- 视频：`t2v` / `i2v`
- 图片：`t2i` / `i2i`

查看当前内置支持模型：

```bash
python -m ai302 model list t2v
python -m ai302 model get t2v --random
python -m ai302 model list t2i
```

设置默认模型（写入本地配置）：

```bash
ai302 model set t2v minimaxi-t2v-01
ai302 model set i2v minimaxi-hailuo-2.3-fast
ai302 model set t2i flux-kontext-max-t2i
ai302 model set i2i wan2.6-image
```

## CLI status enums

异步任务（video / tts）状态枚举固定为：
- `pending`：准备/排队中
- `processing`：处理中
- `completed`：完成
- `failed`：失败

同步接口（image）只会返回：
- `completed`：完成
- `failed`：失败


## Video

视频模块提供 **异步视频生成任务**（text-to-video / image-to-video），支持创建任务与查询任务结果。

创建任务：

```bash
ai302 video create --prompt "a cat run" --model minimaxi-t2v-01 --api_key "sk-..."
```

返回字段补充：`request` 会包含本次请求的 method/url/headers(仅脱敏 Authorization)/params/body。

查询任务：

```bash
ai302 video fetch <taskid> --api_key "sk-..."
# 使用 --short 仅返回关键状态和结果 URL
ai302 video fetch <taskid> --short
```

## TTS

首次使用建议先刷新 provider/model/voice 信息到本地缓存（会写入 `$AI302_CONFIG_DIR/tts/providers.json`）：

```bash
ai302 tts refresh --api_key "sk-..."
```

查看可用 provider：

```bash
ai302 tts providers
ai302 tts providers-get --random
```

查看可用 voices（建议用 `--provider` 过滤）：

```bash
ai302 tts voices --provider openai
ai302 tts voices-get openai --random
```

创建 TTS 任务（异步）：

```bash
ai302 tts create --text "生活就像海洋，只有意志坚强的人才能到达彼岸" --provider openai --voice alloy --api_key "sk-..."
```

返回字段补充：`request` 会包含本次请求的 method/url/headers(仅脱敏 Authorization)/params/body。

查询任务结果：

```bash
ai302 tts fetch <taskid> --api_key "sk-..."
# 使用 --short 仅返回关键状态和结果 URL
ai302 tts fetch <taskid> --short
```

## Image (sync)

同步生图：

```bash
ai302 image generate --prompt "sky city" --model flux-kontext-max-t2i --api_key "sk-..."
```

返回字段补充：`request` 会包含本次请求的 method/url/headers(仅脱敏 Authorization)/params/body。

## Image (async)

异步生图（创建任务）：

```bash
ai302 image create --prompt "sky city" --model flux-kontext-max-t2i --api_key "sk-..."
```

查询任务结果：

```bash
ai302 image fetch <taskid> --api_key "sk-..."
# 使用 --short 仅返回关键状态和结果 URL
ai302 image fetch <taskid> --short
```

图生图（可重复传 `--image`）：

```bash
ai302 image generate --prompt "添加墨镜" --image "https://..." --api_key "sk-..."
## Task (YAML editor)

默认目录：`ai302/templates/workspace/tasks`（文件名按时间倒序取最新的 `*.yaml`）。

支持字段编辑、数组元素添加与移除，以及通过 `--path` 指定特定文件：

```bash
# 修改默认最新文件的字段
ai302 task edit --set "workflow.steps[step=2].parameters.prompt=生成一只更可爱的小猫"

# 指定特定文件进行编辑
ai302 task edit --path "./tasks/my_task.yaml" --set "a=b"

# 添加数组元素
ai302 task edit --add "workflow.running_steps=Node_C"
...
```

参数说明：
- `--set`：设置值，支持 `+=`, `-=` 语法
- `--add`：追加元素到数组
- `--remove`：从数组移除元素
- `--path`：指定要编辑的 YAML 文件路径（如果不提供，则自动寻找默认目录下最新的文件）

# 或者使用 += 语法
ai302 task edit --set "workflow.running_steps+=Node_C"

# 移除数组元素 (支持精确值匹配)
ai302 task edit --remove "workflow.pending_steps=Node_C"
# 或者使用 -= 语法
ai302 task edit --set "workflow.pending_steps-=Node_C"

# 移除数组元素 (支持对象字段匹配)
ai302 task edit --remove "workflow.steps=step=1"
```

`@json=` 用法：当值是数组/对象时，用 `@json` 让 CLI 把值按 JSON 解析，并写回为 YAML 的 **flow style**（数组 `[...]` / 对象 `{...}`）。

- list：`depends_on@json=[1,3]` → `depends_on: [1, 3]`
- object：`parameters.extra@json={"a":1,"b":[2,3]}` → `extra: {a: 1, b: [2, 3]}`

路径语法：
- dotted：`a.b.c=...`
- 列表下标：`steps[0].parameters.prompt=...`
- 列表筛选（按字段匹配）：`steps[step=2].parameters.prompt=...`

运算符说明：
- `=`：设置值（默认）
- `+=`：向数组追加元素
- `-=`：从数组中移除匹配的元素（值匹配或字段筛选匹配）

## History / Local files

## File

- snapshot

```bash
ai302 file snapshot --dir "./asset" --out before.json
```

- diff

```bash
ai302 file diff before.json after.json
```

- upload

```bash
ai302 file upload ./a.png --url "https://your-upload-endpoint" --prefix img
```


- History（JSONL）：`$AI302_CONFIG_DIR/history.jsonl`
- Video task snapshots：`$AI302_CONFIG_DIR/tasks/<taskid>.json`

查看 history 路径：

```bash
ai302 history path
```

按条件查询（输出匹配的 jsonl 行）：

```bash
ai302 history list --kind video --op fetch --limit 20
```
