# pi-subscription-image

[English](./README.md) | [简体中文](./README.zh-CN.md)

一个 [Pi](https://github.com/earendil-works/pi-mono) 扩展：使用 OpenAI Codex 或 xAI Grok 的订阅额度生成和编辑图片，提供 `generate_image_with_subscription` 工具和 `/img` 命令。

`/subscription-image status` 输出示例：

```text
Image Generation: Codex ready; Grok ready
```

`/img` 命令示例：

```text
/img 一枚红熊猫扁平矢量图标
```

## 支持的提供商

登录方法：输入 `/login`，先选 `Sign in with an account`（下表记为 Account），再在列表里选下表中的名称。Pi 界面只有英文，这里的选项名称都按界面原文写。

| 提供商 | `/login` 中选择 | 支持功能 | 默认模型 | 输出格式 |
| --- | --- | --- | --- | --- |
| OpenAI Codex (`codex`) | Account → `OpenAI Codex (legacy)` | 文生图、参考图编辑（最多 5 张） | `gpt-5.6-sol`（底层 `gpt-image-2`） | `png`（默认）、`jpeg`、`webp` |
| xAI Grok (`grok`) | Account → `xAI` | 文生图、`1k` / `2k` 分辨率、`low` / `medium` 质量 | `grok-imagine-image-2.0` | 由服务端决定（`png`、`jpeg` 或 `webp`） |

### 提供商说明

#### OpenAI Codex

用 ChatGPT Plus 或 Pro 账号登录（Account → `OpenAI Codex (legacy)`）。参考图编辑最多支持 5 张本地图片（`png`、`jpeg` 或 `webp`，单张不超过 20 MB）或当前对话中最近的图片。指定 `aspectRatio` 时，扩展会在提示词末尾追加对应的宽高比要求。

#### xAI Grok

用 X Premium 或 SuperGrok 账号登录（Account → `xAI`）。Grok Imagine 将 `aspectRatio`（默认 `1:1`）、`resolution`（默认 `1k`，可选 `2k`）和 `quality`（`low` 或 `medium`，仅 `grok-imagine-image-2.0` 支持）作为原生请求参数发送。

## 安装

需要 Node.js >= 22.19.0。

从 npm 安装：

```bash
pi install npm:@specode/pi-subscription-image
```

从 GitHub 安装：

```bash
pi install git:github.com/specode/pi-subscription-image
```

从本地目录安装（开发调试）：

```bash
pi install /path/to/pi-subscription-image
```

安装后执行 `/reload` 或重启 Pi 生效。

## 使用说明

按上面的方法登录后，可以直接在对话中描述要生成的图片，或执行 `/img <提示词>`：

- 生成的图片会在对话中内联显示，并默认保存到 `~/.pi/agent/generated-images/`。
- 执行 `/subscription-image status` 可查看 Codex 和 Grok 登录是否就绪。
- 一次生成多张图片（`n` 为 `1`–`4`）时按顺序逐张生成并立即写入磁盘；如果后续某张失败或中途取消，前面已生成的图片仍会返回并保留在磁盘上。

### 提供商选择顺序

未指定 `provider` 或设为 `"auto"` 时，扩展按以下顺序选择后端：

1. 传入了参考图（`referencedImagePaths` 或 `numLastImagesToInclude`）→ `codex`
2. 当前会话模型属于 `openai-codex` → `codex`
3. 当前会话模型属于 `xai` → `grok`
4. 配置文件或环境变量设置了 `defaultProvider` → 使用该默认提供商
5. 以上都不满足时，提示显式传入 `provider="codex"` 或 `provider="grok"`（或配置 `defaultProvider`）。

### 工具参数（`generate_image_with_subscription`）

| 参数 | 说明 |
| --- | --- |
| `prompt` | 必填，图片描述或编辑指令 |
| `provider` | `auto`（默认）、`codex`（别名 `openai`、`openai-codex`）或 `grok`（别名 `xai`、`grok-cli`） |
| `model` | 模型覆盖（Codex 路由模型或 Grok Imagine 模型） |
| `aspectRatio` | `1:1`、`3:4`、`4:3`、`9:16`、`16:9`、`2:3`、`3:2`、`9:19.5` 或 `19.5:9`（兼容别名 `aspect_ratio`） |
| `n` | 顺序生成张数（`1`–`4`，默认 `1`） |
| `outputFormat` | 仅 Codex：`png`（默认）、`jpeg` 或 `webp` |
| `referencedImagePaths` | 仅 Codex：最多 5 张本地参考图路径（`png`、`jpeg`、`webp`） |
| `numLastImagesToInclude` | 仅 Codex：引用当前对话中最近的 `1`–`5` 张图片 |
| `resolution` | 仅 Grok：`1k`（默认）或 `2k` |
| `quality` | 仅 Grok Imagine 2.0：`low` 或 `medium`（默认不传） |
| `save` | `global`（默认，`~/.pi/agent/generated-images/`）、`project`（`<cwd>/.pi/generated-images/`）、`custom` 或 `none` |
| `saveDir` | `save="custom"` 时的保存目录 |

## 配置

可在 `~/.pi/agent/extensions/subscription-image.json`（全局）或 `.pi/extensions/subscription-image.json`（受信任项目的局部覆盖）中配置：

```json
{
  "defaultProvider": "codex",
  "save": "global",
  "saveDir": "~/Pictures/generated",
  "providers": {
    "codex": {
      "routingModel": "gpt-5.6-sol",
      "outputFormat": "png"
    },
    "grok": {
      "imageModel": "grok-imagine-image-2.0",
      "resolution": "1k"
    }
  }
}
```

可选设置 `providers.grok.quality` 为 `"low"` 或 `"medium"`；同时兼容旧版顶层键 `codexRoutingModel` 和 `grokImageModel`。

### 环境变量

| 变量名 | 说明 |
| --- | --- |
| `PI_SUBSCRIPTION_IMAGE_PROVIDER` | 默认提供商（`codex` 或 `grok`） |
| `PI_SUBSCRIPTION_IMAGE_SAVE_MODE` | 保存模式（`global`、`project`、`custom` 或 `none`；兼容 `PI_IMAGE_SAVE_MODE`） |
| `PI_SUBSCRIPTION_IMAGE_SAVE_DIR` | `save="custom"` 时的保存目录（兼容 `PI_IMAGE_SAVE_DIR`） |
| `PI_SUBSCRIPTION_IMAGE_CODEX_MODEL` | 默认 Codex 路由模型 |
| `PI_SUBSCRIPTION_IMAGE_CODEX_OUTPUT_FORMAT` | 默认 Codex 输出格式（`png`、`jpeg` 或 `webp`） |
| `PI_SUBSCRIPTION_IMAGE_GROK_MODEL` | 默认 Grok 生图模型 |
| `PI_SUBSCRIPTION_IMAGE_GROK_RESOLUTION` | 默认 Grok 分辨率（`1k` 或 `2k`） |
| `PI_SUBSCRIPTION_IMAGE_GROK_QUALITY` | 默认 Grok 质量（`low` 或 `medium`） |
| `PI_SUBSCRIPTION_IMAGE_GROK_BASE_URL` | 自定义 Grok 接口地址（默认 `https://api.x.ai/v1`） |

## 隐私与安全

- 仅从 Pi 自身的登录注册表读取凭据，扩展不会将令牌写入磁盘。
- Codex 请求发往 `https://chatgpt.com/backend-api/codex/responses`，Grok 请求发往 `https://api.x.ai/v1/images/generations`（或 `PI_SUBSCRIPTION_IMAGE_GROK_BASE_URL` 指定的地址）。
- 保存目录和平台参数会在发起生图请求前完成校验，配置错误不会消耗额度。
- 提示词按原样发送（仅在 Codex 下指定 `aspectRatio` 时追加一行宽高比要求）。

## 本地开发

```bash
# 运行测试
npm test

# 运行类型检查、测试、加载检查和打包检查
npm run check

# 不安装直接加载扩展验证
pi --no-extensions --offline -e ./src/index.ts --list-models
```

### 在 Codemode 脚本中调用

在支持工具 `outputSchema` 和 `structuredContent` 的 Pi 版本中，可以在 Codemode 脚本里直接调用 `tools.generate_image_with_subscription`：

```js
const result = await tools.generate_image_with_subscription({
  prompt: "一只水彩风格的红熊猫",
});
for (const block of result.output) {
  if (block.type === "image") image(block);
  else text(block.text);
}
```

返回结构为 `{ provider, model, output, generationErrors, savedPaths, saveWarnings }`。图片块请传给 `image(block)`，不要把完整结果或 base64 数据传给 `text()`、`console.log` 或 `return`，以免触发 Codemode 单脚本 16 MiB 输出上限。单次脚本生成多张 Codex 图片时，建议将 `outputFormat` 设为 `"webp"` 或 `"jpeg"`。

## 许可证

[MIT](./LICENSE)。改编的第三方源码及许可证信息见 [THIRD_PARTY_NOTICES.md](./THIRD_PARTY_NOTICES.md)。
