Metadata-Version: 2.5
Name: cli-302ai
Version: 1.0.5a4
Summary: 302.ai unified CLI
Requires-Python: >=3.10
Requires-Dist: aioboto3>=13.0
Requires-Dist: httpx>=0.27
Requires-Dist: ruamel-yaml>=0.18
Requires-Dist: typer>=0.12
Provides-Extra: 3d
Requires-Dist: pyvista>=0.43.0; extra == '3d'
Requires-Dist: trimesh>=4.0; extra == '3d'
Description-Content-Type: text/markdown

# 302ai CLI

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

## Project architecture

代码按职责拆分为三层：

- `ai302/cli/`
  - `ai302/cli/app.py`：CLI 根入口（挂载各子命令）
  - `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/create/fetch/edit）
  - `ai302/cli/tts.py`：TTS（refresh/providers/voices/create/fetch）
  - `ai302/cli/stt.py`：STT（models/transcribe）
  - `ai302/cli/song.py`：音乐（create/generate/lyrics/fetch）
  - `ai302/cli/sfx.py`：音效（create）
  - `ai302/cli/three_d.py`：3D（create/fetch/models）
  - `ai302/cli/search.py`：联网搜索
  - `ai302/cli/history.py`：本地 history 查询（path/list）
  - `ai302/cli/task.py` / `ai302/cli/file.py`：内部命令，仅 `AI302_EDITION=internal` 时注册

- `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`：安装后命令 `302ai ...` 的脚本入口（同时也是 `-v/--version` 的版本来源）

## Install (dev)

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

## Run (no install)

```bash
python -m 302ai -h
```

## Environment

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

### 结果转存到 Cloudflare R2（可选）

五项全部配置后才启用，缺任意一项则整体跳过（输出与未配置时完全一致）：

- `R2_ENDPOINT`、`R2_ACCESS_KEY_ID`、`R2_SECRET_ACCESS_KEY`、`R2_BUCKET`、`R2_PUBLIC_BASE_URL`
- `R2_REGION`（默认 `auto`）

启用后，图片/视频/音频/3D/歌曲等命令的**产物 URL**（`result_url`、`image_url(s)`、`audio_url`、`video_url`、`music_url`）会先下载并转存到 R2，输出里换成 `R2_PUBLIC_BASE_URL` 下的公开链接。为避免 agent 总结时把原始链接带出去，stdout **不再输出** `raw` / `raw_fetch` / `raw_response`；`message` 等自由文本里若嵌了已转存的原始 URL，也会替换成 R2。请求体（`request`）保留。转存失败时命令以 `status: failed` 退出。

PowerShell:

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

## Models

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

查看当前内置支持模型：

```bash
python -m 302ai model list t2v
python -m 302ai model get t2v --random
python -m 302ai model list t2i
```

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

```bash
302ai model set t2v google-veo3.1-t2v
302ai model set i2v google-veo3.1-i2v
302ai model set t2i gpt-image-2-t2i
302ai model set i2i gpt-image-2-i2i
```

## CLI status enums

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

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


## Video

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

创建任务：

```bash
302ai video create --prompt "a cat run" --model google-veo3.1-t2v --api_key "sk-..."
```

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

查询任务：

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

## TTS

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

```bash
302ai tts refresh --api_key "sk-..."
```

查看可用 provider：

```bash
302ai tts providers
302ai tts providers-get --random
```

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

```bash
302ai tts voices --provider openai
302ai tts voices-get openai --random
```

创建 TTS 任务（异步）：

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

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

查询任务结果：

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

## Image (sync)

同步生图：

```bash
302ai image generate --prompt "sky city" --model gpt-image-2-t2i --api_key "sk-..."
```

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

## Image (async)

异步生图（创建任务）：

```bash
302ai image create --prompt "sky city" --model gpt-image-2-t2i --api_key "sk-..."
```

查询任务结果：

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

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

```bash
302ai image generate --prompt "添加墨镜" --image "https://..." --api_key "sk-..."
```

## Task (YAML editor)

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

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

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

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

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

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

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

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

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

> `task` 与 `file` 为内部命令，仅在 `AI302_EDITION=internal` 时注册；下同。

`@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
302ai file snapshot --dir "./asset" --out before.json
```

- diff

```bash
302ai file diff before.json after.json
```

- upload

```bash
302ai 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
302ai history path
```

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

```bash
302ai history list --kind video --op fetch --limit 20
```
