Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
82 commits
Select commit Hold shift + click to select a range
02219bd
feat: integrate Steam Workshop browsing and management functionality
FallenCrystal Jul 6, 2026
0e277fb
style: adjust 'view all' button size and position on workshop home & …
FallenCrystal Jul 6, 2026
ca43d44
feat(workshop): UI/UX improvements for workshop browser
FallenCrystal Jul 6, 2026
417258c
feat(workshop): scrape and display extra details for workshop items (…
FallenCrystal Jul 6, 2026
d0b6cc7
feat(workshop): add loading animation, crossfade gallery & fullscreen…
FallenCrystal Jul 6, 2026
b13a155
test: add comprehensive tests, resolve lint issues, and optimize comp…
FallenCrystal Jul 6, 2026
390b302
feat(addon): implement content-based addon identification via file ha…
FallenCrystal Jul 6, 2026
c21dcb6
feat(addon): optimize hashing with fast MD5 and transition to identif…
FallenCrystal Jul 7, 2026
c0621a3
feat: background load workshop details in DetailModal, extract shared…
FallenCrystal Jul 7, 2026
1906633
fix(workshop): fix download progress percentage being multiplied by 1…
FallenCrystal Jul 7, 2026
3c0edbb
feat: add master collections and improve uninstalled addons management
FallenCrystal Jul 7, 2026
f8af367
refactor: use Tauri IPC for cache image loading & improve addon downl…
FallenCrystal Jul 7, 2026
2ebad53
feat(workshop): integrate background download and metadata caching fr…
FallenCrystal Jul 7, 2026
866e520
refactor: split tauri commands and vpk modules
FallenCrystal Jul 7, 2026
ac10c35
feat: allow clicking undownloaded workshop items to view detail page
FallenCrystal Jul 7, 2026
40cc513
feat(workshop): capture richer Steam metadata
FallenCrystal Jul 7, 2026
085434e
refactor backend runtime storage layout
FallenCrystal Jul 7, 2026
648631e
Restrict background workshop fetches to known addons
FallenCrystal Jul 7, 2026
fa82132
chore: add /l4a to .gitignore
FallenCrystal Jul 7, 2026
1f4233c
style(card): hide disabled badge for uninstalled addons and apply dar…
FallenCrystal Jul 7, 2026
9ae7218
fix(workshop): reduce scroll flicker and hover jank
FallenCrystal Jul 7, 2026
c213c16
Fix Tauri dev hot reload
FallenCrystal Jul 7, 2026
9f5e236
Add hybrid Steam workshop bridge layer
FallenCrystal Jul 8, 2026
c78f75a
chore: skip installer bundle when building release
FallenCrystal Jul 8, 2026
56cc59a
fix workshop author name resolution
FallenCrystal Jul 8, 2026
20cc65f
feat(ui): update search placeholder, improve topbar layout wrapping, …
FallenCrystal Jul 8, 2026
d81006e
style: 为所有图片加载添加失败占位图,避免默认图裂图标
FallenCrystal Jul 8, 2026
002c749
chore: remove package-lock.json from tracking and add to .gitignore
FallenCrystal Jul 8, 2026
9560ad6
Add addon file watcher auto refresh
FallenCrystal Jul 8, 2026
693649f
fix(lint): fix frontend oxlint and backend cargo clippy issues
FallenCrystal Jul 8, 2026
6412fa9
feat(tasks): add task center for background downloads and workshop sync
FallenCrystal Jul 8, 2026
944bde7
Fix duplicate watcher refresh toasts
FallenCrystal Jul 8, 2026
4612d87
feat(steam): stage bridge runtime files and add sdk warnings
FallenCrystal Jul 8, 2026
c43cba0
Fix Steamworks workshop lifecycle and sorting
FallenCrystal Jul 8, 2026
9b73c7b
Format remaining Rust source files
FallenCrystal Jul 8, 2026
1e198de
Add Steamworks SDK disable safeguards
FallenCrystal Jul 8, 2026
e6da728
Refine Steam workshop sync sources
FallenCrystal Jul 8, 2026
c04dfd3
feat: improve integrated workshop fetching
FallenCrystal Jul 8, 2026
2239b1b
Improve workshop source policy and caching
FallenCrystal Jul 8, 2026
7eca5f6
Fix Steam bridge runtime loading on Linux
FallenCrystal Jul 8, 2026
20163a5
fix: limit workshop image caching to known items
FallenCrystal Jul 8, 2026
b27c000
Fix workshop snapshot caching and author mapping
FallenCrystal Jul 8, 2026
52a5aa6
Fix workshop collection snapshots and cache schema
FallenCrystal Jul 8, 2026
9cd4b6a
Fix Steamworks SDK startup when disabled by settings
FallenCrystal Jul 8, 2026
ba2923e
Fix workshop dependency detail resolution
FallenCrystal Jul 9, 2026
1b6bf61
feat: implement integrated steam workshop command handlers and settin…
FallenCrystal Jul 9, 2026
f937862
Fix workshop downloads overriding dummy addons
FallenCrystal Jul 9, 2026
bc70626
Add download settings and resumable workshop downloads
FallenCrystal Jul 9, 2026
7a1b44c
Extract i18n resources into JSON
FallenCrystal Jul 9, 2026
4fcd748
docs: update steamworks-sdk-details.md
FallenCrystal Jul 9, 2026
5d9e61a
Ensure downloaded group addons sort first
FallenCrystal Jul 9, 2026
a8c314b
Fix batch action state filtering
FallenCrystal Jul 9, 2026
83207d0
feat: improve UI feedback and prevent double clicks during submission
FallenCrystal Jul 9, 2026
9e6b7b0
style: fix batch action bar buttons wrapping on narrow screens
FallenCrystal Jul 9, 2026
d35e7a6
refactor(src-tauri): split handlers.rs into multiple submodules
FallenCrystal Jul 10, 2026
df3d2c2
Fix Rust backend lint warnings
FallenCrystal Jul 10, 2026
2d8647c
Fix workshop detail descriptions
FallenCrystal Jul 10, 2026
a33fc87
fix: resolve race conditions and detail modal behavior for workshop i…
FallenCrystal Jul 10, 2026
8a91a35
feat: improve frontend multi-select operations
FallenCrystal Jul 10, 2026
fa74a26
feat(batch-action): optimize selectDownloaded and selectUndownloaded …
FallenCrystal Jul 10, 2026
d865766
feat: add automatic retry for url downloads and style number input sp…
FallenCrystal Jul 10, 2026
da9e100
feat: support custom http headers in mirror config
FallenCrystal Jul 10, 2026
01a34b5
feat: improve mirror matching with regex and object-based config
FallenCrystal Jul 10, 2026
435651d
Fix group and master collection handling
FallenCrystal Jul 10, 2026
050d2f3
Fix mirrors unused assignment warning
FallenCrystal Jul 10, 2026
a9ef8e5
feat(workshop): update steam workshop integration and UI optimizations
FallenCrystal Jul 11, 2026
e1c4a8f
feat: add delete and batch delete functionality for installed addons
FallenCrystal Jul 12, 2026
d58e6bd
feat: optimize group selection modal font, remove mirror web buttons,…
FallenCrystal Jul 12, 2026
aacdd0c
fix(clippy/test): resolve cargo clippy warnings and fix SettingsView …
FallenCrystal Jul 12, 2026
c4b1ea1
feat: implement dependency prompt modal and related configurations
FallenCrystal Jul 12, 2026
d97b6b2
test: fix npm test failures
FallenCrystal Jul 12, 2026
fa1b42a
fix(workshop): dependency check can ignored workshop items
FallenCrystal Jul 12, 2026
916cb72
fix(workshop): use raw workshop IDs as identifiers
FallenCrystal Jul 12, 2026
20093bc
fix(workshop): prompt and label missing dependencies
FallenCrystal Jul 12, 2026
5ea717e
fix: preserve workshop cover images without gallery
FallenCrystal Jul 12, 2026
a52a816
fix: dependency check unable to delete or retry
FallenCrystal Jul 12, 2026
48dc2a8
Merge branch 'refs/heads/main' into feat/integrated-steam-workshop
FallenCrystal Jul 12, 2026
a4e1611
docs: update readme
FallenCrystal Jul 12, 2026
8b821a6
feat: refactor workshop item detection; filter collection workshop id
FallenCrystal Jul 12, 2026
9542da2
fix: validate VPK workshop IDs by source
FallenCrystal Jul 12, 2026
b2027ee
fix: rebuild campaign auto grouping safely
FallenCrystal Jul 12, 2026
f098fab
fix: clean checks and cover mirror rules
FallenCrystal Jul 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .cargo/config.toml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
[target.x86_64-pc-windows-gnu]
linker = "x86_64-w64-mingw32-gcc"
8 changes: 8 additions & 0 deletions .gitignore
Original file line numberDiff line numberDiff line change
Expand Up@@ -23,6 +23,7 @@ WebView2Loader.dll

# Rust/Tauri Target
src-tauri/target/
steam-bridge/target/

# Editor directories and files
.vscode/*
Expand All@@ -34,3 +35,10 @@ src-tauri/target/
*.njsproj
*.sln
*.sw?

# Left4Addons specific ignores
.playwright-mcp
known_addons.json
/l4a
package-lock.json

38 changes: 31 additions & 7 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -24,24 +24,24 @@
>
> Antigravity 并没有我想象中的那么难用, 但是就想闲暇之余蹬一下额度而已.
> 我只做了找bug和UI/UX反馈, 没有对其进行代码Review.
> 环境为 Antigravity + Gemini (3.5 Flash High & 3.1 Pro High)

> [!WARNING]
>
> 当前分支 `main` 落后太多且有较多问题. 在这上面冒的险还不如构建使用分支 `integrated-steam-workshop`. 但在我看来两个分支都有相当多问题, 在稳定前不建议深度使用.

> 环境:
> - Antigravity + Gemini 3.5 Flash / 3.1 Pro (High)
> - Codex + GPT 5.4 / 5.5 / 5.6 Terra (xHigh / High)
---

## 特色功能

- 战役 (Campaign) Part 合并: 支持自动检测将分散的战役 Part 文件合并为一组.
- (批量) 重命名: 自动重命名为可读名称, 避免在创意工坊 ID 列表里大海捞针
- 快速移动: 将想要的附加组件从创意工坊内移动到 `addons` 文件夹下.
(但是不支持自动取消订阅)
- 快速切换: 快速启用或禁用特定的附加组件.
(不支持还未移动到 `addons` 文件夹下的组件)
- Dummy Bypass (实验性): 通过一个空的合法 `.vpk` 文件,
允许在不取消订阅的情况下将附件移出创意工坊并绕过创意工坊更新检查.
- 内置创意工坊 & 下载: 无需订阅, 无需启动游戏 一键下载并加载组件!
自动解析组件依赖关系(创意工坊), 自动重试断点续传和并发下载(默认2)等.
- 一键抓取现有 Steam 创意工坊订阅 (需要启用 Steamworks SDK)
- 为高级用户准备的 [mirror.json](docs/mirrors-configuration.md), 修改 HTTP 请求头, 自配置CDN等..

## 局限性
- Dummy Bypass:
Expand All@@ -50,6 +50,12 @@
- 游戏内的附加内容会看到两份相同的附件
一份是创意工坊名 一份是附件内 `addoninfo.txt` 的名
尽管创意工坊侧的 Dummy 附件不添加任何游戏内容.
- Steamworks SDK 集成:
- 使用 Steamworks SDK 会让 Left 4 Addons 伪造成“求生之路”游戏, 以通过 Steam 访问其创意工坊内容.
- Left 4 Addons 使用 Steamworks SDK 时,
启动《求生之路》会导致游戏本体不被 VAC 信任. (但不会导致 VAC 封禁)
启动游戏时应先关闭 L4A.
- 更完整的 SDK 搜索/下载限制与实现细节见 [文档](docs/steamworks-sdk-details.md).

---

Expand DownExpand Up@@ -92,6 +98,24 @@ npm run tauri:build

构建完成后,你可以在 `src-tauri/target/release/` 下找到生成的可执行文件。

### Linux 上交叉构建 Windows 版本

如果你当前在 Linux 上开发,推荐先使用 `x86_64-pc-windows-gnu` 目标:

```bash
rustup target add x86_64-pc-windows-gnu
npm run tauri:build:win-gnu
```

构建完成后,Windows 产物位于 `src-tauri/target/x86_64-pc-windows-gnu/release/`。

其中 Steamworks bridge 运行时文件会自动放到 `src-tauri/target/x86_64-pc-windows-gnu/release/steam/`:

- `l4a-steam-bridge.dll`
- `steam_api64.dll`

这样无需再手动复制 Steam bridge 相关 DLL。

---

## 许可证
Expand Down
119 changes: 119 additions & 0 deletions docs/mirrors-configuration.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
# 镜像代理配置指南 (Mirrors Configuration)

Left4Addons 支持配置自定义的请求镜像代理 (`mirrors.json`)。通过配置,你可以将应用发往特定域名(例如 Steam 创意工坊)的 HTTP/HTTPS 请求自动重定向到自定义的反向代理或者镜像节点。

## 配置文件位置

当你启动应用后,配置文件会自动读取自应用的运行时目录,通常位于应用的配置文件夹下。如果没有文件,可以手动新建一个 `mirrors.json`。

## 基本语法

`mirrors.json` 是一个包含多个**规则对象**的 JSON 数组。代理匹配支持三种模式:**对象模式**、**高级正则模式**、以及**简易字符串模式**。

### 字段说明 (通用)

- **`target`** (`String`, 必填)
重定向到的目标域名。可以使用 `$1`, `$2` 等占位符来引用匹配规则中捕获的内容(例如被匹配到的子域名)。
- 若为了保持向后兼容,如果你使用了简易字符串模式并保留了 `*` 号,`*` 仍然会被自动替换为第一个捕获组。
- **`keep-host`** (`Boolean`, 可选,默认 `false`)
如果设置为 `true`,将在发送请求时自动添加一个 `Host` 请求头,值为被代理前的原始域名。这通常用于需要验证原始域名的反向代理。
- **`headers`** (`Object`, 可选,默认无)
允许在通过此镜像规则发起请求时,自动添加或覆盖特定的 HTTP 请求头。

---

### 模式一:对象模式 (推荐)
通过结构化的对象定义匹配规则,清晰且易于维护。

- **`domain`** (`String`, 必填)
需要匹配的基础域名,例如 `"steamstatic.com"`。
- **`subdomains`** (`Array<String>`, 可选)
需要匹配的子域名列表。例如 `["store", "media"]`。
- 如果想要匹配任意子域名,可以使用 `["*"]`。
- 子域名将被作为**第一个捕获组** `$1`。
- **`allow-www`** (`Boolean`, 可选,默认 `false`)
是否允许可选的 `www.` 前缀。如果你希望 `www.steamstatic.com` 和 `steamstatic.com` 都能被匹配到,请设为 `true`。(`www.` 不会被捕获,不影响 `$1`)

**配置示例:**
```json
[
{
"domain": "steamstatic.com",
"subdomains": ["store", "media"],
"allow-www": true,
"target": "$1.mirror.example.com"
}
]
```
*以上规则可以匹配 `store.steamstatic.com` 和 `www.media.steamstatic.com`,重定向时 `$1` 会被替换为 `store` 或 `media`。*

---

### 模式二:简易字符串模式 (向下兼容)
通过一条字符串规则快速匹配,支持简单的分组和通配符。

- **`rules`** (`String`, 必填)
- 组匹配:`[a,b].example.com`(相当于正则中的 `(a|b).example.com`),会作为捕获组 `$1`。
- 可选组:`[www.]?example.com`,在 `]` 后面加上 `?` 表示该组为可选,这解决了以往匹配可选前缀时语法怪异的问题。
- 通配符匹配:`*`,匹配并捕获任何内容。
- **提示**:在新版本中,建议在 `target` 中使用 `$1`, `$2` 来精确引用对应的捕获组,以避免 `[]` 组匹配意外抢占了通配符 `*` 的内容。

**配置示例:**
```json
[
{
"rules": "[www.]?*.steamcommunity.com",
"target": "$2.steam.example.com",
"keep-host": true
}
]
```
*上述规则中,`[www.]?` 是第一个捕获组 `$1`(无论是否匹配上),而 `*` 则是第二个捕获组 `$2`。我们在 `target` 中明确使用了 `$2`,避免了冲突。*

---

### 模式三:高级正则模式
如果内置的匹配模式无法满足需求,你可以直接提供标准的正则表达式进行完全匹配控制。

- **`regex`** (`String`, 必填)
标准正则表达式字符串。正则表达式将针对请求的完整 Host (包括端口,如果有的话) 进行匹配。

**配置示例:**
```json
[
{
"regex": "^(?:www\\.)?(.*?)\\.steampowered\\.com$",
"target": "$1.proxy.my-server.com"
}
]
```

## 其它配置示例

### 代理 Steam 创意工坊接口并保持 Host

```json
[
{
"rules": "api.steampowered.com",
"target": "192.168.1.100:8080",
"keep-host": true
}
]
```

### 附加特定的 User-Agent

```json
[
{
"domain": "steampowered.com",
"subdomains": ["store", "cdn"],
"target": "$1.proxy.my-server.com",
"headers": {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
"X-Forwarded-For": "114.114.114.114"
}
}
]
```
125 changes: 125 additions & 0 deletions docs/steamworks-sdk-details.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
# Steamworks SDK 细节与限制

本文档记录 Left 4 Addons 当前接入 Steamworks SDK 时已经确认的行为、限制和取舍.

## 1. 总结

- Steamworks SDK 的查询结果与 Steam Community 网页端并不等价, 目前无法仅依靠 SDK 实现高可用性的精准搜索.
- L4A (Left 4 Addons) 可通过 Steamworks SDK 触发 Steam 下载附件, 但过程不可靠. 这也是为何我们要尽可能回退到“通过 URL 下载”方案的原因之一.

## 2. 搜索行为限制

### 2.1 SDK 搜索不等同于网页搜索

当前使用的 SDK 搜索基于 `ISteamUGC` 文本检索能力. 实测它和网页端 `steamcommunity.com/workshop/browse` 的语义差异很大:

多词查询经常劣化为宽松匹配 (逻辑近似 OR, 而不是网页端符合预期的短语或相关性匹配):
- 搜索 `Early Days`
- 网页端可返回 `Early Days` 战役相关 `Part 1-6`
- SDK 侧则可能返回 `Early 2008 style`、`Early Zombie`、`Day Break`、`Release Day Bots`

单词查询结果同样可能严重偏离:
- 搜索 `Cambalache`
- 预期结果是 `Cambalache 2`
- SDK 结果里完全没有相关附件


SDK 文本搜索目前完全无法复刻网页端的搜索体验. 如果需要“像网页那样”的精准搜索, 仍必须依赖网页抓取或混合方案.

### 2.2 分类浏览无法纯 SDK 完整复原

当前分类浏览依赖 Steam Community 首页 SSR 数据里的 `declared_tags_v5` 等页面信息.

- “分类树/分类浏览”目前是网页端或 SDK+HTML 混合能力
- 截止目前, 仅靠纯 Steamworks SDK 不可能实现该功能.

## 3. 下载行为限制

### 3.1 文件格式与较新创意工坊物品不同

对于较新的游戏 (如 Wallpaper Engine) , 创意工坊物品通常是一个包含多个文件的文件夹 (甚至涉及更复杂的着色器编译等) .

但对 L4D2 而言, Workshop 物品由游戏自身处理并安装到 `steamapps/common/Left 4 Dead 2/left4dead2/addons/workshop/` 目录下.

通过 SDK 触发的下载产物位于:

`steamapps/workshop/content/550/<workshop-id>/<longint>_legacy.bin`

> 注: _legacy.bin 似乎是 Steam 针对部分较老的单文件 (如起源引擎用的 `.vpk`) 的重命名机制,
> 但具体细节仍不透明.
> 尽管将 _legacy.bin 手动改名为 .vpk 后能够正常工作, 但这已经是所有下载问题中最小的一个.

### 3.2 Steam 下载进度不可靠

Steam客户端的下载管理会出现非真实状态的情况:

- Steam 下载管理里长时间显示 0 进度 / 0 网络 / 0 磁盘
- 可能会进入“正在停止”
- 没有稳定可见的进度条
- 突然显示已完成

虽然 L4A 内部获取的进度看起来正常, 但无法保证底层确实在正常工作.

### 3.3 无法重新下载或只能保留两个副本

- 如果直接删除 `steamapps/workshop/content/550/...` 下的文件夹或里面的文件,
再次请求后 Steam 也不会重新下载.
- 取消订阅后退出游戏进程 (无论是L4A还是求生之路 即游戏退出未运行的状态时),
Steam 不会删除目标文件/文件夹.
- Steam 可能还持久化保存了如 Manifest 状态.
虽怀疑是 `steamapps/workshop/appworkshop_550.acf` 作祟,
但删除后重启 Steam 仍然不起作用
这是 L4A 无法稳定通过 SDK 下载附件它的核心阻碍之一.

在 Wallpaper Engine 侧测试时发现,
如果在 Steam 自动删除前手动删除了物品缓存 (无论是否已订阅) 都会导致严重状态错误.
最致命的影响之一是永久无法再次订阅该物品
(除非去网页端订阅, 或换一台计算机操作, 但后续行为暂未测试, 具体后续行为也是个未知数).

## 4. Steamworks SDK 无法直接获取下载 URL

SDK 里确实有 `ISteamRemoteStorage::GetPublishedFileDetails`

> `Deprecated - Only used with the deprecated RemoteStorage based Workshop API`

这是旧版 RemoteStorage API 的接口,且其返回值中并没有暴露文件的直接下载链接。

虽然它看起来和网页端免鉴权的 Web API
即 (https://api.steampowered.com/ISteamRemoteStorage/GetPublishedFileDetails/v1/)
名字几乎一样, 但 SDK 侧偏偏缺少了最核心的 `file_url` 字段,
导致无法在不额外请求网络 API 的情况下得到下载链接.

## 5. 从旧README中迁移过来的已知缺点

- 使用 Steamworks SDK 会使 Left 4 Addons 在 Steam 状态中“伪装”成求生之路, 以此来获取访问创意工坊的权限.
- **VAC 信任问题**:
如果你在使用 L4A 调用 SDK 时启动游戏. 会导致游戏本体短暂不被 VAC 信任.
这不会导致封号,但你必须彻底退出 L4A 后再启动游戏才能恢复正常。
- 仅靠 SDK 无法满足现有需求, 但某些加速器只给加速 Steam 相关进程. 求生之路本体都是自己下的Addon 那些加速器那就是啥用没有 挂个梯子吧.
- 只要 L4A 调用过一次 SDK, Steam 就会一直显示你“正在玩求生之路”, 直到 L4A 进程完全结束.
如果你在 Steam 库里好奇点了一下“停止”, L4A 就会被关掉.
- 由于 L4D2 创意工坊的 Addon 是游戏内/第三方直连下载
市面上那些仅加速特定进程的加速器对此毫无作用.
建议根据自身网络环境决定是否禁用 Steamworks SDK, 或直接使用系统级代理工具.

## 后记

我要写点有人味的东西, 这样你才不会觉得太枯燥(或许) 或者完全是用 AI 生成的垃圾什么的.

清理了一下 GPT 生成的无意义描写. 依旧给GPT语擦屁股. 虽然我叫它狗屁通 但写出来的东西也不完全是狗屁不通. 跑分还怪高的嘞

没有网页版的创意工坊简直就是地狱, 这个 SDK 的搜索逻辑 ——小红车用户自适应太牛逼了.

写了这么多缺点, Steamworks SDK 也并非没有好处. 相反效果还挺好的, 只是明显只靠它不是最佳解决方案.

Steamworks SDK 特色功能:
- (几乎) 无速率限制的 API 请求. 或者 Steam 自己已经帮我们处理好了这点
- 不需要爬网站就可以解析创意工坊物品的依赖 (这样不会战役Part冲突就瞎几把报“假阳性"了)
- 我可以一把抓到你的所有创意工坊订阅 (但是我好像拉不到收藏的合集 但自己导入L4A其实也很简单了)

你别看我现在就写出来这3个 其实算是很强大的了 因为我总不可能爬几百个附件对应的网站.
也可以其实, 那 Too many request 伺候就你就不嘻嘻了.

希望 V 社越做越好吧. 别跟我说史山的事, 至少我希望之后 SDK 和创意工坊相关的逻辑不会这么屎. 大概多久? 可能是 2028 年吧. 2028 年应该有足够强大的模型给史山擦屁股了.

最近几周创意工坊网页更新很棒. SDK 只要能做一样的事那算是祖坟冒青烟了.
Loading