# 接入 Speclip

`@speclip/pi-speech` 设计为 Speclip 内置 Pi 包。包与 `pi-media` 一样调用 Pi SDK 的 `getAgentDir()` 解析 agent profile，Speclip 负责通过本地 Hono API 和设置页安全写入。

## 凭证路径契约

Speclip 在 fork API server 时必须设置：

```text
PI_CODING_AGENT_DIR=~/.speclip/agent
```

因此 Speclip 中的实际文件固定为：

```text
~/.speclip/agent/speech-credentials.json
~/.speclip/agent/speech-config.json
```

`~/.pi/agent/` 只是没有设置 `PI_CODING_AGENT_DIR` 时裸 Pi CLI 的默认 profile，Speclip 不得在该目录读取、写入、迁移或查找 speech 凭证。包本身不硬编码宿主路径，也不迁移旧 profile；由宿主进程在加载 Extension 和路由之前统一设置环境变量。

## 必需接线

1. `web/package.json` 增加 `@speclip/pi-speech` 依赖。
2. `web/lib/bundled-plugins.ts` 把包加入内置清单，让 Extension 和 Skill 进入统一 ResourceLoader，并运行时遮蔽同名手动安装项。
3. `scripts/build-server.mjs` 显式复制包目录。Pi 资源从 `package.json` 动态发现，`@vercel/nft` 无法静态追踪。
4. 设置中增加稳定分区 `speech`：默认 ASR 显示本地 FireRedASR，默认 TTS 显示本地 DotsTTS，二者都不要求 API Key。OpenRouter 与百炼作为可选云 provider；只有保存云 provider 时才写凭证文件，状态 API 不得返回 API Key。
5. 生产打包测试必须检查包清单、Extension 和 Skill 均存在。

本包只有 TypeScript 和 HTTP 调用，无平台限制，应随 macOS、Linux、Windows 构建一起复制。当前 DotsTTS 整合包只覆盖 Apple Silicon macOS；其他平台若没有兼容的本地服务，应显式选择已配置的云模型，不得把“包可加载”等同于“本地模型可运行”。

## 写入要求

- agent profile 目录权限 `0700`
- `speech-credentials.json` 权限 `0600`
- 写入使用 `proper-lockfile`；保留未知 provider 配置
- 拒绝父目录或文件符号链接
- API 响应只返回 `configured: boolean`、非秘密配置和默认值

包缺少配置时会返回可点击的 `speclip://settings/speech` 链接。

本地 ASR/TTS 不需要首次配置。宿主需要持久化完整 speech 默认值时，应写为两个本地模型；只有用户选择云端 ASR/TTS 时才要求对应 API Key：

```json
{
  "asr": {
    "provider": "fireredasr-local",
    "model": "fireredasr2-ctc-int8"
  },
  "tts": {
    "provider": "dotstts-local",
    "model": "dots-tts-mf",
    "voice": "default",
    "format": "mp3"
  }
}
```

设置页应明确标注：本地 ASR/TTS 分别需要 FireRedASR.app 与 DotsTTS.app 正在运行并已安装模型，但不需要 API Key，也没有云端 API 费用。DotsTTS 默认 MF，可选 SOAR；已注册 `voice_...` 音色必须与模型匹配。Fish Audio TTS 是可选的免费测试/原型路由；OpenRouter Whisper ASR 是付费模型。保存任一云 provider 时保留其他已有配置，便于回退，但不得把云模型悄悄改成默认值。百炼的 `workspaceId` 仍是子业务空间的可选高级设置。

每个云供应商自己的 TTS 参数同时写入 `providers[provider]`：OpenRouter 保存 `voice`，百炼保存 `voice`、`format` 和 `sampleRate`。DotsTTS 的默认音色和格式直接保存在 `defaults.tts`；其服务地址不开放配置覆盖。这样备用供应商即使不是全局默认，显式选择其模型时仍能恢复用户保存的高级设置。
